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

📄 tube.cpp

📁 机甲指挥官2源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		m_vertices[6] = Stuff::Vector3D(0.0f, 0.0f, 1.0f);
		m_uvs.SetLength(7);
		m_uvs[0] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 0.0f);
		m_uvs[1] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 1.0f/6.0f);
		m_uvs[2] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 2.0f/6.0f);
		m_uvs[3] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 0.5f);
		m_uvs[4] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 4.0f/6.0f);
		m_uvs[5] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 5.0f/6.0f);
		m_uvs[6] = Stuff::Vector2DOf<Stuff::Scalar>(0.0f, 1.0f);
		break;
	}
}

//------------------------------------------------------------------------------
//
bool
	gosFX::Tube__Specification::CalculateUBias(bool adjust)
{
	Check_Object(this);

	//
	//----------------------------------
	// Calculate the worst case UV scale
	//----------------------------------
	//
	int max_index = m_maxProfileCount-1;
	Stuff::Scalar max_scale, min_scale;
Retry:
	m_pUSize.ExpensiveComputeRange(&min_scale, &max_scale);
	Stuff::Scalar lower = min_scale * max_index;
	if (lower > 0.0f)
		lower = 0.0f;
	Stuff::Scalar upper = max_scale * max_index;

	//
	//------------------------------------
	// Calculate the worst case UV offsets
	//------------------------------------
	//
	Stuff::Scalar max_offset, min_offset;
	m_pUOffset.ExpensiveComputeRange(&min_offset, &max_offset);
	lower += min_offset;
	upper += max_offset;
	if (upper - lower >= 198.0f)
	{
		if (!adjust)
			return false;
		lower = max_offset - min_offset;
		Stuff::Scalar scale = static_cast<Stuff::Scalar>(floor((198.0f-lower)/max_index));
		m_pUSize.m_ageCurve.SetCurve(scale);
		m_pUSize.m_seeded = false;
		goto Retry;
	}
	lower += 99.0f;
	if (lower < 0.0f)
	{
		m_UBias = static_cast<Stuff::Scalar>(floor(0.5f-lower));
		return true;
	}
	upper -= 99.0f;
	if (upper > 0.0f)
	{
		m_UBias = static_cast<Stuff::Scalar>(floor(0.5f-upper));
		return true;
	}
	m_UBias = 0.0f;
	return true;
}

//############################################################################
//############################  gosFX::Tube  ###############################
//############################################################################

