⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tube.cpp

📁 机甲指挥官2源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		if (i == m_headProfile)
		{
			box.maxX = bounds.center.x + bounds.radius;
			box.minX = bounds.center.x - bounds.radius;
			box.maxY = bounds.center.y + bounds.radius;
			box.minY = bounds.center.y - bounds.radius;
			box.maxZ = bounds.center.z + bounds.radius;
			box.minZ = bounds.center.z - bounds.radius;
		}
		else
		{
			Stuff::ExtentBox local_box;
			local_box.maxX = bounds.center.x + bounds.radius;
			local_box.minX = bounds.center.x - bounds.radius;
			local_box.maxY = bounds.center.y + bounds.radius;
			local_box.minY = bounds.center.y - bounds.radius;
			local_box.maxZ = bounds.center.z + bounds.radius;
			local_box.minZ = bounds.center.z - bounds.radius;
			box.Union(box, local_box);
		}

		//
		//---------------------------------------------------------------------------
		// Move to the previous profile and wrap to the end of the list if necessary
		//---------------------------------------------------------------------------
		//
		++profile_count;
		if (--i < 0)
			i = spec->m_maxProfileCount-1;
	} while (i != m_tailProfile);
	m_activeProfileCount = profile_count;

	//
	//-----------------------------------------------
	// Put the age back and run the base effect stuff
	//-----------------------------------------------
	//
	m_age = prev_age;
	if (!Effect::Execute(info))
		return false;

	//
	//--------------------------------------------
	// Now, build a info->m_bounds around this box
	//--------------------------------------------
	//
	Verify(box.maxX >= box.minX);
	Verify(box.maxY >= box.minY);
	Verify(box.maxZ >= box.minZ);
	Stuff::OBB local_bounds = Stuff::OBB::Identity;
	local_bounds.axisExtents.x = 0.5f * (box.maxX - box.minX);
	local_bounds.axisExtents.y = 0.5f * (box.maxY - box.minY);
	local_bounds.axisExtents.z = 0.5f * (box.maxZ - box.minZ);
	local_bounds.localToParent(3,0) = box.minX + local_bounds.axisExtents.x;
	local_bounds.localToParent(3,1) = box.minY + local_bounds.axisExtents.y;
	local_bounds.localToParent(3,2) = box.minZ + local_bounds.axisExtents.z;
	local_bounds.sphereRadius = local_bounds.axisExtents.GetLength();
	Stuff::OBB parent_bounds;
	parent_bounds.Multiply(local_bounds, m_localToParent);
	info->m_bounds->Union(*info->m_bounds, parent_bounds);
	return true;
}

//------------------------------------------------------------------------------
//
void gosFX::Tube::Kill()
{
	Check_Object(this);

	//
	//-------------------------------------------------------------
	// Destroy all the profiles and set up an empty profile cloud
	//-------------------------------------------------------------
	//
	Specification *spec = GetSpecification();
	Check_Object(spec);
	if (m_activeProfileCount>0)
	{
		do
		{
			DestroyProfile(m_headProfile--);
			if (m_headProfile<0)
				m_headProfile = spec->m_maxProfileCount-1;
		} while (m_headProfile != m_tailProfile);
	}
	m_activeProfileCount = 0;
	m_headProfile = -1;
	m_tailProfile = -1;
	m_birthAccumulator = 0.0f;

	//
	//----------------------------------------
	// Now let the base effect handle stopping
	//----------------------------------------
	//
	Effect::Kill();
}

//------------------------------------------------------------------------------
//
bool gosFX::Tube::HasFinished()
{
	Check_Object(this);
	return Effect::HasFinished() && (m_activeProfileCount == 0);
}

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::CreateNewProfile(
		unsigned index,
		const Stuff::LinearMatrix4D &origin
	)
{
	Check_Object(this);
	Check_Object(&origin);

	//
	//----------------------------------------------------
	// Figure out the age and age rate of the new profile
	//----------------------------------------------------
	//
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Profile *profile = GetProfile(index);
	Check_Object(profile);
	profile->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);
	profile->m_seed = seed;
	Stuff::Scalar lifetime =
		spec->m_pLifeSpan.ComputeValue(m_age, seed);
	Min_Clamp(lifetime, 0.0333333f);
	profile->m_ageRate = 1.0f / lifetime;

	//
	//------------------------------------------------------------------
	// Establish the base position and figure out the direction of drift
	//------------------------------------------------------------------
	//
	profile->m_profileToWorld = origin;
	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;
	Stuff::Radian angle = pitch_min + Stuff::Random::GetFraction() * pitch_range;
	Stuff::SinCosPair xy(angle);
	profile->m_direction.x = (Stuff::Random::GetFraction() >= 0.5f) ? xy.sine : -xy.sine;
	profile->m_direction.y = 0.0f;
	profile->m_direction.z = xy.cosine;
	Check_Object(&profile->m_direction);
}

