* 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
This commit is contained in:
false_genesis 2008-04-03 23:11:23 +00:00
parent 025e084b09
commit 1d00b8b6ea
9 changed files with 97 additions and 128 deletions

View File

@ -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:"<<M2MeshName.c_str()<<"\n";
//logger->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;i<header.nVertices;i++)
{
file->read(&tempM2MVert,sizeof(ModelVertex));
@ -55,7 +62,9 @@ namespace irr
}
std::cout << "Read "<<M2MVertices.size()<<"/"<<header.nVertices<<" Vertices\n";
//Views == Sets of vertices. Usage yet unknown
if(M2MViews.size()>0)
M2MViews.clear();
ModelView tempM2MView;
file->seek(header.ofsViews);
for(u32 i =0;i<header.nViews;i++)
@ -67,6 +76,9 @@ namespace irr
logger->log("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 "<<M2MIndices.size()<<"/"<<M2MViews[0].nIndex<<" Indices\n";
//Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle
if(M2MTriangles.size()>0)
M2MTriangles.clear();
u16 tempM2Triangle;
file->seek(M2MViews[0].ofsTris);
for(u32 i =0;i<M2MViews[0].nTris;i++)
@ -86,13 +103,24 @@ namespace irr
}
std::cout << "Read "<<M2MTriangles.size()<<"/"<<M2MViews[0].nTris<<" Triangle Indices\n";
//Texture Lookup table.
file->seek(header.ofsTexLookup);
for(u32 i=0;i<header.nTexLookup;i++)
{
}
//Now, M2MTriangles refers to M2MIndices and not to M2MVertices.
//And M2MVertices are not usable like this. Thus we transform
if(M2Vertices.size()>0)
M2Vertices.clear();
for(u32 i=0;i<M2MVertices.size();i++)
{
M2Vertices.push_back(video::S3DVertex(M2MVertices[i].pos,M2MVertices[i].normal, video::SColor(255,100,100,100),M2MVertices[i].texcoords));
}
if(M2Indices.size()>0)
M2Indices.clear();
for(u32 i=0;i<M2MTriangles.size();i++)
{
@ -101,25 +129,27 @@ namespace irr
Mesh=new SMesh();
// irr 1.3
SMeshBuffer* IMB = new SMeshBuffer();
for(u32 i = 0; i < IMB->Vertices.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 "<<M2Vertices.size() <<" Vertices and " << M2Indices.size() <<" Indices to the MeshBuffer\n";
IMB->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;
}

View File

@ -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());
}
}

View File

@ -26,6 +26,7 @@ private:
irr::scene::ISceneNode* cube;
irr::scene::ITextSceneNode *text;
PseuInstance *_instance;
irr::core::vector3df rotation;
};

View File

@ -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<s32> scrn = _driver->getScreenSize();

View File

@ -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<irr::s32> _screendimension;
WorldPosition _worldpos_tmp;
bool _updateWorldPos;
};

View File

@ -65,7 +65,6 @@ public:
void RelocateCamera(void);
WorldPosition GetWorldPosition(void);
void SetWorldPosition(WorldPosition);
private:
ShTlTerrainSceneNode *terrain;

View File

@ -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<s32> 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())));
}

View File

@ -75,6 +75,10 @@ PseuInstance::~PseuInstance()
if(_gui)
_gui->Shutdown();
logdebug("Waiting for GUI to quit...");
while(_gui)
Sleep(1);
if(_guithread)
_guithread->wait();

View File

@ -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));
}
}