// Emit will return a particle list, which will be rendered public void updateParticles(float dt) { int currentEmission = 0; currentTimeEmission += dt; // add particle // if current number of particle is lower than total we can add particles // since we work on emissions per second, one second need to past after timeLastEmission if (particleCount < totalParticles && currentTimeEmission > emissionRateSec) { while (currentEmission < emitsPerRate) { particles[particleCount] = new SandParticle(pos + new Vector3(Random.Range(-1.0f, 1.0f) * posVar.x, Random.Range(-1.0f, 1.0f) * posVar.y, Random.Range(-1.0f, 1.0f) * posVar.z), 20 * fromRotationToDirection(yaw + Random.Range(-1.0f, 1.0f) * yawVar, pitch + Random.Range(-1.0f, 1.0f) * pitchVar)); ++currentEmission; ++particleCount; } currentTimeEmission = 0; } // update particles for (int i = 0; i < particleCount; i++) { particles[i].updateParticle(dt, particles, particleCount); } }
public void updateParticle(float dt, SandParticle[] otherParticles, int aliveParticles) { // Update forces if (applyForce) { Fl = forceHit; applyForce = false; } else { Fl.Set(0, 0, 0); } // Integrate Velocities (Runge Kutta) a = evaluate(position, linearMomentum, angMomentum, 0, new Derivative()); b = evaluate(position, linearMomentum, angMomentum, dt * 0.5f, a); c = evaluate(position, linearMomentum, angMomentum, dt * 0.5f, b); d = evaluate(position, linearMomentum, angMomentum, dt, c); position = position + ((1.0f / 6.0f) * (a.dx + 2.0f * (b.dx + c.dx) + d.dx)) * dt; rotation = addQuaToQua(rotation, multiplyQuaByScalar((angVelocityQua * rotation), 0.5f * dt)); // collision and stuff collision(dt, otherParticles, aliveParticles); // Momentum linearMomentum = linearMomentum + ((1.0f / 6.0f) * (a.dm + 2.0f * (b.dm + c.dm) + d.dm)) * dt; //if (linearMomentum.magnitude < 0.001) //linearMomentum.Set(0, 0, 0); angMomentum = angMomentum + ((1.0f / 6.0f) * (a.dam + 2.0f * (b.dam + c.dam) + d.dam)) * dt; //if (angMomentum.magnitude < 0.001) //angMomentum.Set(0, 0, 0); // Velocity linearVelocity = linearMomentum / mass; angVelocity = Vector3.Scale(new Vector3(1.0f / inertiaTensor.x, 1.0f / inertiaTensor.y, 1.0f / inertiaTensor.z), angMomentum); angVelocityQua = new Quaternion(angVelocity.x, angVelocity.y, angVelocity.z, 0); // Natural Roll ? naturalRoll = (Mathf.Abs(linearVelocity.magnitude - (radius * angVelocity.magnitude)) < 0.1); }
void collision(float dt, SandParticle[] otherParticles, int aliveParticles) { Vector3 pos; float distance; float kn = 0.1f; float ys = 0.3f; float u = 0.05f; float ks = 20; penaltyFl.Set(0, 0, 0); penaltyFt.Set(0, 0, 0); //floorCollision = (transform.position.y <= 0.5); if (transform.position.y <= radius) { distance = Vector3.Distance(new Vector3(transform.position.x, 0, transform.position.z), transform.position); Vector3 N = Vector3.Normalize(new Vector3(transform.position.x, 0, transform.position.z) - transform.position); Vector3 relativeVelocity = linearVelocity; float e = radius - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(60 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } for (int i = 0; i < aliveParticles; ++i) { pos = otherParticles[i].position; distance = Vector3.Distance(pos, transform.position); if (distance <= radius + 0.5f) { Vector3 N = Vector3.Normalize(pos - transform.position); Vector3 relativeVelocity = linearVelocity - otherParticles[i].linearVelocity; float e = (radius + 0.5f) - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(kn * Mathf.Pow(e, 3 / 2) + ys * ep * Mathf.Pow(e, 1 / 2)) * N; Vector3 Ft = -Mathf.Min(u * Fn.magnitude, ks * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } } }
void collision(float dt, SandParticle[] otherParticles, int aliveParticles) { Vector3 pos; float distance; float kn = 60; float ys = 3; float u = 0.05f; float ks = 20; penaltyFl.Set(0, 0, 0); penaltyFt.Set(0, 0, 0); //floorCollision = (transform.position.y <= 0.5); if (position.y <= radius) { distance = Vector3.Distance(new Vector3(position.x, 0, position.z), position); Vector3 N = Vector3.Normalize(new Vector3(position.x, 0, position.z) - position); Vector3 relativeVelocity = linearVelocity; float e = 0.5f - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(40 * Mathf.Pow(e, 3 / 2) + 10 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } // walls pos = GameObject.Find("Wall1").transform.position; distance = Vector3.Distance(new Vector3(pos.x, position.y, position.z), position); if (distance <= 1) { Vector3 N = Vector3.Normalize(new Vector3(pos.x, position.y, position.z) - position); Vector3 relativeVelocity = linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } pos = GameObject.Find("Wall2").transform.position; distance = Vector3.Distance(new Vector3(pos.x, position.y, position.z), position); if (distance <= 1) { Vector3 N = Vector3.Normalize(new Vector3(pos.x, position.y, position.z) - position); Vector3 relativeVelocity = linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } pos = GameObject.Find("Wall3").transform.position; distance = Vector3.Distance(new Vector3(position.x, position.y, pos.z), position); if (distance <= 1) { Vector3 N = Vector3.Normalize(new Vector3(position.x, position.y, pos.z) - position); Vector3 relativeVelocity = linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } pos = GameObject.Find("Wall4").transform.position; distance = Vector3.Distance(new Vector3(position.x, position.y, pos.z), position); if (distance <= 1) { Vector3 N = Vector3.Normalize(new Vector3(position.x, position.y, pos.z) - position); Vector3 relativeVelocity = linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; penaltyFl += Fn; } //obj collisions pos = GameObject.Find("Obj1").transform.position; distance = Vector3.Distance(pos, position); if (distance <= 8) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity; float e = 8 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 30 * ep * Mathf.Pow(e, 1 / 2)) * N; Fn += 0.7f * Vector3.Normalize(linearVelocity);//Add some value to affect the friction Vector3 Ft = -Mathf.Min(0.5f * Fn.magnitude, 100 * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } pos = GameObject.Find("Obj2").transform.position; distance = Vector3.Distance(pos, position); if (distance <= 5.5f) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity; float e = 5.5f - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 30 * ep * Mathf.Pow(e, 1 / 2)) * N; Fn += 0.7f * Vector3.Normalize(linearVelocity);//Add some value to affect the friction Vector3 Ft = -Mathf.Min(0.5f * Fn.magnitude, 100 * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } pos = GameObject.Find("Obj3").transform.position; distance = Vector3.Distance(pos, position); if (distance <= 4.5f) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity; float e = 4.5f - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(50 * Mathf.Pow(e, 3 / 2) + 30 * ep * Mathf.Pow(e, 1 / 2)) * N; Fn += 0.7f * Vector3.Normalize(linearVelocity);//Add some value to affect the friction Vector3 Ft = -Mathf.Min(0.5f * Fn.magnitude, 100 * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } // Sphere pos = GameObject.Find("Sphere").transform.position; distance = Vector3.Distance(pos, position); if (distance <= radius + 5 ) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity - GameObject.Find("Sphere").GetComponent<MetalSphere>().linearVelocity; float e = (radius + 5) - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(60 * Mathf.Pow(e, 3 / 2) + 60 * ep * Mathf.Pow(e, 1 / 2)) * N; Vector3 Ft = -Mathf.Min(u * Fn.magnitude, ks * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } // sphere objs for (int i = 1; i < 81; ++i) { pos = GameObject.Find("Sphere (" + i + ")").transform.position; distance = Vector3.Distance(pos, position); if (distance <= 2 * radius && distance != 0) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(60 * Mathf.Pow(e, 3 / 2) + 40 * ep * Mathf.Pow(e, 1 / 2)) * N; Vector3 Ft = -Mathf.Min(u * Fn.magnitude, ks * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } } for (int i = 0; i < aliveParticles; ++i) { pos = otherParticles[i].position; distance = Vector3.Distance(pos, position); if (distance <= 2*radius && distance != 0) { Vector3 N = Vector3.Normalize(pos - position); Vector3 relativeVelocity = linearVelocity - otherParticles[i].linearVelocity; float e = 1 - distance; float ep = Vector3.Dot(relativeVelocity, N); Vector3 tangentialVelocity = relativeVelocity - ep * N; Vector3 Fn = -(kn * Mathf.Pow(e, 3 / 2) + ys * ep * Mathf.Pow(e, 1 / 2)) * N; Vector3 Ft = -Mathf.Min(u * Fn.magnitude, ks * tangentialVelocity.magnitude) * Vector3.Cross(N / 2, tangentialVelocity).normalized; penaltyFl += Fn; //-(kn * Mathf.Pow(e, 3 / 2) - ys * penetrationRate1 * Mathf.Pow(e, 1 / 2)) * N; penaltyFt += Ft; // 0.3f * Vector3.Cross(new Vector3(0, -0.5f, 0), N / 2); } } }