loki1985 wrote:but the real world data DFFs are stored in the archive gta3.img.
ahhhh, got them !!!
well, first I found a bug with the textures, they are all mirrored, you can see this on surfaces with text on it:
![Image](http://people.freenet.de/abusoft/gtatextflip2.jpg)
I only tested it with GTA3 though...
to load the maps I wrote a map-loader class that parses the ipl files (GTA3, GTAVC and GTASA)...
![Wink ;)](./images/smilies/icon_wink.gif)
maybe you can use it, too...
cGTALoader.h
Code: Select all
#ifndef CGTALOADER_H
#define CGTALOADER_H
#include <irrlicht.h>
#include "CDFFMeshFileLoader.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
enum gtaVersion{
gta3 = 0,
gtaVC,
gtaSA
};
struct datMesh{
s32 id;
stringc file;
vector3df pos;
vector3df scl;
vector3df rot;
};
class cGTALoader{
private:
ISceneManager* sceneManager;
IrrlichtDevice* irrDevice;
bool loadMesh(datMesh mesh, ISceneNode* root, bool asOctTree);
datMesh parse3(stringc s);
datMesh parseVC(stringc s);
datMesh parseSA(stringc s);
public:
cGTALoader(IrrlichtDevice* dvc);
ISceneNode* loadMap(char* iplFile, gtaVersion v, bool asOctTree = true);
};
#endif // CGTALOADER_H
cGTALoader.cpp
Code: Select all
#include "cGTALoader.h"
cGTALoader::cGTALoader(IrrlichtDevice* dvc){
irrDevice = dvc;
sceneManager = irrDevice->getSceneManager();
CDFFMeshFileLoader* dffLoader = new CDFFMeshFileLoader(irrDevice);
sceneManager->addExternalMeshLoader(dffLoader);
}
datMesh cGTALoader::parse3(stringc s){
datMesh neu;
int p;
/*! GTA3
inst
id, name, x, y, z, sx, sy, sz, rx, ry, rz, rw
end
*/
// get ID
p = s.findFirst(',');
s[p] = '\0';
stringc ID = s.c_str();
ID.trim();
s = &s[p + 1];
neu.id = atoi(ID.c_str());
// get Name
p = s.findFirst(',');
s[p] = '\0';
neu.file = s.c_str();
neu.file.trim();
neu.file += ".dff";
s = &s[p + 1];
// get posX
p = s.findFirst(',');
s[p] = '\0';
stringc pX = s.c_str();
pX.trim();
s = &s[p + 1];
neu.pos.X = atof(pX.c_str());
// get posY
p = s.findFirst(',');
s[p] = '\0';
stringc pY = s.c_str();
pY.trim();
s = &s[p + 1];
neu.pos.Y = atof(pY.c_str());
// get posZ
p = s.findFirst(',');
s[p] = '\0';
stringc pZ = s.c_str();
pZ.trim();
s = &s[p + 1];
neu.pos.Z = atof(pZ.c_str());
// get sclX
p = s.findFirst(',');
s[p] = '\0';
stringc sX = s.c_str();
sX.trim();
s = &s[p + 1];
neu.scl.X = atof(sX.c_str());
// get sclY
p = s.findFirst(',');
s[p] = '\0';
stringc sY = s.c_str();
sY.trim();
s = &s[p + 1];
neu.scl.Y = atof(sY.c_str());
// get sclZ
p = s.findFirst(',');
s[p] = '\0';
stringc sZ = s.c_str();
sZ.trim();
s = &s[p + 1];
neu.scl.Z = atof(sZ.c_str());
// get rotX
p = s.findFirst(',');
s[p] = '\0';
stringc rX = s.c_str();
rX.trim();
s = &s[p + 1];
neu.rot.X = atof(rX.c_str());
// get rotY
p = s.findFirst(',');
s[p] = '\0';
stringc rY = s.c_str();
rY.trim();
s = &s[p + 1];
neu.rot.Y = atof(rY.c_str());
// get rotZ
p = s.findFirst(',');
s[p] = '\0';
stringc rZ = s.c_str();
rZ.trim();
s = &s[p + 1];
neu.rot.Z = atof(rZ.c_str());
return neu;
}
datMesh cGTALoader::parseVC(stringc s){
datMesh neu;
int p;
/*! GTAVC
inst
id, name, int, x, y, z, sx, sy, sz, rx, ry, rz, rw
end
*/
// get ID
p = s.findFirst(',');
s[p] = '\0';
stringc ID = s.c_str();
ID.trim();
s = &s[p + 1];
neu.id = atoi(ID.c_str());
// get Name
p = s.findFirst(',');
s[p] = '\0';
neu.file = s.c_str();
neu.file.trim();
neu.file += ".dff";
s = &s[p + 1];
// get Interior Number
p = s.findFirst(',');
s = &s[p + 1];
// get posX
p = s.findFirst(',');
s[p] = '\0';
stringc pX = s.c_str();
pX.trim();
s = &s[p + 1];
neu.pos.X = atof(pX.c_str());
// get posY
p = s.findFirst(',');
s[p] = '\0';
stringc pY = s.c_str();
pY.trim();
s = &s[p + 1];
neu.pos.Y = atof(pY.c_str());
// get posZ
p = s.findFirst(',');
s[p] = '\0';
stringc pZ = s.c_str();
pZ.trim();
s = &s[p + 1];
neu.pos.Z = atof(pZ.c_str());
// get sclX
p = s.findFirst(',');
s[p] = '\0';
stringc sX = s.c_str();
sX.trim();
s = &s[p + 1];
neu.scl.X = atof(sX.c_str());
// get sclY
p = s.findFirst(',');
s[p] = '\0';
stringc sY = s.c_str();
sY.trim();
s = &s[p + 1];
neu.scl.Y = atof(sY.c_str());
// get sclZ
p = s.findFirst(',');
s[p] = '\0';
stringc sZ = s.c_str();
sZ.trim();
s = &s[p + 1];
neu.scl.Z = atof(sZ.c_str());
// get rotX
p = s.findFirst(',');
s[p] = '\0';
stringc rX = s.c_str();
rX.trim();
s = &s[p + 1];
neu.rot.X = atof(rX.c_str());
// get rotY
p = s.findFirst(',');
s[p] = '\0';
stringc rY = s.c_str();
rY.trim();
s = &s[p + 1];
neu.rot.Y = atof(rY.c_str());
// get rotZ
p = s.findFirst(',');
s[p] = '\0';
stringc rZ = s.c_str();
rZ.trim();
s = &s[p + 1];
neu.rot.Z = atof(rZ.c_str());
return neu;
}
datMesh cGTALoader::parseSA(stringc s){
datMesh neu;
int p;
/*! GTASA
inst
id, name, int, x, y, z, rx, ry, rz, rw, lod
end
*/
// get ID
p = s.findFirst(',');
s[p] = '\0';
stringc ID = s.c_str();
ID.trim();
s = &s[p + 1];
neu.id = atoi(ID.c_str());
// get Name
p = s.findFirst(',');
s[p] = '\0';
neu.file = s.c_str();
neu.file.trim();
neu.file += ".dff";
s = &s[p + 1];
// get Interior Number
p = s.findFirst(',');
s = &s[p + 1];
// get posX
p = s.findFirst(',');
s[p] = '\0';
stringc pX = s.c_str();
pX.trim();
s = &s[p + 1];
neu.pos.X = atof(pX.c_str());
// get posY
p = s.findFirst(',');
s[p] = '\0';
stringc pY = s.c_str();
pY.trim();
s = &s[p + 1];
neu.pos.Y = atof(pY.c_str());
// get posZ
p = s.findFirst(',');
s[p] = '\0';
stringc pZ = s.c_str();
pZ.trim();
s = &s[p + 1];
neu.pos.Z = atof(pZ.c_str());
// get rotX
p = s.findFirst(',');
s[p] = '\0';
stringc rX = s.c_str();
rX.trim();
s = &s[p + 1];
neu.rot.X = atof(rX.c_str());
// get rotY
p = s.findFirst(',');
s[p] = '\0';
stringc rY = s.c_str();
rY.trim();
s = &s[p + 1];
neu.rot.Y = atof(rY.c_str());
// get rotZ
p = s.findFirst(',');
s[p] = '\0';
stringc rZ = s.c_str();
rZ.trim();
s = &s[p + 1];
neu.rot.Z = atof(rZ.c_str());
// get sclX (always 1,1,1)
neu.scl = vector3df(1,1,1);
return neu;
}
ISceneNode* cGTALoader::loadMap(char* iplFile, gtaVersion v, bool asOctTree){
array<datMesh> lstMeshes;
char inp[1024];
bool inINST = false;
if(FILE* fTMP = fopen(iplFile, "r")){
while(!feof(fTMP)){
if(fgets(inp, 1024, fTMP) != NULL){
stringc test = inp;
test.trim();
if(!inINST){
if(test.equals_ignore_case("inst")) inINST = true;
}else{
if(test.equals_ignore_case("end")) break;
datMesh neu;
switch(v){
case gta3:
neu = parse3(test);
break;
case gtaVC:
neu = parseVC(test);
break;
case gtaSA:
neu = parseSA(test);
break;
}
lstMeshes.push_back(neu);
}
}
}
fclose(fTMP);
}
ISceneNode* root = sceneManager->addEmptySceneNode();
for(u32 t = 0; t < lstMeshes.size(); ++t)
loadMesh(lstMeshes[t], root, asOctTree);
return root;
}
bool cGTALoader::loadMesh(datMesh mesh, ISceneNode* root, bool asOctTree){
IAnimatedMesh* m = sceneManager->getMesh(mesh.file.c_str());
if(!m) return false;
ISceneNode* node;
if(asOctTree){
node = sceneManager->addOctTreeSceneNode(m, root, mesh.id);
}else{
node = sceneManager->addAnimatedMeshSceneNode(m, root, mesh.id);
}
if(!node) return false;
node->setPosition(mesh.pos);
node->setRotation(mesh.rot);
node->setScale(mesh.scl);
return true;
}
and a test program:
Code: Select all
#include "cGTALoader.h"
int main(){
IrrlichtDevice *device = createDevice(EDT_DIRECT3D9, dimension2d<s32>(640, 480), 16, false, false, false, 0);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
device->setWindowCaption(L"GTA-Loader");
// for easyness I packed all mesh and texture files in an archive
device->getFileSystem()->addZipFileArchive("gta3img.zip");
// load a map via ipl file
cGTALoader gtaLoader(device);
ISceneNode* map = gtaLoader.loadMap("maps\\comSW.ipl", gta3);
map->setRotation(vector3df(-90,0,0));
map->setScale(vector3df(2,2,2));
// setup and run Irrlicht render loop
smgr->addCameraSceneNodeFPS(0,50,50);
device->getCursorControl()->setVisible(false);
while(device->run()){
driver->beginScene(true, true, video::SColor(0,0,0,200));
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}