gosFX::Tube::ClassData*
	gosFX::Tube::DefaultData = NULL;

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::InitializeClass()
{
	Verify(!DefaultData);
	Verify(gos_GetCurrentHeap() == Heap);
	DefaultData =
		new ClassData(
			TubeClassID,
			"gosFX::Tube",
			Effect::DefaultData,
			(Effect::Factory)&Make,
			(Specification::Factory)&Specification::Make
		);
	Register_Object(DefaultData);
}

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//------------------------------------------------------------------------------
//
gosFX::Tube::Tube(
	Specification *spec,
	unsigned flags
):
	Effect(DefaultData, spec, flags)
{
	Check_Pointer(this);
	Check_Object(spec);
	Verify(gos_GetCurrentHeap() == Heap);

	//
	//----------------------------------
	// Figure out how much space we need
	//----------------------------------
	//
	m_profiles.SetLength(spec->m_maxProfileCount);
	unsigned vertex_count = spec->m_vertices.GetLength();
	Verify(vertex_count < 8);
	unsigned index_count = (vertex_count - 1)*6;
	unsigned size =
		sizeof(Stuff::Point3D)
		 + sizeof(Stuff::RGBAColor)
		 + sizeof(Stuff::Vector2DOf<Stuff::Scalar>);
	size *= vertex_count*spec->m_maxProfileCount;
	size += sizeof(unsigned short)*(spec->m_maxProfileCount-1)*index_count;

	//
	//-----------------------
	// Allocate the tube mesh
	//-----------------------
	//
	gos_PushCurrentHeap(MidLevelRenderer::Heap);
	m_mesh =
		new MidLevelRenderer::MLRIndexedTriangleCloud(
			spec->m_maxProfileCount*(vertex_count-1)*2
		);
	Register_Object(m_mesh);
	gos_PopCurrentHeap();

	//
	//------------------------------------------------
	// Set up the data pointers into the channel block
	//------------------------------------------------
	//
	m_triangleCount = 0;
	m_vertexCount = 0;
	m_data.SetLength(size);
	m_P_vertices = Cast_Pointer(Stuff::Point3D*, &m_data[0]);
	size = spec->m_maxProfileCount*vertex_count*sizeof(Stuff::Point3D);
	m_P_colors = Cast_Pointer(Stuff::RGBAColor*, &m_data[size]);
	size += spec->m_maxProfileCount*vertex_count*sizeof(Stuff::RGBAColor);
	m_P_uvs = Cast_Pointer(Stuff::Vector2DOf<Stuff::Scalar>*, &m_data[size]);
	size += spec->m_maxProfileCount*vertex_count*sizeof(Stuff::Vector2DOf<Stuff::Scalar>);
	unsigned short *mesh_indices = Cast_Pointer(unsigned short*, &m_data[size]);
	m_mesh->SetData(
		&m_triangleCount,
		&m_vertexCount,
		mesh_indices,
		m_P_vertices,
		m_P_colors,
		m_P_uvs
	);
	BuildMesh(mesh_indices);

	//
	//-------------------------------
	// Set up an empty profile cloud
	//-------------------------------
	//
	m_activeProfileCount = 0;
	m_headProfile = -1;
	m_tailProfile = -1;
	m_birthAccumulator = 0.0f;
}

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::BuildMesh(unsigned short *indices)
{
	Check_Object(this);
	Check_Pointer(indices);

	//
	//--------------------------------------
	// Figure out the parameters of the mesh
	//--------------------------------------
	//
	Specification *spec = GetSpecification();
	Check_Object(spec);
	unsigned vertex_count = spec->m_vertices.GetLength();
	Verify(vertex_count < 8);

	//
	//-------------------------------------------------
	// Crosses are built different from everything else
	//-------------------------------------------------
	//
	if (spec->m_profileType != Specification::e_Cross)
	{
		for (unsigned short profile=0; profile<spec->m_maxProfileCount-1; ++profile)
		{
			unsigned short base = static_cast<short>(profile * vertex_count);
			for (unsigned short panel=0; panel<vertex_count-1; ++panel)
			{
				if (spec->m_insideOut)
				{
					*indices++ = static_cast<short>(base+panel+1);
					*indices++ = static_cast<short>(base+panel);
					*indices++ = static_cast<short>(base+panel+vertex_count+1);
					*indices++ = static_cast<short>(base+panel+vertex_count);
					*indices++ = static_cast<short>(base+panel+vertex_count+1);
					*indices++ = static_cast<short>(base+panel);
				}
				else
				{
					*indices++ = static_cast<short>(base+panel);
					*indices++ = static_cast<short>(base+panel+1);
					*indices++ = static_cast<short>(base+panel+vertex_count+1);
					*indices++ = static_cast<short>(base+panel+vertex_count+1);
					*indices++ = static_cast<short>(base+panel+vertex_count);
					*indices++ = static_cast<short>(base+panel);
				}
			}
		}
	}
	else
	{
		Verify(vertex_count==5);
		for (unsigned short profile=0; profile<spec->m_maxProfileCount-1; ++profile)
		{
			unsigned short base = static_cast<short>(profile * vertex_count);
			for (unsigned short panel=0; panel<4; ++panel)
			{
				if (spec->m_insideOut)
				{
					*indices++ = static_cast<short>(base+panel+1);
					*indices++ = base;
					*indices++ = static_cast<short>(base+panel+6);
					*indices++ = static_cast<short>(base+5);
					*indices++ = static_cast<short>(base+panel+6);
					*indices++ = base;
				}
				else
				{
					*indices++ = base;
					*indices++ = static_cast<short>(base+panel+1);
					*indices++ = static_cast<short>(base+panel+6);
					*indices++ = static_cast<short>(base+panel+6);
					*indices++ = static_cast<short>(base+5);
					*indices++ = base;
				}
			}
		}
	}
}

