void getEdge(int p, int q, double* X, int N, int D, double* ts, int* e1, int* e2, double* ed, double eps) {
	double dpq = sqrt(getSqrDist(X, N, D, p, q));
	double tp = ts[p];
	double tq = ts[q];
	double alpha;
	
	//SEE SHEEHY PAGE 8
	if (tq < tp) {
		//Make sure tp indexes the earlier of the two death times
		double temp = tq;
		tq = tp;
		tp = temp;
	}
	//Case a (no warping has occurred yet)
	if (dpq < tp*(1-2*eps)) {
		*e1 = p;
		*e2 = q;
		*ed = dpq;
		return;
	}
	//Case b: alpha is between (1-2eps)tp and tp but is less than (1-2eps)tq
	alpha = 2*dpq - (1-2*eps)*tp;
	if (alpha >= (1-2*eps)*tp && alpha <= tp && alpha <= (1-2*eps)*tq) {
		*e1 = p;
		*e2 = q;
		*ed = alpha;
		return;
	}
	
	//Otherwise, it's never added
	*e1 = -1;
	*e2 = -1;
}
Example #2
0
	bool Sphere::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
	{
		float r2 = radius * radius;
		float dist0 = getSqrDist(getTransformedPosition(),v0);
		float dist1 = getSqrDist(getTransformedPosition(),v1);

		if ((dist0 <= r2) == (dist1 <= r2))
			return false;

		if (intersection != NULL)
		{
			Vector3D vDir = v1 - v0;
			float norm = vDir.getNorm();

			float d = dotProduct(vDir,getTransformedPosition() - v0) / norm;
			float a = std::sqrt(r2 - dist0 + d * d);

			float ti;
			if (dist0 <= r2)
				ti = d - a;
			else
				ti = d + a;

			ti /= norm;

			if (ti < 0.0f) ti = 0.0f;
			if (ti > 1.0f) ti = 1.0f;

			norm *= ti;
			ti = norm < APPROXIMATION_VALUE ? 0.0f : ti * (norm - APPROXIMATION_VALUE) / norm;

			vDir *= ti;
			*intersection = v0 + vDir;

			if (normal != NULL)
			{
				if (dist0 <= r2)
					*normal = getTransformedPosition() - *intersection;
				else
					*normal = *intersection - getTransformedPosition();
				normal->normalize();
			}
		}

		return true;
	}
Example #3
0
	void Collider::modify(Group& group,DataSet* dataSet,float deltaTime) const
	{
		float groupSqrRadius = group.getPhysicalRadius() * group.getPhysicalRadius();
		SPK_ASSERT(group.getOctree() != NULL,"GLQuadRenderer::render(const Group&,const DataSet*,RenderBuffer*) - renderBuffer must not be NULL");
		const Octree& octree = *group.getOctree();

		for (GroupIterator particleIt0(group); !particleIt0.end(); ++particleIt0)
		{
			Particle& particle0 = *particleIt0;
			float radius0 = particle0.getParam(PARAM_SCALE);
			float m0 = particle0.getParam(PARAM_MASS);

			size_t index0 = particle0.getIndex();

			const Octree::Array<size_t>& neighborCells = octree.getNeighborCells(index0);
			size_t nbCells = neighborCells.size();

			for (size_t i = 0; i < nbCells; ++i) // For each neighboring cell in the octree
			{
				const Octree::Cell& cell = octree.getCell(neighborCells[i]);
				size_t nbParticleInCells = cell.particles.size();

				for (size_t j = 0; j < nbParticleInCells; ++j) // for each particles in the cell
				{
					size_t index1 = cell.particles[j];
					if (index1 >= index0)
						break; // as particle are ordered

					Particle particle1 = group.getParticle(index1);
					float radius1 = particle1.getParam(PARAM_SCALE);

					float sqrRadius = radius0 + radius1;
					sqrRadius *= sqrRadius * groupSqrRadius;

					// Gets the normal of the collision plane
					Vector3D normal = particle0.position() - particle1.position();
					float sqrDist = normal.getSqrNorm();

					if (sqrDist < sqrRadius) // particles are intersecting each other
					{
						Vector3D delta = particle0.velocity() - particle1.velocity();

						if (dotProduct(normal,delta) < 0.0f) // particles are moving towards each other
						{
							float oldSqrDist = getSqrDist(particle0.oldPosition(),particle1.oldPosition());
							if (oldSqrDist > sqrDist)
							{
								// Disables the move from this frame
								particle0.position() = particle0.oldPosition();
								particle1.position() = particle1.oldPosition();

								normal = particle0.position() - particle1.position();

								if (dotProduct(normal,delta) >= 0.0f)
									continue;
							}

							normal.normalize();

							// Gets the normal components of the velocities
							Vector3D normal0 = normal * dotProduct(normal,particle0.velocity());
							Vector3D normal1 = normal * dotProduct(normal,particle1.velocity());

							// Resolves collision
							float m1 = particle1.getParam(PARAM_MASS);

							if (oldSqrDist < sqrRadius && sqrDist < sqrRadius)
							{
								// Tweak to separate particles that intersects at both t - deltaTime and t
								// In that case the collision is no more considered as punctual
								if (dotProduct(normal,normal0) < 0.0f)
								{
									particle0.velocity() -= normal0;
									particle1.velocity() += normal0;
								}

								if (dotProduct(normal,normal1) > 0.0f)
								{
									particle1.velocity() -= normal1;
									particle0.velocity() += normal1;
								}
							}
							else
							{
								// Else classic collision equations are applied
								// Tangent components of the velocities are left untouched
								float elasticityM0 = elasticity * m0;
								float elasticityM1 = elasticity * m1;
								float invM01 = 1 / (m0 + m1);

								particle0.velocity() -= (1.0f + (elasticityM1 - m0) * invM01) * normal0;
								particle1.velocity() -= (1.0f + (elasticityM0 - m1) * invM01) * normal1;

								normal0 *= (elasticityM0 + m0) * invM01;
								normal1 *= (elasticityM1 + m0) * invM01;

								particle0.velocity() += normal1;
								particle1.velocity() += normal0;
							}
						}
					}
				}
			}
		}
	}
