From 0e691c444ac62232c0bddda3c23da7b76be5367f Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Wed, 12 Mar 2014 14:47:13 +0100 Subject: [PATCH 01/15] gitignore. --- .gitignore | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..764194f --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.lib +*.sbr +*.sdf +*.opensdf +*.unsuccessfulbuild +ipch/ +[Oo]bj/ +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad + +#MonoDevelop +*.pidb +*.userprefs + +#Tooling +_ReSharper*/ +*.resharper +[Tt]est[Rr]esult* +*.sass-cache + +#Project files +[Bb]uild/ + +#Subversion files +.svn + +# Office Temp Files +~$* + +# vim Temp Files +*~ + +#NuGet +packages/ +*.nupkg + +#ncrunch +*ncrunch* +*crunch*.local.xml + +# visual studio database projects +*.dbmdl + +#Test files +*.testsettings \ No newline at end of file From 0bc7291cceed20b66e5fed8785a5c9554c6ddb07 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Wed, 12 Mar 2014 15:06:25 +0100 Subject: [PATCH 02/15] ignore gitignore. --- .gitignore | 68 ---------------------------------- ModelMultiParticlePersistFX.cs | 7 ++++ 2 files changed, 7 insertions(+), 68 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 764194f..0000000 --- a/.gitignore +++ /dev/null @@ -1,68 +0,0 @@ -#OS junk files -[Tt]humbs.db -*.DS_Store - -#Visual Studio files -*.[Oo]bj -*.user -*.aps -*.pch -*.vspscc -*.vssscc -*_i.c -*_p.c -*.ncb -*.suo -*.tlb -*.tlh -*.bak -*.[Cc]ache -*.ilk -*.log -*.lib -*.sbr -*.sdf -*.opensdf -*.unsuccessfulbuild -ipch/ -[Oo]bj/ -[Bb]in -[Dd]ebug*/ -[Rr]elease*/ -Ankh.NoLoad - -#MonoDevelop -*.pidb -*.userprefs - -#Tooling -_ReSharper*/ -*.resharper -[Tt]est[Rr]esult* -*.sass-cache - -#Project files -[Bb]uild/ - -#Subversion files -.svn - -# Office Temp Files -~$* - -# vim Temp Files -*~ - -#NuGet -packages/ -*.nupkg - -#ncrunch -*ncrunch* -*crunch*.local.xml - -# visual studio database projects -*.dbmdl - -#Test files -*.testsettings \ No newline at end of file diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index e231747..34c0682 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -41,6 +41,13 @@ public class ModelMultiParticlePersistFX : EffectBehaviour [Persistent] public float sizeClamp = 50; + + // Initial density of the particle seen as a volume size^3 of perfect gas. + // We then assume (only true for ideally expanded exhaust) that the + // expansion is isobaric (by mixing with the atmosphere) in order to copmute + // the density afterwards. + [Persistent] + public float initialGasDensity = .1f; public FXCurve emission = new FXCurve("emission", 1f); From 29bf8883ee4dc70ee104ec52880dc01b65659d19 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Wed, 12 Mar 2014 20:45:34 +0100 Subject: [PATCH 03/15] First attempt at buoyancy and weight, better collision. --- ModelMultiParticlePersistFX.cs | 53 +++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 34c0682..93e3c05 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -42,12 +42,16 @@ public class ModelMultiParticlePersistFX : EffectBehaviour [Persistent] public float sizeClamp = 50; - // Initial density of the particle seen as a volume size^3 of perfect gas. - // We then assume (only true for ideally expanded exhaust) that the + // Initial density of the particle seen as sphere of radius size of perfect + // gas. We then assume (only true for ideally expanded exhaust) that the // expansion is isobaric (by mixing with the atmosphere) in order to copmute - // the density afterwards. + // the density afterwards. Units (SI): kg / m^3. [Persistent] - public float initialGasDensity = .1f; + public float initialDensity = .1f; + + // Whether to apply Archimedes' force, gravity and other things to the particle. + [Persistent] + public bool physical = true; public FXCurve emission = new FXCurve("emission", 1f); @@ -97,6 +101,9 @@ public class ModelMultiParticlePersistFX : EffectBehaviour public FXCurve angle = new FXCurve("angle", 1f); public FXCurve distance = new FXCurve("distance", 1f); + // Don't waste time on a division. + private const double fourThirdsPi = 4 / 3 * Math.PI; + private List peristantEmitters; private float emissionPower; @@ -229,6 +236,28 @@ public void FixedUpdate() { particles[j].size = Mathf.Min(particles[j].size, sizeClamp); + if (physical) { + Vector3d pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); + Vector3d pVel = peristantEmitters[i].pe.useWorldSpace ? particles[j].velocity : peristantEmitters[i].pe.transform.TransformDirection(particles[j].velocity); + float r = particles[j].size; + float rMin = peristantEmitters[i].pe.minSize; + float rMax = peristantEmitters[i].pe.maxSize; + // TODO(robin): this a bad idea. There must be a way to + // keep the actual initial volume, but I'm lazy. + // N.B.: multiplications rather than Pow, Pow is slow, + // multiplication by .5 rather than division by 2 (same + // reason). + double estimatedInitialVolume = fourThirdsPi * rMin * rMin * rMin; + double currentVolume = fourThirdsPi * r * r * r; + double volumeChange = currentVolume - estimatedInitialVolume; + double density = (estimatedInitialVolume * initialDensity + volumeChange) / currentVolume; + double atmosphericDensity = FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(pPos)); + Vector3d acceleration = (1 - (atmosphericDensity / density)) * FlightGlobals.getGeeForceAtPosition(pPos); + // Euler is good enough for graphics. + pVel = pVel + acceleration * TimeWarp.fixedDeltaTime; + particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); + } + if (collision) { Vector3 pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); @@ -236,13 +265,14 @@ public void FixedUpdate() if (Physics.Raycast(pPos, pVel, out hit, particles[j].velocity.magnitude * 2f * TimeWarp.fixedDeltaTime, mask)) if (hit.collider.name != "Launch Pad Grate") - { - pVel = Vector3.Reflect(pVel, hit.normal); + { Vector3 hVel = Vector3.Exclude(hit.normal, pVel); - //Vector3d vVel = Vector3d.Project(pVel, hit.normal); - // Make up something a bit more realistic ... - pVel = ((1 - collideRatio) * hVel + collideRatio * pVel).normalized * pVel.magnitude; - //pVel = hVel.normalized * pVel.magnitude; + Vector3 reflectedNormalVelocity = hVel - pVel; + // An attempt at a better velocity change; the blob collides with some + // restitution coefficient collideRatio << 1 and we add a random horizonal term + // for flow conservation---randomness handwaved in through fluid dynamics: + Vector3 flowConservationDirection = Vector3.Exclude(hit.normal, UnityEngine.Random.onUnitSphere); + pVel = hVel + collideRatio * reflectedNormalVelocity + flowConservationDirection * (1 - collideRatio) * reflectedNormalVelocity.magnitude; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } else @@ -425,6 +455,9 @@ public void Update() public override void OnInitialize() { +#if TRACE + print("ModelMultiParticlePersistFX.OnInitialize called;"); +#endif // The shader loading require proper testing // Unity doc says that "Creating materials this way supports only simple shaders (fixed function ones). // If you need a surface shader, or vertex/pixel shaders, you'll need to create shader asset in the editor and use that." From 7ab31f5f866b73d67d2df4fc6313e34f29a280c3 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Wed, 12 Mar 2014 22:23:30 +0100 Subject: [PATCH 04/15] foo --- ModelMultiParticlePersistFX.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 93e3c05..945266c 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -101,9 +101,6 @@ public class ModelMultiParticlePersistFX : EffectBehaviour public FXCurve angle = new FXCurve("angle", 1f); public FXCurve distance = new FXCurve("distance", 1f); - // Don't waste time on a division. - private const double fourThirdsPi = 4 / 3 * Math.PI; - private List peristantEmitters; private float emissionPower; @@ -247,14 +244,14 @@ public void FixedUpdate() // N.B.: multiplications rather than Pow, Pow is slow, // multiplication by .5 rather than division by 2 (same // reason). - double estimatedInitialVolume = fourThirdsPi * rMin * rMin * rMin; - double currentVolume = fourThirdsPi * r * r * r; + double estimatedInitialVolume = 0.75 * Math.PI * rMin * rMin * rMin; + double currentVolume = 0.75 * Math.PI * r * r * r; double volumeChange = currentVolume - estimatedInitialVolume; double density = (estimatedInitialVolume * initialDensity + volumeChange) / currentVolume; double atmosphericDensity = FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(pPos)); Vector3d acceleration = (1 - (atmosphericDensity / density)) * FlightGlobals.getGeeForceAtPosition(pPos); // Euler is good enough for graphics. - pVel = pVel + acceleration * TimeWarp.fixedDeltaTime; + // pVel = pVel + acceleration * TimeWarp.fixedDeltaTime; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } @@ -267,12 +264,14 @@ public void FixedUpdate() if (hit.collider.name != "Launch Pad Grate") { Vector3 hVel = Vector3.Exclude(hit.normal, pVel); - Vector3 reflectedNormalVelocity = hVel - pVel; + Vector3 reflectedNormalVelocity = collideRatio * (hVel - pVel); + float residualFlow = reflectedNormalVelocity.magnitude * (1 - collideRatio); // An attempt at a better velocity change; the blob collides with some // restitution coefficient collideRatio << 1 and we add a random horizonal term // for flow conservation---randomness handwaved in through fluid dynamics: - Vector3 flowConservationDirection = Vector3.Exclude(hit.normal, UnityEngine.Random.onUnitSphere); - pVel = hVel + collideRatio * reflectedNormalVelocity + flowConservationDirection * (1 - collideRatio) * reflectedNormalVelocity.magnitude; + float randomAngle = UnityEngine.Random.value * 360.0f; + Vector3d flowConservationTerm = Quaternion.AngleAxis(randomAngle, hit.normal) * hVel.normalized * residualFlow; + pVel = hVel + reflectedNormalVelocity + flowConservationTerm; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } else From d107aa1280c22461723422e9b48f9f01b29e5d10 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Thu, 13 Mar 2014 00:54:36 +0100 Subject: [PATCH 05/15] Good progress. Ditch the damping and whatever was offsetting the direction, but this is on the Unity side. --- ModelMultiParticlePersistFX.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 945266c..cc41a96 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -249,9 +249,14 @@ public void FixedUpdate() double volumeChange = currentVolume - estimatedInitialVolume; double density = (estimatedInitialVolume * initialDensity + volumeChange) / currentVolume; double atmosphericDensity = FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(pPos)); + double dragCoefficient = .5; // Computed by Pifomètre (R). Make it a setting? + double mass = density * currentVolume; + // Weight and buoyancy. Vector3d acceleration = (1 - (atmosphericDensity / density)) * FlightGlobals.getGeeForceAtPosition(pPos); + // Drag. TODO(robin): simplify. + acceleration += - 0.5 * atmosphericDensity * pVel * pVel.magnitude * dragCoefficient * Math.PI * r * r / mass; // Euler is good enough for graphics. - // pVel = pVel + acceleration * TimeWarp.fixedDeltaTime; + pVel = pVel + acceleration * TimeWarp.fixedDeltaTime; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } @@ -264,14 +269,14 @@ public void FixedUpdate() if (hit.collider.name != "Launch Pad Grate") { Vector3 hVel = Vector3.Exclude(hit.normal, pVel); - Vector3 reflectedNormalVelocity = collideRatio * (hVel - pVel); + Vector3 reflectedNormalVelocity = hVel - pVel; float residualFlow = reflectedNormalVelocity.magnitude * (1 - collideRatio); // An attempt at a better velocity change; the blob collides with some // restitution coefficient collideRatio << 1 and we add a random horizonal term // for flow conservation---randomness handwaved in through fluid dynamics: float randomAngle = UnityEngine.Random.value * 360.0f; Vector3d flowConservationTerm = Quaternion.AngleAxis(randomAngle, hit.normal) * hVel.normalized * residualFlow; - pVel = hVel + reflectedNormalVelocity + flowConservationTerm; + pVel = hVel + collideRatio * reflectedNormalVelocity + flowConservationTerm; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } else From 7efbe3186680c43cf39cb140662002d799866796 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Thu, 13 Mar 2014 01:00:14 +0100 Subject: [PATCH 06/15] Remove trace. --- ModelMultiParticlePersistFX.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index cc41a96..c33274c 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -459,9 +459,6 @@ public void Update() public override void OnInitialize() { -#if TRACE - print("ModelMultiParticlePersistFX.OnInitialize called;"); -#endif // The shader loading require proper testing // Unity doc says that "Creating materials this way supports only simple shaders (fixed function ones). // If you need a surface shader, or vertex/pixel shaders, you'll need to create shader asset in the editor and use that." From cbcf20bf47b252fe55e66016fa0be90fcac947bb Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Thu, 13 Mar 2014 01:25:05 +0100 Subject: [PATCH 07/15] More advanced Pifometry. --- ModelMultiParticlePersistFX.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index c33274c..774cf9e 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -249,7 +249,7 @@ public void FixedUpdate() double volumeChange = currentVolume - estimatedInitialVolume; double density = (estimatedInitialVolume * initialDensity + volumeChange) / currentVolume; double atmosphericDensity = FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(pPos)); - double dragCoefficient = .5; // Computed by Pifomètre (R). Make it a setting? + double dragCoefficient = .4; // Computed by Pifomètre. Make it a setting? double mass = density * currentVolume; // Weight and buoyancy. Vector3d acceleration = (1 - (atmosphericDensity / density)) * FlightGlobals.getGeeForceAtPosition(pPos); @@ -268,14 +268,15 @@ public void FixedUpdate() if (hit.collider.name != "Launch Pad Grate") { + Vector3 unitTangent = (hit.normal.x == 0 && hit.normal.y == 0) ? new Vector3(1, 0, 0) : Vector3.Exclude(hit.normal, new Vector3(0, 0, 1)).normalized; Vector3 hVel = Vector3.Exclude(hit.normal, pVel); Vector3 reflectedNormalVelocity = hVel - pVel; float residualFlow = reflectedNormalVelocity.magnitude * (1 - collideRatio); // An attempt at a better velocity change; the blob collides with some - // restitution coefficient collideRatio << 1 and we add a random horizonal term + // restitution coefficient collideRatio << 1 and we add a random tangential term // for flow conservation---randomness handwaved in through fluid dynamics: float randomAngle = UnityEngine.Random.value * 360.0f; - Vector3d flowConservationTerm = Quaternion.AngleAxis(randomAngle, hit.normal) * hVel.normalized * residualFlow; + Vector3d flowConservationTerm = Quaternion.AngleAxis(randomAngle, hit.normal) * unitTangent * residualFlow; pVel = hVel + collideRatio * reflectedNormalVelocity + flowConservationTerm; particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } From 8441ce4c40d356d26f6865b80393617e334f44fb Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Thu, 13 Mar 2014 04:07:44 +0100 Subject: [PATCH 08/15] =?UTF-8?q?Let=20the=20user=20use=20his=20pifom?= =?UTF-8?q?=C3=A8tre.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ModelMultiParticlePersistFX.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 774cf9e..f100d1a 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -52,6 +52,9 @@ public class ModelMultiParticlePersistFX : EffectBehaviour // Whether to apply Archimedes' force, gravity and other things to the particle. [Persistent] public bool physical = true; + + [Persistent] + public double dragCoefficient = 0.1; public FXCurve emission = new FXCurve("emission", 1f); @@ -247,9 +250,8 @@ public void FixedUpdate() double estimatedInitialVolume = 0.75 * Math.PI * rMin * rMin * rMin; double currentVolume = 0.75 * Math.PI * r * r * r; double volumeChange = currentVolume - estimatedInitialVolume; - double density = (estimatedInitialVolume * initialDensity + volumeChange) / currentVolume; double atmosphericDensity = FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(pPos)); - double dragCoefficient = .4; // Computed by Pifomètre. Make it a setting? + double density = (estimatedInitialVolume * initialDensity + volumeChange * atmosphericDensity) / currentVolume; double mass = density * currentVolume; // Weight and buoyancy. Vector3d acceleration = (1 - (atmosphericDensity / density)) * FlightGlobals.getGeeForceAtPosition(pPos); From d4462d4862ca361bfbfafd9223c64dd796de859a Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Thu, 13 Mar 2014 19:48:39 +0100 Subject: [PATCH 09/15] Sticky particles. --- ModelMultiParticlePersistFX.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index f100d1a..930411e 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -53,6 +53,10 @@ public class ModelMultiParticlePersistFX : EffectBehaviour [Persistent] public bool physical = true; + // How much of the particles stick to objects they collide to. + [Persistent] + public float stickiness = 0.9f; + [Persistent] public double dragCoefficient = 0.1; @@ -276,10 +280,10 @@ public void FixedUpdate() float residualFlow = reflectedNormalVelocity.magnitude * (1 - collideRatio); // An attempt at a better velocity change; the blob collides with some // restitution coefficient collideRatio << 1 and we add a random tangential term - // for flow conservation---randomness handwaved in through fluid dynamics: + // for outflowing particles---randomness handwaved in through fluid dynamics: float randomAngle = UnityEngine.Random.value * 360.0f; - Vector3d flowConservationTerm = Quaternion.AngleAxis(randomAngle, hit.normal) * unitTangent * residualFlow; - pVel = hVel + collideRatio * reflectedNormalVelocity + flowConservationTerm; + Vector3d outflow = Quaternion.AngleAxis(randomAngle, hit.normal) * unitTangent * residualFlow; + pVel = hVel + collideRatio * reflectedNormalVelocity + outflow * (1 - stickiness); particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } else From 516a765424bd07652e00e70cb6c8968bd86e455d Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 02:07:41 +0100 Subject: [PATCH 10/15] Changed defaults for compatibility, implemented logarithmic growth. --- ModelMultiParticlePersistFX.cs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 930411e..1ed7a04 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -28,7 +28,7 @@ public class ModelMultiParticlePersistFX : EffectBehaviour public string collide = "false"; [Persistent] - public float collideRatio = 0.01f; + public float collideRatio = 0.0f; [Persistent] public Vector3 localRotation = Vector3.zero; @@ -47,18 +47,25 @@ public class ModelMultiParticlePersistFX : EffectBehaviour // expansion is isobaric (by mixing with the atmosphere) in order to copmute // the density afterwards. Units (SI): kg / m^3. [Persistent] - public float initialDensity = .1f; + public double initialDensity = .6; // Whether to apply Archimedes' force, gravity and other things to the particle. [Persistent] - public bool physical = true; + public bool physical = false; - // How much of the particles stick to objects they collide to. + // How much the particles stick to objects they collide with. [Persistent] - public float stickiness = 0.9f; + public double stickiness = 0.9; [Persistent] public double dragCoefficient = 0.1; + + // Logarithmic growth applied to to the particle. + // The size at time t after emission will be approximately + // (Log(logarithmicGrowth * t + 1) + 1) * initialSize, assuming growth = 0. + // TODO(sarbian): make this a cfg-configurable curve (as a function of density). + [Persistent] + public double logarithmicGrowth = 0.0; public FXCurve emission = new FXCurve("emission", 1f); @@ -239,15 +246,22 @@ public void FixedUpdate() if (particles[j].energy > 0) { particles[j].size = Mathf.Min(particles[j].size, sizeClamp); + // No need to waste time doing a division if the result is 0. + if(logarithmicGrowth != 0.0) { + // Euler integration of the derivative of Log(logarithmicGrowth * t + 1) + 1. + // TODO(robin): We use minSize rather than keeping the initial size. + // This might look weird. + particles[j].size += (float)(((TimeWarp.fixedDeltaTime * logarithmicGrowth) / (1 + (particles[j].startEnergy - particles[j].energy) * logarithmicGrowth)) * peristantEmitters[i].pe.minSize); + } if (physical) { Vector3d pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); Vector3d pVel = peristantEmitters[i].pe.useWorldSpace ? particles[j].velocity : peristantEmitters[i].pe.transform.TransformDirection(particles[j].velocity); - float r = particles[j].size; - float rMin = peristantEmitters[i].pe.minSize; - float rMax = peristantEmitters[i].pe.maxSize; - // TODO(robin): this a bad idea. There must be a way to - // keep the actual initial volume, but I'm lazy. + double r = particles[j].size; + double rMin = peristantEmitters[i].pe.minSize; + // TODO(robin): using rMin is probably a bad idea, as above. + // There must be a way to keep the actual initial volume, + // but I'm lazy. // N.B.: multiplications rather than Pow, Pow is slow, // multiplication by .5 rather than division by 2 (same // reason). From 1a1f14bdd2e391f11e0494db1b78b9aecf80ace8 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 18:17:42 +0100 Subject: [PATCH 11/15] Second attempt at fixing dotted smoke............ --- ModelMultiParticlePersistFX.cs | 49 ++++++++++++++++++++++++++------- PersistantKSPParticleEmitter.cs | 1 + 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 1ed7a04..bcfacd6 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -67,6 +67,10 @@ public class ModelMultiParticlePersistFX : EffectBehaviour [Persistent] public double logarithmicGrowth = 0.0; + // Whether to emit particles every FixedUpdate rather than every Update. + [Persistent] + public bool fixedEmissions = true; + public FXCurve emission = new FXCurve("emission", 1f); public FXCurve energy = new FXCurve("energy", 1f); @@ -161,7 +165,8 @@ private void OnDestroy() for (int i = 0; i < peristantEmitters.Count; i++) if (peristantEmitters[i].go != null && peristantEmitters[i].go.transform.parent != null) { - peristantEmitters[i].pe.emit = false; + peristantEmitters[i].fixedEmit = false; + peristantEmitters[i].pe.emit = false; // detach from the parent so the emmitter(and its particle) don't get removed instantly peristantEmitters[i].go.transform.parent = null; @@ -188,13 +193,21 @@ public override void OnEvent(float power) if (power > 0f) { UpdateEmitters(power); - for (int i = 0; i < peristantEmitters.Count; i++) + for (int i = 0; i < peristantEmitters.Count; i++) { + if (fixedEmissions) { + peristantEmitters[i].fixedEmit = true; + peristantEmitters[i].pe.emit = false; + } else { peristantEmitters[i].pe.emit = true; + } + } } else { - for (int j = 0; j < peristantEmitters.Count; j++) - peristantEmitters[j].pe.emit = false; + for (int j = 0; j < peristantEmitters.Count; j++) { + peristantEmitters[j].fixedEmit = false; + peristantEmitters[j].pe.emit = false; + } } } @@ -230,10 +243,20 @@ public void FixedUpdate() for (int i = 0; i < peristantEmitters.Count; i++) { + // Emit particles on fixedUpdate rather than Update so that the + // appearance is not performance-dependent (dotted smoke effect). + if(peristantEmitters[i].fixedEmit) { + // Number of particles to emit: + double averageEmittedParticles = UnityEngine.Random.Range(peristantEmitters[i].pe.minEmission, peristantEmitters[i].pe.maxEmission) * TimeWarp.fixedDeltaTime; + int emittedParticles = (int)Math.Floor(averageEmittedParticles) + (UnityEngine.Random.value < averageEmittedParticles - Math.Floor(averageEmittedParticles) ? 1 : 0); + for (int k = 0; k < emittedParticles; ++k) { + peristantEmitters[k].pe.EmitParticle(); + } + } Particle[] particles = peristantEmitters[i].pe.pe.particles; for (int j = 0; j < particles.Length; j++) - { + { // Check if we need to cull the number of particles if (particuleDecimate != 0 && particles.Length > decimateFloor) @@ -245,6 +268,9 @@ public void FixedUpdate() if (particles[j].energy > 0) { + Vector3d pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); + Vector3d pVel = peristantEmitters[i].pe.useWorldSpace ? particles[j].velocity : peristantEmitters[i].pe.transform.TransformDirection(particles[j].velocity); + particles[j].size = Mathf.Min(particles[j].size, sizeClamp); // No need to waste time doing a division if the result is 0. if(logarithmicGrowth != 0.0) { @@ -254,9 +280,12 @@ public void FixedUpdate() particles[j].size += (float)(((TimeWarp.fixedDeltaTime * logarithmicGrowth) / (1 + (particles[j].startEnergy - particles[j].energy) * logarithmicGrowth)) * peristantEmitters[i].pe.minSize); } + if (particles[j].energy == particles[j].startEnergy) { + // Uniformly scatter the particles along the emitter's trajectory in order to remove the dotted smoke effect. + pPos += hostPart.vel * UnityEngine.Random.value * TimeWarp.fixedDeltaTime; + } + if (physical) { - Vector3d pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); - Vector3d pVel = peristantEmitters[i].pe.useWorldSpace ? particles[j].velocity : peristantEmitters[i].pe.transform.TransformDirection(particles[j].velocity); double r = particles[j].size; double rMin = peristantEmitters[i].pe.minSize; // TODO(robin): using rMin is probably a bad idea, as above. @@ -282,8 +311,6 @@ public void FixedUpdate() if (collision) { - Vector3 pPos = peristantEmitters[i].pe.useWorldSpace ? particles[j].position : peristantEmitters[i].pe.transform.TransformPoint(particles[j].position); - Vector3 pVel = peristantEmitters[i].pe.useWorldSpace ? particles[j].velocity : peristantEmitters[i].pe.transform.TransformDirection(particles[j].velocity); if (Physics.Raycast(pPos, pVel, out hit, particles[j].velocity.magnitude * 2f * TimeWarp.fixedDeltaTime, mask)) if (hit.collider.name != "Launch Pad Grate") @@ -298,7 +325,6 @@ public void FixedUpdate() float randomAngle = UnityEngine.Random.value * 360.0f; Vector3d outflow = Quaternion.AngleAxis(randomAngle, hit.normal) * unitTangent * residualFlow; pVel = hVel + collideRatio * reflectedNormalVelocity + outflow * (1 - stickiness); - particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } else { @@ -307,6 +333,9 @@ public void FixedUpdate() AddLaunchPadColliders(hit); } } + + particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); + particles[j].position = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pPos : peristantEmitters[i].pe.transform.InverseTransformPoint(pPos)); } } peristantEmitters[i].pe.pe.particles = particles; diff --git a/PersistantKSPParticleEmitter.cs b/PersistantKSPParticleEmitter.cs index 1de5ffe..893405c 100644 --- a/PersistantKSPParticleEmitter.cs +++ b/PersistantKSPParticleEmitter.cs @@ -19,6 +19,7 @@ public class PersistantKSPParticleEmitter { public GameObject go; public KSPParticleEmitter pe; + public bool fixedEmit = false; public float baseMaxSize; public PersistantKSPParticleEmitter(GameObject go, KSPParticleEmitter pe, float ms) From f0ab19b731ea7d72025223fc5500fbab178b94a9 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 18:20:17 +0100 Subject: [PATCH 12/15] argument range safety officer. --- ModelMultiParticlePersistFX.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index bcfacd6..ada67ae 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -250,7 +250,7 @@ public void FixedUpdate() double averageEmittedParticles = UnityEngine.Random.Range(peristantEmitters[i].pe.minEmission, peristantEmitters[i].pe.maxEmission) * TimeWarp.fixedDeltaTime; int emittedParticles = (int)Math.Floor(averageEmittedParticles) + (UnityEngine.Random.value < averageEmittedParticles - Math.Floor(averageEmittedParticles) ? 1 : 0); for (int k = 0; k < emittedParticles; ++k) { - peristantEmitters[k].pe.EmitParticle(); + peristantEmitters[i].pe.EmitParticle(); } } Particle[] particles = peristantEmitters[i].pe.pe.particles; From 04ac7dfae3fd5e69f7e629bda6ce2072bc05161e Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 18:25:32 +0100 Subject: [PATCH 13/15] don't collide on creation. --- ModelMultiParticlePersistFX.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index ada67ae..88bd4b0 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -309,7 +309,8 @@ public void FixedUpdate() particles[j].velocity = (peristantEmitters[i].pe.useWorldSpace ? (Vector3)pVel : peristantEmitters[i].pe.transform.InverseTransformDirection(pVel)); } - if (collision) + if (particles[j].energy != particles[j].startEnergy && // Do not collide newly created particles (they collide with the emitter and things look bad). + collision) { if (Physics.Raycast(pPos, pVel, out hit, particles[j].velocity.magnitude * 2f * TimeWarp.fixedDeltaTime, mask)) From f53d490d42cffe35a1f13b93a607e083906481cf Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 18:57:25 +0100 Subject: [PATCH 14/15] Fixed the dotted smoke problem. --- ModelMultiParticlePersistFX.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 88bd4b0..7c2cd3b 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -67,9 +67,11 @@ public class ModelMultiParticlePersistFX : EffectBehaviour [Persistent] public double logarithmicGrowth = 0.0; - // Whether to emit particles every FixedUpdate rather than every Update. + // Whether to nudge particles in order to alleviate the dotted smoke effect. [Persistent] public bool fixedEmissions = true; + + private float variableDeltaTime; public FXCurve emission = new FXCurve("emission", 1f); @@ -243,8 +245,8 @@ public void FixedUpdate() for (int i = 0; i < peristantEmitters.Count; i++) { - // Emit particles on fixedUpdate rather than Update so that the - // appearance is not performance-dependent (dotted smoke effect). + // Emit particles on fixedUpdate rather than Update so that we know which particles + // were just created and should be nudged, should not be collided, etc. if(peristantEmitters[i].fixedEmit) { // Number of particles to emit: double averageEmittedParticles = UnityEngine.Random.Range(peristantEmitters[i].pe.minEmission, peristantEmitters[i].pe.maxEmission) * TimeWarp.fixedDeltaTime; @@ -280,9 +282,9 @@ public void FixedUpdate() particles[j].size += (float)(((TimeWarp.fixedDeltaTime * logarithmicGrowth) / (1 + (particles[j].startEnergy - particles[j].energy) * logarithmicGrowth)) * peristantEmitters[i].pe.minSize); } - if (particles[j].energy == particles[j].startEnergy) { + if (fixedEmissions && particles[j].energy == particles[j].startEnergy) { // Uniformly scatter the particles along the emitter's trajectory in order to remove the dotted smoke effect. - pPos += hostPart.vel * UnityEngine.Random.value * TimeWarp.fixedDeltaTime; + pPos -= hostPart.rb.velocity * UnityEngine.Random.value * variableDeltaTime; } if (physical) { @@ -491,7 +493,7 @@ public void UpdateEmitters(float power) public void Update() { - + variableDeltaTime = Time.deltaTime; if (peristantEmitters == null) { return; From 13573a573e2064d872d0bb98ca228217b3507f28 Mon Sep 17 00:00:00 2001 From: Robin Leroy Date: Fri, 14 Mar 2014 19:09:24 +0100 Subject: [PATCH 15/15] No silent policement here. --- ModelMultiParticlePersistFX.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ModelMultiParticlePersistFX.cs b/ModelMultiParticlePersistFX.cs index 7c2cd3b..2b78c73 100644 --- a/ModelMultiParticlePersistFX.cs +++ b/ModelMultiParticlePersistFX.cs @@ -44,7 +44,7 @@ public class ModelMultiParticlePersistFX : EffectBehaviour // Initial density of the particle seen as sphere of radius size of perfect // gas. We then assume (only true for ideally expanded exhaust) that the - // expansion is isobaric (by mixing with the atmosphere) in order to copmute + // expansion is isobaric (by mixing with the atmosphere) in order to compute // the density afterwards. Units (SI): kg / m^3. [Persistent] public double initialDensity = .6;