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

📄 m2loader.cpp

📁 3D游戏展示程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------
// 更新粒子系统
//----------------------------------------------------
void CM2Loader::UpdatePaticle(void)
{
	if(!m_bHasParticle)
		return;
	if(m_LastTime != 0)
	{
		DWORD dt = g_GlobalTime - m_LastTime;
		for(uint32 i=0; i<m_Header.nParticleEmitters; i++)
		{
			m_pParticle[i].Update(dt/1000.0f);
		}
	}
	m_LastTime = g_GlobalTime;
}

//----------------------------------------------------
// 更新动画
//----------------------------------------------------
void CM2Loader::UpdateAnimation(void)
{
	if(!m_bAnimated)	return;
	m_pAniController->Update(g_ElapsedTime);

	if(g_GlobalTime - m_LastUpdate>=20)
	{
		m_LastUpdate = g_GlobalTime;
	}
	else
	{
		return;
	}
	

	m_CurAnimation = m_pAniController->GetAnim();
	m_AnimationTime = m_pAniController->GetFrame();
	int tmax = m_pAniController->GetFrameCount();
	if(tmax==0) 
		tmax = 1;

	if(m_bAnimBones)
		CalculateBone();
	
	if(m_bAnimGeometry) 
	{
		// 顶点变换
		D3DXVECTOR3 transVertex;
		D3DXVECTOR3 transNormal;
		ModelVertex *pVertex = (ModelVertex*)(m_pData+m_Header.ofsVertices);
		ModelView *pView = (ModelView*)(m_pData+m_Header.ofsViews);
		ModelGeoset *pSubMesh = (ModelGeoset*)(m_pData+pView->ofsSub);
		for(uint32 j=0; j<pView->nSub; j++) 
		{
			// 只变换显示的顶点(5.5ms降低至1.7ms处理时间平稳)
			if(m_bShowSubMesh[j])
			{
				for(uint16 i=pSubMesh[j].vstart; i<(pSubMesh[j].vstart+pSubMesh[j].vcount); i++) 
				{
					D3DXVECTOR3 v(0.0f, 0.0f, 0.0f), n(0.0f, 0.0f, 0.0f);
					for(uint32 b=0; b<4; b++) 
					{
						if(pVertex[i].weights[b]>0) 
						{
							D3DXVec3TransformCoord(&transVertex, &pVertex[i].pos, &m_pBone[pVertex[i].bones[b]].m_matTrans);		
							D3DXVec3TransformCoord(&transNormal, &pVertex[i].normal, &m_pBone[pVertex[i].bones[b]].m_matRotate);
							v += transVertex * ((float)pVertex[i].weights[b] / 255.0f);
							n += transNormal * ((float)pVertex[i].weights[b] / 255.0f);
						}
					}
					m_pVertex[i].m_position = v;
					m_pVertex[i].m_normal = n;
				//	D3DXVec3Normalize(&m_pVertex[i].m_normal, &m_pVertex[i].m_normal);
				}
			}
		}	
	}
	// 粒子系统
	/*
	for(uint32 i=0; i<m_Header.nParticleEmitters; i++)
	{
	//	int pt = ani.timeStart + (m_AnimationTime + (int)(tmax*m_pParticle[i].m_Tofs)) % tmax;
	//	m_pParticle[i].Setup(m_CurAnimation, pt);
	}
	*/
}

//--------------------------------------------------
// 计算骨架
//--------------------------------------------------
void CM2Loader::CalculateBone()
{
	// 骨骼变换
	for(uint32 i=0; i<m_Header.nBones; i++) 
	{
		m_pBone[i].m_bCalc = false;
	}
	if(m_bChar)
	{
		
		int	ani;
		uint32 time;
		//--------------------------------------------------
		if(m_BoneLookup[BONE_ROOT] > -1)
		{
			for(int i=0; i<=m_BoneLookup[BONE_ROOT]; i++)
			{
				m_pBone[i].CalcMatrix(m_pBone, m_CurAnimation, m_AnimationTime);
			}
		}
		//--------------------------------------------------

		// secondary animation.
		if(m_pAniController->IsChannelEnable(1))
		{
			ani = m_pAniController->GetAnim(1);
			time = m_pAniController->GetFrame(1);
		} 
		else 
		{
			ani = m_CurAnimation;
			time = m_AnimationTime;
		}
		
		// 组合动画
		for(int i=0; i<5; i++)
		{
			if(m_BoneLookup[i] > -1)
				m_pBone[m_BoneLookup[i]].CalcMatrix(m_pBone, ani, time);
		}
		if(m_BoneLookup[BONE_JAW] > -1)
			m_pBone[m_BoneLookup[BONE_HEAD]].CalcMatrix(m_pBone, ani, time);
		if(m_BoneLookup[BONE_JAW] > -1)
			m_pBone[m_BoneLookup[BONE_JAW]].CalcMatrix(m_pBone, ani, time);

		for(int i=18; i<27; i++)
		{
			if(m_BoneLookup[i] > -1)
				m_pBone[m_BoneLookup[i]].CalcMatrix(m_pBone, ani, time);
		}
			
	}
	else
	{
		for(int i=0; i<m_BoneLookup[BONE_ROOT]; i++)
		{
			m_pBone[i].CalcMatrix(m_pBone, m_CurAnimation, m_AnimationTime);
		}
	}

	for(uint32 i=0; i<m_Header.nBones; i++) 
	{
		m_pBone[i].CalcMatrix(m_pBone, m_CurAnimation, m_AnimationTime);
	}
}