Example #4
0
	bool Group::updateParticles(float deltaTime)
	{
		// Prepares the additionnal data
		prepareAdditionnalData();

		size_t nbAutoBorn = 0;
		size_t nbManualBorn = nbBufferedParticles;

		// Checks the number of born particles
		bool hasAliveEmitters = false;
		activeEmitters.clear();

		for (std::vector<Ref<Emitter> >::const_iterator it = emitters.begin(); it != emitters.end(); ++it)
			if ((*it)->isActive())
			{
				int nb = (*it)->updateTankFromTime(deltaTime);
				if (nb > 0)
				{
					activeEmitters.push_back(WeakEmitterPair(*it,nb));
					nbAutoBorn += nb;
				}

				hasAliveEmitters |= ((*it)->getCurrentTank() != 0); // An emitter with some particles in its tank is still potentially alive
			}

		size_t emitterIndex = 0;
		size_t nbBorn = nbAutoBorn + nbManualBorn;

		// Updates the age of the particles function of the delta time
		for (size_t i = 0; i < particleData.nbParticles; ++i)
			particleData.ages[i] += deltaTime;

		// Computes the energy of the particles (if they are not immortal)
		if (!immortal)
			for (size_t i = 0; i < particleData.nbParticles; ++i)
				particleData.energies[i] = 1.0f - particleData.ages[i] / particleData.lifeTimes[i];

		// Updates the position of particles function of their velocity
		if (!still)
			for (size_t i = 0; i < particleData.nbParticles; ++i)
			{
				particleData.oldPositions[i] = particleData.positions[i];
				particleData.positions[i] += particleData.velocities[i] * deltaTime;
			}

		// Interpolates the parameters
		if (colorInterpolator.obj)
			colorInterpolator.obj->interpolate(particleData.colors,*this,colorInterpolator.dataSet);
		for (size_t i = 0; i < nbEnabledParameters; ++i)
		{
			FloatInterpolatorDef& interpolator = paramInterpolators[enabledParamIndices[i]];
			interpolator.obj->interpolate(particleData.parameters[enabledParamIndices[i]],*this,interpolator.dataSet);
		}

		// Updates the octree if one
		if (octree != NULL)
			octree->update();

		// Modifies the particles with specific active modifiers behavior
		for (std::vector<WeakModifierDef>::const_iterator it = activeModifiers.begin(); it != activeModifiers.end(); ++it)
			it->obj->modify(*this,it->dataSet,deltaTime);

		// Updates the renderer data
		if (renderer.obj)
			renderer.obj->update(*this,renderer.dataSet);

		// Checks dead particles and reinits or swaps
		for (size_t i = 0; i < particleData.nbParticles; ++i)
			if (particleData.energies[i] <= 0.0f)
			{
				// Death action
				if (deathAction && deathAction->isActive())
				{
				    Particle particle = getParticle(i); // fix for gcc
					deathAction->apply(particle);
				}

				bool replaceDeadParticle = false;
				while (!replaceDeadParticle && nbBorn > 0)
				{
					if (initParticle(i,emitterIndex,nbManualBorn))
						replaceDeadParticle = true;
					--nbBorn;
				}

				if (!replaceDeadParticle)
				{
					swapParticles(i,particleData.nbParticles - 1);
					--particleData.nbParticles;
					--i; // As we need to test the swapped particle
				}
			}

		// Emits new particles if some left
		while (nbBorn > 0 && particleData.maxParticles - particleData.nbParticles > 0)
		{
			if (!initParticle(particleData.nbParticles++,emitterIndex,nbManualBorn))
				--particleData.nbParticles;
			--nbBorn;
		}

		// Computes the distance of particles from the camera
		if (distanceComputationEnabled)
		{
			for (size_t i = 0; i < particleData.nbParticles; ++i)
				particleData.sqrDists[i] = getSqrDist(particleData.positions[i],system->getCameraPosition());
		}

		emptyBufferedParticles();

		return hasAliveEmitters || particleData.nbParticles > 0;
	}
