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

📄 model.cpp

📁 骨骼动画....把魔兽模型解出的代码..
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//+-----------------------------------------------------------------------------
//| Included files
//+-----------------------------------------------------------------------------
#include "Model.h"
#include "AnimationWindow.h"
#include "NodeManagerWindow.h"
#include "CameraManagerWindow.h"
#include "GeosetManagerWindow.h"
#include "GeosetAnimationManagerWindow.h"
#include "TextureManagerWindow.h"
#include "TextureAnimationManagerWindow.h"
#include "MaterialManagerWindow.h"
#include "SequenceManagerWindow.h"
#include "GlobalSequenceManagerWindow.h"


//+-----------------------------------------------------------------------------
//| Global objects
//+-----------------------------------------------------------------------------
MODEL Model;


//+-----------------------------------------------------------------------------
//| Constructor
//+-----------------------------------------------------------------------------
MODEL::MODEL()
{
	BoundsRadius = 0.0f;
	BoundsCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

	SequenceNode.SetData(this);

	Root = new MODEL_HELPER();
	Root->BaseData()->TreeViewItem = TVI_ROOT;
}


//+-----------------------------------------------------------------------------
//| Destructor
//+-----------------------------------------------------------------------------
MODEL::~MODEL()
{
	delete Root;
}


//+-----------------------------------------------------------------------------
//| Clears the model
//+-----------------------------------------------------------------------------
VOID MODEL::Clear()
{
	ParticleManager.Clear();
	RibbonManager.Clear();

	ObjectIdManager.ClearAllObjectIds();

	ModelData.BaseContainer.Clear();

	SAFE_CLEAR(ModelData.AttachmentContainer);
	SAFE_CLEAR(ModelData.BoneContainer);
	SAFE_CLEAR(ModelData.CollisionShapeContainer);
	SAFE_CLEAR(ModelData.EventObjectContainer);
	SAFE_CLEAR(ModelData.HelperContainer);
	SAFE_CLEAR(ModelData.LightContainer);
	SAFE_CLEAR(ModelData.ParticleEmitterContainer);
	SAFE_CLEAR(ModelData.ParticleEmitter2Container);
	SAFE_CLEAR(ModelData.RibbonEmitterContainer);

	SAFE_CLEAR(ModelData.CameraContainer);
	SAFE_CLEAR(ModelData.GeosetContainer);
	SAFE_CLEAR(ModelData.GeosetAnimationContainer);
	SAFE_CLEAR(ModelData.GlobalSequenceContainer);
	SAFE_CLEAR(ModelData.MaterialContainer);
	SAFE_CLEAR(ModelData.SequenceContainer);
	SAFE_CLEAR(ModelData.TextureContainer);
	SAFE_CLEAR(ModelData.PivotPointContainer);
	SAFE_CLEAR(ModelData.TextureAnimationContainer);

	BoundsRadius = 0.0f;
	BoundsCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

	AnimationTime = SEQUENCE_TIME();

	ModelData = MODEL_DATA();
}


//+-----------------------------------------------------------------------------
//| Returns a reference to the data
//+-----------------------------------------------------------------------------
MODEL_DATA& MODEL::Data()
{
	return ModelData;
}


//+-----------------------------------------------------------------------------
//| Rebuilds the meshes next time it's rendered
//+-----------------------------------------------------------------------------
VOID MODEL::Rebuild()
{
	INT i;

	for(i = 0; i < ModelData.GeosetContainer.GetTotalSize(); i++)
	{
		if(ModelData.GeosetContainer.ValidIndex(i))
		{
			ModelData.GeosetContainer[i]->Rebuild();
		}
	}
}