//------------------------------------------------------------------------------
//
gosFX::Tube::~Tube()
{
	Unregister_Object(m_mesh);
	delete m_mesh;
}

//------------------------------------------------------------------------------
//
gosFX::Tube*
	gosFX::Tube::Make(
		Specification *spec,
		unsigned flags
	)
{
	Check_Object(spec);

	gos_PushCurrentHeap(Heap);
	Tube *tube = new gosFX::Tube(spec, flags);
	gos_PopCurrentHeap();

	return tube;
}

//------------------------------------------------------------------------------
//
void
	gosFX::Tube::Start(ExecuteInfo *info)
{
	Check_Object(this);
	Check_Pointer(info);

	//
	//----------------------
	// Let effect initialize
	//----------------------
	//
	Effect::Start(info);

	//
	//--------------------------------------------------------------------------
	// If the effect is off, we will create two profiles.  If they effect is on,
	// we just keep doing what we do
	//--------------------------------------------------------------------------
	//
	m_birthAccumulator = 1.0f;
}

//------------------------------------------------------------------------------
//
bool gosFX::Tube::Execute(ExecuteInfo *info)
{
	Check_Object(this);
	Check_Object(info);

	//
	//----------------------------------------
	// If we aren't supposed to execute, don't
	//----------------------------------------
	//
	if (!IsExecuted())
		return false;

	//
	//----------------------------------------------------------------------
	// Update the head of the tube to the current location, then compute the
	// inverse transformation to keep all particles in their place of origin
	//----------------------------------------------------------------------
	//
	Stuff::LinearMatrix4D new_world_to_local;
	Stuff::LinearMatrix4D local_to_world;
	local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
	new_world_to_local.Invert(local_to_world);

	//
	//--------------------------
	// Figure out the birth rate
	//--------------------------
	//
	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_profilesPerSecond.ComputeValue(m_age, m_seed);
		Min_Clamp(new_life, 0.0f);
		m_birthAccumulator += dT * new_life;

		//
		//------------------------------------------------------------------
		// If it is time for a new child and there is room, move the head of
		// the tube and create the new profile, then clear out the integer
		// part of the accumulator - stacking up would look stupid
		//------------------------------------------------------------------
		//
		if (m_birthAccumulator >= 1.0f && m_activeProfileCount < spec->m_maxProfileCount)
		{
			if (!m_activeProfileCount)
			{
				m_headProfile = 1;
				m_tailProfile = spec->m_maxProfileCount-1;
				CreateNewProfile(0, local_to_world);
				m_activeProfileCount = 2;
			}
			else
			{
				m_profiles[m_headProfile].m_profileToWorld = local_to_world;
				if (++m_headProfile == spec->m_maxProfileCount)
					m_headProfile = 0;
			}
			CreateNewProfile(m_headProfile, local_to_world);
			m_birthAccumulator -= static_cast<Stuff::Scalar>(floor(m_birthAccumulator));
		}
		else
			m_profiles[m_headProfile].m_profileToWorld = local_to_world;
	}

	//
	//--------------------------------------------------------------------
	// If we don't have any profiles, just execute the children and return
	//--------------------------------------------------------------------
	//
	if (!m_activeProfileCount)
	{
		m_age = prev_age;
		return Effect::Execute(info);
	}

	//
	//----------------------------------
	// Deal with all the active profiles
	//----------------------------------
	//
	Stuff::ExtentBox box(Stuff::Point3D::Identity, Stuff::Point3D::Identity);
	int i = m_headProfile;
	int profile_count = 0;
	Verify(i >= 0);
	do
	{
		//
		//----------------------------------------------------------------------
		// Age and animate the profile.  If the profile should die, it becomes
		// the end of the tail
		//----------------------------------------------------------------------
		//
		Profile *profile = GetProfile(i);
		Check_Object(profile);
		Verify (profile->m_age < 1.0f);
		profile->m_age += dT*profile->m_ageRate;
		Stuff::Sphere bounds;
		if (!AnimateProfile(i, profile_count, new_world_to_local, info->m_time, &bounds))
		{
			m_tailProfile = i;
			break;
		}

		//
		//---------------------
		// Deal with the bounds
		//---------------------
		//

⌨️ 快捷键说明

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