From 1d00b8b6ea786ee78c5d82fb56589d2c9acf6c4f Mon Sep 17 00:00:00 2001 From: false_genesis Date: Thu, 3 Apr 2008 23:11:23 +0000 Subject: [PATCH] * updated shlainn's M2 mesh loader (crash fixes and some more) * fixed terrain texturing & fog after irr 1.4 * fixed orientation<->rotation transformation, models now look into correct direction * code cleanups --- src/Client/GUI/CM2MeshFileLoader.cpp | 68 ++++++++++++++++++++-------- src/Client/GUI/DrawObject.cpp | 50 ++++++++++---------- src/Client/GUI/DrawObject.h | 1 + src/Client/GUI/PseuGUI.cpp | 19 -------- src/Client/GUI/PseuGUI.h | 23 ++++++---- src/Client/GUI/Scene.h | 1 - src/Client/GUI/SceneWorld.cpp | 58 ++---------------------- src/Client/PseuWoW.cpp | 4 ++ src/Client/World/WorldSession.cpp | 1 - 9 files changed, 97 insertions(+), 128 deletions(-) diff --git a/src/Client/GUI/CM2MeshFileLoader.cpp b/src/Client/GUI/CM2MeshFileLoader.cpp index 89b2d2e..b5ee476 100644 --- a/src/Client/GUI/CM2MeshFileLoader.cpp +++ b/src/Client/GUI/CM2MeshFileLoader.cpp @@ -8,8 +8,7 @@ namespace irr CM2MeshFileLoader::CM2MeshFileLoader(IrrlichtDevice* device):Device(device) { - Mesh = NULL; - aniMesh = NULL; + } CM2MeshFileLoader::~CM2MeshFileLoader() @@ -18,7 +17,7 @@ namespace irr } - bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename) const + bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename)const { return strstr(filename, ".m2")!=0; } @@ -42,12 +41,20 @@ namespace irr } else logger->log(L"header okay",ELL_INFORMATION); //Name -> not very important I think, but save it nontheless; + std::cout << "Name offset:" << header.nameOfs << "Name length:" << header.nameLength << "\n"; file->seek(header.nameOfs); file->read(&M2MeshName[0],header.nameLength); - logger->log("Mesh Name",M2MeshName.c_str(),ELL_INFORMATION); + std::cout << "Read name:"<log("Mesh Name",M2MeshName.c_str(),ELL_INFORMATION); + //Now we load all kinds of data from the file + + //Vertices + if(!M2MVertices.empty()) + M2MVertices.clear(); ModelVertex tempM2MVert; file->seek(header.ofsVertices); + for(u32 i =0;iread(&tempM2MVert,sizeof(ModelVertex)); @@ -55,7 +62,9 @@ namespace irr } std::cout << "Read "<0) + M2MViews.clear(); ModelView tempM2MView; file->seek(header.ofsViews); for(u32 i =0;ilog("Using View 0 for all further operations",ELL_INFORMATION); + //Vertex indices of a specific view. + if(M2MIndices.size()>0) + M2MIndices.clear(); u16 tempM2Index; file->seek(M2MViews[0].ofsIndex); @@ -77,6 +89,11 @@ namespace irr } std::cout << "Read "<0) + M2MTriangles.clear(); + u16 tempM2Triangle; file->seek(M2MViews[0].ofsTris); for(u32 i =0;iseek(header.ofsTexLookup); + for(u32 i=0;i0) + M2Vertices.clear(); for(u32 i=0;i0) + M2Indices.clear(); for(u32 i=0;iVertices.size(); i++) - IMB->Vertices.push_back(M2Vertices[i]); - for(u32 i = 0; i < IMB->Indices.size(); i++) - IMB->Indices.push_back(M2Indices[i]); - // irr 1.4 - //IMB->append(M2Vertices.const_pointer(),M2Vertices.size(),M2Indices.const_pointer(),M2Indices.size()); - //Device->getSceneManager()->getMeshManipulator()->recalculateNormals(IMB,false); + SMeshBuffer* IMB = new SMeshBuffer; + while(Mesh->getMeshBufferCount()>0) + { + Mesh->MeshBuffers.erase(0); + } + + std::cout << "Sending "<append(M2Vertices.const_pointer(),M2Vertices.size(),M2Indices.const_pointer(),M2Indices.size()); + IMB->recalculateBoundingBox(); Mesh->addMeshBuffer(IMB); - //IMesh* tangentMesh = Device->getSceneManager()->getMeshManipulator()->createMeshWithTangents(Mesh); - aniMesh= new SAnimatedMesh(); - aniMesh->addMesh(Mesh); - aniMesh->recalculateBoundingBox(); - IMB->drop(); + aniMesh= new SAnimatedMesh(); + + + aniMesh->addMesh(Mesh); Mesh->drop(); + Mesh = 0; + + aniMesh->recalculateBoundingBox(); return aniMesh; } diff --git a/src/Client/GUI/DrawObject.cpp b/src/Client/GUI/DrawObject.cpp index c140e2e..3c2b5c4 100644 --- a/src/Client/GUI/DrawObject.cpp +++ b/src/Client/GUI/DrawObject.cpp @@ -39,35 +39,40 @@ void DrawObject::_Init(void) if(!cube && _obj->IsWorldObject()) // only world objects have coords and can be drawn { uint32 displayid = _obj->IsUnit() ? _obj->GetUInt32Value(UNIT_FIELD_DISPLAYID) : 0; // TODO: in case its GO get it from proto data - uint32 modelid = _instance->dbmgr.GetDB("creaturedisplayinfo").GetField(displayid).GetInteger("model"); + SCPDatabase& cdi = _instance->dbmgr.GetDB("creaturedisplayinfo"); + SCPField& crdata = cdi.GetField(displayid); + uint32 modelid = crdata.GetInteger("model"); std::string modelfile = std::string("data/model/") + _instance->dbmgr.GetDB("creaturemodeldata").GetField(modelid).GetString("file"); - //scene::IAnimatedMesh *mesh = _smgr->getMesh(modelfile.c_str()); - // ok we use a model that works for sure until crashs with some M2 files, especially character models, are fixed - /*scene::IAnimatedMesh *mesh = _smgr->getMesh("data/model/gyrocopter.m2"); + uint32 opacity = crdata.GetInteger("opacity"); + scene::IAnimatedMesh *mesh = _smgr->getMesh(modelfile.c_str()); if(mesh) { + rotation.X = 270.0f; // M2 models are stored "lying on the side" - this puts them standing + // ok, this f*cks up the text scene node, but shouldnt be such a problem right now, + // until the M2-loader has been corrected so far that this line can be removed cube = _smgr->addAnimatedMeshSceneNode(mesh); //video::ITexture *tex = _device->getVideoDriver()->getTexture("data/misc/square.jpg"); //cube->setMaterialTexture(0, tex); - //tex->drop(); } else - {*/ - cube = _smgr->addCubeSceneNode(2); - //} - cube->setName("OBJECT"); - //cube->setPosition(irr::core::vector3di(100,100,100)); - cube->setRotation(core::vector3df(0,0,0)); - - if(_obj->IsPlayer()) { - cube->getMaterial(0).DiffuseColor.set(255,255,0,0); + cube = _smgr->addCubeSceneNode(2); + } + cube->getMaterial(0).DiffuseColor.setAlpha(opacity); + cube->setName("OBJECT"); + cube->getMaterial(0).setFlag(video::EMF_LIGHTING, true); + cube->getMaterial(0).setFlag(video::EMF_FOG_ENABLE, true); + + text=_smgr->addTextSceneNode(_guienv->getBuiltInFont(), L"TestText" , irr::video::SColor(255,255,255,255),cube, irr::core::vector3df(0,5,0)); + if(_obj->IsPlayer()) + { + text->setTextColor(irr::video::SColor(255,255,0,0)); } else if(_obj->IsCreature()) { - cube->getMaterial(0).DiffuseColor.set(255,0,255,0); + text->setTextColor(irr::video::SColor(255,0,0,255)); } - text=_smgr->addTextSceneNode(_guienv->getBuiltInFont(), L"TestText" , irr::video::SColor(255,255,255,255),cube, irr::core::vector3df(0,5,0)); + } DEBUG(logdebug("initialize DrawObject 0x%X obj: 0x%X "I64FMT,this,_obj,_obj->GetGUID())) @@ -84,21 +89,13 @@ void DrawObject::Draw(void) { WorldPosition pos = ((WorldObject*)_obj)->GetPosition(); cube->setPosition(irr::core::vector3df(-pos.x,pos.z,-pos.y)); - if(_obj->IsPlayer()) - { - cube->getMaterial(0).DiffuseColor.set(255,255,0,0); - text->setTextColor(irr::video::SColor(255,255,0,0)); - } - else if(_obj->IsCreature()) - { - cube->getMaterial(0).DiffuseColor.set(255,0,0,255); - text->setTextColor(irr::video::SColor(255,0,0,255)); - } + rotation.Y = O_TO_IRR(pos.o); float s = _obj->GetFloatValue(OBJECT_FIELD_SCALE_X); if(s <= 0) s = 1; cube->setScale(irr::core::vector3df(s,s,s)); + cube->setRotation(rotation); //cube->setRotation(irr::core::vector3df(0,RAD_TO_DEG(((WorldObject*)_obj)->GetO()),0)); irr::core::stringw tmp = L""; @@ -113,6 +110,7 @@ void DrawObject::Draw(void) tmp += _obj->GetName().c_str(); } text->setText(tmp.c_str()); + } } diff --git a/src/Client/GUI/DrawObject.h b/src/Client/GUI/DrawObject.h index 827a10d..5555545 100644 --- a/src/Client/GUI/DrawObject.h +++ b/src/Client/GUI/DrawObject.h @@ -26,6 +26,7 @@ private: irr::scene::ISceneNode* cube; irr::scene::ITextSceneNode *text; PseuInstance *_instance; + irr::core::vector3df rotation; }; diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index d3bda15..7c8b3bd 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -44,7 +44,6 @@ PseuGUI::PseuGUI() _guienv = NULL; _scene = NULL; _passtime = _lastpasstime = _passtimediff = 0; - _updateWorldPos = false; } PseuGUI::~PseuGUI() @@ -186,8 +185,6 @@ void PseuGUI::Run(void) if(_scene && _initialized) { - if(_updateWorldPos) - SetWorldPosition(_worldpos_tmp); _scene->OnUpdate(_passtimediff); } @@ -293,22 +290,6 @@ WorldPosition PseuGUI::GetWorldPosition(void) return WorldPosition(); } -// used to notify the SceneWorld about a position change the server sent to us -void PseuGUI::SetWorldPosition(WorldPosition wp) -{ - // buffer new position if the scene is not (yet) a world scene - _worldpos_tmp = wp; - if(_scene && _scene->GetState() == SCENESTATE_WORLD) - { - _updateWorldPos = false; - ((SceneWorld*)_scene)->SetWorldPosition(wp); - } - else - { - _updateWorldPos = true; - } -} - void PseuGUI::_HandleWindowResize(void) { dimension2d scrn = _driver->getScreenSize(); diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index d1ce51c..d6c42fb 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -34,13 +34,21 @@ enum DriverIDs #define ANGLE_STEP (M_PI/180.0f) #define DEG_TO_RAD(x) ((x)*ANGLE_STEP) #define RAD_TO_DEG(x) ((x)/ANGLE_STEP) -#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) ) -#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) ) -#define IRR_TO_O(x) (DEG_TO_RAD(x) + ((M_PI*3.0f)/2.0f)) -#define O_TO_IRR(x) (((M_PI/3.0f)*2.0f) - DEG_TO_RAD(x)) +#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : ( ((x)<0) ? ((x)+(2*M_PI)) : (x) ) ) +#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : ( ((x)<0) ? ((x)+360) : (x) ) ) +#define IRR_TO_O(x) RAD_FIX(M_PI-DEG_TO_RAD(x)) // convert World orientation (rad) into irrlicht rotation (deg) +#define O_TO_IRR(x) DEG_FIX(180-RAD_TO_DEG(x)) // ... and the other way around + +inline irr::core::vector3df WPToIrr(WorldPosition wp) +{ + return irr::core::vector3df(-wp.x, wp.z, -wp.y); +} + +inline WorldPosition IrrToWP(irr::core::vector3df v, float o_rad) +{ + return WorldPosition(-v.X, v.Z, -v.Y, RAD_FIX(IRR_TO_O(o_rad))); // rotate by 90° and fix value +} -#define COORD_SCALE_VALUE_X 0.336f -#define COORD_SCALE_VALUE_Y 0.2f class PseuGUIRunnable : public ZThread::Runnable { @@ -90,7 +98,6 @@ public: // helpers WorldPosition GetWorldPosition(void); - void SetWorldPosition(WorldPosition); private: void _Init(void); @@ -111,8 +118,6 @@ private: irr::ITimer *_timer; uint32 _passtime, _lastpasstime, _passtimediff; irr::core::dimension2d _screendimension; - WorldPosition _worldpos_tmp; - bool _updateWorldPos; }; diff --git a/src/Client/GUI/Scene.h b/src/Client/GUI/Scene.h index cb5ca7c..9360437 100644 --- a/src/Client/GUI/Scene.h +++ b/src/Client/GUI/Scene.h @@ -65,7 +65,6 @@ public: void RelocateCamera(void); WorldPosition GetWorldPosition(void); - void SetWorldPosition(WorldPosition); private: ShTlTerrainSceneNode *terrain; diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index ab4cb87..1c1b027 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -170,7 +170,7 @@ void SceneWorld::OnUpdate(s32 timediff) str += camera->getPosition().Z; str += L"\n"; str += " ## HEAD: "; - str += DEG_TO_RAD(camera->getHeading()); + str += IRR_TO_O(camera->getHeading()); str += L" Pos: "; str = ((((((str + wp.x) + L" | ") + wp.y) + L" | ") + wp.z) + L" | OR:") + wp.o; str += L" -- Terrain: Sectors: "; @@ -210,9 +210,9 @@ void SceneWorld::InitTerrain(void) terrain = new ShTlTerrainSceneNode(smgr,mapsize,mapsize,tilesize,meshsize); terrain->drop(); terrain->follow(camera->getNode()); - terrain->setMaterialTexture(0, driver->getTexture("data/misc/dirt_test.jpg")); - terrain->setMaterialFlag(video::EMF_LIGHTING, true); - terrain->setMaterialFlag(video::EMF_FOG_ENABLE, true); + terrain->getMaterial(0).setTexture(0, driver->getTexture("data/misc/dirt_test.jpg")); + terrain->getMaterial(0).setFlag(video::EMF_LIGHTING, true); + terrain->getMaterial(0).setFlag(video::EMF_FOG_ENABLE, true); } @@ -355,55 +355,7 @@ WorldPosition SceneWorld::GetWorldPosition(void) { // TODO: later do not use CAMERA, but CHARACTER position, as soon as camera is changed from 1st to 3rd person view // and floating around character in the middle - vector3df cam = camera->getPosition(); - // TODO: need to correct camera values, the coords irrlicht returns are not suitable - - // get the current maptile and use the coords of the top-left corner as relative positions - MapTile *tile = mapmgr->GetCurrentTile(); - if(!tile) - { - logerror("SceneWorld::GetWorldPosition failed, MapTile not loaded!"); - return WorldPosition(); - } - - float mapx = tile->GetBaseX(); - float mapy = tile->GetBaseY(); - - // the following formulas are NOT correct, just estimated. in most places they will differ from real expected values a lot! - float relx = cam.X * COORD_SCALE_VALUE_X + CHUNKSIZE; - float rely = cam.Z * COORD_SCALE_VALUE_Y + CHUNKSIZE; - - float o = IRR_TO_O(camera->getHeading()) + ((M_PI*3.0f)/2.0f); - return WorldPosition(mapx - relx, mapy - rely, cam.Y, RAD_FIX(o) ); -} - -void SceneWorld::SetWorldPosition(WorldPosition wp) -{ - return; - UpdateTerrain(); - vector3df cam; - dimension2d tsize = terrain->getSize(); - MapTile *tile = mapmgr->GetTile(MapMgr::GetGridCoord(wp.x), MapMgr::GetGridCoord(wp.y)); - ASSERT(tile == mapmgr->GetCurrentTile()); // for debugging; we should already be located on the new tile - if(!tile) - { - logerror("SceneWorld::SetWorldPosition(): MapTile not loaded!"); - return; - } - cam.X = tile->GetBaseX() - wp.x + (tsize.Width * UNITSIZE); - cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE); - float heading = O_TO_IRR(wp.o); - float heading_diff = camera->getHeading() - heading; - //logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading); - //camera->turnLeft(heading_diff); - - // TODO: - // - correct the above formulas - // - find out terrain height where the camera should be set - // - set camera to correct position - // - correct camera turning - //camera->setPosition(cam); - //camera->turnRight(heading_diff); + return IrrToWP(camera->getPosition(), IRR_TO_O(DEG_TO_RAD(camera->getHeading()))); } diff --git a/src/Client/PseuWoW.cpp b/src/Client/PseuWoW.cpp index 9643840..ec6a763 100644 --- a/src/Client/PseuWoW.cpp +++ b/src/Client/PseuWoW.cpp @@ -75,6 +75,10 @@ PseuInstance::~PseuInstance() if(_gui) _gui->Shutdown(); + logdebug("Waiting for GUI to quit..."); + while(_gui) + Sleep(1); + if(_guithread) _guithread->wait(); diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index a6b3e04..d61f1d7 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -1213,7 +1213,6 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket) if(PseuGUI *gui = GetInstance()->GetGUI()) { gui->SetSceneState(SCENESTATE_WORLD); - gui->SetWorldPosition(WorldPosition(x,y,z,o)); } }