//+-----------------------------------------------------------------------------
//| Renders the model
//+-----------------------------------------------------------------------------
VOID MODEL::Render(INT TimeDifference)
{
	INT i;
	INT Interval;
	INT RealTimeDifference;
	BOOL Animated;
	MODEL_SEQUENCE* Sequence;
	MODEL_GLOBAL_SEQUENCE* GlobalSequence;
	std::list<INT> RenderOrderList1;
	std::list<INT> RenderOrderList2;
	std::list<INT> RenderOrderList3;
	std::list<INT> RenderOrderList4;
	std::list<INT>::iterator j;

	RealTimeDifference = TimeDifference;

	while(SequenceNode.IsAttached() && (TimeDifference != 0))
	{
		Sequence = SequenceNode.GetObjectData();
		Interval = AnimationTime.IntervalEnd - AnimationTime.IntervalStart;

		if(Interval < 0)
		{
			SequenceNode.Detach();
			break;
		}

		AnimationTime.Time += TimeDifference;
		if(AnimationTime.Time > AnimationTime.IntervalEnd)
		{
			if(Properties().Minor.AlwaysLoop)
			{
				AnimationTime.Time = AnimationTime.IntervalStart;
			}
			else if(Properties().Minor.NeverLoop)
			{
				AnimationTime.Time = AnimationTime.IntervalEnd;
				//TimeDifference = 0;
			}
			else if(Sequence->Data().NonLooping)
			{
				AnimationTime.Time = AnimationTime.IntervalEnd;
				//TimeDifference = 0;
			}
			else
			{
				AnimationTime.Time = AnimationTime.IntervalStart;
			}
		}

		for(i = 0; i < ModelData.GlobalSequenceContainer.GetTotalSize(); i++)
		{
			if(ModelData.GlobalSequenceContainer.ValidIndex(i))
			{
				GlobalSequence = ModelData.GlobalSequenceContainer[i];

				GlobalSequence->Data().Time += TimeDifference;
				if(GlobalSequence->Data().Time >= GlobalSequence->Data().Duration)
				{
					GlobalSequence->Data().Time = 0;
				}
			}
		}

		ParticleManager.Update(AnimationTime, RealTimeDifference, (TimeDifference > 0));
		RibbonManager.Update(AnimationTime, RealTimeDifference, (TimeDifference > 0));

		Root->BuildMatrix(AnimationTime);

		break;
	}

	for(i = 0; i < ModelData.GeosetContainer.GetTotalSize(); i++)
	{
		if(ModelData.GeosetContainer.ValidIndex(i))
		{
			switch(ModelData.GeosetContainer[i]->GetRenderOrder())
			{
				case 1:
				{
					RenderOrderList1.push_back(i);
					break;
				}

				case 2:
				{
					RenderOrderList2.push_back(i);
					break;
				}

				case 3:
				{
					RenderOrderList3.push_back(i);
					break;
				}

				case 4:
				{
					RenderOrderList4.push_back(i);
					break;
				}
			}
		}
	}

	Animated = SequenceNode.IsAttached();

	j = RenderOrderList1.begin();
	while(j != RenderOrderList1.end())
	{
		ModelData.GeosetContainer[*j]->Render(AnimationTime, Animated);
		j++;
	}

	j = RenderOrderList2.begin();
	while(j != RenderOrderList2.end())
	{
		ModelData.GeosetContainer[*j]->Render(AnimationTime, Animated);
		j++;
	}

	j = RenderOrderList3.begin();
	while(j != RenderOrderList3.end())
	{
		ModelData.GeosetContainer[*j]->Render(AnimationTime, Animated);
		j++;
	}

	j = RenderOrderList4.begin();
	while(j != RenderOrderList4.end())
	{
		ModelData.GeosetContainer[*j]->Render(AnimationTime, Animated);
		j++;
	}

	Graphics.PrepareForLines();

	if(Properties().ShowBones) RenderBones();
	if(Properties().ShowLights) RenderLights();
	if(Properties().ShowCameras) RenderCameras();
	if(Properties().ShowAttachments) RenderAttachments();
	if(Properties().ShowCollisionShapes) RenderCollisionShapes();
}


//+-----------------------------------------------------------------------------
//| Plays an animation
//+-----------------------------------------------------------------------------
VOID MODEL::PlayAnimation(MODEL_SEQUENCE* Sequence)
{
	INT i;

	AnimationTime = SEQUENCE_TIME();

	for(i = 0; i < ModelData.GlobalSequenceContainer.GetTotalSize(); i++)
	{
		if(ModelData.GlobalSequenceContainer.ValidIndex(i))
		{
			ModelData.GlobalSequenceContainer[i]->Data().Time = 0;
		}
	}

	SequenceNode.Detach();

	ParticleManager.Clear();
	RibbonManager.Clear();

	if(Sequence == NULL) return;

	SequenceNode.Attach(Sequence->ModelNodes);
	AnimationTime.IntervalStart = static_cast<INT>(Sequence->Data().Interval.x);
	AnimationTime.IntervalEnd = static_cast<INT>(Sequence->Data().Interval.y);
	AnimationTime.Time = AnimationTime.IntervalStart;
}