Example #5
0
	void Collision::modify(Particle& particle,float deltaTime) const
	{
		size_t index = particle.getIndex();
		float radius1 = particle.getParamCurrentValue(PARAM_SIZE) * scale * 0.5f;
		float m1 = particle.getParamCurrentValue(PARAM_MASS);
		Group& group = *particle.getGroup();

		// Tests collisions with all the particles that are stored before in the pool
		for (size_t i = 0; i < index; ++i)
		{
			Particle& particle2 = group.getParticle(i);
			float radius2 = particle2.getParamCurrentValue(PARAM_SIZE) * scale * 0.5f;				
			
			float sqrRadius = radius1 + radius2;
			sqrRadius *= sqrRadius;

			// Gets the normal of the collision plane
			vec3 normal = particle.position();
			normal -= particle2.position();
//			float sqrDist = normal.getSqrNorm();
			float sqrDist = glm::length2(normal);

			if (sqrDist < sqrRadius) // particles are intersecting each other
			{
				vec3 delta = particle.velocity();
				delta -= particle2.velocity();

				if (dotProduct(normal,delta) < 0.0f) // particles are moving towards each other
				{
					float oldSqrDist = getSqrDist(particle.oldPosition(),particle2.oldPosition());
					if (oldSqrDist > sqrDist)
					{
						// Disables the move from this frame
						particle.position() = particle.oldPosition();
						particle2.position() = particle2.oldPosition();

						normal = particle.position();
						normal -= particle2.position();

						if (dotProduct(normal,delta) >= 0.0f)
							continue;
					}

//					normal.normalize();
					normal = glm::normalize(normal);

					// Gets the normal components of the velocities
					vec3 normal1(normal);
					vec3 normal2(normal);
					normal1 *= dotProduct(normal,particle.velocity());
					normal2 *= dotProduct(normal,particle2.velocity());

					// Resolves collision
					float m2 = particle2.getParamCurrentValue(PARAM_MASS);

					if (oldSqrDist < sqrRadius && sqrDist < sqrRadius)
					{
						// Tweak to separate particles that intersects at both t - deltaTime and t
						// In that case the collision is no more considered as punctual
						if (dotProduct(normal,normal1) < 0.0f)
						{
							particle.velocity() -= normal1;
							particle2.velocity() += normal1;
						}

						if (dotProduct(normal,normal2) > 0.0f)
						{
							particle2.velocity() -= normal2;
							particle.velocity() += normal2;
						}
					}
					else
					{
						// Else classic collision equations are applied
						// Tangent components of the velocities are left untouched
						particle.velocity() -= (1.0f + (elasticity * m2 - m1) / (m1 + m2)) * normal1;
						particle2.velocity() -= (1.0f + (elasticity * m1 - m2) / (m1 + m2)) * normal2;

						normal1 *= ((1.0f + elasticity) * m1) / (m1 + m2);
						normal2 *= ((1.0f + elasticity) * m2) / (m1 + m2);

						particle.velocity() += normal2;
						particle2.velocity() += normal1;
					}
				}
			}
		}
	}
Example #6
0
	float getDist(const Vector3D& v0,const Vector3D& v1)
	{
		return std::sqrt(getSqrDist(v0,v1));
	}
Example #7
0
	bool Sphere::contains(const Vector3D& v) const
	{
		return getSqrDist(getTransformedPosition(),v) <= radius * radius;
	}
Example #8
0
	void Particle::computeSqrDist()
	{
		data->sqrDist = getSqrDist(position(),System::getCameraPosition());
	}