void UpdateMatrix(ParticleEmitterShape emitShape, Transform trans) { var localScale = trans.localScale; Profiler.BeginSample("Set matrices"); Matrix4x4 id = Matrix4x4.identity; switch (Manager.SimulationSpace) { case Space.World: var rot = trans.rotation; if (m_lastRot != rot || m_lastScale != localScale) { m_emitMatrix = Matrix4x4.TRS(Vector3.zero, rot, localScale); m_emitRotationMatrix = Matrix4x4.TRS(Vector3.zero, rot, Vector3.one); m_lastRot = rot; m_lastScale = localScale; } TCHelper.SetMatrix(ComputeShader, SID._EmitterMatrix, m_emitMatrix); TCHelper.SetMatrix(ComputeShader, SID._EmitterRotationMatrix, m_emitRotationMatrix); break; case Space.Local: TCHelper.SetMatrix(ComputeShader, SID._EmitterMatrix, Matrix4x4.TRS(Vector3.zero, Quaternion.identity, localScale)); TCHelper.SetMatrix(ComputeShader, SID._EmitterRotationMatrix, id); break; case Space.LocalWithScale: TCHelper.SetMatrix(ComputeShader, SID._EmitterMatrix, id); TCHelper.SetMatrix(ComputeShader, SID._EmitterRotationMatrix, id); break; case Space.Parent: if (trans.parent != null) { var rot2 = trans.localRotation; TCHelper.SetMatrix(ComputeShader, SID._EmitterMatrix, Matrix4x4.TRS(Vector3.zero, rot2, localScale)); TCHelper.SetMatrix(ComputeShader, SID._EmitterRotationMatrix, Matrix4x4.TRS(Vector3.zero, rot2, Vector3.one)); } break; } if (emitShape.startDirectionType == StartDirection.Vector) { TCHelper.SetMatrix(ComputeShader, SID._EmitterStartRotationMatrix, Matrix4x4.TRS(Vector3.zero, Quaternion.FromToRotation(Vector3.forward, emitShape.startDirectionVector), Vector3.one)); } Profiler.EndSample(); }
private static extern void Internal_setShape(IntPtr thisPtr, ParticleEmitterShape shape);
public static void DrawEmitterShape(ParticleEmitterShape pes, Transform transform, TCWireframeDrawer drawer) { var col = new Color(0.6f, 0.9f, 1.0f); Handles.color = col; switch (pes.shape) { case EmitShapes.Sphere: pes.radius.Max = RadiusHandle(transform, pes.radius.Max, true); if (!pes.radius.IsConstant) { Handles.color = new Color(0.6f, 0.9f, 1.0f, 0.4f); if (pes.radius.Min > 0.0f) { pes.radius.Min = RadiusHandle(transform, pes.radius.Min, true); } Handles.color = col; } break; case EmitShapes.Box: pes.cubeSize = CubeHandle(transform, pes.cubeSize); break; case EmitShapes.HemiSphere: pes.radius.Value = HemisphereHandle(transform, pes.radius.Max, true); if (!pes.radius.IsConstant) { if (pes.radius.Min > 0.0f) { pes.radius.Min = HemisphereHandle(transform, pes.radius.Min, true); } } break; case EmitShapes.Cone: float coneAngle = pes.coneAngle; float coneHeight = pes.coneHeight; float coneRadius = pes.coneRadius; ConeHandle(ref coneAngle, ref coneHeight, ref coneRadius, transform); pes.coneAngle = coneAngle; pes.coneHeight = coneHeight; pes.coneRadius = coneRadius; break; case EmitShapes.Ring: float ringRadius = pes.ringRadius; float ringOuter = pes.ringOuterRadius; TorusHandle(ref ringRadius, ref ringOuter, transform); pes.ringRadius = ringRadius; pes.ringOuterRadius = ringOuter; break; case EmitShapes.Line: pes.lineLength = LineHandle(pes.lineLength, transform); break; case EmitShapes.Mesh: if (pes.emitMesh == null) { break; } drawer.DrawWireMesh(transform); break; } }
private static void Draw(ParticleSystem component) { SceneObject so = component.SceneObject; // Draw collision planes, if enabled Gizmos.Color = Color.Yellow; ParticleEvolver[] evolvers = component.Evolvers; foreach (var entry in evolvers) { if (entry is ParticleCollisions collisions) { if (collisions.Options.mode == ParticleCollisionMode.Plane) { void DrawPlane(Vector3 position, Vector3 right, Vector3 up, Vector3 forward) { Vector3 topLeft = position - right + up; Vector3 topRight = position + right + up; Vector3 botLeft = position - right - up; Vector3 botRight = position + right - up; Gizmos.DrawLine(topLeft, topRight); Gizmos.DrawLine(topRight, botRight); Gizmos.DrawLine(botRight, botLeft); Gizmos.DrawLine(botLeft, topLeft); Gizmos.DrawLine(position, position + forward * 0.4f); } SceneObject[] planeObjects = collisions.PlaneObjects; foreach (var planeSO in planeObjects) { Vector3 position = planeSO.Position; Vector3 right = planeSO.Rotation.Rotate(Vector3.XAxis); Vector3 up = planeSO.Rotation.Rotate(Vector3.YAxis); Vector3 forward = planeSO.Forward; DrawPlane(position, right, up, forward); } Plane[] planes = collisions.Planes; foreach (var plane in planes) { Vector3 right, up; Vector3.OrthogonalComplement(plane.normal, out right, out up); DrawPlane(plane.normal * plane.d, right, up, plane.normal); } } } } // Draw emitter shapes Gizmos.Transform = Matrix4.TRS(so.Position, Quaternion.LookRotation(so.Rotation.Forward, so.Rotation.Up), Vector3.One); Gizmos.Color = Color.Green; ParticleEmitter[] emitters = component.Emitters; foreach (var entry in emitters) { ParticleEmitterShape shape = entry?.Shape; if (shape == null) { continue; } if (shape is ParticleEmitterBoxShape boxShape) { Gizmos.DrawWireCube(Vector3.Zero, boxShape.Options.extents); } else if (shape is ParticleEmitterSphereShape sphereShape) { ParticleSphereShapeOptions options = sphereShape.Options; Gizmos.DrawWireSphere(Vector3.Zero, options.radius); if (options.thickness > 0.0f) { float innerRadius = options.radius * (1.0f - MathEx.Clamp01(options.thickness)); if (options.thickness < 1.0f) { Gizmos.Color = Color.Green * new Color(0.5f, 0.5f, 0.5f); Gizmos.DrawWireSphere(Vector3.Zero, innerRadius); } Gizmos.Color = Color.Green * new Color(0.25f, 0.25f, 0.25f); Gizmos.DrawLine(Vector3.XAxis * innerRadius, Vector3.XAxis * options.radius); Gizmos.DrawLine(-Vector3.XAxis * innerRadius, -Vector3.XAxis * options.radius); Gizmos.DrawLine(Vector3.YAxis * innerRadius, Vector3.YAxis * options.radius); Gizmos.DrawLine(-Vector3.YAxis * innerRadius, -Vector3.YAxis * options.radius); Gizmos.DrawLine(Vector3.ZAxis * innerRadius, Vector3.ZAxis * options.radius); Gizmos.DrawLine(-Vector3.ZAxis * innerRadius, -Vector3.ZAxis * options.radius); } } else if (shape is ParticleEmitterHemisphereShape hemisphereShape) { ParticleHemisphereShapeOptions options = hemisphereShape.Options; Gizmos.DrawWireHemisphere(Vector3.Zero, options.radius); DrawArcWithThickness(Vector3.Zero, options.radius, new Degree(360.0f), options.thickness, Color.Green); if (options.thickness > 0.0f) { float innerRadius = options.radius * (1.0f - MathEx.Clamp01(options.thickness)); if (options.thickness < 1.0f) { Gizmos.Color = Color.Green * new Color(0.5f, 0.5f, 0.5f); Gizmos.DrawWireHemisphere(Vector3.Zero, innerRadius); } Gizmos.Color = Color.Green * new Color(0.25f, 0.25f, 0.25f); Gizmos.DrawLine(Vector3.XAxis * innerRadius, Vector3.XAxis * options.radius); Gizmos.DrawLine(-Vector3.XAxis * innerRadius, -Vector3.XAxis * options.radius); Gizmos.DrawLine(Vector3.YAxis * innerRadius, Vector3.YAxis * options.radius); Gizmos.DrawLine(-Vector3.YAxis * innerRadius, -Vector3.YAxis * options.radius); Gizmos.DrawLine(Vector3.ZAxis * innerRadius, Vector3.ZAxis * options.radius); } } else if (shape is ParticleEmitterCircleShape circleShape) { ParticleCircleShapeOptions options = circleShape.Options; DrawArcWithThickness(Vector3.Zero, options.radius, options.arc, options.thickness, Color.Green); } else if (shape is ParticleEmitterLineShape lineShape) { float halfLength = lineShape.Options.length * 0.5f; Gizmos.DrawLine(new Vector3(-halfLength, 0.0f, 0.0f), new Vector3(halfLength, 0.0f, 0.0f)); } else if (shape is ParticleEmitterRectShape rectShape) { Vector2 extents = rectShape.Options.extents; Vector3 right = new Vector3(extents.x, 0.0f, 0.0f); Vector3 up = new Vector3(0.0f, extents.y, 0.0f); Vector3 topLeft = -right + up; Vector3 topRight = right + up; Vector3 botLeft = -right - up; Vector3 botRight = right - up; Gizmos.DrawLine(topLeft, topRight); Gizmos.DrawLine(topRight, botRight); Gizmos.DrawLine(botRight, botLeft); Gizmos.DrawLine(botLeft, topLeft); } else if (shape is ParticleEmitterConeShape coneShape) { ParticleConeShapeOptions options = coneShape.Options; float topRadius = options.radius; float baseRadius = options.length * MathEx.Tan(options.angle); Radian arc = options.arc; if (topRadius > 0.0f) { DrawArcWithThickness(Vector3.Zero, topRadius, arc, options.thickness, Color.Green); } DrawArcWithThickness(new Vector3(0.0f, 0.0f, -options.length), baseRadius, arc, options.thickness, Color.Green); Gizmos.Color = Color.Green; DrawConeBorder(topRadius, baseRadius, arc, options.length); if (options.thickness > 0.0f && options.thickness < 1.0f) { Gizmos.Color = Color.Green * new Color(0.5f, 0.5f, 0.5f); DrawConeBorder( topRadius * (1.0f - MathEx.Clamp01(options.thickness)), baseRadius * (1.0f - MathEx.Clamp01(options.thickness)), arc, options.length); } } else if (shape is ParticleEmitterStaticMeshShape staticMeshShape) { RRef <Mesh> mesh = staticMeshShape.Options.mesh; if (mesh.IsLoaded) { Gizmos.DrawWireMesh(mesh.Value.MeshData); } } else if (shape is ParticleEmitterSkinnedMeshShape skinnedMeshShape) { Renderable renderable = skinnedMeshShape.Options.renderable; if (renderable != null) { RRef <Mesh> mesh = renderable.Mesh; if (mesh.IsLoaded) { Gizmos.DrawWireMesh(mesh.Value.MeshData); } } } } // Draw manual bounds if (!component.Settings.UseAutomaticBounds) { Gizmos.Color = Color.LightGray; AABox bounds = component.Settings.CustomBounds; Gizmos.DrawWireCube(bounds.Center, bounds.Size * 0.5f); } }
public static void DrawEmitterShape(ParticleEmitterShape pes, Transform transform) { var col = new Color(0.6f, 0.9f, 1.0f); Handles.color = col; switch (pes.shape) { case EmitShapes.Sphere: pes.radius.Max = RadiusHandle(transform, pes.radius.Max, true); if (!pes.radius.IsConstant) { Handles.color = new Color(0.6f, 0.9f, 1.0f, 0.4f); if (pes.radius.Min > 0.0f) { pes.radius.Min = RadiusHandle(transform, pes.radius.Min, true); } Handles.color = col; } break; case EmitShapes.Box: pes.cubeSize = CubeHandle(transform, pes.cubeSize); break; case EmitShapes.HemiSphere: pes.radius.Value = HemisphereHandle(transform, pes.radius.Max, true); if (!pes.radius.IsConstant) { if (pes.radius.Min > 0.0f) { pes.radius.Min = HemisphereHandle(transform, pes.radius.Min, true); } } break; case EmitShapes.Cone: float coneAngle = pes.coneAngle; float coneHeight = pes.coneHeight; float coneRadius = pes.coneRadius; ConeHandle(ref coneAngle, ref coneHeight, ref coneRadius, transform); pes.coneAngle = coneAngle; pes.coneHeight = coneHeight; pes.coneRadius = coneRadius; break; case EmitShapes.Ring: float ringRadius = pes.ringRadius; float ringOuter = pes.ringOuterRadius; TorusHandle(ref ringRadius, ref ringOuter, transform); pes.ringRadius = ringRadius; pes.ringOuterRadius = ringOuter; break; case EmitShapes.Line: pes.lineLength = LineHandle(pes.lineLength, transform); break; case EmitShapes.Mesh: if (pes.emitMesh == null) { break; } if (s_lineMat == null) { s_lineMat = new Material(Shader.Find("Hidden/TCWireframeShader")); s_lineMat.hideFlags = HideFlags.HideAndDontSave; } GL.wireframe = true; for (int i = 0; i < s_lineMat.passCount; ++i) { s_lineMat.SetPass(i); Graphics.DrawMeshNow(pes.emitMesh, Matrix4x4.TRS(transform.position, transform.rotation, transform.localScale)); } GL.wireframe = false; break; } }
void SetShapeData(ParticleEmitterShape emitShape, Transform trans, ref Vector3 prevPos, ref Vector3 prevSpeed) { var emitter = m_emitSet[0]; emitter.Shape = (uint)emitShape.shape; switch (emitShape.shape) { case EmitShapes.Box: emitter.CubeSize = emitShape.cubeSize * 0.5f; break; case EmitShapes.Cone: emitter.RadiusMin = emitShape.coneRadius; float tan = Mathf.Tan(emitShape.coneAngle * Mathf.Deg2Rad); emitter.RadiusMax = emitShape.coneRadius + tan * emitShape.coneHeight; emitter.ConePointUnder = new Vector3(0.0f, 0.0f, -Mathf.Tan((90.0f - emitShape.coneAngle) * Mathf.Deg2Rad) * emitShape.coneRadius); emitter.ConeHeight = emitShape.coneHeight; break; case EmitShapes.HemiSphere: emitter.RadiusMin = emitShape.radius.IsConstant ? 0.0f : Mathf.Max(Mathf.Min(emitShape.radius.Min, emitShape.radius.Max), 0); emitter.RadiusMax = emitShape.radius.Max; break; case EmitShapes.Line: emitter.LineLength = emitShape.lineLength; emitter.RadiusMin = 0.0f; emitter.RadiusMax = emitShape.lineRadius; break; case EmitShapes.Mesh: emitShape.SetMeshData(ComputeShader, EmitKernel, ref emitter); break; case EmitShapes.Ring: emitter.RadiusMin = emitShape.ringRadius; emitter.RadiusMax = emitShape.ringOuterRadius; break; case EmitShapes.Sphere: emitter.RadiusMin = emitShape.radius.IsConstant ? 0.0f : Mathf.Max(Mathf.Min(emitShape.radius.Min, emitShape.radius.Max), 0.0f); emitter.RadiusMax = emitShape.radius.Max; break; } if (m_toEmitList != null) { ComputeShader.SetFloat(SID._UseEmitList, 1.0f); pes.SetListData(ComputeShader, EmitKernel, m_toEmitList); ComputeShader.SetVector(SID._UseVelSizeColorPos, m_emitUseVelSizeColorPos); m_toEmitList = null; } else { ComputeShader.SetFloat(SID._UseEmitList, 0.0f); } emitter.VelType = (uint)emitShape.startDirectionType; emitter.RandomAngle = Mathf.Cos(emitShape.startDirectionRandomAngle * Mathf.Deg2Rad); var localScale = trans.localScale; emitter.Scale = localScale; UpdateMatrix(emitShape, trans); emitter.Pos = prevPos; var pos = GetEmitPos(SystemComp, trans); Vector3 speed = pos - prevPos; emitter.Vel = speed; prevPos = pos; emitter.Accel = (speed - prevSpeed); prevSpeed = speed; m_emitSet[0] = emitter; m_emitBuffer.SetData(m_emitSet); }