📄 model.cpp
字号:
//+-----------------------------------------------------------------------------
//| 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 + -