/**
 *	This method generates the vectors for CylinderVectorGenerator.
 *
 *	@param	vector	Vector to be over-written with the new vector.
 */
void CylinderVectorGenerator::generate( Vector3 &vector ) const
{
	BW_GUARD;
	// Get a point along the axis of the cylinder.
	vector = origin_ + unitRand() * direction_;

    // Make sure that the radii are sorted:
    float minR = minRadius_;
    float maxR = maxRadius_;
    if (minR > maxR) 
        std::swap(minR, maxR);

    // Choosing points in a disc uniformly is not as easy as you may first
    // think.  Choosing the angle and radius randomly gives a distribution
    // concentrated at the center.  A correct formula is given by:
    //    http://mathworld.wolfram.com/DiskPointPicking.html
    // Here we adjust for the fact that we are not on the unit disc, but on
    // an annulus.  To do this we convert the radius range from 
    // [minRadius_, maxRadius] to [alpha, 1.0] where 
    // alpha = minRadius_/maxRadius_, do the sqrt random distribution and
    // then convert back to the range [minRadius_, maxRadius].
    float angle = unitRand() * 2.0f * MATH_PI;
    float r;
    if (minR == maxR) // handle case where radii are equal (or both zero)
    {
        r = minR;
    }
    else
    {        
        float alpha = minR/maxR;
        float k1    = std::sqrtf( unitRand() * ( 1.0f - alpha ) + minR );
        r  = Math::lerp( k1, alpha, 1.0f, minR, maxR );
    }
    vector += r * ( std::cosf( angle ) * basisU_ + std::sinf( angle ) * basisV_ );
}
예제 #2
0
 void DenseMatrix<Complex> :: randomize( void )
 // replaces entries with uniformly distributed real random numbers in the interval [-1,1]
 {
    for( int i = 0; i < m*n; i++ )
    {
       data[i].re = 2.*unitRand() - 1.;
       data[i].im = 2.*unitRand() - 1.;
    }
 }
예제 #3
0
 void DenseMatrix<Quaternion> :: randomize( void )
 // replaces entries with uniformly distributed real random numbers in the interval [-1,1]
 {
    for( int i = 0; i < m*n; i++ )
    {
       for( int k = 0; k < 4; k++ )
       {
          data[i][k] = 2.*unitRand() - 1.;
       }
    }
 }
/**
 *	This method generates the vectors for SphereVectorGenerator.
 *
 *	@param	vector	Vector to be over-written with the new vector.
 */
void SphereVectorGenerator::generate( Vector3 &vector ) const
{
	// Generate a random point on the unit sphere
    // (based upon http://mathworld.wolfram.com/SpherePointPicking.html):
    float theta  = 2.0f * MATH_PI * unitRand();
    float phi    = std::acosf( 2.0f * unitRand() - 1.0f );
    float sinphi = std::sinf( phi );
    float x      = std::cosf( theta ) * sinphi;
    float y      = std::sinf( theta ) * sinphi;
    float z      = std::cosf( phi );
    vector       = Vector3(x, y, z);

    // Make sure that the radii are sorted:
    float minR = minRadius_;
    float maxR = maxRadius_;
    if (minR > maxR) 
        std::swap(minR, maxR);

    // Choose a random radius, taking into account that spherical shells
    // go as r^2 dr (integrate to give the volume of the shell and then
    // bias the choice of radius based upon that).
    float r;
    if (minR == maxR) // handle case where radii are equal (or both zero)
    {
        r = minR;
    }
    else
    {
        float alpha = minR / maxR;
        float k1    = std::powf( unitRand() * ( 1.0f - alpha ) + minR , 1.0f/3.0f);
        r           = Math::lerp( k1, alpha, 1.0f, minR, maxR );
    }

	// Scale the point to the sphere we want and move it into position.
	vector = r*vector + centre_;
}
/**
 *	This method executes the action for the given frame of time. The dTime
 *	parameter is the time elapsed since the last call.
 *
 *	@param particleSystem	The particle system on which to operate.
 *	@param dTime			Elapsed time in seconds.
 */
