public int randomSeed = 0; // A property specific random seed; // CONVERT COORDINATE SYSTEM // // // TODO: Move it to AmpsHelpers. public Vector4 ConvertCoordinateSystem(Vector4 v, int particleIndex) { Vector3 returnValue = v; switch (coordSystem) { case AmpsHelpers.eCoordSystems.World: //switch (coordSystemConversionMode) //{ // case eCoordSystemConversionMode.AsPosition: // break; // case eCoordSystemConversionMode.AsRotation: // break; // case eCoordSystemConversionMode.AsVelocity: // break; // case eCoordSystemConversionMode.AsScale: // break; //} break; case AmpsHelpers.eCoordSystems.Emitter: switch (coordSystemConversionMode) { case eCoordSystemConversionMode.AsPosition: returnValue += ownerBlueprint.ownerEmitter.transform.position; returnValue = AmpsHelpers.RotateAroundPoint(returnValue, ownerBlueprint.ownerEmitter.emitterPosition, ownerBlueprint.ownerEmitter.transform.rotation); break; case eCoordSystemConversionMode.AsRotation: returnValue += ownerBlueprint.ownerEmitter.transform.rotation.eulerAngles; break; case eCoordSystemConversionMode.AsVelocity: returnValue = ownerBlueprint.ownerEmitter.emitterMatrixPositionZero.MultiplyPoint3x4(returnValue); break; case eCoordSystemConversionMode.AsScale: returnValue.x *= ownerBlueprint.ownerEmitter.transform.lossyScale.x; returnValue.y *= ownerBlueprint.ownerEmitter.transform.lossyScale.y; returnValue.z *= ownerBlueprint.ownerEmitter.transform.lossyScale.z; break; } break; } return(AmpsHelpers.ConvertVector3Vector4(returnValue, 0)); }
public int randomSeed = 0; // A curve specific random seed; // GET CURVE INPUT // // public float GetCurveInput(AmpsBlueprint ownerBlueprint, int particleIndex) { float returnValue = 0; Vector3 v3 = Vector3.zero; Vector4 v4 = Vector4.zero; //Matrix4x4 toMatrix = AmpsHelpers.identityMatrix; // Slightly faster than Matrix4x4.identity; v4 = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, curveInput); // The only need to work with conversion to emitter space as everything // is world relative by default. if (curveInputCoordSystem == AmpsHelpers.eCoordSystems.Emitter) { //toMatrix = ownerBlueprint.ownerEmitter.emitterMatrixFull; if (AmpsHelpers.isPositionInput(curveInput)) { v3 = AmpsHelpers.ConvertVector4Vector3(v4); v3 -= ownerBlueprint.ownerEmitter.transform.position; v3 = AmpsHelpers.RotateAroundPoint(v3, ownerBlueprint.ownerEmitter.emitterPosition, ownerBlueprint.ownerEmitter.transform.rotation); v4 = AmpsHelpers.ConvertVector3Vector4(v3, 0); } else if (AmpsHelpers.isRotationInput(curveInput)) { v3 = AmpsHelpers.ConvertVector4Vector3(v4); v3 += ownerBlueprint.ownerEmitter.transform.rotation.eulerAngles; v4 = AmpsHelpers.ConvertVector3Vector4(v3, 0); } else if (AmpsHelpers.isVelocityInput(curveInput)) { v3 = AmpsHelpers.ConvertVector4Vector3(v4); v3 += ownerBlueprint.ownerEmitter.emitterMatrixPositionZero.MultiplyPoint3x4(v3); v4 = AmpsHelpers.ConvertVector3Vector4(v3, 0); } else if (AmpsHelpers.isScaleInput(curveInput)) { v3 = AmpsHelpers.ConvertVector4Vector3(v4); v3.x *= ownerBlueprint.ownerEmitter.transform.lossyScale.x; v3.y *= ownerBlueprint.ownerEmitter.transform.lossyScale.y; v3.z *= ownerBlueprint.ownerEmitter.transform.lossyScale.z; v4 = AmpsHelpers.ConvertVector3Vector4(v3, 0); } } if (AmpsHelpers.isFloatInput(curveInput)) { returnValue = v4.x; } else { //if (AmpsHelpers.isPositionInput(curveInput)) v = toMatrix.MultiplyPoint3x4(v); //else v = toMatrix.MultiplyVector(v); switch (curveInputVectorComponent) { case AmpsHelpers.eVectorComponents.X: returnValue = v4.x; break; case AmpsHelpers.eVectorComponents.Y: returnValue = v4.y; break; case AmpsHelpers.eVectorComponents.Z: returnValue = v4.z; break; case AmpsHelpers.eVectorComponents.W: returnValue = v4.w; break; case AmpsHelpers.eVectorComponents.Mag: returnValue = new Vector3(v4.x, v4.y, v4.z).magnitude; break; } // TODO: Handle Color. } // Normalize input. float finalInputRangeMin = inputRangeMin; float finalInputRangeMax = inputRangeMax; if (isInputRangeRandom) { System.Random theRandom = new System.Random(ownerBlueprint.ownerEmitter.randomSeed + randomSeed + ownerBlueprint.ownerEmitter.particleIds[particleIndex]); finalInputRangeMin = Mathf.Lerp(inputRangeMin, inputRangeRandomMin, (float)theRandom.NextDouble()); finalInputRangeMax = Mathf.Lerp(inputRangeMax, inputRangeRandomMax, (float)theRandom.NextDouble()); } if (finalInputRangeMax - finalInputRangeMin == 0) { returnValue = 0; } else { returnValue = (returnValue - finalInputRangeMin) / (finalInputRangeMax - finalInputRangeMin); } return(returnValue); }
// MANAGE SAMPLING // // // Does the actual sampling. override public void ManageSampling(int particleIndex) { Vector3 v = Vector3.zero; bool shouldIndeedSample = (particleIndex < 0 && ShouldSample()) || (particleIndex >= 0 && ShouldSample(particleIndex)); // Leave if it's not time yet to sample. if (shouldIndeedSample == false) { return; } // INVALID SAMPLE: Referenced GameObject is not available. if (theMesh == null) { isValidSample[particleIndex] = false; return; } // TODO: Regenerate element index if order is random or sequential. Vector3[] triangleVertexPositions = new Vector3[3]; Vector3[] triangleVertexNormals = new Vector3[3]; Vector3[] triangleVertexTangents = new Vector3[3]; eMeshElements selectedMeshElement = (eMeshElements)sampledMeshElement.GetValue(); switch (selectedMeshElement) { case eMeshElements.VertexPosition: v = theMesh.vertices[elementIndices[particleIndex]]; break; case eMeshElements.VertexNormal: if (theMesh.normals.Length > 0) { v = theMesh.normals[elementIndices[particleIndex]]; } else { v = Vector3.zero; } break; case eMeshElements.TrianglePosition: triangleVertexPositions[0] = theMesh.vertices[theMesh.triangles[elementIndices[particleIndex] * 3]]; triangleVertexPositions[1] = theMesh.vertices[theMesh.triangles[elementIndices[particleIndex] * 3] + 1]; triangleVertexPositions[2] = theMesh.vertices[theMesh.triangles[elementIndices[particleIndex] * 3] + 2]; v = (triangleVertexPositions[0] + triangleVertexPositions[1] + triangleVertexPositions[2]) / 3; break; case eMeshElements.TriangleNormal: triangleVertexNormals[0] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3]]; triangleVertexNormals[1] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3] + 1]; triangleVertexNormals[2] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3] + 2]; v = (triangleVertexNormals[0] + triangleVertexNormals[1] + triangleVertexNormals[2]) / 3; break; case eMeshElements.TriangleRotation: triangleVertexNormals[0] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3]]; triangleVertexNormals[1] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3] + 1]; triangleVertexNormals[2] = theMesh.normals[theMesh.triangles[elementIndices[particleIndex] * 3] + 2]; Vector3 triangleNormal = (triangleVertexNormals[0] + triangleVertexNormals[1] + triangleVertexNormals[2]) / 3; triangleNormal *= -1; triangleVertexTangents[0] = theMesh.tangents[theMesh.triangles[elementIndices[particleIndex] * 3]]; triangleVertexTangents[1] = theMesh.tangents[theMesh.triangles[elementIndices[particleIndex] * 3] + 1]; triangleVertexTangents[2] = theMesh.tangents[theMesh.triangles[elementIndices[particleIndex] * 3] + 2]; Vector3 triangleTangent = (triangleVertexTangents[0] + triangleVertexTangents[1] + triangleVertexTangents[2]) / 3; Quaternion theQuaternion = Quaternion.LookRotation(triangleNormal, triangleTangent); v = theQuaternion.eulerAngles; break; } // Optional conversion to emitter space. if (isEmitterRelative.GetValue()) { if (selectedMeshElement == eMeshElements.TrianglePosition || selectedMeshElement == eMeshElements.VertexPosition) { v += ownerBlueprint.ownerEmitter.transform.position; v = AmpsHelpers.RotateAroundPoint(v, ownerBlueprint.ownerEmitter.emitterPosition, ownerBlueprint.ownerEmitter.transform.rotation); } else if (selectedMeshElement == eMeshElements.TriangleRotation) { v += ownerBlueprint.ownerEmitter.transform.rotation.eulerAngles; } } vectors[particleIndex] = new Vector4(v.x, v.y, v.z, 0); isValidSample[particleIndex] = true; }
// EVALUATE // // override public void Evaluate() { Vector4 customVector; Vector3 position; Vector3 pivotOffset; Vector3 rotation; Quaternion quaternionRotation; Vector3 scale; Color color; bool shouldRecreateMesh; bool shouldBeDoubleSided; Quaternion camFacingRotation; int vertexIndexSteps; int triangleIndexSteps; if (ownerBlueprint == null || ownerBlueprint.ownerEmitter == null || ownerBlueprint.ownerEmitter.particleMarkers == null) { return; // To fix null ref log spam after script rebuild. } if (finalMesh == null) { SoftReset(); } ownerBlueprint.ownerEmitter.activeParticleIndices = ownerBlueprint.ownerEmitter.particleMarkers.GetActiveIndices(); particleCount = ownerBlueprint.ownerEmitter.activeParticleIndices.Length; shouldRecreateMesh = (particleCount != lastParticleCount); shouldBeDoubleSided = isDoubleSided.GetValue(); if (shouldBeDoubleSided) { vertexIndexSteps = 8; triangleIndexSteps = 12; } else { vertexIndexSteps = 4; triangleIndexSteps = 6; } // TODO: Investigate why this line fails at runtime around 2 * 4: //shouldRecreateMesh = triangles.Length != particleCount * vertexIndexSteps; if (shouldRecreateMesh) { finalMesh.Clear(); vertices = new Vector3[particleCount * vertexIndexSteps]; normals = new Vector3[particleCount * vertexIndexSteps]; tangents = new Vector4[particleCount * vertexIndexSteps]; uvs = new Vector2[particleCount * vertexIndexSteps]; uv2s = new Vector2[particleCount * vertexIndexSteps]; colors = new Color[particleCount * vertexIndexSteps]; triangles = new int[particleCount * triangleIndexSteps]; lastParticleCount = particleCount; } int particleIndex; for (int i = 0; i < ownerBlueprint.ownerEmitter.activeParticleIndices.Length; i++) { particleIndex = ownerBlueprint.ownerEmitter.activeParticleIndices[i]; customVector = ownerBlueprint.customVectorStack.values[particleIndex]; position = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.ownerEmitter.blueprint.positionStack.values[particleIndex]); // Raw position stack result. position = AmpsHelpers.RotateAroundPoint(position, ownerBlueprint.ownerEmitter.transform.position, Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation)); position -= ownerBlueprint.ownerEmitter.emitterPosition; // Compensating for emitter position, turning position world relative. pivotOffset = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.pivotOffsetStack.values[particleIndex]); rotation = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.rotationStack.values[particleIndex]); // Raw particle stack result. quaternionRotation = Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation) * Quaternion.Euler(rotation); scale = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.scaleStack.values[particleIndex]); color = ownerBlueprint.colorStack.values[particleIndex]; // Setting up the quad, particle is at the center. vertices[i * vertexIndexSteps] = (position + pivotOffset) + (new Vector3(scale.x, scale.y, 0) / 2); vertices[i * vertexIndexSteps + 1] = (position + pivotOffset) + (new Vector3(-scale.x, scale.y, 0) / 2); vertices[i * vertexIndexSteps + 2] = (position + pivotOffset) + (new Vector3(-scale.x, -scale.y, 0) / 2); vertices[i * vertexIndexSteps + 3] = (position + pivotOffset) + (new Vector3(scale.x, -scale.y, 0) / 2); switch (orientation.GetValue()) { case (int)eOrientation.Rotated: // Rotating the (pivot offset) vertices around particle position. vertices[i * vertexIndexSteps] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps], position, quaternionRotation); vertices[i * vertexIndexSteps + 1] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 1], position, quaternionRotation); vertices[i * vertexIndexSteps + 2] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 2], position, quaternionRotation); vertices[i * vertexIndexSteps + 3] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 3], position, quaternionRotation); break; case (int)eOrientation.CameraFacing: camFacingRotation = Quaternion.LookRotation(ownerBlueprint.ownerEmitter.currentCameraTransform.forward, ownerBlueprint.ownerEmitter.currentCameraTransform.up); camFacingRotation = Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation) * camFacingRotation; // TODO: Research if camera-particle position diff vector is better. // Rotating all vertices around the center so the quad faces the camera. vertices[i * vertexIndexSteps] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps], position, camFacingRotation); vertices[i * vertexIndexSteps + 1] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 1], position, camFacingRotation); vertices[i * vertexIndexSteps + 2] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 2], position, camFacingRotation); vertices[i * vertexIndexSteps + 3] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 3], position, camFacingRotation); break; case (int)eOrientation.RotatedCameraFacing: camFacingRotation = Quaternion.LookRotation(ownerBlueprint.ownerEmitter.currentCameraTransform.forward, ownerBlueprint.ownerEmitter.currentCameraTransform.up); camFacingRotation = Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation) * camFacingRotation; camFacingRotation = camFacingRotation * Quaternion.Euler(rotation); // Rotating all vertices around the center so the quad faces the camera. vertices[i * vertexIndexSteps] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps], position, camFacingRotation); vertices[i * vertexIndexSteps + 1] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 1], position, camFacingRotation); vertices[i * vertexIndexSteps + 2] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 2], position, camFacingRotation); vertices[i * vertexIndexSteps + 3] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 3], position, camFacingRotation); break; case (int)eOrientation.VectorAlignedCameraFacing: //Vector3 upVector = Vector3.Normalize(alignmentVector.GetValue()); //Vector3 forwardVector = ownerBlueprint.ownerEmitter.currentCameraTransform.forward; ////ownerBlueprint.ownerEmitter.currentCameraTransform.up; //camFacingRotation = Quaternion.LookRotation(forwardVector, upVector); ////camFacingRotation = Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation) * camFacingRotation; camFacingRotation = Quaternion.LookRotation(ownerBlueprint.ownerEmitter.currentCameraTransform.forward, Vector3.up); Vector3 eulerRotation = camFacingRotation.eulerAngles; eulerRotation.x = 0; // Discard rotation around x. eulerRotation.z = 0; // Discard rotation around z. camFacingRotation = Quaternion.Euler(eulerRotation); // Rotating all vertices around the center so the quad faces the camera. vertices[i * vertexIndexSteps] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps], position, camFacingRotation); vertices[i * vertexIndexSteps + 1] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 1], position, camFacingRotation); vertices[i * vertexIndexSteps + 2] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 2], position, camFacingRotation); vertices[i * vertexIndexSteps + 3] = AmpsHelpers.RotateAroundPoint(vertices[i * vertexIndexSteps + 3], position, camFacingRotation); break; } if (shouldBeDoubleSided) { vertices[i * vertexIndexSteps + 4] = vertices[i * vertexIndexSteps]; vertices[i * vertexIndexSteps + 5] = vertices[i * vertexIndexSteps + 1]; vertices[i * vertexIndexSteps + 6] = vertices[i * vertexIndexSteps + 2]; vertices[i * vertexIndexSteps + 7] = vertices[i * vertexIndexSteps + 3]; } colors[i * vertexIndexSteps] = color; colors[i * vertexIndexSteps + 1] = color; colors[i * vertexIndexSteps + 2] = color; colors[i * vertexIndexSteps + 3] = color; if (shouldBeDoubleSided) { if ((eDoubleSidedColorMode)doubleSidedColorMode.GetValue() == eDoubleSidedColorMode.ColorStack) { colors[i * vertexIndexSteps + 4] = colors[i * vertexIndexSteps]; colors[i * vertexIndexSteps + 5] = colors[i * vertexIndexSteps + 1]; colors[i * vertexIndexSteps + 6] = colors[i * vertexIndexSteps + 2]; colors[i * vertexIndexSteps + 7] = colors[i * vertexIndexSteps + 3]; } else { colors[i * vertexIndexSteps + 4] = customVector; colors[i * vertexIndexSteps + 5] = customVector; colors[i * vertexIndexSteps + 6] = customVector; colors[i * vertexIndexSteps + 7] = customVector; } } switch (normalMode.GetValue()) { case (int)eNormalMode.Skip: break; case (int)eNormalMode.Flat: Vector3 calculatedNormal = Vector3.Cross((vertices[i * vertexIndexSteps + 2] - vertices[i * vertexIndexSteps]), (vertices[i * vertexIndexSteps + 1] - vertices[i * vertexIndexSteps])); calculatedNormal = Vector3.Normalize(calculatedNormal); normals[i * vertexIndexSteps] = calculatedNormal; normals[i * vertexIndexSteps + 1] = calculatedNormal; normals[i * vertexIndexSteps + 2] = calculatedNormal; normals[i * vertexIndexSteps + 3] = calculatedNormal; break; } if (shouldBeDoubleSided) { normals[i * vertexIndexSteps + 4] = normals[i * vertexIndexSteps] * -1; normals[i * vertexIndexSteps + 5] = normals[i * vertexIndexSteps + 1] * -1; normals[i * vertexIndexSteps + 6] = normals[i * vertexIndexSteps + 2] * -1; normals[i * vertexIndexSteps + 7] = normals[i * vertexIndexSteps + 3] * -1; } switch (uv2Mode.GetValue()) { case (int)eUV2Mode.Skip: break; case (int)eUV2Mode.CustomVectorXY: uv2s[i * vertexIndexSteps] = new Vector2(customVector.x, customVector.y); uv2s[i * vertexIndexSteps + 1] = new Vector2(customVector.x, customVector.y); uv2s[i * vertexIndexSteps + 2] = new Vector2(customVector.x, customVector.y); uv2s[i * vertexIndexSteps + 3] = new Vector2(customVector.x, customVector.y); break; case (int)eUV2Mode.CustomVectorXYZW: // BUG: Doesn't really work... Vector2 calculatedUv2 = Vector2.zero; calculatedUv2.x = AmpsHelpers.PackVector2(new Vector2(customVector.x, customVector.y)); calculatedUv2.y = AmpsHelpers.PackVector2(new Vector2(customVector.z, customVector.w)); uv2s[i * vertexIndexSteps] = calculatedUv2; uv2s[i * vertexIndexSteps + 1] = calculatedUv2; uv2s[i * vertexIndexSteps + 2] = calculatedUv2; uv2s[i * vertexIndexSteps + 3] = calculatedUv2; break; } if (shouldBeDoubleSided) { uv2s[i * vertexIndexSteps + 4] = uv2s[i * vertexIndexSteps]; uv2s[i * vertexIndexSteps + 5] = uv2s[i * vertexIndexSteps + 1]; uv2s[i * vertexIndexSteps + 6] = uv2s[i * vertexIndexSteps + 2]; uv2s[i * vertexIndexSteps + 7] = uv2s[i * vertexIndexSteps + 3]; } switch (tangentMode.GetValue()) { case (int)eTangentMode.Skip: break; case (int)eTangentMode.Generate: //Vector3 rawTangent = Vector3.Normalize(vertices[i * 4 + 3] - vertices[i * 4 + 1]); Vector3 rawTangent = Vector3.Normalize(vertices[i * 4 + 0] - vertices[i * 4 + 1]); Vector4 calculatedTangent = new Vector4(rawTangent.x, rawTangent.y, rawTangent.z, -1); tangents[i * vertexIndexSteps] = calculatedTangent; tangents[i * vertexIndexSteps + 1] = calculatedTangent; tangents[i * vertexIndexSteps + 2] = calculatedTangent; tangents[i * vertexIndexSteps + 3] = calculatedTangent; break; case (int)eTangentMode.CustomVectorXYZW: tangents[i * vertexIndexSteps] = customVector; tangents[i * vertexIndexSteps + 1] = customVector; tangents[i * vertexIndexSteps + 2] = customVector; tangents[i * vertexIndexSteps + 3] = customVector; break; } if (shouldBeDoubleSided) { // TODO: Should it be multiplied by -1? tangents[i * vertexIndexSteps + 4] = tangents[i * vertexIndexSteps]; tangents[i * vertexIndexSteps + 5] = tangents[i * vertexIndexSteps + 1]; tangents[i * vertexIndexSteps + 6] = tangents[i * vertexIndexSteps + 2]; tangents[i * vertexIndexSteps + 7] = tangents[i * vertexIndexSteps + 3]; } if (shouldRecreateMesh) // Things go in here which don't change unless particle count changes. { uvs[i * vertexIndexSteps] = new Vector2(1, 1); uvs[i * vertexIndexSteps + 1] = new Vector2(0, 1); uvs[i * vertexIndexSteps + 2] = new Vector2(0, 0); uvs[i * vertexIndexSteps + 3] = new Vector2(1, 0); if (shouldBeDoubleSided) { uvs[i * vertexIndexSteps + 4] = new Vector2(1, 1); uvs[i * vertexIndexSteps + 5] = new Vector2(0, 1); uvs[i * vertexIndexSteps + 6] = new Vector2(0, 0); uvs[i * vertexIndexSteps + 7] = new Vector2(1, 0); } //First triangle. triangles[i * triangleIndexSteps] = i * vertexIndexSteps; triangles[i * triangleIndexSteps + 1] = i * vertexIndexSteps + 2; triangles[i * triangleIndexSteps + 2] = i * vertexIndexSteps + 1; //Second triangle. triangles[i * triangleIndexSteps + 3] = i * vertexIndexSteps + 2; triangles[i * triangleIndexSteps + 4] = i * vertexIndexSteps; triangles[i * triangleIndexSteps + 5] = i * vertexIndexSteps + 3; if (shouldBeDoubleSided) { //Third triangle. triangles[i * triangleIndexSteps + 6] = i * vertexIndexSteps + 5; triangles[i * triangleIndexSteps + 7] = i * vertexIndexSteps + 6; triangles[i * triangleIndexSteps + 8] = i * vertexIndexSteps + 4; //Forth triangle. triangles[i * triangleIndexSteps + 9] = i * vertexIndexSteps + 7; triangles[i * triangleIndexSteps + 10] = i * vertexIndexSteps + 4; triangles[i * triangleIndexSteps + 11] = i * vertexIndexSteps + 6; } } } // TODO: Bubble sort with limited run time. finalMesh.vertices = vertices; finalMesh.uv = uvs; finalMesh.uv2 = uv2s; finalMesh.normals = normals; finalMesh.tangents = tangents; finalMesh.colors = colors; finalMesh.triangles = triangles; }
// EVALUATE // // override public void Evaluate() { bool shouldRecreateMesh; Vector3 position; Vector3 pivotOffset; Vector3 rotation; Quaternion quaternionRotation; Vector3 scale; Color color; System.Random theRandom = new System.Random(); InitializeNewParticles(); if (ownerBlueprint.ownerEmitter.particleMarkers == null) { return; // To fix null ref log spam after script rebuild. } ownerBlueprint.ownerEmitter.activeParticleIndices = ownerBlueprint.ownerEmitter.particleMarkers.GetActiveIndices(); particleCount = ownerBlueprint.ownerEmitter.activeParticleIndices.Length; shouldRecreateMesh = particleCount != lastParticleCount; if (shouldRecreateMesh) { ownerBlueprint.ownerEmitter.emitterMesh.Clear(); lastParticleCount = particleCount; } CombineInstance[] combine = new CombineInstance[particleCount]; int particleIndex; for (int i = 0; i < ownerBlueprint.ownerEmitter.activeParticleIndices.Length; i++) { particleIndex = ownerBlueprint.ownerEmitter.activeParticleIndices[i]; position = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.ownerEmitter.blueprint.positionStack.values[particleIndex]); // Raw position stack result. position = AmpsHelpers.RotateAroundPoint(position, ownerBlueprint.ownerEmitter.transform.position, Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation)); position -= ownerBlueprint.ownerEmitter.emitterPosition; // Compensating for emitter position, turning position world relative. pivotOffset = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.pivotOffsetStack.values[particleIndex]); rotation = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.rotationStack.values[particleIndex]); // Raw particle stack result. quaternionRotation = Quaternion.Inverse(ownerBlueprint.ownerEmitter.transform.rotation) * Quaternion.Euler(rotation); scale = AmpsHelpers.ConvertVector4Vector3(ownerBlueprint.scaleStack.values[particleIndex]); color = ownerBlueprint.colorStack.values[particleIndex]; if (meshIndices[particleIndex] < 0) { meshIndices[particleIndex] = theRandom.Next(0, inputMeshes.Length); } Mesh pickedMesh = inputMeshes[meshIndices[particleIndex]].GetValue(); meshCache[particleIndex].Clear(); combine[i].mesh = meshCache[particleIndex]; if (pickedMesh != null) { combine[i].mesh.vertices = pickedMesh.vertices; combine[i].mesh.normals = pickedMesh.normals; combine[i].mesh.uv = pickedMesh.uv; combine[i].mesh.triangles = pickedMesh.triangles; combine[i].mesh.tangents = pickedMesh.tangents; Color[] vertexColors = new Color[pickedMesh.vertices.Length]; for (int j = 0; j < pickedMesh.vertices.Length; j++) { vertexColors[j] = color; } combine[i].mesh.colors = vertexColors; combine[i].transform = Matrix4x4.TRS(position + pivotOffset, quaternionRotation, scale); } else { combine[i].transform = new Matrix4x4(); } if (shouldRecreateMesh) // Things go in here which don't change unless particle count changes. { } } finalMesh.CombineMeshes(combine, true, true); }