// EVALUATE ACCELERATION// // override public void Evaluate_Acceleration() { if (modifyAcceleration.GetValue() || modifyMomentum.GetValue()) { Vector4 v; int particleIndex; for (int i = 0; i < ownerBlueprint.ownerEmitter.activeParticleIndices.Length; i++) { particleIndex = ownerBlueprint.ownerEmitter.activeParticleIndices[i]; if (modifyAcceleration.GetValue()) { v = accelerationMultiplier.GetValue(particleIndex); ownerBlueprint.accelerationStack.values[particleIndex].x *= v.x; ownerBlueprint.accelerationStack.values[particleIndex].y *= v.y; ownerBlueprint.accelerationStack.values[particleIndex].z *= v.z; } if (modifyMomentum.GetValue()) { v = momentumMultiplier.GetValue(particleIndex); ownerBlueprint.ownerEmitter.accelerationAccumulators[particleIndex].x *= v.x; ownerBlueprint.ownerEmitter.accelerationAccumulators[particleIndex].y *= v.y; ownerBlueprint.ownerEmitter.accelerationAccumulators[particleIndex].z *= v.z; } } } }
// EVALUATE VELOCITY// // override public void Evaluate_Velocity() { if (modifyVelocity.GetValue() || modifyDisplacement.GetValue()) { Vector4 v; int particleIndex; for (int i = 0; i < ownerBlueprint.ownerEmitter.activeParticleIndices.Length; i++) { particleIndex = ownerBlueprint.ownerEmitter.activeParticleIndices[i]; if (modifyVelocity.GetValue()) { v = velocityMultiplier.GetValue(particleIndex); ownerBlueprint.velocityStack.values[particleIndex].x *= v.x; ownerBlueprint.velocityStack.values[particleIndex].y *= v.y; ownerBlueprint.velocityStack.values[particleIndex].z *= v.z; } if (modifyDisplacement.GetValue()) { v = displacementMultiplier.GetValue(particleIndex); ownerBlueprint.ownerEmitter.velocityAccumulators[particleIndex].x *= v.x; ownerBlueprint.ownerEmitter.velocityAccumulators[particleIndex].y *= v.y; ownerBlueprint.ownerEmitter.velocityAccumulators[particleIndex].z *= v.z; } } } }
// EVALUATE // // // Evaluate when particle specific data is NOT available. override public void Evaluate(ref float input) { float output = 0; float finalValueA = useStackValue.GetValue() ? input : valueA.GetValue(); switch (condition.GetValue()) { case (int)eConditions.Greater: if (finalValueA > valueB.GetValue()) { output = valueTrue.GetValue(); } else { output = valueFalse.GetValue(); } break; case (int)eConditions.Less: if (finalValueA < valueB.GetValue()) { output = valueTrue.GetValue(); } else { output = valueFalse.GetValue(); } break; case (int)eConditions.Equal: if (finalValueA == valueB.GetValue()) { output = valueTrue.GetValue(); } else { output = valueFalse.GetValue(); } break; case (int)eConditions.NotEqual: if (finalValueA != valueB.GetValue()) { output = valueTrue.GetValue(); } else { output = valueFalse.GetValue(); } break; } input = Blend(input, output, weight.GetValue()); }
// EVALUATE // // // Evaluate when particle specific data is NOT available. override public void Evaluate(ref float input) { float f; ManageSampling(-1); // We only do anything if there is a valid sample to work with. if (isValidSample[0] && lastSampleTimes[0] != -1) { f = Blend(input, samples[0], weight.GetValue()); if (modifyX.GetValue()) { input = f; } } }
private float[] accumulatedValues; // The accumulator floats for each particle. // EVALUATE // // // Evaluate when particle specific data is NOT available. override public void Evaluate(ref float input) { InitializeNewParticles(); if (useStackValue.GetValue()) { accumulatedValues[0] += input * ownerBlueprint.ownerEmitter.deltaTime; } else { accumulatedValues[0] += changePerSecond.GetValue() * ownerBlueprint.ownerEmitter.deltaTime; } input = Blend(input, accumulatedValues[0], weight.GetValue()); }
// EVALUATE // // // Evaluate when particle specific data IS available. override public void Evaluate(ref Vector4[] input) { Vector4 v; InitializeNewParticles(); int particleIndex; for (int i = 0; i < ownerBlueprint.ownerEmitter.activeParticleIndices.Length; i++) { particleIndex = ownerBlueprint.ownerEmitter.activeParticleIndices[i]; ManageSampling(particleIndex); if (isValidSample[particleIndex] && lastSampleTimes[particleIndex] != -1) { v = Blend(input[particleIndex], samples[particleIndex], weight.GetValue(particleIndex)); if (modifyX.GetValue()) { input[particleIndex].x = v.x; } if (modifyY.GetValue()) { input[particleIndex].y = v.y; } if (modifyZ.GetValue()) { input[particleIndex].z = v.z; } if (modifyW.GetValue()) { input[particleIndex].w = v.w; } } } }
// EVALUATE // // // Evaluate when particle specific data is NOT available. override public void Evaluate(ref float input) { Vector4 finalValue = untriggeredValue.GetValue(); if (ownerBlueprint.ownerEmitter.emitterLoopTime < previousLoopTime) { currentTriggerCount = 0; } previousLoopTime = ownerBlueprint.ownerEmitter.emitterLoopTime; if (triggerToggle.GetValue() == false && ownerBlueprint.ownerEmitter.emitterTime > lastTriggerTime + triggerDuration.GetValue()) { isTriggered = false; } if (isTriggered) { switch ((eTriggerDataModes)triggerDataMode.GetValue()) { case eTriggerDataModes.CustomValue: finalValue = triggeredCustomValue.GetValue(); break; case eTriggerDataModes.EventData1: finalValue = lastEventData.DataSlot1; break; case eTriggerDataModes.EventData2: finalValue = lastEventData.DataSlot2; break; case eTriggerDataModes.EventData3: finalValue = lastEventData.DataSlot3; break; case eTriggerDataModes.EventData4: finalValue = lastEventData.DataSlot4; break; } } input = Blend(input, finalValue, weight.GetValue()); }
// EVALUATE // // // Evaluate when particle specific data is NOT available. override public void Evaluate(ref float input) { #if UNITY_EDITOR if (showCurrentStack.GetValue()) { label.value = input.ToString("F3"); } else { if (ownerBlueprint.ownerEmitter.exampleInputParticleIndex < 0) { return; } Vector4 v = AmpsHelpers.GetSystemProperty(ownerBlueprint, ownerBlueprint.ownerEmitter.exampleInputParticleIndex, (AmpsHelpers.eCurveInputs)property.GetValue()); label.value = v.x.ToString("F3") + ", " + v.y.ToString("F3") + ", " + v.z.ToString("F3") + ", " + v.w.ToString("F3"); } moduleName.value = label.value; #endif }
// HANDLE EVENT // // public void HandleEvent(EventData theEventData) { bool isTriggerCountFine = infiniteTriggerCount.GetValue() || (infiniteTriggerCount.GetValue() == false && currentTriggerCount < maxTriggerCount.GetValue()); if (theEventData.eventName == eventName.GetValue() && isTriggerCountFine) { if (triggerToggle.GetValue()) { isTriggered = isTriggered == false; } else { isTriggered = true; } lastEventData = theEventData; lastTriggerTime = ownerBlueprint.ownerEmitter.emitterTime; currentTriggerCount++; } }
// GET VALUE // // public bool GetValue() { bool returnValue = false; #if UNITY_EDITOR CheckReferences(); #endif switch (dataMode) { case eDataMode.Constant: returnValue = value; break; case eDataMode.Reference: if (reference != null) { BoolProperty theReference = (BoolProperty)reference.property; returnValue = theReference.GetValue(); } break; case eDataMode.Parameter: if (wasParameterQueried == false) { parameter = ownerBlueprint.ownerEmitter.GetParameter(parameterName, AmpsHelpers.eParameterTypes.Bool); wasParameterQueried = true; } if (parameter != null) { returnValue = parameter.GetBoolValue(); } else { returnValue = value; } break; } return(returnValue); }
// SHOULD SAMPLE // // // Check sampling condition when particle data IS available. public bool ShouldSample(int particleIndex) { bool returnValue = false; float currentTime; // Get "currentTime" from the proper source. if (ownerStack.isParticleStack) { currentTime = ownerBlueprint.ownerEmitter.particleTimes[particleIndex]; } else { currentTime = ownerBlueprint.ownerEmitter.emitterTime; } // Apply time offset if appropriate. if (samplerCondition.GetValue() == (int)eSamplerConditions.ByTime) { currentTime = currentTime - intervalOffset.GetValue(); if (currentTime < 0) { currentTime = 0; } } else if (samplerCondition.GetValue() == (int)eSamplerConditions.OnCreation && lastSampleTimes[particleIndex] < 0 && currentTime >= intervalOffset.GetValue()) { lastSampleTimes[particleIndex] = currentTime; returnValue = true; } // We do a sample if we should on spawn and if the last sample timestamp is -1 i.e. no sample has been taken yet. if (sampleOnSpawn.GetValue() && lastSampleTimes[particleIndex] < 0) { lastSampleTimes[particleIndex] = currentTime; returnValue = true; } switch ((eSamplerConditions)samplerCondition.GetValue()) { // AmpsHelpers.eSamplerConditions.OnCreation was handled above. case eSamplerConditions.ByTime: if (currentTime >= lastSampleTimes[particleIndex] + interval.GetValue()) { returnValue = true; lastSampleTimes[particleIndex] = Mathf.Round(currentTime / interval.GetValue()) * interval.GetValue(); } break; case eSamplerConditions.ByDirectValue: float theDirectValue = 0; if (ownerStack.isParticleStack) { theDirectValue = directValue.GetValue(particleIndex); } else { theDirectValue = directValue.GetValue(); } if (theDirectValue >= 1) { returnValue = true; lastSampleTimes[particleIndex] = currentTime; } break; case eSamplerConditions.OnCollision: // True if collision occured on last update. // TODO: Implement collision. break; } return(returnValue); }
// MANAGE EVENT // // void ManageEvent(Vector4 input, bool isInputFloat, int particleIndex) { bool shouldTriggerEvent = false; Vector4 rawProperty; bool isRawPropertyFloat = isInputFloat; float thePropertyValue = 0; if (useCurrentStack.GetValue() == false) { rawProperty = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)property.GetValue()); isRawPropertyFloat = AmpsHelpers.isFloatInput((AmpsHelpers.eCurveInputs)property.GetValue()); } else { rawProperty = input; } if (isRawPropertyFloat) { thePropertyValue = rawProperty.x; } else { switch (propertyVectorComponent.GetValue()) { case (int)AmpsHelpers.eVectorComponents.X: thePropertyValue = rawProperty.x; break; case (int)AmpsHelpers.eVectorComponents.Y: thePropertyValue = rawProperty.y; break; case (int)AmpsHelpers.eVectorComponents.Z: thePropertyValue = rawProperty.z; break; case (int)AmpsHelpers.eVectorComponents.W: thePropertyValue = rawProperty.w; break; case (int)AmpsHelpers.eVectorComponents.Mag: thePropertyValue = new Vector3(rawProperty.x, rawProperty.y, rawProperty.z).magnitude; break; } } switch (condition.GetValue()) { case (int)eConditions.Greater: shouldTriggerEvent = thePropertyValue > value.GetValue(); break; case (int)eConditions.Less: shouldTriggerEvent = thePropertyValue < value.GetValue(); break; case (int)eConditions.Equal: shouldTriggerEvent = thePropertyValue == value.GetValue(); break; case (int)eConditions.NotEqual: shouldTriggerEvent = thePropertyValue != value.GetValue(); break; } if (shouldTriggerEvent) { AmpsEmitter[] childEmitters = ownerBlueprint.ownerEmitter.transform.GetComponentsInChildren <AmpsEmitter>(); for (int i = 0; i < childEmitters.Length; i++) { switch ((eActions)action.GetValue()) { case eActions.ResetAndPlay: childEmitters[i].Play(); break; case eActions.PlayIfNotPlaying: if (childEmitters[i].isStopped) { childEmitters[i].Play(); } else if (childEmitters[i].isPaused) { childEmitters[i].Unpause(); } break; case eActions.Pause: if (childEmitters[i].isPaused == false) { childEmitters[i].Pause(); } break; default: break; } } timeOfLastEvent = ownerBlueprint.ownerEmitter.emitterTime; } }
// 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; }
// MANAGE EVENT // // void ManageEvent(Vector4 input, bool isInputFloat, int particleIndex) { bool shouldTriggerEvent = false; Vector4 rawProperty; bool isRawPropertyFloat = isInputFloat; float thePropertyValue = 0; if (useCurrentStack.GetValue() == false) { rawProperty = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)property.GetValue()); isRawPropertyFloat = AmpsHelpers.isFloatInput((AmpsHelpers.eCurveInputs)property.GetValue()); } else { rawProperty = input; } if (isRawPropertyFloat) { thePropertyValue = rawProperty.x; } else { switch (propertyVectorComponent.GetValue()) { case (int)AmpsHelpers.eVectorComponents.X: thePropertyValue = rawProperty.x; break; case (int)AmpsHelpers.eVectorComponents.Y: thePropertyValue = rawProperty.y; break; case (int)AmpsHelpers.eVectorComponents.Z: thePropertyValue = rawProperty.z; break; case (int)AmpsHelpers.eVectorComponents.W: thePropertyValue = rawProperty.w; break; case (int)AmpsHelpers.eVectorComponents.Mag: thePropertyValue = new Vector3(rawProperty.x, rawProperty.y, rawProperty.z).magnitude; break; } } switch (condition.GetValue()) { case (int)eConditions.Greater: shouldTriggerEvent = thePropertyValue > value.GetValue(); break; case (int)eConditions.Less: shouldTriggerEvent = thePropertyValue < value.GetValue(); break; case (int)eConditions.Equal: shouldTriggerEvent = thePropertyValue == value.GetValue(); break; case (int)eConditions.NotEqual: shouldTriggerEvent = thePropertyValue != value.GetValue(); break; } if (shouldTriggerEvent) { EventData theEventData = new EventData(); theEventData.eventName = eventName.GetValue(); theEventData.particleIndex = particleIndex; theEventData.DataSlot1 = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)sentProperty1.GetValue()); theEventData.DataSlot2 = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)sentProperty2.GetValue()); theEventData.DataSlot3 = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)sentProperty3.GetValue()); theEventData.DataSlot4 = AmpsHelpers.GetSystemProperty(ownerBlueprint, particleIndex, (AmpsHelpers.eCurveInputs)sentProperty4.GetValue()); #if UNITY_EDITOR AmpsEmitter[] selfAndChildEmitters = ownerBlueprint.ownerEmitter.transform.root.GetComponentsInChildren <AmpsEmitter>(); for (int i = 0; i < selfAndChildEmitters.Length; i++) { selfAndChildEmitters[i].AmpsHandleEvent(theEventData); } #else ownerBlueprint.ownerEmitter.BroadcastMessage("AmpsHandleEvent", theEventData, SendMessageOptions.DontRequireReceiver); #endif currentEventCount++; timeOfLastEvent = ownerBlueprint.ownerEmitter.emitterTime; } }
// 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; }
// MANAGE SAMPLING // // // Does the actual sampling. override public void ManageSampling(int particleIndex) { int finalParticleIndex = (particleIndex < 0 ? 0 : particleIndex); AmpsHelpers.eCurveInputs wantedProperty = (AmpsHelpers.eCurveInputs)property.GetValue(); bool isWantedPropertyParticleRelated = AmpsHelpers.isParticleRelatedInput(wantedProperty); bool shouldIndeedSample = (particleIndex < 0 && ShouldSample()) || (particleIndex >= 0 && ShouldSample(particleIndex)); if (wasParentChecked == false) { if (ownerBlueprint.ownerEmitter.transform.parent != null) { parentEmitter = ownerBlueprint.ownerEmitter.transform.parent.GetComponent <AmpsEmitter>(); } wasParentChecked = true; } if (sampleFromParent.GetValue()) { // Leave if it's not time yet to sample. if (shouldIndeedSample == false) { return; } // INVALID SAMPLE: Parent doesn't exist or has no emitter component or no blueprint. if (parentEmitter == null || parentEmitter.blueprint == null) { isValidSample[finalParticleIndex] = false; return; } // Try to get valid parent particle index. if (parentParticleIndices[finalParticleIndex] < 0) { parentParticleIndices[finalParticleIndex] = parentEmitter.GetRandomParticleIndex(ownerBlueprint.ownerEmitter.particleIds[finalParticleIndex]); } // TODO: Invalid sample case: particle id at current particle index is different, ie we did lose // original particle index as it got replaced by another. // INVALID SAMPLE: Invalid parent particle index. // // TODO: We might have an invalid parent particle index but we might not need it anymore since // we already got a valid sample from it before and we don't need a new one for the time being. if (parentParticleIndices[finalParticleIndex] < 0) { isValidSample[finalParticleIndex] = false; return; } // INVALID SAMPLE: Parent particle is dead. if (parentParticleIndices[finalParticleIndex] >= 0 && parentEmitter.particleMarkers.IsActive(parentParticleIndices[finalParticleIndex]) == false) { parentParticleIndices[finalParticleIndex] = -1; isValidSample[finalParticleIndex] = false; return; } // INVALID SAMPLE: Asking for particle specific data but have no valid particle index. if (isWantedPropertyParticleRelated && parentParticleIndices[finalParticleIndex] < 0) { return; } samples[finalParticleIndex] = AmpsHelpers.GetSystemProperty(parentEmitter.blueprint, parentParticleIndices[finalParticleIndex], wantedProperty); isValidSample[finalParticleIndex] = true; } else { // Leave if it's not time yet to sample. if (shouldIndeedSample == false) { return; } // INVALID SAMPLE: Asking for particle specific data but have no valid particle index. if (isWantedPropertyParticleRelated && finalParticleIndex < 0) { return; } samples[finalParticleIndex] = AmpsHelpers.GetSystemProperty(ownerBlueprint, finalParticleIndex, wantedProperty); isValidSample[finalParticleIndex] = true; } }