#include "dxstdafx.h" #include "./Object3d.h" #include "GameManager.h" #include "Scene.h" #include Object3d::Object3d(void) : Node() { myMesh = NULL; myProgressiveMesh = NULL; adjacencyInfo = NULL; g_dwNumMaterials = 0; this->isAPMesh = false; this->modelLoaded = false; this->isManagedByResourceManager = false; this->deleteMesh = true; this->pVertices = NULL; this->pIndices = NULL; this->writeBuffer = NULL; this->maxFaces = 0; this->minFaces = 0; this->nodeType |= Scene::NODE_OBJECT3D; this->xfilename = ""; } Object3d::~Object3d(void) { //TODO noch mehr releasen? leaks gefunden! if(myMesh!=NULL && !(isManagedByResourceManager)) { (myMesh)->Release(); } if(myProgressiveMesh!=NULL) { myProgressiveMesh->Release(); } if(!(isManagedByResourceManager)) { delete [] adjacencyInfo; } this->Materials.clear(); /*for(UINT i = 0; i < Textures.size(); i++) { if (Textures[i] != 0 && (!this->isTerrainPatch)) Textures[i]->Release(); Textures[i] = 0; }*/ if(this->pVertices) { delete[] this->pVertices; this->pVertices = NULL; } if(this->pIndices) { delete[] this->pIndices; this->pIndices = NULL; } if(this->writeBuffer) { delete this->writeBuffer; this->writeBuffer = NULL; } } LPD3DXMESH* Object3d::getMesh() { return &myMesh; } void Object3d::setMesh(LPD3DXMESH *_mesh) { this->myMesh = *_mesh; } LPD3DXPMESH* Object3d::getProgressiveMesh() { return &myProgressiveMesh; } void Object3d::loadMeshFromFile(std::string filename) { //this->myScene->manager->printToConsole(filename); bool success = this->myScene->manager->resManager.loadXModel(filename, this); if(!success) { // set everything to NULL myMesh = NULL; this->g_dwNumMaterials = 0; this->modelLoaded = false; this->myScene->manager->printToConsole("loading model failed!"); } else { this->xfilename = filename; //this->myScene->manager->printToConsole("3d model loaded successfully!"); } } void Object3d::computeAdjacency () { if(myMesh!=NULL) { if (adjacencyInfo != NULL) delete [] adjacencyInfo; //generate new DWORD array adjacencyInfo = new DWORD[(myMesh)->GetNumFaces() * 3]; memset(adjacencyInfo,0,(myMesh)->GetNumFaces() * 3); // Get the adjacency info of the mesh. (myMesh)->GenerateAdjacency(0.0f, adjacencyInfo); } } void Object3d::computeNormals() { if(myMesh!=NULL) { // if mesh vertices have no normal variables defined, add them if ( !((myMesh)->GetFVF() & D3DFVF_NORMAL)) { // define a temp mesh for the mesh with normal variables LPD3DXMESH pTempMesh; // clone the mesh, add normal variables (myMesh)->CloneMeshFVF((myMesh)->GetOptions(), (myMesh)->GetFVF() | D3DFVF_NORMAL, DXUTGetD3DDevice(), &pTempMesh ); // release the old mesh (myMesh)->Release(); myMesh = pTempMesh; } if (adjacencyInfo == NULL) computeAdjacency(); D3DXComputeNormals( myMesh, adjacencyInfo ); } } bool Object3d::isModelLoaded() { return this->modelLoaded; } void Object3d::setModelLoaded(bool value) { this->modelLoaded = value; } void Object3d::setXFilename(std::string _xfilename) { this->xfilename = _xfilename; } void Object3d::generateAndUsePMesh(float *weights) { if(this->myProgressiveMesh != NULL) this->myProgressiveMesh->Release(); if(adjacencyInfo == NULL) { this->computeAdjacency(); } //generate progressive mesh: HRESULT hr = D3DXGeneratePMesh( myMesh, this->adjacencyInfo, // adjacency 0, // default vertex attribute weights weights, // default vertex weights 1, // simplify as low as possible D3DXMESHSIMP_FACE, // simplify by face count &myProgressiveMesh); if(FAILED(hr)) { // go to previous state: if(this->myProgressiveMesh != NULL) { this->myProgressiveMesh->Release(); this->myProgressiveMesh = NULL; } this->isAPMesh = false; } else { // set to original detail maxFaces = this->myProgressiveMesh->GetMaxFaces(); minFaces = this->myProgressiveMesh->GetMinFaces() + 40; //set to max this->myProgressiveMesh->SetNumFaces(maxFaces); // this is now a progressive mesh! :) this->isAPMesh = true; } } void Object3d::generateAndUsePMesh() { this->generateAndUsePMesh(NULL); } bool Object3d::isPMesh() { return this->isAPMesh; } void Object3d::generatePhysicMesh(int type) { if(this->pVertices) { delete[] this->pVertices; this->pVertices = NULL; } if(this->pIndices) { delete[] this->pIndices; this->pIndices = NULL; } if(this->writeBuffer) { delete this->writeBuffer; this->writeBuffer = NULL; } this->shapeType = type; NxInitCooking(); int numVertices = (myMesh)->GetNumVertices(); int numFaces = (myMesh)->GetNumFaces(); int vertexSize = (myMesh)->GetNumBytesPerVertex(); //Vertex Data byte* verPointer; pVertices = new NxVec3[numVertices]; (myMesh)->LockVertexBuffer(0, (void**)&verPointer); bool changed=false; for(int i=0;i=1 && pVertices[i-1].y-pVertices[i].y!=0) { changed = true; } else if(i>=1 && i==numVertices-1 && changed==false) { pVertices[i].y+=0.0005f; } verPointer+=vertexSize; } (myMesh)->UnlockVertexBuffer(); //Indices Data WORD *indexPointer; pIndices = new DWORD[3*numFaces]; (myMesh)->LockIndexBuffer(0, (void**) &indexPointer); for(int i=0;i<3*numFaces;i++) { pIndices[i] = (WORD) indexPointer[i]; } (myMesh)->UnlockIndexBuffer(); if(type!=this->COL_CONVEX) { // Build the triangle mesh. this->pTriangleMeshDesc.numVertices = numVertices; this->pTriangleMeshDesc.numTriangles = numFaces; this->pTriangleMeshDesc.pointStrideBytes = sizeof(NxVec3); this->pTriangleMeshDesc.triangleStrideBytes = 3*sizeof(DWORD); this->pTriangleMeshDesc.points = pVertices; this->pTriangleMeshDesc.triangles = pIndices; this->pTriangleMeshDesc.flags = 0; if(type==this->COL_HEIGHTFIELD) { this->pTriangleMeshDesc.heightFieldVerticalAxis= NX_Y; this->pTriangleMeshDesc.heightFieldVerticalExtent= -1000.0f; } if(!this->pTriangleMeshDesc.isValid()) { this->myScene->manager->printToConsole("pTriangleMeshDesc IS NOT VALID!"); } if(writeBuffer!=NULL) delete this->writeBuffer; this->writeBuffer = new MemoryWriteBuffer; if(!NxCookTriangleMesh(this->pTriangleMeshDesc, *this->writeBuffer)) { this->myScene->manager->printToConsole("COOKING NOT SUCCESSFULL!!!!!"); } //Create the mesh from the cooked data. MemoryReadBuffer readBuffer(this->writeBuffer->data); this->pTriangleMesh = this->myScene->manager->pPhysicsSDK->createTriangleMesh(readBuffer); //Use PMap as coldet model? if(type==this->COL_PMAP) { std::string pmapFilename; pmapFilename = this->xfilename+".pmap"; NxPMap pPMap; pPMap.dataSize = 0; pPMap.data = NULL; // PMap stuff this->myScene->manager->printToConsole("trying to load pmap"); FILE* fp = fopen(pmapFilename.c_str(), "rb"); if(!fp) { // Not found => create PMap this->myScene->manager->printToConsole("please wait while precomputing pmap..."); if(NxCreatePMap(pPMap, *this->pTriangleMesh, 64)) { // The pmap has successfully been created, save it to disk for later use fp = fopen(pmapFilename.c_str(), "wb"); if(fp) { fwrite(pPMap.data, pPMap.dataSize, 1, fp); fclose(fp); fp = NULL; } //assign pmap to mesh this->pTriangleMesh->loadPMap(pPMap); // sdk created data => sdk deletes it NxReleasePMap(pPMap); } this->myScene->manager->printToConsole("...done!"); } else { // Found pmap file pPMap.dataSize = getFileSize(pmapFilename.c_str()); pPMap.data = new NxU8[pPMap.dataSize]; fread(pPMap.data, pPMap.dataSize, 1, fp); fclose(fp); //assign pmap to mesh this->pTriangleMesh->loadPMap(pPMap); //we created data => we delete it delete pPMap.data; } } this->pMeshShapeDesc.meshData = this->pTriangleMesh; if(!pMeshShapeDesc.isValid()) { this->myScene->manager->printToConsole("SHAPEDESCRIPTOR IS NOT VALID!"); } this->pActorDesc.shapes.pushBack(&pMeshShapeDesc); if(!this->pActorDesc.isValid()) { this->myScene->manager->printToConsole("generatePhysicsMesh:: ActorDescriptor is not valid!!"); return; } } else { this->pConvexDesc.numVertices = numVertices; this->pConvexDesc.pointStrideBytes = sizeof(NxVec3); this->pConvexDesc.points = this->pVertices; this->pConvexDesc.flags = NX_CF_COMPUTE_CONVEX; if(!this->pConvexDesc.isValid()) { this->myScene->manager->printToConsole("pConvexMeshDesc IS NOT VALID!"); } if(writeBuffer!=NULL) delete this->writeBuffer; this->writeBuffer = new MemoryWriteBuffer; if(NxCookConvexMesh(this->pConvexDesc, *this->writeBuffer)) { this->pConvexShapeDesc.meshData = this->myScene->manager->pPhysicsSDK->createConvexMesh(MemoryReadBuffer(this->writeBuffer->data)); if(this->pConvexShapeDesc.meshData) { this->pActorDesc.shapes.pushBack(&this->pConvexShapeDesc); } else { this->myScene->manager->printToConsole("Getting convexShapeDesc from SDK failed!"); } } else { this->myScene->manager->printToConsole("Cooking pConvexMeshDesc FAILED! MAYBE NX_CF_USE_LEGACY_COOKER FLAG WOULD HELP?"); } } NxCloseCooking(); } NxU32 Object3d::getFileSize(const char* name) { #ifndef SEEK_END #define SEEK_END 2 #endif FILE* File = fopen(name, "rb"); if(!File) return 0; fseek(File, 0, SEEK_END); NxU32 eof_ftell = ftell(File); fclose(File); return eof_ftell; } NxShapeDesc* Object3d::getPhysicShape() { switch(this->shapeType) { case this->COL_CONVEX: return &this->pConvexShapeDesc; break; case this->COL_MESH: return &this->pMeshShapeDesc; break; default: return NULL; break; } } Node* Object3d::clone() { //this->myScene->manager->printToConsole("Object3d.clone not implemented!"); Object3d* obj = (Object3d*) this->myScene->createNode(Scene::NODE_OBJECT3D,*this->father, true, false); this->cloneChildren(obj); return this->cloneObject3d(obj); } Object3d* Object3d::cloneObject3d(Object3d* obj) { obj->setMesh(&this->myMesh); //set number of materials obj->g_dwNumMaterials = (DWORD)this->Materials.size(); //set adjacency info obj->adjacencyInfo = this->adjacencyInfo; //set materials & textures: obj->Materials.resize(this->Materials.size()); obj->Textures.resize(this->Textures.size()); for (UINT i = 0; i < this->Materials.size(); i++) { obj->Materials[i] = this->Materials[i]; obj->Textures[i] = this->Textures[i]; } obj->minAABBox = this->minAABBox; obj->maxAABBox = this->maxAABBox; obj->setXFilename(this->xfilename); obj->isManagedByResourceManager = true; obj->setModelLoaded(true); obj->softKill = this->softKill; obj->softKillDuration = this->softKillDuration; //if(this->pActor!=NULL) { //Physic Stuff obj->pBodyDesc = this->pBodyDesc; obj->pActorDesc.body = &obj->pBodyDesc; obj->pActorDesc = this->pActorDesc; //obj->setBehaveAs(this->behaveAs); //} obj->aClone = true; return obj; } void Object3d::setDetail(Vector ObjectCenter) { if(this->isPMesh()) { //jetzt mus etwas passieren :) Vector dist = this->myScene->getActiveCamera()->getPosition() - ObjectCenter; float distance = sqrt(dist.x*dist.x + dist.y*dist.y + dist.z*dist.z); if (distance < 150) { this->myProgressiveMesh->SetNumFaces(this->maxFaces/4); } else { float maxdist = sqrt(2 * this->myScene->getWidth() * this->myScene->getWidth()); float factor = (maxdist - distance)/maxdist/2; float myNumberOfFaces = (maxFaces - minFaces) * factor; this->myProgressiveMesh->SetNumFaces((DWORD)myNumberOfFaces); //this->myProgressiveMesh->SetNumFaces(this->minFaces); } } } void Object3d::OnDestroyDevice( void* pUserContext ) { if(myMesh!=NULL && !(isManagedByResourceManager)) { SAFE_RELEASE(myMesh);//->Release(); } if(myProgressiveMesh!=NULL) { SAFE_RELEASE(myProgressiveMesh);//->Release(); } if(!(isManagedByResourceManager)) { delete [] adjacencyInfo; } this->Textures.clear(); this->Materials.clear(); } HRESULT Object3d::OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { if(this->xfilename.compare("")!=0) { this->loadMeshFromFile(this->xfilename); } return S_OK; } /*void Object3d::update(float dt) { Node::update(dt); if(this->timeToLive!=-100) { if(this->timeToLive<=this->softKillDuration) { this->doingSoftKill = true; this->softKillAlpha = this->timeToLive/this->softKillDuration; } } }*/