//+-----------------------------------------------------------------------------
//| Calculates the bounds radius
//+-----------------------------------------------------------------------------
VOID MODEL::CalculateBoundsRadius()
{
	INT i;
	INT j;
	MODEL_GEOSET* Geoset;
	std::vector<D3DXVECTOR3> VertexList;

	for(i = 0; i < ModelData.GeosetContainer.GetTotalSize(); i++)
	{
		if(ModelData.GeosetContainer.ValidIndex(i))
		{
			Geoset = ModelData.GeosetContainer[i];
			VertexList.reserve(static_cast<INT>(VertexList.size()) + Geoset->Data().VertexContainer.GetSize());

			for(j = 0; j < Geoset->Data().VertexContainer.GetTotalSize(); j++)
			{
				if(Geoset->Data().VertexContainer.ValidIndex(j))
				{
					VertexList.push_back(Geoset->Data().VertexContainer[j]->Position);
				}
			}
		}
	}

	if(static_cast<INT>(VertexList.size()) > 0)
	{
		if(FAILED(D3DXComputeBoundingSphere(&VertexList[0], static_cast<INT>(VertexList.size()), sizeof(D3DXVECTOR3), &BoundsCenter, &BoundsRadius)))
		{
			BoundsRadius = 0.0f;
			BoundsCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
		}
	}
	else
	{
		BoundsRadius = 0.0f;
		BoundsCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	}
}


//+-----------------------------------------------------------------------------
//| Returns the radius of the bounding sphere
//+-----------------------------------------------------------------------------
FLOAT MODEL::GetBoundsRadius()
{
	return BoundsRadius;
}


//+-----------------------------------------------------------------------------
//| Returns the center of the bounding sphere
//+-----------------------------------------------------------------------------
D3DXVECTOR3 MODEL::GetBoundsCenter()
{
	return BoundsCenter;
}


//+-----------------------------------------------------------------------------
//| Adds an attachment
//+-----------------------------------------------------------------------------
MODEL_GEOSET* MODEL::GetIntersectedGeoset(CONST D3DXVECTOR3& RayPosition, CONST D3DXVECTOR3& RayDirection)
{
	INT i;
	BOOL Animated;
	FLOAT CurrentDistance;
	FLOAT ClosestDistance;
	MODEL_GEOSET* CurrentGeoset;
	MODEL_GEOSET* ClosestGeoset;

	ClosestGeoset = NULL;
	ClosestDistance = std::numeric_limits<FLOAT>::max();
	Animated = SequenceNode.IsAttached();

	for(i = 0; i < ModelData.GeosetContainer.GetTotalSize(); i++)
	{
		if(ModelData.GeosetContainer.ValidIndex(i))
		{
			CurrentGeoset = ModelData.GeosetContainer[i];

			if(CurrentGeoset->RayIntersects(RayPosition, RayDirection, Animated, &CurrentDistance))
			{
				if(CurrentDistance < ClosestDistance)
				{
					ClosestGeoset = CurrentGeoset;
					ClosestDistance = CurrentDistance;
				}
			}
		}
	}

	return ClosestGeoset;
}


//+-----------------------------------------------------------------------------
//| Adds an attachment
//+-----------------------------------------------------------------------------
BOOL MODEL::AddAttachment(MODEL_ATTACHMENT* Attachment, MODEL_BASE* ParentNode)
{
	if(!AddBaseNode(Attachment, ParentNode)) return FALSE;

	if(!ModelData.AttachmentContainer.Add(Attachment))
	{
		Error.SetMessage("Unable to add a new attachment!");
		return FALSE;
	}

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Adds a bone
//+-----------------------------------------------------------------------------
BOOL MODEL::AddBone(MODEL_BONE* Bone, MODEL_BASE* ParentNode)
{
	if(!AddBaseNode(Bone, ParentNode)) return FALSE;

	if(!ModelData.BoneContainer.Add(Bone))
	{
		Error.SetMessage("Unable to add a new bone!");
		return FALSE;
	}

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Adds a collision shape
//+-----------------------------------------------------------------------------
BOOL MODEL::AddCollisionShape(MODEL_COLLISION_SHAPE* CollisionShape, MODEL_BASE* ParentNode)
{
	if(!AddBaseNode(CollisionShape, ParentNode)) return FALSE;

	if(!ModelData.CollisionShapeContainer.Add(CollisionShape))
	{
		Error.SetMessage("Unable to add a new collision shape!");
		return FALSE;
	}

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Adds an event object
//+-----------------------------------------------------------------------------
BOOL MODEL::AddEventObject(MODEL_EVENT_OBJECT* EventObject, MODEL_BASE* ParentNode)
{
	if(!AddBaseNode(EventObject, ParentNode)) return FALSE;

⌨️ 快捷键说明

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