//--------------------------------------------------
// 关于灯光
// 1, 正确设置材质和法线
// 2, D3DRS_LIGHTING为TRUE
// 3, LightEnable为TRUE
// 4, 正确设置灯光SetLight
// 5, 设置D3DRS_AMBIENT环境光
//--------------------------------------------------

//--------------------------------------------------
// Skeletal
//--------------------------------------------------
void CM2Loader::RenderBone(void)
{
	M2BoundVertex vertex[200];
	int point = 0;
	for(uint32 i=0; i<m_Header.nBones; i++)
	{
		if(m_pBone[i].m_Parent != -1)
		{
			vertex[point++].SetVertex(m_pBone[i].m_TransPoint);
			vertex[point++].SetVertex(m_pBone[m_pBone[i].m_Parent].m_TransPoint);
		}
	}
	g_pD3DDevice->SetFVF(M2BOUNDFVF);
	g_pD3DDevice->SetTexture(0, NULL);
	g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
	g_pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, point/2, vertex, sizeof(M2BoundVertex));
	g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

}

//--------------------------------------------------
// 包围体
//--------------------------------------------------
void CM2Loader::RenderBound(void)
{
	// 包围体
	g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	g_pD3DDevice->SetFVF(M2BOUNDFVF);
	g_pD3DDevice->SetTexture(0, NULL);
	g_pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, m_Header.nBoundingVertices, m_Header.nBoundingTriangles/3, 
		m_pBoundIndex, D3DFMT_INDEX16, m_pBoundVertex, sizeof(M2BoundVertex));
	g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
	g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
}

//--------------------------------------------------
// Particle System
//--------------------------------------------------
void CM2Loader::RenderParticle(const D3DXMATRIX &matRotate)
{
	//--------------------------------------------------
	// 粒子系统的渲染
	// 主要问题:
	// 1, BillBoard在attachment根旋转时不正确	OK
	// 2, Particle显示会清除人物显示地面背景(估计渲染顺利造成的, 粒子系统应放在模型外渲染)
	// 3, 效果与Wowmodelviewer相差太大
	//--------------------------------------------------
	SET_TEXTURE_TYPE(0, 1007);
	for(uint32 i=0; i<m_Header.nParticleEmitters; i++)
	{
		m_pParticle[i].Render(matRotate);
	}
}

//--------------------------------------------------
// Render模型
//--------------------------------------------------
void CM2Loader::Render(void)
{
	if(!m_bRender)
		return;
	// 暂时关闭灯光
	g_pD3DDevice->LightEnable(0, TRUE);
	g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	// 注: 打开灯光人物头部显示有问题
	/*
	D3DMATERIAL9 mater;
	mater.Diffuse.a = 1.0f;
	mater.Diffuse.r = 1.0f;
	mater.Diffuse.g = 1.0f;
	mater.Diffuse.b = 1.0f;
	mater.Ambient.a = 1.0f;
	mater.Ambient.r = 1.0f;
	mater.Ambient.g = 1.0f;
	mater.Ambient.b = 1.0f;
	mater.Emissive.a = 0.0f;
	mater.Emissive.r = 0.0f;
	mater.Emissive.g = 0.0f;
	mater.Emissive.b = 0.0f;
	mater.Power = 0.0f;
	g_pD3DDevice->SetMaterial(&mater);
	g_pD3DDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
	*/
	
	g_pD3DDevice->SetFVF(M2FVF);
	unsigned long OldTex = 0;
	for(size_t i=0; i<m_RenderPass.size(); i++)
	{
		M2RenderPass &pass = m_RenderPass[i];
		if(m_bShowSubMesh[pass.m_SubMeshIndex])
		{
			unsigned long texHandle = 0;
			if(m_SpecialTextureIndex[pass.m_TextureIndex]==-1) 
				texHandle = m_pTexture[pass.m_TextureIndex];
			else 
				texHandle = m_ReplaceTexture[m_SpecialTextureIndex[pass.m_TextureIndex]];
			if(OldTex != texHandle)
			{
				if(m_SpecialTextureIndex[pass.m_TextureIndex]!=-1 || 
					m_pTexture[pass.m_TextureIndex]!=0)
				{
					SET_TEXTURE_TYPE(0, texHandle);
				}
				OldTex = texHandle;
			}
			
			// vertex start, vertex count, 图元数量, 索引数组, 格式, 顶点数组, 顶点格式
			pass.OpenState(this);
			g_pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, pass.m_VertexCount+pass.m_VertexStart, 
				pass.m_IndexCount/3, m_pVertexIndex+pass.m_IndexStart, D3DFMT_INDEX16, m_pVertex, sizeof(M2Vertex));
			pass.CloseState();
		}
	}
	g_pD3DDevice->LightEnable(0, FALSE);
	g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
}

