* 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:
parent
025e084b09
commit
1d00b8b6ea
@ -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;
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ private:
|
||||
irr::scene::ISceneNode* cube;
|
||||
irr::scene::ITextSceneNode *text;
|
||||
PseuInstance *_instance;
|
||||
irr::core::vector3df rotation;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -65,7 +65,6 @@ public:
|
||||
void RelocateCamera(void);
|
||||
|
||||
WorldPosition GetWorldPosition(void);
|
||||
void SetWorldPosition(WorldPosition);
|
||||
|
||||
private:
|
||||
ShTlTerrainSceneNode *terrain;
|
||||
|
||||
@ -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())));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -75,6 +75,10 @@ PseuInstance::~PseuInstance()
|
||||
|
||||
if(_gui)
|
||||
_gui->Shutdown();
|
||||
logdebug("Waiting for GUI to quit...");
|
||||
while(_gui)
|
||||
Sleep(1);
|
||||
|
||||
if(_guithread)
|
||||
_guithread->wait();
|
||||
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user