/// <summary> /// Gets vertices and normals from a skinned world object in Vector3[] format (notice that the array is modified by reference). /// </summary> /// <param name="particleStateWorldObject">Skinned World Object.</param> /// <param name="updateNormals">If set to <c>true</c> update normals.</param> public static void GetPosition (SkinnedWorldObject particleStateWorldObject, bool updateNormals) { PlaygroundParticlesC.GetPosition(particleStateWorldObject, updateNormals); }
/// <summary> /// Returns a copy of this SkinnedWorldObject. /// </summary> public SkinnedWorldObject Clone () { SkinnedWorldObject skinnedWorldObject = new SkinnedWorldObject(); skinnedWorldObject.downResolution = downResolution; skinnedWorldObject.gameObject = gameObject; skinnedWorldObject.transform = transform; skinnedWorldObject.rigidbody = rigidbody; skinnedWorldObject.renderer = renderer; skinnedWorldObject.meshFilter = meshFilter; skinnedWorldObject.mesh = mesh; skinnedWorldObject.updateNormals = updateNormals; return skinnedWorldObject; }
public SimplexNoise turbulenceSimplex; // The Simplex Noise of this manipulator property /// <summary> /// Updates this ManipulatorPropertyC. /// </summary> public void Update () { if (type==MANIPULATORPROPERTYTYPEC.Target) { for (int i = 0; i<targets.Count; i++) targets[i].Update(); } else if (type==MANIPULATORPROPERTYTYPEC.MeshTarget) { if (meshTarget.gameObject!=null) { if (meshTarget.cachedId!=meshTarget.gameObject.GetInstanceID()) meshTarget = PlaygroundParticlesC.NewWorldObject (meshTarget.gameObject.transform); if (meshTarget.mesh!=null) { meshTargetMatrix.SetTRS(meshTarget.transform.position, meshTarget.transform.rotation, meshTarget.transform.localScale); if (meshTargetIsProcedural) UpdateMeshTarget(); } if (meshTarget.initialized && (targetSortingList==null || targetSortingList.Length!=meshTarget.vertexPositions.Length || previousTargetSorting!=targetSorting)) TargetSorting(); } } else if (type==MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget) { if (skinnedMeshTarget.gameObject!=null) { if (skinnedMeshTarget.cachedId!=skinnedMeshTarget.gameObject.GetInstanceID() || !skinnedMeshTarget.initialized) { skinnedMeshTarget = PlaygroundParticlesC.NewSkinnedWorldObject (skinnedMeshTarget.gameObject.transform); } if (skinnedMeshTarget.initialized) { if (meshTargetIsProcedural) UpdateSkinnedMeshTarget(); skinnedMeshTarget.BoneUpdate(); PlaygroundC.RunAsync(()=>{ skinnedMeshTarget.Update(); }); if (targetSortingList==null || targetSortingList.Length!=skinnedMeshTarget.vertexPositions.Length || previousTargetSorting!=targetSorting) TargetSorting(); } } } else if (type==MANIPULATORPROPERTYTYPEC.StateTarget) { if (!stateTarget.initialized && (stateTarget.stateMesh!=null || stateTarget.stateTexture!=null) && stateTarget.stateTransform!=null) { stateTarget.Initialize(); } else if (stateTarget.initialized && stateTarget.stateTransform!=null) { stateTarget.stateTransformMx.SetTRS(stateTarget.stateTransform.position, stateTarget.stateTransform.rotation, stateTarget.stateTransform.localScale); } if (stateTarget.initialized && (targetSortingList==null || targetSortingList.Length!=stateTarget.positionLength || previousTargetSorting!=targetSorting)) TargetSorting(); } else if (type==MANIPULATORPROPERTYTYPEC.SplineTarget) { splineTargetIsReady = splineTarget!=null&&splineTarget.IsReady(); } else if (type==MANIPULATORPROPERTYTYPEC.Turbulence) { if (turbulenceSimplex==null) turbulenceSimplex = new SimplexNoise(); } else if (type==MANIPULATORPROPERTYTYPEC.Math) { } }
/// <summary> /// Creates a new SkinnedWorldObject. /// </summary> /// <returns>The skinned world object.</returns> /// <param name="meshTransform">Mesh transform.</param> public static SkinnedWorldObject NewSkinnedWorldObject(Transform meshTransform) { SkinnedWorldObject skinnedWorldObject = new SkinnedWorldObject(); if (meshTransform.GetComponentInChildren<SkinnedMeshRenderer>()) { skinnedWorldObject.transform = meshTransform; skinnedWorldObject.Initialize (); } else Debug.Log("Could not find a skinned mesh in "+meshTransform.name+"."); return skinnedWorldObject; }
/// <summary> /// Prepares all values for calculation which is not thread-safe. /// </summary> /// <returns><c>true</c>, if threaded calculations was prepared, <c>false</c> otherwise.</returns> public bool PrepareThreadedCalculations() { // Component disabled? if (!enabled) return false; // Auto-Pause (start/stop calculation when particle system is out of view. if (pauseCalculationWhenInvisible) { bool skipFrustumCheck = false; #if UNITY_EDITOR if (!UnityEditor.EditorApplication.isPlaying) { calculate = true; skipFrustumCheck = true; } #endif if (!skipFrustumCheck && Camera.main!=null && PlaygroundC.frustumPlanes!=null) { bool shouldRender = GeometryUtility.TestPlanesAABB(PlaygroundC.frustumPlanes, new Bounds(calculationTriggerTransform==null?particleSystemTransform.position+calculationTriggerOffset:calculationTriggerTransform.position+calculationTriggerOffset, calculationTriggerSize)); if (!shouldRender && calculate && !particleSystemRenderer.isVisible) { calculate = false; #if UNITY_EDITOR if (!didHierarchyRepaint) UnityEditor.EditorApplication.RepaintHierarchyWindow(); didHierarchyRepaint = true; #endif return false; } else if (shouldRender && !calculate) { calculate = true; #if UNITY_EDITOR if (!didHierarchyRepaint) UnityEditor.EditorApplication.RepaintHierarchyWindow(); didHierarchyRepaint = true; #endif if (prewarm) {Start(); return false;} else SetParticleTimeNow (thisInstance); } } } else if (!calculate) { calculate = true; #if UNITY_EDITOR if (!didHierarchyRepaint) UnityEditor.EditorApplication.RepaintHierarchyWindow(); didHierarchyRepaint = true; #endif if (prewarm) {Start(); return false;} else SetParticleTimeNow (thisInstance); } if (!calculate) return false; // Has the calculation been paused previously? if (cameFromNonCalculatedFrame && hasActiveParticles) { StartCoroutine(Boot()); cameFromNonCalculatedFrame = false; return false; } // Apply locked position if (applyLockPosition) { if (lockPositionIsLocal) particleSystemTransform.localPosition = lockPosition; else particleSystemTransform.position = lockPosition; } // Apply locked rotation if (applyLockRotation) { if (lockRotationIsLocal) particleSystemTransform.localRotation = Quaternion.Euler(lockRotation); else particleSystemTransform.rotation = Quaternion.Euler(lockRotation); } // Apply locked scale if (applyLockScale) particleSystemTransform.localScale = lockScale; // Update active particle check hasActiveParticles = !threadHadNoActiveParticles || emit&&loop&&particleCount>0; if (!hasActiveParticles) { if (disableOnDone) queueEmissionHalt = true; } realSimulationTime = particleTimescale*Time.timeScale; cancelDeltaPositioningOnSync = false; // Prepare Source positions if (PlaygroundC.reference.IsDoneThread() && isDoneThread) { stRot = Quaternion.identity; stDir = new Vector3(); } localSpace = (shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local); overflow = (overflowOffset!=Vector3.zero); skinnedWorldObjectReady = false; renderModeStretch = particleSystemRenderer2.renderMode==ParticleSystemRenderMode.Stretch; particleSystemRotation = particleSystemTransform.rotation; particleSystemInverseRotation = particleSystemRotation; particleSystemInverseRotation.x = -particleSystemInverseRotation.x; particleSystemInverseRotation.y = -particleSystemInverseRotation.y; particleSystemInverseRotation.z = -particleSystemInverseRotation.z; particleSystemInverseRotation.w = -particleSystemInverseRotation.w; // Prepare turbulence if (!onlySourcePositioning && !onlyLifetimePositioning && turbulenceType!=TURBULENCETYPE.None) { if (turbulenceType==TURBULENCETYPE.Simplex && turbulenceSimplex==null) turbulenceSimplex = new SimplexNoise(); } if (emit) { switch (source) { case SOURCEC.Script: break; case SOURCEC.State: if (states.Count>0) { if (activeState>states.Count-1) activeState = states.Count-1; if (activeState<0) activeState = 0; if (states[activeState].stateTransform!=null) { if (isDoneThread) { if (!states[activeState].initialized) states[activeState].Initialize(); stRot = states[activeState].stateTransform.rotation; states[activeState].UpdateMatrix(localSpace); } if (localSpace && (states[activeState].stateTransform.parent==particleSystemTransform || states[activeState].stateTransform==particleSystemTransform) && isDoneThread) { cancelDeltaPositioningOnSync = true; stRot = Quaternion.Euler (Vector3.zero); } } } else return false; break; case SOURCEC.Transform: // Handle the availability of Playground Transforms (list of transform wrapper classes). // The single sourceTransform is an old method which needs to be copied over if available. if (sourceTransforms==null) { sourceTransforms = new List<PlaygroundTransformC>(); } if (sourceTransforms.Count==0) { sourceTransforms.Add(new PlaygroundTransformC()); sourceTransforms[0].transform = sourceTransform!=null?sourceTransform:particleSystemTransform; } if (isDoneThread) { for (int i = 0; i<sourceTransforms.Count; i++) { if (!sourceTransforms[i].Update()) return false; if (IsLocalSpace()) { psTransformNum = -1; sourceTransforms[i].SetLocalPosition(particleSystemTransform); sourceTransforms[i].SetPostitionAsLocal(); if (sourceTransforms[i].IsSameAs (particleSystemTransform)) { sourceTransforms[i].SetZeroRotation(); psTransformNum = i; } } } } if (isDoneThread) { stRot = sourceTransform.rotation; } if (localSpace && sourceTransform==particleSystemTransform && isDoneThread) { cancelDeltaPositioningOnSync = true; stRot = Quaternion.Euler (Vector3.zero); } break; case SOURCEC.WorldObject: // Handle vertex data in active World Object if (worldObject.gameObject!=null) { if (worldObject.gameObject.GetInstanceID()!=worldObject.cachedId || !worldObject.initialized) worldObject = NewWorldObject(worldObject.gameObject.transform); if (worldObject.mesh!=null) { if (isDoneThread) { stRot = worldObject.transform.transform.rotation; } if (localSpace && isDoneThread) { cancelDeltaPositioningOnSync = true; stRot = Quaternion.Euler (Vector3.zero); } worldObject.UpdateMatrix(localSpace); worldObject.updateNormals = worldObjectUpdateNormals; if (worldObjectUpdateVertices) worldObject.Update(); } else return false; } else return false; break; case SOURCEC.SkinnedWorldObject: // Handle vertex data in active Skinned World Object if (skinnedWorldObject.gameObject!=null) { if (skinnedWorldObject.gameObject.GetInstanceID()!=skinnedWorldObject.cachedId) { skinnedWorldObject = NewSkinnedWorldObject(skinnedWorldObject.gameObject.transform, skinnedWorldObject.downResolution); } } skinnedWorldObjectReady = skinnedWorldObject.gameObject!=null && skinnedWorldObject.mesh!=null; if (PlaygroundC.reference.skinnedMeshThreadMethod==ThreadMethodComponent.OneForAll && PlaygroundC.reference.IsFirstUnsafeAutomaticFrames() && !PlaygroundC.reference.IsDoneThreadSkinnedMeshes()) return false; if (skinnedWorldObjectReady) { if (isDoneThread) { stRot = skinnedWorldObject.transform.rotation; stDir = skinnedWorldObject.transform.TransformDirection (overflowOffset); } skinnedWorldObject.updateNormals = worldObjectUpdateNormals; if (Time.frameCount%PlaygroundC.skinnedUpdateRate==0) { if (worldObjectUpdateVertices) skinnedWorldObject.MeshUpdate(); skinnedWorldObject.BoneUpdate(); // Forced update for skinned mesh vertices on main-thread if (forceSkinnedMeshUpdateOnMainThread) { skinnedWorldObject.Update(); } } } else return false; break; case SOURCEC.Paint: if (paint.initialized) { if (isDoneThread) { stRot = particleSystemTransform.rotation; } if (paint.positionLength>0) { for (int p = 0; p<particleCache.Length; p++) { paint.Update(p); } } else return false; } else { paint.Initialize (); return false; } break; case SOURCEC.Projection: if (projection.projectionTexture!=null && projection.projectionTransform!=null) { if (!projection.initialized) projection.Initialize(); stRot = projection.projectionTransform.rotation; if (localSpace) shurikenParticleSystem.simulationSpace = ParticleSystemSimulationSpace.World; if (projection.liveUpdate || !projection.hasRefreshed) { projection.UpdateSource(); projection.Update(); stDir = projection.projectionTransform.TransformDirection (overflowOffset); projection.hasRefreshed = true; } } else return false; break; case SOURCEC.Spline: if (splines.Count>0) { for (int i = 0; i<splines.Count; i++) if (splines[i]==null || !splines[i].enabled || !splines[i].IsReady()) return false; if (isDoneThread) { stRot = particleSystemTransform.rotation; if (localSpace) { cancelDeltaPositioningOnSync = true; stRot = Quaternion.Euler (Vector3.zero); } } } else return false; break; } } // Collision detection (runs on main-thread) if (collision) Collisions(thisInstance); // Prepare Particle colors stateReadyForTextureColor = (source==SOURCEC.State && states[activeState].stateTexture!=null && states[activeState].colorLength>0); hasEventManipulatorLocal = false; hasEventManipulatorGlobal = false; hasGlobalAffectingManipulators = false; manipulatorEventCount = 0; thisLayer = particleSystemGameObject.layer; // Prepare Local Manipulators for (int m = 0; m<manipulators.Count; m++) { manipulators[m].Update(); manipulators[m].transform.SetLocalPosition(particleSystemTransform); manipulators[m].SetLocalTargetsPosition(particleSystemTransform); if (manipulators[m].trackParticles) { hasEventManipulatorLocal = true; manipulatorEventCount++; } } // Prepare Global Manipulators from this local space, bundle the thread call in case any Global Manipulator is tracking particles if (PlaygroundC.reference.HasEnabledGlobalManipulators()) { for (int m = 0; m<PlaygroundC.reference.manipulators.Count; m++) { if ((PlaygroundC.reference.manipulators[m].affects.value & 1<<GetLayer())!=0) { hasGlobalAffectingManipulators = true; PlaygroundC.reference.manipulators[m].transform.SetLocalPosition(particleSystemTransform); if (PlaygroundC.reference.manipulators[m].trackParticles && PlaygroundC.reference.threadMethod!=ThreadMethod.NoThreads) { threadMethod = ThreadMethodLocal.OneForAll; hasEventManipulatorGlobal = true; manipulatorEventCount++; } } } } hasSeveralManipulatorEvents = (manipulatorEventCount>1); // Prepare events hasEvent = events.Count>0; hasTimerEvent = false; if (hasEvent) { for (int i = 0; i<events.Count; i++) { events[i].Initialize(); if (events[i].initializedTarget && events[i].broadcastType!=EVENTBROADCASTC.EventListeners) if (!events[i].target.eventControlledBy.Contains (thisInstance)) events[i].target.eventControlledBy.Add (thisInstance); if (events[i].eventType==EVENTTYPEC.Time && ((events[i].broadcastType!=EVENTBROADCASTC.EventListeners && events[i].initializedTarget) || events[i].broadcastType==EVENTBROADCASTC.EventListeners && events[i].initializedEvent)) { hasTimerEvent = events[i].UpdateTime(); } } } // All good! Next step is to send all particles to calculation. return true; }
// Get vertices from a skinned world object in a Vector3-array public static void GetPosition(SkinnedWorldObject particleStateWorldObject, bool updateNormals) { if (updateNormals) particleStateWorldObject.normals = particleStateWorldObject.mesh.normals; Vector3[] vertices = particleStateWorldObject.mesh.vertices; BoneWeight[] weights = particleStateWorldObject.mesh.boneWeights; Matrix4x4[] bindPoses = particleStateWorldObject.mesh.bindposes; Matrix4x4[] boneMatrices = new Matrix4x4[particleStateWorldObject.renderer.bones.Length]; int i = 0; for (; i<boneMatrices.Length; i++) { boneMatrices[i] = particleStateWorldObject.renderer.bones[i].localToWorldMatrix * bindPoses[i]; } PlaygroundC.RunAsync(()=>{ Matrix4x4 vertexMatrix = new Matrix4x4(); for (i = 0; i<vertices.Length; i++) { BoneWeight weight = weights[i]; Matrix4x4 m0 = boneMatrices[weight.boneIndex0]; Matrix4x4 m1 = boneMatrices[weight.boneIndex1]; Matrix4x4 m2 = boneMatrices[weight.boneIndex2]; Matrix4x4 m3 = boneMatrices[weight.boneIndex3]; for (int n=0;n<16;n++) { vertexMatrix[n] = m0[n] * weight.weight0 + m1[n] * weight.weight1 + m2[n] * weight.weight2 + m3[n] * weight.weight3; } vertices[i] = vertexMatrix.MultiplyPoint3x4(vertices[i]); } particleStateWorldObject.vertexPositions = vertices; }); }
// Lerp to a Skinned World Object public static void Lerp (PlaygroundParticlesC playgroundParticles, SkinnedWorldObject particleStateWorldObject, float time) { if(time<0) time = 0f; Vector3[] vertices = particleStateWorldObject.mesh.vertices; BoneWeight[] weights = particleStateWorldObject.mesh.boneWeights; Matrix4x4[] boneMatrices = new Matrix4x4[particleStateWorldObject.renderer.bones.Length]; int i; for (i = 0; i<boneMatrices.Length; i++) boneMatrices[i] = particleStateWorldObject.renderer.bones[i].localToWorldMatrix * particleStateWorldObject.mesh.bindposes[i]; Matrix4x4 vertexMatrix = new Matrix4x4(); for (i = 0; i<playgroundParticles.particleCache.Length; i++) { BoneWeight weight = weights[i]; Matrix4x4 m0 = boneMatrices[weight.boneIndex0]; Matrix4x4 m1 = boneMatrices[weight.boneIndex1]; Matrix4x4 m2 = boneMatrices[weight.boneIndex2]; Matrix4x4 m3 = boneMatrices[weight.boneIndex3]; for(int n=0;n<16;n++){ vertexMatrix[n] = m0[n] * weight.weight0 + m1[n] * weight.weight1 + m2[n] * weight.weight2 + m3[n] * weight.weight3; } playgroundParticles.particleCache[i].position = Vector3.Lerp(playgroundParticles.particleCache[i].position, vertexMatrix.MultiplyPoint3x4(vertices[i%vertices.Length]), time); } }
/// <summary> /// Prepares all values for calculation which is not thread-safe. /// </summary> /// <returns><c>true</c>, if threaded calculations was prepared, <c>false</c> otherwise.</returns> public bool PrepareThreadedCalculations() { // Component disabled? if (!enabled) return false; // Has the calculation been paused previously? if (cameFromNonCalculatedFrame && hasActiveParticles) { StartCoroutine(Boot()); cameFromNonCalculatedFrame = false; return false; } // Apply locked position if (applyLockPosition) { if (lockPositionIsLocal) particleSystemTransform.localPosition = lockPosition; else particleSystemTransform.position = lockPosition; } // Apply locked rotation if (applyLockRotation) { if (lockRotationIsLocal) particleSystemTransform.localRotation = Quaternion.Euler(lockRotation); else particleSystemTransform.rotation = Quaternion.Euler(lockRotation); } // Apply locked scale if (applyLockScale) particleSystemTransform.localScale = lockScale; // Set delta time t = (localDeltaTime*particleTimescale); // Update active particle check hasActiveParticles = !threadHadNoActiveParticles; if (!hasActiveParticles) { if (disableOnDone) queueEmissionHalt = true; } // Prepare Source positions if (PlaygroundC.reference.IsDoneThread() && isDoneThread) { stPos = Vector3.zero; stRot = Quaternion.identity; stSca = new Vector3(1f, 1f, 1f); stDir = new Vector3(); } localSpace = (shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local); overflow = (overflowOffset!=Vector3.zero); skinnedWorldObjectReady = false; renderModeStretch = particleSystemRenderer2.renderMode==ParticleSystemRenderMode.Stretch; particleSystemInverseRotation = particleSystemTransform.rotation; // Prepare turbulence if (!onlySourcePositioning && !onlyLifetimePositioning && turbulenceStrength>0 && turbulenceType!=TURBULENCETYPE.None) { if (turbulenceType==TURBULENCETYPE.Simplex && turbulenceSimplex==null) turbulenceSimplex = new SimplexNoise(); } if (emit) { switch (source) { case SOURCEC.Script: break; case SOURCEC.State: if (states.Count>0) { if (states[activeState].stateTransform!=null) { if (isDoneThread) { if (!states[activeState].initialized) states[activeState].Initialize(); stPos = states[activeState].stateTransform.position; stRot = states[activeState].stateTransform.rotation; stSca = states[activeState].stateTransform.localScale; } if (localSpace && (states[activeState].stateTransform.parent==particleSystemTransform || states[activeState].stateTransform==particleSystemTransform) && isDoneThread) { stPos = Vector3.zero; stRot = Quaternion.Euler (Vector3.zero); } } } else return false; break; case SOURCEC.Transform: if (isDoneThread) { stPos = sourceTransform.position; stRot = sourceTransform.rotation; stSca = sourceTransform.localScale; } if (localSpace && sourceTransform==particleSystemTransform && isDoneThread) { stPos = Vector3.zero; stRot = Quaternion.Euler (Vector3.zero); } break; case SOURCEC.WorldObject: // Handle vertex data in active World Object if (worldObject.gameObject!=null) { if (worldObject.gameObject.GetInstanceID()!=worldObject.cachedId || !worldObject.initialized) worldObject = NewWorldObject(worldObject.gameObject.transform); if (worldObject.mesh!=null) { if (isDoneThread) { stPos = worldObject.transform.transform.position; stRot = worldObject.transform.transform.rotation; stSca = worldObject.transform.transform.localScale; } if (localSpace && isDoneThread) { stPos = Vector3.zero; stRot = Quaternion.Euler (Vector3.zero); } worldObject.updateNormals = worldObjectUpdateNormals; if (worldObjectUpdateVertices) worldObject.Update(); } else return false; } else return false; break; case SOURCEC.SkinnedWorldObject: // Handle vertex data in active Skinned World Object if (skinnedWorldObject.gameObject!=null) { if (skinnedWorldObject.gameObject.GetInstanceID()!=skinnedWorldObject.cachedId) skinnedWorldObject = NewSkinnedWorldObject(skinnedWorldObject.gameObject.transform, skinnedWorldObject.downResolution); } skinnedWorldObjectReady = skinnedWorldObject.gameObject!=null && skinnedWorldObject.mesh!=null; if (PlaygroundC.reference.skinnedMeshThreadMethod==ThreadMethodComponent.OneForAll && PlaygroundC.reference.IsFirstUnsafeAutomaticFrames() && !PlaygroundC.reference.IsDoneThreadSkinnedMeshes()) return false; if (skinnedWorldObjectReady) { if (isDoneThread) { stPos = skinnedWorldObject.transform.position; stRot = skinnedWorldObject.transform.rotation; stSca = skinnedWorldObject.transform.localScale; stDir = skinnedWorldObject.transform.TransformDirection (overflowOffset); } skinnedWorldObject.updateNormals = worldObjectUpdateNormals; if (Time.frameCount%PlaygroundC.skinnedUpdateRate==0) { if (worldObjectUpdateVertices) skinnedWorldObject.MeshUpdate(); skinnedWorldObject.BoneUpdate(); } } else return false; break; case SOURCEC.Paint: if (paint.initialized) { if (isDoneThread) { stPos = particleSystemTransform.position; stRot = particleSystemTransform.rotation; stSca = particleSystemTransform.localScale; } if (paint.positionLength>0) { for (int p = 0; p<particleCache.Length; p++) { paint.Update(p); } } else return false; } else { paint.Initialize (); return false; } break; case SOURCEC.Projection: if (projection.projectionTexture!=null && projection.projectionTransform!=null) { if (!projection.initialized) projection.Initialize(); stPos = projection.projectionTransform.position; stRot = projection.projectionTransform.rotation; stSca = projection.projectionTransform.localScale; if (localSpace) shurikenParticleSystem.simulationSpace = ParticleSystemSimulationSpace.World; if (projection.liveUpdate || !projection.hasRefreshed) { projection.UpdateSource(); projection.Update(); stDir = projection.projectionTransform.TransformDirection (overflowOffset); projection.hasRefreshed = true; } } else return false; break; } } // Collision detection (runs on main-thread) if (collision) Collisions(thisInstance); // Sync positions to main-thread if (syncPositionsOnMainThread) { if (particleCache.Length!=playgroundCache.position.Length) return false; for (int p = 0; p<particleCount; p++) { particleCache[p].position = playgroundCache.position[p]; } } // Prepare Particle colors stateReadyForTextureColor = (source==SOURCEC.State && states[activeState].stateTexture!=null); hasEventManipulatorLocal = false; hasEventManipulatorGlobal = false; manipulatorEventCount = 0; // Prepare local manipulators for (int m = 0; m<manipulators.Count; m++) { manipulators[m].Update(); manipulators[m].transform.SetLocalPosition(particleSystemTransform); manipulators[m].SetLocalTargetsPosition(particleSystemTransform); manipulators[m].willAffect = true; if (manipulators[m].trackParticles) { hasEventManipulatorLocal = true; manipulatorEventCount++; } } // Prepare global manipulators from this local space for (int m = 0; m<PlaygroundC.reference.manipulators.Count; m++) { PlaygroundC.reference.manipulators[m].willAffect = ((PlaygroundC.reference.manipulators[m].affects.value & 1<<particleSystemGameObject.layer)!=0); PlaygroundC.reference.manipulators[m].transform.SetLocalPosition(particleSystemTransform); if (PlaygroundC.reference.manipulators[m].trackParticles) { hasEventManipulatorGlobal = true; manipulatorEventCount++; } } hasSeveralManipulatorEvents = (manipulatorEventCount>1); // Prepare events hasEvent = events.Count>0; hasTimerEvent = false; if (hasEvent) { for (int i = 0; i<events.Count; i++) { events[i].Initialize(); if (events[i].initializedTarget && events[i].broadcastType!=EVENTBROADCASTC.EventListeners) if (!events[i].target.eventControlledBy.Contains (thisInstance)) events[i].target.eventControlledBy.Add (thisInstance); if (events[i].eventType==EVENTTYPEC.Time && ((events[i].broadcastType!=EVENTBROADCASTC.EventListeners && events[i].initializedTarget) || events[i].broadcastType==EVENTBROADCASTC.EventListeners && events[i].initializedEvent)) { hasTimerEvent = events[i].UpdateTime(); } } } // All good! Next step is to send all particles to calculation. return true; }
// Linear interpolation to object in world space public static void Lerp (PlaygroundParticlesC playgroundParticles, SkinnedWorldObject particleStateWorldObject, float time) { PlaygroundParticlesC.Lerp(playgroundParticles,particleStateWorldObject,time); }
TARGETSORTINGC previousTargetSorting; // The previous sorting type // Update this ManipulatorPropertyC public void Update () { if (type==MANIPULATORPROPERTYTYPEC.Target) { for (int i = 0; i<targets.Count; i++) targets[i].Update(); } else if (type==MANIPULATORPROPERTYTYPEC.MeshTarget) { if (meshTarget.gameObject!=null) { if (meshTarget.cachedId!=meshTarget.gameObject.GetInstanceID()) meshTarget = PlaygroundParticlesC.NewWorldObject (meshTarget.gameObject.transform); if (meshTarget.mesh!=null) meshTargetMatrix.SetTRS(meshTarget.transform.position, meshTarget.transform.rotation, meshTarget.transform.localScale); if (meshTarget.initialized && (targetSortingList==null || targetSortingList.Length!=meshTarget.vertexPositions.Length || previousTargetSorting!=targetSorting)) TargetSorting(); } } else if (type==MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget) { if (skinnedMeshTarget.gameObject!=null) { if (skinnedMeshTarget.cachedId!=skinnedMeshTarget.gameObject.GetInstanceID() || !skinnedMeshTarget.initialized) { skinnedMeshTarget = PlaygroundParticlesC.NewSkinnedWorldObject (skinnedMeshTarget.gameObject.transform); } if (skinnedMeshTarget.initialized) { skinnedMeshTarget.BoneUpdate(); PlaygroundC.RunAsync(()=>{ skinnedMeshTarget.Update(); }); if (targetSortingList==null || targetSortingList.Length!=skinnedMeshTarget.vertexPositions.Length || previousTargetSorting!=targetSorting) TargetSorting(); } } } }