//------------------------------------------------------------------------------
//
bool
	gosFX::Tube::AnimateProfile(
		unsigned index,
		unsigned profile_index,
		const Stuff::LinearMatrix4D &world_to_new_local,
		Stuff::Time till,
		Stuff::Sphere *bounds
	)
{
	Check_Object(this);

	//
	//----------------------------------------------------
	// If the profile gets too old, don't do anything else
	//----------------------------------------------------
	//
	Profile *profile = GetProfile(index);
	Check_Object(profile);
	Stuff::Scalar age = profile->m_age;
	if (age >= 1.0f)
		return false;

	//
	//--------------------------------------------------------------------
	// Figure out the scale and displacement of the profile in world space
	//--------------------------------------------------------------------
	//
	Set_Statistic(Profile_Count, Profile_Count+1);
	Stuff::Scalar seed = profile->m_seed;
	Specification *spec = GetSpecification();
	Check_Object(spec);
	Stuff::Scalar scale = spec->m_pScale.ComputeValue(age, seed);
	Verify(scale >= 0.0f);
	Stuff::Scalar disp = spec->m_pDisplacement.ComputeValue(age, seed);
	Stuff::Point3D offset;
	offset.Multiply(profile->m_direction, disp);

	//
	//-------------------------------------------------
	// Now build the template to new local space matrix
	//-------------------------------------------------
	//
	Stuff::AffineMatrix4D template_to_profile(true);
	template_to_profile(0,0) = scale;
	template_to_profile(1,1) = scale;
	template_to_profile(2,2) = scale;
	template_to_profile.BuildTranslation(offset);
	Stuff::AffineMatrix4D template_to_world;
	template_to_world.Multiply(template_to_profile, profile->m_profileToWorld);
	Stuff::AffineMatrix4D template_to_new_local;
	template_to_new_local.Multiply(template_to_world, world_to_new_local);
	bounds->center = template_to_new_local;
	bounds->radius = scale;

	//
	//------------------------------------------------------------------------
	// Now we just multiply the template through to the vertices unless we are
	// doing the aligned ribbon
	//------------------------------------------------------------------------
	//
	unsigned i;
	unsigned vertex_count = spec->m_vertices.GetLength();
	Verify(vertex_count < 8);
	unsigned vertex_index = profile_index * vertex_count;
	if (spec->m_profileType != Specification::e_AlignedRibbon)
	{
		Check_Pointer(m_P_vertices);
		for (i=0; i<vertex_count; ++i)
		{
			m_P_vertices[vertex_index+i].Multiply(
				spec->m_vertices[i],
				template_to_new_local
			);
		}
	}

	//
	//------------------------------
	// Figure out the UV adjustments
	//------------------------------
	//
	Check_Pointer(m_P_uvs);
	Stuff::Scalar u = spec->m_pUOffset.ComputeValue(age, seed);
	Stuff::Scalar v = spec->m_pVOffset.ComputeValue(age, seed);
	Stuff::Scalar u2 = spec->m_pUSize.ComputeValue(age, seed);
	Stuff::Scalar v2 = spec->m_pVSize.ComputeValue(age, seed);
	u += u2*profile_index + spec->m_UBias;
	for (i=0; i<vertex_count; ++i)
	{
		m_P_uvs[vertex_index+i].x = u;
		m_P_uvs[vertex_index+i].y = spec->m_uvs[i].y*v2 + v;
	}

	//
	//---------------------------
	// Lastly, animate the colors
	//---------------------------
	//
	Check_Pointer(m_P_colors);
	Stuff::RGBAColor color;
	color.red = spec->m_pRed.ComputeValue(age, seed);
	color.green = spec->m_pGreen.ComputeValue(age, seed);
	color.blue = spec->m_pBlue.ComputeValue(age, seed);
	color.alpha = spec->m_pAlpha.ComputeValue(age, seed);
	for (i=0; i<vertex_count; ++i)
		m_P_colors[vertex_index+i] = color;
	return true;
}

//------------------------------------------------------------------------------
//
void gosFX::Tube::DestroyProfile(unsigned index)
{
	Profile *profile = GetProfile(index);
	Check_Object(profile);
	profile->m_age = 1.0f;
}

