//------------------------------------------------------------------------------
//
bool
	gosFX::ShapeCloud::AnimateParticle(
		unsigned index,
		const Stuff::LinearMatrix4D *world_to_new_local,
		Stuff::Time till
	)
{
	Check_Object(this);

	//
	//-----------------------------------------
	// Animate the parent then get our pointers
	//-----------------------------------------
	//
	if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till))
		return false;
	Set_Statistic(Shape_Count, Shape_Count+1);
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Particle *particle = GetParticle(index);
	Check_Object(particle);
	Stuff::Scalar seed = particle->m_seed;
	Stuff::Scalar age = particle->m_age;

	//
	//------------------
	// Animate the color
	//------------------
	//
	particle->m_color.red = spec->m_pRed.ComputeValue(age, seed);
	particle->m_color.green = spec->m_pGreen.ComputeValue(age, seed);
	particle->m_color.blue = spec->m_pBlue.ComputeValue(age, seed);
	particle->m_color.alpha = spec->m_pAlpha.ComputeValue(age, seed);
	return true;
}
//------------------------------------------------------------------------------
//
void gosFX::CardCloud::CreateNewParticle(uint32_t index, Stuff::Point3D* translation)
{
	// Check_Object(this);
	//
	//-------------------------------------------------------------------
	// Let our parent do creation, then turn on the particle in the cloud
	//-------------------------------------------------------------------
	//
	SpinningCloud::CreateNewParticle(index, translation);
	m_cloudImplementation->TurnOn(index);
	_ASSERT(m_cloudImplementation->IsOn(index));
	//
	//-----------------------------
	// Figure out the particle size
	//-----------------------------
	//
	Specification* spec = GetSpecification();
	Check_Object(spec);
	Particle* particle = GetParticle(index);
	Check_Object(particle);
	particle->m_halfY = spec->m_halfHeight.ComputeValue(m_age, particle->m_seed);
	particle->m_halfX =
		particle->m_halfY * spec->m_aspectRatio.ComputeValue(m_age, particle->m_seed);
	particle->m_radius =
		Stuff::Sqrt(particle->m_halfX * particle->m_halfX + particle->m_halfY * particle->m_halfY);
}
Beispiel #3
0
//------------------------------------------------------------------------------
//
void
gosFX::Card::Start(ExecuteInfo *info)
{
    Check_Object(this);
    Check_Object(info);
    Singleton::Start(info);

    Specification *spec = GetSpecification();
    Check_Object(spec);
    m_halfY = spec->m_halfHeight.ComputeValue(m_age, m_seed);
    m_halfX = m_halfY * spec->m_aspectRatio.ComputeValue(m_age, m_seed);
    m_radius = Stuff::Sqrt(m_halfX * m_halfX + m_halfY * m_halfY);
    m_cardCloud->TurnOn(0);
}
//------------------------------------------------------------------------------
//
void gosFX::PointCloud::Draw(DrawInfo* info)
{
	Check_Object(this);
	Check_Object(info);
	if(m_activeParticleCount)
	{
		MidLevelRenderer::DrawEffectInformation dInfo;
		dInfo.effect = m_cloudImplementation;
		Specification* spec = GetSpecification();
		Check_Object(spec);
		dInfo.state.Combine(info->m_state, spec->m_state);
		dInfo.clippingFlags = info->m_clippingFlags;
		Stuff::LinearMatrix4D local_to_world;
		local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
		dInfo.effectToWorld = &local_to_world;
		info->m_clipper->DrawEffect(&dInfo);
	}
	ParticleCloud::Draw(info);
}
Beispiel #5
0
//------------------------------------------------------------------------------
//
void
	gosFX::ParticleCloud::Start(ExecuteInfo *info)
{
	Check_Object(this);
	Check_Pointer(info);

	//
	//--------------------------------------------------------------------------
	// Let effect initialize, then figure out how many particles we want to make
	//--------------------------------------------------------------------------
	//
	Effect::Start(info);
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Stuff::Scalar newbies =
		spec->m_startingPopulation.ComputeValue(m_age, m_seed);
	Min_Clamp(newbies, 0.0f);
	m_birthAccumulator += newbies;
}
//------------------------------------------------------------------------------
//
void
	gosFX::ShapeCloud::CreateNewParticle(
		unsigned index,
		Stuff::Point3D *translation
	)
{
	Check_Object(this);

	//
	//-------------------------------------------------------------------
	// Let our parent do creation, then turn on the particle in the cloud
	//-------------------------------------------------------------------
	//
	SpinningCloud::CreateNewParticle(index, translation);
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Particle *particle = GetParticle(index);
	Check_Object(particle);
	particle->m_radius = spec->m_radius;
}
//------------------------------------------------------------------------------
//
void gosFX::ShapeCloud::Draw(DrawInfo *info)
{
	Check_Object(this);
	Check_Object(info);
	Check_Object(info->m_parentToWorld);

	//
	//----------------------------
	// Set up the common draw info
	//----------------------------
	//
	if (m_activeParticleCount)
	{
		MidLevelRenderer::DrawScalableShapeInformation dinfo;
		MidLevelRenderer::MLRShape *shape = GetSpecification()->m_shape;
		dinfo.clippingFlags.SetClippingState(0x3f);
		dinfo.worldToShape = NULL;
		Specification *spec = GetSpecification();
		Check_Object(spec);
		dinfo.state.Combine(info->m_state, spec->m_state);
		dinfo.activeLights = NULL;
		dinfo.nrOfActiveLights = 0;
		dinfo.shape = shape;
		Stuff::LinearMatrix4D local_to_world;
		local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);

		//
		//--------------------------------------------------------------
		// Check the orientation mode.  The first case is XY orientation
		//--------------------------------------------------------------
		//
		unsigned i;
		if (spec->m_alignZUsingX)
		{
			if (spec->m_alignZUsingY)
			{
				//
				//-----------------------------------------
				// Get the camera location into local space
				//-----------------------------------------
				//
				Stuff::Point3D
					camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
				Stuff::Point3D camera_in_cloud;
				camera_in_cloud.MultiplyByInverse(
					camera_in_world,
					local_to_world
				);
				for (unsigned i = 0; i < m_activeParticleCount; i++)
				{
					Particle *particle = GetParticle(i);
					Check_Object(particle);

					//
					//-----------------------------------------------------------------
					// If the particle is still alive, concatenate into world space and
					// issue the draw command
					//-----------------------------------------------------------------
					//
					if (particle->m_age < 1.0f)
					{
						Stuff::Vector3D direction_in_cloud;
						direction_in_cloud.Subtract(
							camera_in_cloud,
							particle->m_localTranslation
						);
						Stuff::LinearMatrix4D shape_to_cloud;
						shape_to_cloud.BuildRotation(particle->m_localRotation);
						shape_to_cloud.AlignLocalAxisToWorldVector(
							direction_in_cloud,
							Stuff::Z_Axis,
							Stuff::Y_Axis,
							Stuff::X_Axis
						);
						shape_to_cloud.BuildTranslation(particle->m_localTranslation);
						Stuff::LinearMatrix4D shape_to_world;
						shape_to_world.Multiply(
							shape_to_cloud,
							local_to_world
						);
						dinfo.shapeToWorld = &shape_to_world;
						Stuff::Vector3D
							scale(
								particle->m_scale,
								particle->m_scale,
								particle->m_scale
							);
						dinfo.scaling = &scale;
						dinfo.paintMe = &particle->m_color;
		 				info->m_clipper->DrawScalableShape(&dinfo);
						//magic 28112011 begin
						dinfo.shapeToWorld = NULL;
						dinfo.scaling = NULL;
						//magic 28112011 end
					}
				}
			}

			//
			//-----------------------
			// Handle X-only rotation
			//-----------------------
			//
			else
			{
				//
				//-----------------------------------------
				// Get the camera location into local space
				//-----------------------------------------
				//
				Stuff::Point3D
					camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
				Stuff::Point3D camera_in_cloud;
				camera_in_cloud.MultiplyByInverse(
					camera_in_world,
					local_to_world
				);
				for (unsigned i = 0; i < m_activeParticleCount; i++)
				{
					Particle *particle = GetParticle(i);
					Check_Object(particle);

					//
					//-----------------------------------------------------------------
					// If the particle is still alive, concatenate into world space and
					// issue the draw command
					//-----------------------------------------------------------------
					//
					if (particle->m_age < 1.0f)
					{
						Stuff::Vector3D direction_in_cloud;
						direction_in_cloud.Subtract(
							camera_in_cloud,
							particle->m_localTranslation
						);
						Stuff::LinearMatrix4D shape_to_cloud;
						shape_to_cloud.BuildRotation(particle->m_localRotation);
						shape_to_cloud.AlignLocalAxisToWorldVector(
							direction_in_cloud,
							Stuff::Z_Axis,
							Stuff::X_Axis,
							-1
						);
						shape_to_cloud.BuildTranslation(particle->m_localTranslation);
						Stuff::LinearMatrix4D shape_to_world;
						shape_to_world.Multiply(
							shape_to_cloud,
							local_to_world
						);
						dinfo.shapeToWorld = &shape_to_world;
						Stuff::Vector3D
							scale(
								particle->m_scale,
								particle->m_scale,
								particle->m_scale
							);
						dinfo.scaling = &scale;
						dinfo.paintMe = &particle->m_color;
		 				info->m_clipper->DrawScalableShape(&dinfo);
						//magic 28112011 begin
						dinfo.shapeToWorld = NULL;
						dinfo.scaling = NULL;
						//magic 28112011 end
					}
				}
			}
		}

		//
		//-------------------------------------------------------
		// Each matrix needs to be aligned to the camera around Y
		//-------------------------------------------------------
		//
		else if (spec->m_alignZUsingY)
		{
			//
			//-----------------------------------------
			// Get the camera location into local space
			//-----------------------------------------
			//
			Stuff::Point3D
				camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
			Stuff::Point3D camera_in_cloud;
			camera_in_cloud.MultiplyByInverse(
				camera_in_world,
				local_to_world
			);
			for (unsigned i = 0; i < m_activeParticleCount; i++)
			{
				Particle *particle = GetParticle(i);
				Check_Object(particle);

				//
				//-----------------------------------------------------------------
				// If the particle is still alive, concatenate into world space and
				// issue the draw command
				//-----------------------------------------------------------------
				//
				if (particle->m_age < 1.0f)
				{
					Stuff::Vector3D direction_in_cloud;
					direction_in_cloud.Subtract(
						camera_in_cloud,
						particle->m_localTranslation
					);
					Stuff::LinearMatrix4D shape_to_cloud;
					shape_to_cloud.BuildRotation(particle->m_localRotation);
					shape_to_cloud.AlignLocalAxisToWorldVector(
						direction_in_cloud,
						Stuff::Z_Axis,
						Stuff::Y_Axis,
						-1
					);
					shape_to_cloud.BuildTranslation(particle->m_localTranslation);
					Stuff::LinearMatrix4D shape_to_world;
					shape_to_world.Multiply(
						shape_to_cloud,
						local_to_world
					);
					dinfo.shapeToWorld = &shape_to_world;
					Stuff::Vector3D
						scale(
							particle->m_scale,
							particle->m_scale,
							particle->m_scale
						);
					dinfo.scaling = &scale;
					dinfo.paintMe = &particle->m_color;
		 			info->m_clipper->DrawScalableShape(&dinfo);
						//magic 28112011 begin
						dinfo.shapeToWorld = NULL;
						dinfo.scaling = NULL;
						//magic 28112011 end
				}
			}
		}

		//
		//---------------------------------------------------------------
		// No alignment is necessary, so just multiply out all the active
		// particles
		//---------------------------------------------------------------
		//
		else
		{
			for (i=0; i < m_activeParticleCount; i++)
			{
				Particle *particle = GetParticle(i);
				Check_Object(particle);

				//
				//-----------------------------------------------------------------
				// If the particle is still alive, concatenate into world space and
				// issue the draw command
				//-----------------------------------------------------------------
				//
				if (particle->m_age < 1.0f)
				{
					Stuff::LinearMatrix4D shape_to_cloud;
					shape_to_cloud.BuildTranslation(particle->m_localTranslation);
					shape_to_cloud.BuildRotation(particle->m_localRotation);
					Stuff::LinearMatrix4D shape_to_world;
					shape_to_world.Multiply(
						shape_to_cloud,
						local_to_world
					);
					dinfo.shapeToWorld = &shape_to_world;
					Stuff::Vector3D
						scale(
							particle->m_scale,
							particle->m_scale,
							particle->m_scale
						);
					dinfo.scaling = &scale;
					dinfo.paintMe = &particle->m_color;
		 			info->m_clipper->DrawScalableShape(&dinfo);
						//magic 28112011 begin
						dinfo.shapeToWorld = NULL;
						dinfo.scaling = NULL;
						//magic 28112011 end
				}
			}
		}
	}

	//
	//----------------------------
	// Let our parent do its thing
	//----------------------------
	//
	SpinningCloud::Draw(info);
}
//------------------------------------------------------------------------------
//
bool
gosFX::PointCloud::AnimateParticle(
	uint32_t index,
	const Stuff::LinearMatrix4D* world_to_new_local,
	Stuff::Time till
)
{
	Check_Object(this);
	//
	//-----------------------------------------------------------------------
	// If this cloud is unparented, we need to transform the point from local
	// space into world space and set the internal position/velocity pointers
	// to these temporary values
	//-----------------------------------------------------------------------
	//
	Particle* particle = GetParticle(index);
	Check_Object(particle);
	float age = particle->m_age;
	if(age >= 1.0f)
		return false;
	Set_Statistic(Point_Count, Point_Count + 1);
	Stuff::Vector3D* velocity = &particle->m_localLinearVelocity;
	Stuff::Point3D* translation = &m_P_localTranslation[index];
	int32_t sim_mode = GetSimulationMode();
	if(sim_mode == DynamicWorldSpaceSimulationMode)
	{
		Check_Object(translation);
		Check_Object(velocity);
		particle->m_worldLinearVelocity.Multiply(*velocity, m_localToWorld);
		particle->m_worldTranslation.Multiply(*translation, m_localToWorld);
		translation = &particle->m_worldTranslation;
		velocity = &particle->m_worldLinearVelocity;
	}
	Check_Object(translation);
	Check_Object(velocity);
	//
	//------------------------------------------------------------------
	// First, calculate the drag on the particle.  Drag can never assist
	// velocity
	//------------------------------------------------------------------
	//
	float seed = particle->m_seed;
	Specification* spec = GetSpecification();
	Check_Object(spec);
	Stuff::Vector3D ether;
	ether.x = spec->m_pEtherVelocityX.ComputeValue(age, seed);
	ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed);
	ether.z = spec->m_pEtherVelocityZ.ComputeValue(age, seed);
	Stuff::Vector3D accel(Stuff::Vector3D::Identity);
	//
	//-------------------------------------------------------------------
	// Deal with pseudo-world simulation.  In this mode, we interpret the
	// forces as if they are already in worldspace, and we transform them
	// back to local space
	//-------------------------------------------------------------------
	//
	float drag = -spec->m_pDrag.ComputeValue(age, seed);
	Max_Clamp(drag, 0.0f);
	if(sim_mode == StaticWorldSpaceSimulationMode)
	{
		Stuff::LinearMatrix4D world_to_effect;
		world_to_effect.Invert(m_localToWorld);
		Stuff::Vector3D local_ether;
		local_ether.MultiplyByInverse(ether, world_to_effect);
		Stuff::Vector3D rel_vel;
		rel_vel.Subtract(*velocity, local_ether);
		accel.Multiply(rel_vel, drag);
		//
		//-----------------------------------------
		// Now, add in acceleration of the particle
		//-----------------------------------------
		//
		Stuff::Vector3D world_accel;
		world_accel.x = spec->m_pAccelerationX.ComputeValue(age, seed);
		world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed);
		world_accel.z = spec->m_pAccelerationZ.ComputeValue(age, seed);
		Stuff::Vector3D local_accel;
		local_accel.Multiply(world_accel, world_to_effect);
		accel += local_accel;
	}
	//
	//----------------------------------------------------------------------
	// Otherwise, just add the forces in the same space the particles are in
	//----------------------------------------------------------------------
	//
	else
	{
		Stuff::Vector3D rel_vel;
		rel_vel.Subtract(*velocity, ether);
		accel.Multiply(rel_vel, drag);
		//
		//-----------------------------------------
		// Now, add in acceleration of the particle
		//-----------------------------------------
		//
		accel.x += spec->m_pAccelerationX.ComputeValue(age, seed);
		accel.y += spec->m_pAccelerationY.ComputeValue(age, seed);
		accel.z += spec->m_pAccelerationZ.ComputeValue(age, seed);
	}
	//
	//-------------------------------------------------
	// Compute the particle's new velocity and position
	//-------------------------------------------------
	//
	float time_slice =
		static_cast<float>(till - m_lastRan);
	velocity->AddScaled(*velocity, accel, time_slice);
	translation->AddScaled(*translation, *velocity, time_slice);
	//
	//---------------------------------------------------------------------
	// If we are unparented, we need to transform the velocity and position
	// data back into the NEW local space
	//---------------------------------------------------------------------
	//
	if(sim_mode == DynamicWorldSpaceSimulationMode)
	{
		Check_Object(world_to_new_local);
		particle->m_localLinearVelocity.Multiply(
			particle->m_worldLinearVelocity,
			*world_to_new_local
		);
		m_P_localTranslation[index].Multiply(
			particle->m_worldTranslation,
			*world_to_new_local
		);
	}
	//
	//------------------
	// Animate the color
	//------------------
	//
	Check_Pointer(m_P_color);
	m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed);
	m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed);
	m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed);
	m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed);
	return true;
}
//------------------------------------------------------------------------------
//
void gosFX::CardCloud::Draw(DrawInfo* info)
{
	// Check_Object(this);
	Check_Object(info);
	//
	//---------------------------------------------------------
	// If we have active particles, set up the draw information
	//---------------------------------------------------------
	//
	if (m_activeParticleCount)
	{
		MidLevelRenderer::DrawEffectInformation dInfo;
		dInfo.effect		= m_cloudImplementation;
		Specification* spec = GetSpecification();
		Check_Object(spec);
		dInfo.state.Combine(info->m_state, spec->m_state);
		dInfo.clippingFlags = info->m_clippingFlags;
		Stuff::LinearMatrix4D local_to_world;
		local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
		dInfo.effectToWorld = &local_to_world;
		//
		//--------------------------------------------------------------
		// Check the orientation mode.  The first case is XY orientation
		//--------------------------------------------------------------
		//
		uint32_t i;
		uint32_t vert = 0;
		if (spec->m_alignZUsingX)
		{
			if (spec->m_alignZUsingY)
			{
				//
				//-----------------------------------------
				// Get the camera location into local space
				//-----------------------------------------
				//
				Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
				Stuff::Point3D camera_in_cloud;
				camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world);
				//
				//--------------------------------------
				// Spin through all the active particles
				//--------------------------------------
				//
				for (i = 0; i < m_activeParticleCount; i++)
				{
					Particle* particle = GetParticle(i);
					Check_Object(particle);
					if (particle->m_age < 1.0f)
					{
						//
						//--------------------------------
						// Build the local to cloud matrix
						//--------------------------------
						//
						Stuff::Vector3D direction_in_cloud;
						direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation);
						Stuff::LinearMatrix4D card_to_cloud;
						card_to_cloud.BuildRotation(particle->m_localRotation);
						card_to_cloud.AlignLocalAxisToWorldVector(
							direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, Stuff::X_Axis);
						card_to_cloud.BuildTranslation(particle->m_localTranslation);
						//
						//-------------------------------------------------
						// Figure out the scale, then build the four points
						//-------------------------------------------------
						//
						float scale = particle->m_scale;
						m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX,
														  -scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
														  -scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
														  scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX,
														  scale * particle->m_halfY, 0.0f),
							card_to_cloud);
					}
					else
						vert += 4;
				}
			}
			//
			//-----------------------
			// Handle X-only rotation
			//-----------------------
			//
			else
			{
				//
				//-----------------------------------------
				// Get the camera location into local space
				//-----------------------------------------
				//
				Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
				Stuff::Point3D camera_in_cloud;
				camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world);
				//
				//--------------------------------------
				// Spin through all the active particles
				//--------------------------------------
				//
				for (i = 0; i < m_activeParticleCount; i++)
				{
					Particle* particle = GetParticle(i);
					Check_Object(particle);
					if (particle->m_age < 1.0f)
					{
						//
						//--------------------------------
						// Build the local to cloud matrix
						//--------------------------------
						//
						Stuff::Vector3D direction_in_cloud;
						direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation);
						Stuff::LinearMatrix4D card_to_cloud;
						card_to_cloud.BuildRotation(particle->m_localRotation);
						card_to_cloud.AlignLocalAxisToWorldVector(
							direction_in_cloud, Stuff::Z_Axis, Stuff::X_Axis, -1);
						card_to_cloud.BuildTranslation(particle->m_localTranslation);
						//
						//-------------------------------------------------
						// Figure out the scale, then build the four points
						//-------------------------------------------------
						//
						float scale = particle->m_scale;
						m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX,
														  -scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
														  -scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
														  scale * particle->m_halfY, 0.0f),
							card_to_cloud);
						m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX,
														  scale * particle->m_halfY, 0.0f),
							card_to_cloud);
					}
					else
						vert += 4;
				}
			}
		}
		//
		//-------------------------------------------------------
		// Each matrix needs to be aligned to the camera around Y
		//-------------------------------------------------------
		//
		else if (spec->m_alignZUsingY)
		{
			//
			//-----------------------------------------
			// Get the camera location into local space
			//-----------------------------------------
			//
			Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
			Stuff::Point3D camera_in_cloud;
			camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world);
			//
			//--------------------------------------
			// Spin through all the active particles
			//--------------------------------------
			//
			for (i = 0; i < m_activeParticleCount; i++)
			{
				Particle* particle = GetParticle(i);
				Check_Object(particle);
				if (particle->m_age < 1.0f)
				{
					//
					//--------------------------------
					// Build the local to cloud matrix
					//--------------------------------
					//
					Stuff::Vector3D direction_in_cloud;
					direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation);
					Stuff::LinearMatrix4D card_to_cloud;
					card_to_cloud.BuildRotation(particle->m_localRotation);
					card_to_cloud.AlignLocalAxisToWorldVector(
						direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, -1);
					card_to_cloud.BuildTranslation(particle->m_localTranslation);
					//
					//-------------------------------------------------
					// Figure out the scale, then build the four points
					//-------------------------------------------------
					//
					float scale = particle->m_scale;
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
													  -scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f),
						card_to_cloud);
				}
				else
					vert += 4;
			}
		}
		//
		//---------------------------------------------------------------
		// No alignment is necessary, so just multiply out all the active
		// particles
		//---------------------------------------------------------------
		//
		else
		{
			for (i = 0; i < m_activeParticleCount; i++)
			{
				Particle* particle = GetParticle(i);
				Check_Object(particle);
				if (particle->m_age < 1.0f)
				{
					//
					//--------------------------------
					// Build the local to cloud matrix
					//--------------------------------
					//
					Stuff::LinearMatrix4D card_to_cloud;
					card_to_cloud.BuildRotation(particle->m_localRotation);
					card_to_cloud.BuildTranslation(particle->m_localTranslation);
					//
					//-------------------------------------------------
					// Figure out the scale, then build the four points
					//-------------------------------------------------
					//
					float scale = particle->m_scale;
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX,
													  -scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f),
						card_to_cloud);
					m_P_vertices[vert++].Multiply(
						Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f),
						card_to_cloud);
				}
				else
					vert += 4;
			}
		}
		//
		//---------------------
		// Now just do the draw
		//---------------------
		//
		info->m_clipper->DrawEffect(&dInfo);
	}
	SpinningCloud::Draw(info);
}
//------------------------------------------------------------------------------
//
bool gosFX::CardCloud::AnimateParticle(
	uint32_t index, const Stuff::LinearMatrix4D* world_to_new_local, Stuff::Time till)
{
	// Check_Object(this);
	//
	//-----------------------------------------
	// Animate the parent then get our pointers
	//-----------------------------------------
	//
	if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till))
		return false;
	Set_Statistic(Card_Count, Card_Count + 1);
	Specification* spec = GetSpecification();
	Check_Object(spec);
	Particle* particle = GetParticle(index);
	Check_Object(particle);
	float seed = particle->m_seed;
	float age  = particle->m_age;
	//
	//------------------
	// Animate the color
	//------------------
	//
	Check_Pointer(m_P_color);
	m_P_color[index].red   = spec->m_pRed.ComputeValue(age, seed);
	m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed);
	m_P_color[index].blue  = spec->m_pBlue.ComputeValue(age, seed);
	m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed);
	//
	//----------------
	// Animate the uvs
	//----------------
	//
	float u  = spec->m_UOffset.ComputeValue(age, seed);
	float v  = spec->m_VOffset.ComputeValue(age, seed);
	float u2 = spec->m_USize.ComputeValue(age, seed);
	float v2 = spec->m_VSize.ComputeValue(age, seed);
	//
	//--------------------------------------------------------------
	// If we are animated, figure out the row/column to be displayed
	//--------------------------------------------------------------
	//
	if (spec->m_animated)
	{
		uint8_t columns = Stuff::Truncate_Float_To_Byte(spec->m_pIndex.ComputeValue(age, seed));
		uint8_t rows	= static_cast<uint8_t>(columns / spec->m_width);
		columns			= static_cast<uint8_t>(columns - rows * spec->m_width);
		//
		//---------------------------
		// Now compute the end points
		//---------------------------
		//
		u += u2 * columns;
		v += v2 * rows;
	}
	u2 += u;
	v2 += v;
	index *= 4;
	m_P_uvs[index].x   = u;
	m_P_uvs[index].y   = v2;
	m_P_uvs[++index].x = u2;
	m_P_uvs[index].y   = v2;
	m_P_uvs[++index].x = u2;
	m_P_uvs[index].y   = v;
	m_P_uvs[++index].x = u;
	m_P_uvs[index].y   = v;
	return true;
}
Beispiel #11
0
//------------------------------------------------------------------------------
//
void
	gosFX::ParticleCloud::CreateNewParticle(
		unsigned index,
		Stuff::Point3D *translation
	)
{
	Check_Object(this);

	//
	//----------------------------------------------------
	// Figure out the age and age rate of the new particle
	//----------------------------------------------------
	//
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Particle *particle = GetParticle(index);
	Check_Object(particle);
	particle->m_age = 0.0f;
	Stuff::Scalar min_seed =
		spec->m_minimumChildSeed.ComputeValue(m_age, m_seed);
	Stuff::Scalar seed_range =
		spec->m_maximumChildSeed.ComputeValue(m_age, m_seed) - min_seed;
	Stuff::Scalar seed =
		Stuff::Random::GetFraction()*seed_range + min_seed;
	Clamp(seed, 0.0f, 1.0f);
	particle->m_seed = seed;
	Stuff::Scalar lifetime =
		spec->m_pLifeSpan.ComputeValue(m_age, seed);
	Min_Clamp(lifetime, 0.0333333f);
	particle->m_ageRate = 1.0f / lifetime;

	//
	//--------------------------------
	// Figure out the initial position
	//--------------------------------
	//
	Stuff::YawPitchRange
		initial_p(
			Stuff::Random::GetFraction() * Stuff::Two_Pi,
			Stuff::Random::GetFraction() * Stuff::Pi - Stuff::Pi_Over_2,
			Stuff::Random::GetFraction()
		);
	Stuff::Vector3D position(initial_p);
	translation->x =
		position.x * spec->m_emitterSizeX.ComputeValue(m_age, seed);
	translation->y =
		position.y * spec->m_emitterSizeY.ComputeValue(m_age, seed);
	translation->z =
		position.z * spec->m_emitterSizeZ.ComputeValue(m_age, seed);

	//
	//--------------------------------
	// Figure out the initial velocity
	//--------------------------------
	//
	Stuff::Scalar pitch_min =
		spec->m_minimumDeviation.ComputeValue(m_age, seed);
	Stuff::Scalar pitch_range =
		spec->m_maximumDeviation.ComputeValue(m_age, seed) - pitch_min;
	if (pitch_range < 0.0f)
		pitch_range = 0.0f;
	pitch_min +=
		pitch_range * Stuff::Random::GetFraction() - Stuff::Pi_Over_2;
	Stuff::YawPitchRange
		initial_v(
			Stuff::Random::GetFraction() * Stuff::Two_Pi,
			pitch_min,
			spec->m_startingSpeed.ComputeValue(m_age, seed)
		);
	particle->m_localLinearVelocity = initial_v;
}
Beispiel #12
0
//------------------------------------------------------------------------------
//
bool gosFX::ParticleCloud::Execute(ExecuteInfo *info)
{
	Check_Object(this);
	Check_Object(info);
	Verify(IsExecuted());

	//
	//--------------------------------------------------------------------
	// If we were given a new matrix, see if we have a parent.  If so,
	// concatenate the two and figure out its inverse.  If no parent, then
	// just invert the new matrix, otherwise just use the existing one
	//--------------------------------------------------------------------
	//
	Stuff::LinearMatrix4D new_world_to_local;
	Stuff::LinearMatrix4D *matrix = NULL;
	int sim_mode = GetSimulationMode();
	if (sim_mode == DynamicWorldSpaceSimulationMode)
	{
		Stuff::LinearMatrix4D local_to_world;
		local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
		new_world_to_local.Invert(local_to_world);
		matrix = &new_world_to_local;
	}

	//
	//--------------------------------------------------------
	// Figure out the birth rate and request the new particles
	//--------------------------------------------------------
	//
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Stuff::Scalar dT =
		static_cast<Stuff::Scalar>(info->m_time - m_lastRan);
	Verify(dT >= 0.0f);
	Stuff::Scalar prev_age = m_age;
	m_age += dT * m_ageRate;
	if (m_age >= 1.0f)
		m_birthAccumulator = 0.0f;
	else
	{
		Stuff::Scalar new_life =
			spec->m_particlesPerSecond.ComputeValue(m_age, m_seed);
		Min_Clamp(new_life, 0.0f);
		m_birthAccumulator += dT * new_life;
	}

	//
	//-----------------------------------
	// Deal with all the active particles
	//-----------------------------------
	//
	int i;
	int last_real = -1;
	for (i = 0; i < m_activeParticleCount; i++)
	{
		//
		//--------------------------------------------------------------------
		// If the particle is active, age it and if it is not yet time to die,
		// go to the next particle, otherwise kill it
		//--------------------------------------------------------------------
		//
		Particle *particle = GetParticle(i);
		Check_Object(particle);
		if (particle->m_age < 1.0f)
		{
			particle->m_age += dT*particle->m_ageRate;
			if (AnimateParticle(i, matrix, info->m_time))
			{
				last_real = i;
				continue;
			}
			DestroyParticle(i);
		}

		//
		//--------------------------------------------------------------------
		// If there are new particles to be born, go ahead and create them now
		//--------------------------------------------------------------------
		//
		if (m_birthAccumulator >= 1.0f)
		{
			Stuff::Point3D translation;
			CreateNewParticle(i, &translation);
			if (AnimateParticle(i, matrix, info->m_time))
				last_real = i;
			else
				DestroyParticle(i);
			m_birthAccumulator -= 1.0f;
		}
	}
	m_activeParticleCount = last_real + 1;

	//
	//----------------------------------------------------------------------
	// If there are still new particles to be born, then we must try to grow
	// the active particle count
	//----------------------------------------------------------------------
	//
	while (
		m_birthAccumulator >= 1.0f
		 && m_activeParticleCount < spec->m_maxParticleCount
	)
	{
		i = m_activeParticleCount++;
		Stuff::Point3D translation;
		CreateNewParticle(i, &translation);
		if (!AnimateParticle(i, matrix, info->m_time))
		{
			DestroyParticle(i);
			--m_activeParticleCount;
		}
		m_birthAccumulator -= 1.0f;
	}

	//
	//---------------------------------------------------------
	// Only allow fractional births to carry over to next frame
	//---------------------------------------------------------
	//
	m_birthAccumulator -= static_cast<Stuff::Scalar>(floor(m_birthAccumulator));

	//
	//----------------------------
	// Now let effect do its thing
	//----------------------------
	//
	m_age = prev_age;
	return Effect::Execute(info);
}
Beispiel #13
0
//------------------------------------------------------------------------------
//
void gosFX::Shape::Draw(DrawInfo *info)
{
	Check_Object(this);
	Check_Object(info);
	Check_Object(info->m_parentToWorld);

	//
	//----------------------------
	// Set up the common draw info
	//----------------------------
	//
	MidLevelRenderer::DrawScalableShapeInformation dinfo;
	MidLevelRenderer::MLRShape *shape = GetSpecification()->m_shape;
	dinfo.clippingFlags.SetClippingState(0x3f);
	dinfo.worldToShape = NULL;
	Specification *spec = GetSpecification();
	Check_Object(spec);
	dinfo.state.Combine(info->m_state, spec->m_state);
	dinfo.activeLights = NULL;
	dinfo.nrOfActiveLights = 0;
	dinfo.shape = shape;
	Stuff::Vector3D scale(m_scale, m_scale, m_scale);
	dinfo.scaling = &scale;
	dinfo.paintMe = &m_color;
	Stuff::LinearMatrix4D local_to_world;
	local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
	dinfo.shapeToWorld = &local_to_world;

	//
	//--------------------------------------------------------------
	// Check the orientation mode.  The first case is XY orientation
	//--------------------------------------------------------------
	//
	if (spec->m_alignZUsingX)
	{
		Stuff::Point3D
			camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
		Stuff::Point3D card_in_world(local_to_world);
		Stuff::Vector3D look_at;
		look_at.Subtract(camera_in_world, card_in_world);
		if (spec->m_alignZUsingY)
			local_to_world.AlignLocalAxisToWorldVector(
				look_at,
				Stuff::Z_Axis,
				Stuff::Y_Axis,
				Stuff::X_Axis
			);
		else
			local_to_world.AlignLocalAxisToWorldVector(
				look_at,
				Stuff::Z_Axis,
				Stuff::X_Axis,
				-1
			);
	}

	//
	//-------------------------------------------------------
	// Each matrix needs to be aligned to the camera around Y
	//-------------------------------------------------------
	//
	else if (spec->m_alignZUsingY)
	{
		Stuff::Point3D
			camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
		Stuff::Point3D card_in_world(local_to_world);
		Stuff::Vector3D look_at;
		look_at.Subtract(camera_in_world, card_in_world);
		local_to_world.AlignLocalAxisToWorldVector(
			look_at,
			Stuff::Z_Axis,
			Stuff::Y_Axis,
			-1
		);
	}

	//
	//----------------------------
	// Let our parent do its thing
	//----------------------------
	//
	info->m_clipper->DrawScalableShape(&dinfo);
	Singleton::Draw(info);
}
Beispiel #14
0
//------------------------------------------------------------------------------
//
void gosFX::Card::Draw(DrawInfo *info)
{
    Check_Object(this);
    Check_Object(info);

    //
    //----------------------------
    // Set up the common draw info
    //----------------------------
    //
    MidLevelRenderer::DrawEffectInformation dInfo;
    dInfo.effect = m_cardCloud;
    Specification *spec = GetSpecification();
    Check_Object(spec);
    dInfo.state.Combine(info->m_state, spec->m_state);
    dInfo.clippingFlags = info->m_clippingFlags;
    Stuff::LinearMatrix4D local_to_world;
    local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
    dInfo.effectToWorld = &local_to_world;

    //
    //--------------------------------------------------------------
    // Check the orientation mode.  The first case is XY orientation
    //--------------------------------------------------------------
    //
    if (spec->m_alignZUsingX)
    {
        Stuff::Point3D
        camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
        Stuff::Point3D card_in_world(local_to_world);
        Stuff::Vector3D look_at;
        look_at.Subtract(camera_in_world, card_in_world);
        if (spec->m_alignZUsingY)
            local_to_world.AlignLocalAxisToWorldVector(
                look_at,
                Stuff::Z_Axis,
                Stuff::Y_Axis,
                Stuff::X_Axis
            );
        else
            local_to_world.AlignLocalAxisToWorldVector(
                look_at,
                Stuff::Z_Axis,
                Stuff::X_Axis,
                -1
            );
    }

    //
    //-------------------------------------------------------
    // Each matrix needs to be aligned to the camera around Y
    //-------------------------------------------------------
    //
    else if (spec->m_alignZUsingY)
    {
        Stuff::Point3D
        camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
        Stuff::Point3D card_in_world(local_to_world);
        Stuff::Vector3D look_at;
        look_at.Subtract(camera_in_world, card_in_world);
        local_to_world.AlignLocalAxisToWorldVector(
            look_at,
            Stuff::Z_Axis,
            Stuff::Y_Axis,
            -1
        );
    }

    //
    //---------------------
    // Now just do the draw
    //---------------------
    //
    info->m_clipper->DrawEffect(&dInfo);
    Singleton::Draw(info);
}
Beispiel #15
0
//------------------------------------------------------------------------------
//
bool
gosFX::Card::Execute(ExecuteInfo *info)
{
    Check_Object(this);
    Check_Object(info);

    if (!IsExecuted())
        return false;

    //
    //------------------------
    // Do the effect animation
    //------------------------
    //
    if (!Singleton::Execute(info))
        return false;

    //
    //-----------------------------------------
    // Animate the parent then get our pointers
    //-----------------------------------------
    //
    Set_Statistic(Card_Count, Card_Count+1);
    Specification *spec = GetSpecification();
    Check_Object(spec);

    //
    //----------------
    // Animate the uvs
    //----------------
    //
    Stuff::Scalar u = spec->m_UOffset.ComputeValue(m_age, m_seed);
    Stuff::Scalar v = spec->m_VOffset.ComputeValue(m_age, m_seed);
    Stuff::Scalar u2 = spec->m_USize.ComputeValue(m_age, m_seed);
    Stuff::Scalar v2 = spec->m_VSize.ComputeValue(m_age, m_seed);

    //
    //--------------------------------------------------------------
    // If we are animated, figure out the row/column to be displayed
    //--------------------------------------------------------------
    //
    if (spec->m_animated)
    {
        BYTE columns =
            Stuff::Truncate_Float_To_Byte(
                spec->m_index.ComputeValue(m_age, m_seed)
            );
        BYTE rows = static_cast<BYTE>(columns / spec->m_width);
        columns = static_cast<BYTE>(columns - rows*spec->m_width);

        //
        //---------------------------
        // Now compute the end points
        //---------------------------
        //
        u += u2*columns;
        v += v2*rows;
    }
    u2 += u;
    v2 += v;

    m_uvs[0].x = u;
    m_uvs[0].y = v2;
    m_uvs[1].x = u2;
    m_uvs[1].y = v2;
    m_uvs[2].x = u2;
    m_uvs[2].y = v;
    m_uvs[3].x = u;
    m_uvs[3].y = v;

    //
    //------------------
    // Fill in the color
    //------------------
    //
    m_colors[0] = m_color;
    m_colors[1] = m_color;
    m_colors[2] = m_color;
    m_colors[3] = m_color;

    //
    //---------------------
    // Fill in the position
    //---------------------
    //
    m_vertices[0].x = m_scale*m_halfX;
    m_vertices[0].y = -m_scale*m_halfY;
    m_vertices[0].z = 0.0f;

    m_vertices[1].x = -m_scale*m_halfX;
    m_vertices[1].y = -m_scale*m_halfY;
    m_vertices[1].z = 0.0f;

    m_vertices[2].x = -m_scale*m_halfX;
    m_vertices[2].y = m_scale*m_halfY;
    m_vertices[2].z = 0.0f;

    m_vertices[3].x = m_scale*m_halfX;
    m_vertices[3].y = m_scale*m_halfY;
    m_vertices[3].z = 0.0f;

    return true;
}