//--------------------------------------------------
// 判断是否是动画模型
//--------------------------------------------------
bool CM2Loader::IsAnimation(void)
{
	if(m_pData == NULL)	return false;
	m_bAnimGeometry = false;
	m_bAnimBones = false;
	m_bBillBoard = false;
	ModelBoneDef *pBone = (ModelBoneDef*)(m_pData+m_Header.ofsBones);
	ModelVertex *pVertex = (ModelVertex*)(m_pData+m_Header.ofsVertices);
	for(size_t i=0; i<m_Header.nVertices && !m_bAnimGeometry; i++) 
	{
		for(size_t nbone=0; nbone<4; nbone++) 
		{
			if(pVertex[i].weights[nbone]>0) 
			{
				ModelBoneDef &boneref = pBone[pVertex[i].bones[nbone]];
				if(boneref.translation.type || boneref.rotation.type || boneref.scaling.type || (boneref.flags & 8)) 
				{
					if(boneref.flags & 8) // 需要每帧变换
					{
						m_bBillBoard = true;
					}
					// 顶点需要变换有顶点动画
					m_bAnimGeometry = true;
					break;
				}
			}
		}
	}
	// 有顶点动画一定有骨架
	if(m_bAnimGeometry) 
		m_bAnimBones = true;
	else 
	{
		for(size_t i=0; i<m_Header.nBones; i++) 
		{
			ModelBoneDef &boneref = pBone[i];
			if(boneref.translation.type || boneref.rotation.type || boneref.scaling.type) 
			{
				m_bAnimBones = true;
				break;
			}
		}
	}
	// 纹理动画
	m_bAnimTextures = m_Header.nTexAnims > 0;
	// 有摄像机, 灯光, 粒子系统即需要骨架
	bool bAnimMisc = m_Header.nCameras>0 || m_Header.nLights>0 ||
		 m_Header.nParticleEmitters>0 || m_Header.nRibbonEmitters>0;

	if(bAnimMisc) 	m_bAnimBones = true;

	// 颜色变化动画animated colors
	if(m_Header.nColors) 
	{
		ModelColorDef *pColor = (ModelColorDef*)(m_pData+m_Header.ofsColors);
		for(size_t i=0; i<m_Header.nColors; i++) 
		{
			if(pColor[i].color.type!=0 || pColor[i].opacity.type!=0) 
			{
				bAnimMisc = true;
				break;
			}
		}
	}

	// 透明度动画animated opacity
	if(m_Header.nTransparency && !bAnimMisc) 
	{
		ModelTransDef *pTrans = (ModelTransDef*)(m_pData+m_Header.ofsTransparency);
		for(size_t i=0; i<m_Header.nTransparency; i++) 
		{
			if(pTrans[i].trans.type !=0 ) 
			{
				bAnimMisc = true;
				break;
			}
		}
	}

	return m_bAnimGeometry || m_bAnimTextures;// || bAnimMisc;
}

//--------------------------------------------------
// 取得某骨架的变换矩阵
//--------------------------------------------------
D3DXMATRIX CM2Loader::GetAttachmentMatrix(int index)
{
	D3DXMATRIX matRet;
	D3DXMATRIX matBone;
	int attachindex = m_AttachLookup[index];
	if(attachindex>=0)
	{
		int boneindex = m_Attachment[attachindex].GetBoneIndex();
		if(boneindex<0)
			WriteLog(INFO_ERROR, "bone index < 0[CM2Loader::GetAttachmentMatrix]");
		matBone = m_pBone[boneindex].m_matTrans;
		m_Attachment[attachindex].GetMatrix(&matRet, &matBone);
	}
	else
	{
		D3DXMatrixIdentity(&matRet);
	}
	return matRet;
}

//--------------------------------------------------
// 根据动画ID设置当前动画
//--------------------------------------------------
void CM2Loader::SetAnimationByID(int channel, int group, int id, int loop /* = 0 */)
{
	for(uint32 i=0; i<m_Header.nAnimations; i++)
	{
		if(m_pAni[i].animID == id)
		{
			break;
		}
	}
	m_pAniController->SetAni(channel, group, i, loop);
}

//--------------------------------------------------
// 根据动画INDEX设置当前动画
//--------------------------------------------------
void CM2Loader::SetAnimationByIndex(int channel, int group, uint32 index, int loop /* = 0 */)
{
	if(index<m_Header.nAnimations)
	{
		m_pAniController->SetAni(channel, group, index, loop);
	}
}

//--------------------------------------------------
// 根据动画INDEX设置当前动画
//--------------------------------------------------
void CM2Loader::SetNextAnimation(void)
{
//	m_CurAnimation++;
//	if(m_CurAnimation>=m_Header.nAnimations)
//		m_CurAnimation = 0;
}

void CM2Loader::PlayAnimation(void)
{
	//m_pAniController->Play();
}

bool CM2Loader::IsPause(void)
{
	return m_pAniController->IsPause();
}

⌨️ 快捷键说明

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