//------------------------------------------------------------------------------
//
void gosFX::Tube::Draw(DrawInfo *info)
{
	Check_Object(this);
	Check_Object(info);

	//
	//---------------------------------------------------------
	// If we have active particles, set up the draw information
	//---------------------------------------------------------
	//
	if (m_activeProfileCount>1)
	{
		MidLevelRenderer::DrawEffectInformation dInfo;
		dInfo.effect = m_mesh;
		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;
		unsigned vertex_count = spec->m_vertices.GetLength();
		m_vertexCount = m_activeProfileCount * vertex_count;
		m_triangleCount = 2 * (m_activeProfileCount-1) * (vertex_count-1);

		//
		//-------------------------------------------------------------------
		// If we are doing the aligned ribbon, we will have to orient each of
		// the profiles and then compute its vertex positions accordingly
		//-------------------------------------------------------------------
		//
		if (spec->m_profileType == Specification::e_AlignedRibbon)
		{
			int i = m_headProfile;
			int vertex = 0;
			unsigned vertex_count = spec->m_vertices.GetLength();
			Verify(vertex_count < 8);
			Stuff::Point3D
				camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
			Stuff::LinearMatrix4D world_to_local;
			world_to_local.Invert(local_to_world);

			//
			//----------------------------------------------------------------
			// go thru all the profiles and figure out where they are in local
			// space
			//----------------------------------------------------------------
			//
			Verify(i >= 0);
			do
			{
				Profile *profile = GetProfile(i);
				Check_Object(profile);
				Stuff::Point3D camera_in_profile;
				camera_in_profile.MultiplyByInverse(camera_in_world, profile->m_profileToWorld);

				//
				//---------------------------------------------------------
				// Figure out the scale and displacement of the template in
				// profile space
				//---------------------------------------------------------
				//
				Stuff::Scalar age = profile->m_age;
				Stuff::Scalar seed = profile->m_seed;
				Stuff::Scalar scale = spec->m_pScale.ComputeValue(age, seed);
				Stuff::Scalar disp = spec->m_pDisplacement.ComputeValue(age, seed);
				Stuff::Point3D offset_in_profile;
				offset_in_profile.Multiply(profile->m_direction, disp);

				//
				//----------------------------------------------------------
				// Figure out the direction that we want the profile to face
				// and build a rotation vector that does it
				//----------------------------------------------------------
				//
				Stuff::Vector3D direction;
				direction.Subtract(camera_in_profile, offset_in_profile);
				Stuff::LinearMatrix4D template_rotation(true);
				template_rotation.AlignLocalAxisToWorldVector(
					direction,
					Stuff::Z_Axis,
					Stuff::Y_Axis,
					-1
				);

				//
				//-------------------------------------------------
				// Now build the template to new local space matrix
				//-------------------------------------------------
				//
				Stuff::AffineMatrix4D template_to_profile;
				template_to_profile(0,0) = scale*template_rotation(0,0);
				template_to_profile(0,1) = scale*template_rotation(0,1);
				template_to_profile(0,2) = scale*template_rotation(0,2);
				template_to_profile(1,0) = scale*template_rotation(1,0);
				template_to_profile(1,1) = scale*template_rotation(1,1);
				template_to_profile(1,2) = scale*template_rotation(1,2);
				template_to_profile(2,0) = scale*template_rotation(2,0);
				template_to_profile(2,1) = scale*template_rotation(2,1);
				template_to_profile(2,2) = scale*template_rotation(2,2);
				template_to_profile.BuildTranslation(offset_in_profile);
				Stuff::AffineMatrix4D template_to_world;
				template_to_world.Multiply(template_to_profile, profile->m_profileToWorld);
				Stuff::AffineMatrix4D template_to_local;
				template_to_local.Multiply(template_to_world, world_to_local);

				//
				//------------------------------------
				// Multiply the points thru the matrix
				//------------------------------------
				//
				for (int v=0; v<vertex_count; ++v)
				{
					m_P_vertices[vertex++].Multiply(
						spec->m_vertices[v],
						template_to_local
					);
				}

				//
				//---------------------------------------------------------------------------
				// Move to the previous profile and wrap to the end of the list if necessary
				//---------------------------------------------------------------------------
				//
				if (--i < 0)
					i = spec->m_maxProfileCount-1;
			} while (i != m_tailProfile);
		}

		//
		//--------------------
		// Now draw the effect
		//--------------------
		//
	 	info->m_clipper->DrawEffect(&dInfo);
	}

	Effect::Draw(info);
}

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -