#include "MLRHeaders.hpp" #include "MLR\MLRFootstep.hpp" //############################################################################# //############################### MLRShape ################################## //############################################################################# // This switch is used by 3dsMax Animationsuite. Set to 0 when importing ERF int g_bConvertMeshes = 1; extern DWORD gEnableBumpMap; MLRShape::ClassData* MLRShape::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::InitializeClass() { Verify(!DefaultData); Verify(gos_GetCurrentHeap() == StaticHeap); DefaultData = new ClassData( MLRShapeClassID, "MidLevelRenderer::MLRShape", Plug::DefaultData ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRShape::MLRShape( ClassData *class_data, MemoryStream *stream, int version ): Plug(class_data) { Check_Pointer(this); Check_Object(stream); Verify(gos_GetCurrentHeap() == ShapeHeap); if(version<15) { int np; *stream >> np; numPrimitives = static_cast(np); } else { *stream >> numPrimitives; } allPrimitives.SetLength(numPrimitives); for(int i=0;i> class_id; MLRPrimitive::ClassData* class_data = Cast_Object(MLRPrimitive::ClassData*, FindClassData(class_id)); pt_old = (*class_data->primitiveFactory)(stream, version); Register_Object(pt_old); int i, nr, test; if(pt_old->GetReferenceState().GetLightingMode() == MLRState::LightingOffMode) { test = 0; } else { test = 2; } #if COLOR_AS_DWORD DWORD* colors; #else RGBAColor *colors, testColor(1.0f, 1.0f, 1.0f, 1.0f); #endif Cast_Pointer(MLRIndexedPolyMesh*, pt_old)->GetColorData(&colors, &nr); for(i=0;iCopy(Cast_Pointer(MLRIndexedPolyMesh*, pt_old)); break; case 1: pt = new MLR_I_C_PMesh; Cast_Pointer(MLR_I_C_PMesh*, pt)->Copy(Cast_Pointer(MLRIndexedPolyMesh*, pt_old)); break; default: pt = new MLR_I_L_PMesh; Cast_Pointer(MLR_I_L_PMesh*, pt)->Copy(Cast_Pointer(MLRIndexedPolyMesh*, pt_old)); break; } pt_old->DetachReference(); */ } break; default: { RegisteredClass::ClassID class_id; *stream >> class_id; MLRPrimitiveBase::ClassData* class_data = Cast_Pointer(MLRPrimitiveBase::ClassData*, FindClassData(class_id)); Check_Object(class_data); pt = (*class_data->primitiveFactory)(stream, version); Register_Object(pt); if( g_bConvertMeshes && ConvertToTriangleMeshes == true && ( pt->IsDerivedFrom(MLR_I_PMesh::DefaultData) || pt->IsDerivedFrom(MLR_I_C_PMesh::DefaultData) || pt->IsDerivedFrom(MLR_I_L_PMesh::DefaultData) ) ) { const BYTE *length; int i, num, threes, nonThrees; pt->GetSubprimitiveLengths(&length, &num); for(i=0,threes=0,nonThrees=0;i0 && nonThrees==0) //threes > 9*nonThrees) { MLRPrimitiveBase *pt_old = pt; if(pt->GetClassData() == MLR_I_L_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_L_TMesh::PrimitiveHeap); pt = new MLR_I_L_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_L_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_C_TMesh::PrimitiveHeap); pt = new MLR_I_C_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_C_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_TMesh::PrimitiveHeap); pt = new MLR_I_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_L_DT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_L_DT_TMesh::PrimitiveHeap); pt = new MLR_I_L_DT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_L_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_DT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_C_DT_TMesh::PrimitiveHeap); pt = new MLR_I_C_DT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_C_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_DT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_DT_TMesh::PrimitiveHeap); pt = new MLR_I_DT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_L_DeT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_L_DeT_TMesh::PrimitiveHeap); pt = new MLR_I_L_DeT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_L_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_DeT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_DeT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_C_DeT_TMesh::PrimitiveHeap); pt = new MLR_I_C_DeT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_C_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_DeT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_DeT_PMesh::DefaultData) { gos_PushCurrentHeap(MLR_I_DeT_TMesh::PrimitiveHeap); pt = new MLR_I_DeT_TMesh; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_I_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_DeT_PMesh*, pt_old)); } pt_old->DetachReference(); } } else if(gEnableBumpMap>0) { if(pt->IsDerivedFrom(MLR_Water::DefaultData)) { MLRPrimitiveBase *pt_old = pt; static MLRTexture *bumptex1 = NULL; static MLRTexture *bumptex2 = NULL; static MLRTexture *bumptex3 = NULL; if(bumptex1 == NULL) { bumptex1 = MLRTexturePool::Instance->Add("waterbump"); bumptex2 = MLRTexturePool::Instance->Add("waterenv"); bumptex3 = MLRTexturePool::Instance->Add("waterbumpnormal"); } if(bumptex1 != NULL && bumptex2 != NULL) { gos_PushCurrentHeap(MLR_Water::PrimitiveHeap); pt = new MLR_BumpyWater; gos_PopCurrentHeap(); Register_Object(pt); Cast_Pointer(MLR_BumpyWater*, pt)->SetTextures( bumptex1->GetTextureHandle(), bumptex2->GetTextureHandle(), bumptex3->GetTextureHandle() ); Cast_Pointer(MLR_BumpyWater*, pt)->Copy(Cast_Pointer(MLR_Water*, pt_old)); pt_old->DetachReference(); } } } } break; } allPrimitives[i] = pt; } referenceCount = 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRShape::MLRShape(int nr, ClassData *class_data): Plug(class_data), allPrimitives(nr ? nr : 4) { Verify(gos_GetCurrentHeap() == ShapeHeap); numPrimitives = 0; referenceCount = 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRShape::~MLRShape() { int i; MLRPrimitiveBase *pt; for(i=numPrimitives-1;i>=0;i--) { pt = allPrimitives[i]; allPrimitives[i] = NULL; pt->DetachReference(); } Verify(referenceCount==0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRShape* MLRShape::Make( MemoryStream *stream, int version ) { Check_Object(stream); gos_PushCurrentHeap(ShapeHeap); MLRShape *shape = new MLRShape(DefaultData, stream, version); gos_PopCurrentHeap(); return shape; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::Save(MemoryStream *stream) { Check_Object(this); Check_Object(stream); *stream << GetClassID(); *stream << numPrimitives; MLRPrimitiveBase *pt = NULL; int i; gos_PushCurrentHeap(ShapeHeap); for(i=0;iIsDerivedFrom(MLR_I_PMesh::DefaultData) || pt->IsDerivedFrom(MLR_I_C_PMesh::DefaultData) || pt->IsDerivedFrom(MLR_I_L_PMesh::DefaultData) ) ) { const BYTE *length; int i, num, threes, nonThrees; pt->GetSubprimitiveLengths(&length, &num); for(i=0,threes=0,nonThrees=0;i0 && nonThrees==0) //threes > 9*nonThrees) { MLRPrimitiveBase *pt_old = pt; if(pt->GetClassData() == MLR_I_L_PMesh::DefaultData) { pt = new MLR_I_L_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_L_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_PMesh::DefaultData) { pt = new MLR_I_C_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_C_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_PMesh::DefaultData) { pt = new MLR_I_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_L_DT_PMesh::DefaultData) { pt = new MLR_I_L_DT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_L_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_DT_PMesh::DefaultData) { pt = new MLR_I_C_DT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_C_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_DT_PMesh::DefaultData) { pt = new MLR_I_DT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_DT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_DT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_L_DeT_PMesh::DefaultData) { pt = new MLR_I_L_DeT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_L_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_L_DeT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_C_DeT_PMesh::DefaultData) { pt = new MLR_I_C_DeT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_C_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_C_DeT_PMesh*, pt_old)); } else if(pt->GetClassData() == MLR_I_DeT_PMesh::DefaultData) { pt = new MLR_I_DeT_TMesh; Register_Object(pt); Cast_Pointer(MLR_I_DeT_TMesh*, pt)->Copy(Cast_Pointer(MLR_I_DeT_PMesh*, pt_old)); } pt_old->DetachReference(); } } allPrimitives[i] = pt; allPrimitives[i]->Save(stream); } gos_PopCurrentHeap(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::Add (MLRPrimitiveBase *p) { Check_Object(this); Verify(Find(p)<0); if(numPrimitives >= allPrimitives.GetLength() || allPrimitives.GetLength() == 0) { gos_PushCurrentHeap(ShapeHeap); allPrimitives.SetLength(numPrimitives + 4); gos_PopCurrentHeap(); } allPrimitives[numPrimitives] = p; p->AttachReference(); numPrimitives++; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRShape::GetNumPrimitives() { int i, ret = 0; for(i=0;iGetNumPrimitives(); } return ret; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRShape::GetNumDrawnTriangles() { int i, j, ret = 0; for(i=0;iIsDerivedFrom(MLRIndexedPrimitiveBase::DefaultData)) { j = (Cast_Pointer(MLRIndexedPrimitiveBase*, allPrimitives[i]))->GetNumGOSIndices(); } else { j = allPrimitives[i]->GetNumGOSVertices(); } if(j!=0xffff) { ret += j; } } return ret; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRPrimitiveBase* MLRShape::Find (int i) { Check_Object(this); Verify(i=0) { pout->DetachReference(); allPrimitives[num] = pin; pin->AttachReference(); } else { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRPrimitiveBase* MLRShape::Remove(MLRPrimitiveBase *p) { Check_Object(this); Check_Object(p); int i, nr = Find(p); if(nr < 0) { return NULL; } for(i=nr;iDetachReference(); return p; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRPrimitiveBase* MLRShape::Remove(int nr) { Check_Object(this); int i; MLRPrimitiveBase *p = Find(nr); if(nr < 0 || nr >= numPrimitives) { return NULL; } for(i=nr;iDetachReference(); return p; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRShape::Insert(MLRPrimitiveBase *p, int nr) { Check_Object(this); if(nr >= numPrimitives) { Add(p); return numPrimitives; } if(numPrimitives >= allPrimitives.GetLength() || allPrimitives.GetLength() == 0) { gos_PushCurrentHeap(ShapeHeap); allPrimitives.SetLength(numPrimitives + 4); gos_PopCurrentHeap(); } int i; for(i=numPrimitives;i>nr;i--) { allPrimitives[i] = allPrimitives[i-1]; } allPrimitives[i] = p; p->AttachReference(); numPrimitives++; return numPrimitives; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::InitializePrimitives(BYTE vis, const MLRState& master, int parameter) { Check_Object(this); int i; for(i=0;iInitializeDrawPrimitive(vis, parameter); allPrimitives[i]->CombineStates(master); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::CleanMe() { for(int i=0;iCleanMe(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::HurtMe(const Stuff::LinearMatrix4D& pain, Stuff::Scalar radius) { for(int i=0;iHurtMe(pain, radius); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::HurtMe(const Stuff::LinearMatrix4D& pain, Stuff::Scalar radius, MLRTexture *tex) { int num = numPrimitives; for(int i=0;iHurtMe(pain, radius, tex); if(p!=NULL) { Add(p); p->DetachReference(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::StepOnMe( MLRShape *shape, const Stuff::LinearMatrix4D& foot, Stuff::Scalar radius, MLRTexture *tex ) { Check_Object(&foot); Check_Object(shape); if(MLRFootStep::Instance == NULL || MLRFootStep::Instance->ShowSteps()==false) { return; } int num = numPrimitives; UnitVector3D u; for(int i=0;iIsDerivedFrom(MLR_Terrain2::DefaultData)) { MLRPrimitiveBase *p = (Cast_Pointer(MLR_Terrain2*, allPrimitives[i]))->StepOnMe(foot, radius, tex); if(p!=NULL) { shape->Add(p); p->DetachReference(); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // point is at the center of the bottom edge of the texture, uvec is light // direction and the direction the texture is oriented in // void MLRShape::DrawMyShadow(const Stuff::LinearMatrix4D& point, Stuff::UnitVector3D& uvec, Stuff::Scalar radius, DWORD color) { for(int i=0;iDrawMyShadow(point, uvec, radius, color); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* p is the eye point int MLRShape::FindBackFace(const Point3D& p, const Normal3D& n) { Check_Object(this); int i, ret = 0; Point3D sp; sp.Multiply(p, *worldToShape); Normal3D np; np.Multiply(n, *worldToShape); for(i=0;iFindBackFace(sp, np); } return ret; } */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* void MLRShape::Transform(Matrix4D *mat) { Check_Object(this); int i; for(i=0;iTransform(mat); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::Transform() { Check_Object(this); int i; for(i=0;iTransform(&shapeToClipMatrix); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRShape::Clip(MLRClippingState clippingFlags, GOSVertexPool *vp) { Check_Object(this); int i, ret = 0; // gos_GetViewport( &ViewportScalars::MulX, &ViewportScalars::MulY, &ViewportScalars::AddX, &ViewportScalars::AddY ); for(i=0;iClip(clippingFlags, vp); } return ret; } */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRShape::Lighting ( const LinearMatrix4D& WorldToShape, MLRLight* const* lights, int nrLights, BYTE what ) { Check_Object(this); Check_Object(&WorldToShape); if(nrLights == 0) { return; } int i; for(i=0;iSetLightToShapeMatrix(WorldToShape); } for(i=0;iLighting(lights, nrLights); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MLRShape::CastRay ( Line3D *line, Normal3D *normal ) { Check_Object(this); Check_Object(line); Check_Pointer(normal); bool result = false; for(int i=0; iCastRay(line, normal)) result = true; } return result; }