void CollidePSA::execute( ParticleSystem &particleSystem, float dTime )
{
	BW_GUARD;
	SourcePSA* pSource = static_cast<SourcePSA*>( &*particleSystem.pAction( PSA_SOURCE_TYPE_ID ) );

	if ( !pSource )
		return;

	RompColliderPtr pGS = pSource->groundSpecifier();
	if ( !pGS )
		return;

	uint64	tend = timestamp() + stampsPerSecond() / 2000;

	bool soundHit = false;
	float maxVelocity = 0;
	Vector3 soundPos;
	uint materialKind;

	Particles::iterator it = particleSystem.begin();
	Particles::iterator end = particleSystem.end();

	WorldTriangle tri;

	//bust out of the loop if we take more than 0.5 msec

	//Sprite particles don't calculate spin
	while ( it != end && timestamp()<tend )
	{
		Particle &particle = *it++;

		if (!particle.isAlive())
		{		
			continue;
		}

		//note - particles get moved after actions.
		Vector3 velocity;
		particle.getVelocity(velocity);
		Vector3 pos;
		Vector3 newPos;

		if(particleSystem.isLocal())
		{
			Matrix world = particleSystem.worldTransform();
			pos = world.applyPoint(particle.position());
			Vector3 nPos;
			particleSystem.predictPosition( particle, dTime, nPos );
			newPos = world.applyPoint(nPos);
		}
		else
		{
			pos = particle.position();
			particleSystem.predictPosition( particle, dTime, newPos );
		}


		float tValue = pGS->collide( pos, newPos, tri );
		if ( tValue >= 0.f && tValue <= 1.f )
		{
			// calc v as a dotprod of the two normalised vectors (before and after collision)
			Vector3 oldVel = velocity / velocity.length();
			tri.bounce( velocity, elasticity_ );
			particle.setVelocity( velocity );
			float newSpeed = velocity.length();
			Vector3 newVel(velocity / newSpeed);
			float severity = oldVel.dotProduct(newVel);
			//DEBUG_MSG("severity: %1.3f, speed=%1.3f\n", severity, newSpeed);
			float v = (1 - severity) * newSpeed;

			//now spin the particle ( mesh only )
			if ( !spriteBased_ )
			{
				//first, calculate the current rotation, and update the pitch/yaw value.
				Matrix currentRot;
				currentRot.setRotate( particle.yaw(), particle.pitch(), 0.f );
				Matrix spin;
                float spinSpeed = particle.meshSpinSpeed();
                Vector3 meshSpinAxis = particle.meshSpinAxis();
                // If there is no spin direction then creating a rotation 
                // matrix can create weird matrices - e.g. matrices with
                // negative scale components and a translation.  We choose the
                // velocity as the spin direction (aribitrarily choosing, for
                // example up looks weird).
                if (meshSpinAxis == Vector3::zero())
                {
                    meshSpinAxis = velocity;
                    meshSpinAxis.normalise();
                }
				
				D3DXMatrixRotationAxis
                ( 
                    &spin, 
                    &meshSpinAxis, 
                    spinSpeed * (particle.age()-particle.meshSpinAge()) 
                );
				
				currentRot.preMultiply( spin );		
				particle.pitch( currentRot.pitch() );
				particle.yaw( currentRot.yaw() );

				//now, reset the age of the spin 
				particle.meshSpinAge( particle.age() );

				//finally, update the spin ( stored in the particle's colour )
				float addedSpin = unitRand() * (maxAddedRotation_-minAddedRotation_) + minAddedRotation_;
				addedSpin *= min( newSpeed, 1.f );				
				spinSpeed = Math::clamp( 0.f, spinSpeed + addedSpin, 1.f );
                particle.meshSpinSpeed(spinSpeed);
                particle.meshSpinAxis(meshSpinAxis);
			}

			if ( soundEnabled_ && v > 0.5f )
			{
				soundHit = true;
				if (v > maxVelocity) {
					maxVelocity = v;
					soundPos = particle.position();
					materialKind = tri.materialKind();
				}
			}
		}
	}

	if ( soundHit )
	{
		SmartPointer < RompSound > rs = RompSound::getProvider();
		if (rs)
		{
			if (!soundTag_.empty())
			{
				rs->playParticleSound( soundTag_.c_str(), soundPos, maxVelocity, soundSrcIdx_, materialKind );
			}
		}
	}
}
/**
 *	This method generates the vectors for BoxVectorGenerator.
 *
 *	@param	vector	Vector to be over-written with the new vector.
 */
void BoxVectorGenerator::generate( Vector3 &vector ) const
{
	vector.set( corner_.x + unitRand() * ( opposite_.x - corner_.x ),
		corner_.y + unitRand() * ( opposite_.y - corner_.y ),
		corner_.z + unitRand() * ( opposite_.z - corner_.z ) );
}
예제 #7
0
/**
 *	This function returns a uniform random number in the input range.
 */
inline float randInRange( float min, float max )
{
	return min + unitRand() * (max - min);
}