Revision: 1381
http://rigsofrods.svn.sourceforge.net/rigsofrods/?rev=1381&view=rev
Author: rorthomas
Date: 2010-05-08 22:13:25 +0000 (Sat, 08 May 2010)
Log Message:
-----------
added serializer basics, NOT WORKING YET!
Added Paths:
-----------
trunk/source/serializer/
trunk/source/serializer/CMakeLists.txt
trunk/source/serializer/serializationmodules.h
trunk/source/serializer/serializer.cpp
trunk/source/serializer/serializer.h
trunk/source/serializer/tests/
trunk/source/serializer/tests/main.cpp
Added: trunk/source/serializer/CMakeLists.txt
===================================================================
--- trunk/source/serializer/CMakeLists.txt (rev 0)
+++ trunk/source/serializer/CMakeLists.txt 2010-05-08 22:13:25 UTC (rev
1381)
@@ -0,0 +1,26 @@
+project(rorserializer)
+
+add_definitions("-D_UNICODE -DNOLANG")
+
+include_directories(${Ogre_INCLUDE_DIRS})
+link_directories (${Ogre_LIBRARY_DIRS})
+
+include_directories(.)
+include_directories(../main)
+
+# the lib
+FILE(GLOB sources "*.cpp")
+FILE(GLOB headers "*.h")
+add_library(serializer STATIC ${sources} ${headers} ../main/BeamData.h)
+windows_hacks(serializer)
+target_link_libraries(serializer ${Ogre_LIBRARIES})
+
+# the tests
+FILE(GLOB test_sources "tests/*.cpp")
+add_executable(serializer_test ${test_sources})
+windows_hacks(serializer_test)
+target_link_libraries(serializer_test ${Ogre_LIBRARIES} "serializer")
+
+
+
+
Added: trunk/source/serializer/serializationmodules.h
===================================================================
--- trunk/source/serializer/serializationmodules.h
(rev 0)
+++ trunk/source/serializer/serializationmodules.h 2010-05-08 22:13:25 UTC
(rev 1381)
@@ -0,0 +1,995 @@
+
+#include "serializer.h"
+
+#include "OgreLogManager.h"
+#include "Ogre.h"
+
+
+using namespace Ogre;
+
+// format description:
+// http://wiki.rigsofrods.com/pages/Truck_Description_File
+
+
+// global functions
+int add_beam(rig_t *rig, node_t *p1, node_t *p2, int type, float strength,
float spring, float damp, float length=-1, float shortbound=-1, float
longbound=-1, float precomp=1, float diameter=DEFAULT_BEAM_DIAMETER);
+void init_node(rig_t *rig, int pos, float x, float y, float z, int type, float
m=10, int iswheel=0, float friction=CHASSIS_FRICTION_COEF, int id=-1, int
wheelid=-1, float nfriction=NODE_FRICTION_COEF_DEFAULT, float
nvolume=NODE_VOLUME_COEF_DEFAULT, float nsurface=NODE_SURFACE_COEF_DEFAULT,
float nloadweight=NODE_LOADWEIGHT_DEFAULT);
+
+// the serialization modules
+
+class GlobalsSerializer : public RoRSerializationModule
+{
+public:
+ GlobalsSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "globals";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->globals = new globalssection_t();
+ memset(rig->globals, 0, sizeof(globalssection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "globals"))
+ return 1;
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ globalssection_t *g = rig->globals;
+
+ return checkRes(2, sscanf(line,"%f, %f, %s", &g->truckmass,
&g->loadmass, g->texname));
+ }
+
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+class NodeSerializer : public RoRSerializationModule
+{
+public:
+ NodeSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "nodes";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->nodes = new nodessection_t();
+ memset(rig->nodes, 0, sizeof(nodessection_t));
+ // set some defaults, important!
+ rig->nodes->gravitation = -9.81f;
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "nodes"))
+ return 1;
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ nodessection_t *n = rig->nodes;
+
+ if(!rig->globals)
+ {
+ LogManager::getSingleton().logMessage("Nodes section
must come after the globals section");
+ return -1;
+ }
+
+
+ // XXX: TOFIX: logging!
+ // parse nodes
+ int id = 0;
+ float x = 0, y = 0, z = 0, mass = 0;
+ char options[255] = "n";
+ int result = sscanf(line,"%i, %f, %f, %f, %s %f", &id, &x, &y,
&z, options, &mass);
+ // catch some errors
+ if (result < 4 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File " + String(fname) +" line " + StringConverter::toString(linecounter) + ".
trying to continue ...");
+ return 0;
+ }
+ if (id != n->free_node)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Node) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ":");
+ //LogManager::getSingleton().logMessage("Error: lost
sync in nodes numbers after node " + StringConverter::toString(free_node) +
"(got " + StringConverter::toString(id) + " instead)");
+ exit(2);
+ };
+
+ if(n->free_node >= MAX_NODES)
+ {
+ //LogManager::getSingleton().logMessage("nodes limit
reached ("+StringConverter::toString(MAX_NODES)+"): " + String(fname) +" line "
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+
+ Vector3 npos = n->startPos + n->startRot * Vector3(x, y, z);
+ init_node(rig, id, npos.x, npos.y, npos.z, NODE_NORMAL, 10, 0,
0, n->free_node, -1, n->default_node_friction, n->default_node_volume,
n->default_node_surface, n->default_node_loadweight);
+ n->nodes[id].iIsSkin = true;
+
+ if (n->default_node_loadweight >= 0.0f)
+ {
+ n->nodes[id].masstype = NODE_LOADED;
+ n->nodes[id].overrideMass = true;
+ n->nodes[id].mass = n->default_node_loadweight;
+ }
+
+ // merge options and default_node_options
+ strncpy(options, ((String(n->default_node_options) +
String(options)).c_str()), 250);
+
+ // now 'parse' the options
+ char *options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ switch (*options_pointer)
+ {
+ case 'l': // load node
+ if(mass != 0)
+ {
+ n->nodes[id].masstype =
NODE_LOADED;
+ n->nodes[id].overrideMass =
true;
+ n->nodes[id].mass =
mass;
+ }
+ else
+ {
+ n->nodes[id].masstype =
NODE_LOADED;
+ n->masscount++;
+ }
+ break;
+ case 'x': //exhaust
+ // XXX: TOFIX
+ //if (disable_smoke)
+ // break;
+ /*
+ if(s->smokeId == 0 && s->smokeRef != 0)
+ {
+ exhaust_t e;
+ e.emitterNode = id;
+ e.directionNode = smokeRef;
+ e.isOldFormat = true;
+ //smokeId=id;
+ e.smokeNode =
parent->createChildSceneNode();
+ //ParticleSystemManager
*pSysM=ParticleSystemManager::getSingletonPtr();
+ char wname[256];
+ sprintf(wname,
"exhaust-%zu-%s", exhausts.size(), truckname);
+ //if (pSysM)
smoker=pSysM->createSystem(wname, "tracks/Smoke");
+
e.smoker=manager->createParticleSystem(wname, "tracks/Smoke");
+ // ParticleSystem* pSys =
ParticleSystemManager::getSingleton().createSystem("exhaust", "tracks/Smoke");
+ if (!e.smoker)
+ continue;
+
e.smokeNode->attachObject(e.smoker);
+
e.smokeNode->setPosition(nodes[e.emitterNode].AbsPosition);
+ exhausts.push_back(e);
+
+ }
+ */
+ n->nodes[n->smokeId].isHot = true;
+ n->nodes[id].isHot = true;
+ n->smokeId = id;
+ break;
+ case 'y': //exhaust reference
+ // XXX: TOFIX
+ //if (disable_smoke)
+ // break;
+ /*
+ if(smokeId != 0 && smokeRef == 0)
+ {
+ exhaust_t e;
+ e.emitterNode = smokeId;
+ e.directionNode = id;
+ e.isOldFormat = true;
+ //smokeId=id;
+ e.smokeNode =
parent->createChildSceneNode();
+ //ParticleSystemManager
*pSysM=ParticleSystemManager::getSingletonPtr();
+ char wname[256];
+ sprintf(wname,
"exhaust-%zu-%s", exhausts.size(), truckname);
+ //if (pSysM)
smoker=pSysM->createSystem(wname, "tracks/Smoke");
+
e.smoker=manager->createParticleSystem(wname, "tracks/Smoke");
+ // ParticleSystem* pSys =
ParticleSystemManager::getSingleton().createSystem("exhaust", "tracks/Smoke");
+ if (!e.smoker)
+ continue;
+
e.smokeNode->attachObject(e.smoker);
+
e.smokeNode->setPosition(nodes[e.emitterNode].AbsPosition);
+ exhausts.push_back(e);
+
+ nodes[smokeId].isHot=true;
+ nodes[id].isHot=true;
+ }
+ */
+ n->smokeRef = id;
+ break;
+ case 'c': //contactless
+ n->nodes[id].contactless = 1;
+ break;
+ case 'h': //hook
+ // emulate the old behaviour using new
fancy hookgroups
+ // XXX: TOFIX
+ /*
+ hook_t h;
+ h.hookNode=&nodes[id];
+ h.locked=UNLOCKED;
+ h.lockNode=0;
+ h.lockTruck=0;
+ h.lockNodes=true;
+ h.group=-1;
+ hooks.push_back(h);
+ */
+ break;
+ case 'e': //editor
+ n->editorId = id;
+ break;
+ case 'b': //buoy
+ n->nodes[id].buoyancy = 10000.0f;
+ break;
+ case 'p': //diasble particles
+ n->nodes[id].disable_particles = true;
+ break;
+ case 'L': //Log data:
+
LogManager::getSingleton().logMessage("Node " + StringConverter::toString(id) +
" settings. Node load mass: " \
+ +
StringConverter::toString(n->nodes[id].mass) + ", friction coefficient: " +
StringConverter::toString(n->default_node_friction) \
+ + " and buoyancy volume
coefficient: " + StringConverter::toString(n->default_node_volume) + " Fluid
drag surface coefficient: " \
+ +
StringConverter::toString(n->default_node_surface)+ " Particle mode: " +
StringConverter::toString(n->nodes[id].disable_particles));
+ break;
+ }
+ options_pointer++;
+ }
+ n->free_node++;
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+class BeamSerializer : public RoRSerializationModule
+{
+public:
+ BeamSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "beams";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->beams = new beamssection_t();
+ memset(rig->beams, 0, sizeof(beamssection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "beams"))
+ return 1;
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ nodessection_t *n = rig->nodes;
+ beamssection_t *b = rig->beams;
+ if(!n)
+ {
+ LogManager::getSingleton().logMessage("Beams section
must come after the nodes section");
+ return -1;
+ }
+
+ // XXX: TOFIX: logging!
+ //parse beams
+ int id1, id2;
+ char options[50] = "v";
+ int type = BEAM_NORMAL;
+ int result = sscanf(line, "%i, %i, %s", &id1, &id2, options);
+ if (result < 2 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Beam) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+
+ if (id1 >= n->free_node || id2 >= n->free_node)
+ {
+ LogManager::getSingleton().logMessage("Error: unknown
node number in beams section ("
+
+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+ exit(3);
+ };
+
+ if(b->free_beam >= MAX_BEAMS)
+ {
+ //LogManager::getSingleton().logMessage("beams limit
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line "
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+
+ //skip if a beam already exists
+ int i;
+ for (i=0; i < b->free_beam; i++)
+ {
+ if ((b->beams[i].p1 == &n->nodes[id1] && b->beams[i].p2
== &n->nodes[id2]) \
+ || (b->beams[i].p1 == &n->nodes[id2] &&
b->beams[i].p2 == &n->nodes[id1]))
+ {
+ LogManager::getSingleton().logMessage("Skipping
duplicate beams: from node "+StringConverter::toString(id1)+" to node
"+StringConverter::toString(id2));
+ return 0;
+ }
+ }
+
+ // FIXME: separate init_beam and setup_beam to be able to set
all parameters after creation
+ // this is just ugly:
+ char *options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ if(*options_pointer=='i')
+ {
+ type = BEAM_INVISIBLE;
+ break;
+ }
+ options_pointer++;
+ }
+
+ int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], type, \
+ b->default_break * b->default_break_scale, \
+ b->default_spring * b->default_spring_scale, \
+ b->default_damp * b->default_damp_scale, \
+ -1, -1, -1, 1, \
+ b->default_beam_diameter);
+
+ // now 'parse' the options
+ options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ switch (*options_pointer)
+ {
+ case 'i': // invisible
+ b->beams[pos].type = BEAM_INVISIBLE;
+ break;
+ case 'v': // visible
+ b->beams[pos].type = BEAM_NORMAL;
+ break;
+ case 'r':
+ b->beams[pos].bounded = ROPE;
+ break;
+ case 's':
+ b->beams[pos].bounded = SUPPORTBEAM;
+ break;
+ }
+ options_pointer++;
+ }
+
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+class FileInfoSerializer : public RoRSerializationModule
+{
+public:
+ FileInfoSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = commandTrigger = "fileinfo";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->fileinfo = new fileinfo_t();
+ memset(rig->fileinfo, 0, sizeof(fileinfo_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ if(!initiated) initData(rig);
+ return checkRes(1, sscanf(line, "fileinfo %s, %i, %i",
rig->fileinfo->uniquetruckid, &rig->fileinfo->categoryid,
&rig->fileinfo->truckversion));
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ return sprintf(line, "fileinfo %s, %i, %i\n",
rig->fileinfo->uniquetruckid, rig->fileinfo->categoryid,
rig->fileinfo->truckversion);
+ }
+};
+
+
+class AuthorSerializer : public RoRSerializationModule
+{
+public:
+ AuthorSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = commandTrigger = "author";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->fileauthors = new fileauthors_t();
+ // beware or memsetting std::* !
+ rig->fileauthors->authors.clear();
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ if(!initiated) initData(rig);
+ fileauthors_t *a = rig->fileauthors;
+
+ int authorid;
+ char authorname[255], authoremail[255], authortype[255];
+ authorinfo_t author;
+ author.id = -1;
+ strcpy(author.email, "unknown");
+ strcpy(author.name, "unknown");
+ strcpy(author.type, "unknown");
+
+ int result = sscanf(line,"author %s %i %s %s", authortype,
&authorid, authorname, authoremail);
+ if (result < 1 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (author) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+ //replace '_' with ' '
+ char *tmp = authorname;
+ while (*tmp!=0) {if (*tmp=='_') *tmp=' ';tmp++;};
+ //fill the struct now
+ author.id = authorid;
+ if(strnlen(authortype, 250) > 0)
+ strncpy(author.type, authortype, 255);
+ if(strnlen(authorname, 250) > 0)
+ strncpy(author.name, authorname, 255);
+ if(strnlen(authoremail, 250) > 0)
+ strncpy(author.email, authoremail, 255);
+
+ a->authors.push_back(author);
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+class EngineSerializer : public RoRSerializationModule
+{
+public:
+ EngineSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "engine";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->engine = new enginesection_t();
+ memset(rig->engine, 0, sizeof(enginesection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "engine"))
+ return 1;
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ enginesection_t *e = rig->engine;
+
+ //parse engine
+ int numgears;
+ if(rig->driveable == MACHINE)
+ // ignore engine section on machines
+ return 1;
+
+ rig->driveable = TRUCK;
+ int result = sscanf(line, "%f, %f, %f, %f, %f, %f, %f, %f, %f,
%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", \
+ &e->minrpm, \
+ &e->maxrpm, \
+ &e->torque, \
+ &e->dratio, \
+ &e->rear, \
+
&e->gears[0],&e->gears[1],&e->gears[2],&e->gears[3],&e->gears[4],&e->gears[5],&e->gears[6],&e->gears[7],&e->gears[8],&e->gears[9],&e->gears[10],&e->gears[11],&e->gears[12],&e->gears[13],&e->gears[14],&e->gears[15]
+ );
+
+ if (result < 7 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Engine) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+ for (numgears = 0; numgears < MAX_GEARS; numgears++)
+ if (e->gears[numgears] <= 0)
+ break;
+ if (numgears < 3)
+ {
+ //LogManager::getSingleton().logMessage("Trucks with
less than 3 gears are not supported! " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+ e->numgears = numgears;
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+class CamerasSerializer : public RoRSerializationModule
+{
+public:
+ CamerasSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "cameras";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->cameras = new camerassection_t();
+ memset(rig->cameras, 0, sizeof(camerassection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "cameras"))
+ return 1;
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ camerassection_t *c = rig->cameras;
+
+ int nodepos, nodedir, dir;
+ int result = sscanf(line,"%i, %i, %i",&nodepos,&nodedir,&dir);
+ if (result < 3 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Camera) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+
+ if(c->free_camera > MAX_CAMERAS)
+ {
+ return -1;
+ }
+
+ c->cameras[c->free_camera].nodepos = nodepos;
+ c->cameras[c->free_camera].nodedir = nodedir;
+ c->cameras[c->free_camera].dir = dir;
+ c->free_camera++;
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+class ShocksSerializer : public RoRSerializationModule
+{
+public:
+ ShocksSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "shocks";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->shocks = new shockssection_t();
+ memset(rig->shocks, 0, sizeof(shockssection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "shocks"))
+ return 1;
+
+ if(!rig->beams)
+ {
+ LogManager::getSingleton().logMessage("Nodes section
must come after the beams section");
+ return -1;
+ }
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ shockssection_t *s = rig->shocks;
+ beamssection_t *b = rig->beams;
+ nodessection_t *n = rig->nodes;
+
+ int id1, id2;
+ float sp, d, sbound,lbound,precomp;
+ char options[50] = "n";
+ int result = sscanf(line, "%i, %i, %f, %f, %f, %f, %f, %s",
&id1, &id2, &sp, &d, &sbound, &lbound, &precomp, options);
+ if (result < 7 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Shock) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+
+ // checks ...
+ if(b->free_beam >= MAX_BEAMS)
+ {
+ //LogManager::getSingleton().logMessage("beams limit
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line "
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+ if(s->free_shock >= MAX_BEAMS)
+ {
+ //LogManager::getSingleton().logMessage("shock limit
reached ("+StringConverter::toString(MAX_SHOCKS)+"): " + String(fname) +" line
" + StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+ if (id1 >= n->free_node || id2 >= n->free_node)
+ {
+ LogManager::getSingleton().logMessage("Error: unknown
node number in shocks section
("+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+ exit(4);
+ }
+
+ // options
+ int htype = BEAM_HYDRO;
+ int shockflag = SHOCK_FLAG_NORMAL;
+
+ // now 'parse' the options
+ char *options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ switch (*options_pointer)
+ {
+ case 'i': // invisible
+ htype = BEAM_INVISIBLE_HYDRO;
+ shockflag |= SHOCK_FLAG_INVISIBLE;
+ break;
+ case 'l':
+ case 'L':
+ shockflag &= ~SHOCK_FLAG_NORMAL; // not
normal anymore
+ shockflag |= SHOCK_FLAG_LACTIVE;
+ s->free_active_shock++; // this has no
array associated with it. its just to determine if there are active shocks!
+ break;
+ case 'r':
+ case 'R':
+ shockflag &= ~SHOCK_FLAG_NORMAL; // not
normal anymore
+ shockflag |= SHOCK_FLAG_RACTIVE;
+ s->free_active_shock++; // this has no
array associated with it. its just to determine if there are active shocks!
+ break;
+ case 'm':
+ {
+ // metric values: calculate
sbound and lbound now
+ float beam_length =
n->nodes[id1].AbsPosition.distance(n->nodes[id2].AbsPosition);
+ sbound = sbound / beam_length;
+ lbound = lbound / beam_length;
+ }
+ break;
+ }
+ options_pointer++;
+ }
+ int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], htype,
b->default_break * 4.0f, sp, d, -1.0f, sbound, lbound, precomp);
+ b->beams[pos].shock = &s->shocks[s->free_shock];
+ s->shocks[s->free_shock].beamid = pos;
+ s->shocks[s->free_shock].flags = shockflag;
+ s->free_shock++;
+
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+class HydrosSerializer : public RoRSerializationModule
+{
+public:
+ HydrosSerializer(RoRSerializer *s) :
+ RoRSerializationModule(s)
+ {
+ // setup the base descriptions, etc, then register ourself
+ name = sectionTrigger = "hydros";
+ s->registerModuleSerializer(this);
+ }
+
+ void initData(rig_t *rig)
+ {
+ rig->hydros = new hydrossection_t();
+ memset(rig->hydros, 0, sizeof(hydrossection_t));
+ initiated = true;
+ }
+
+ int deserialize(char *line, rig_t *rig)
+ {
+ // ignore section header
+ if(!strcmp(line, "hydros"))
+ return 1;
+
+ if(!rig->beams)
+ {
+ LogManager::getSingleton().logMessage("Hydros section
must come after the beams section");
+ return -1;
+ }
+
+ if(!initiated) initData(rig);
+
+ // shortcuts
+ hydrossection_t *h = rig->hydros;
+ beamssection_t *b = rig->beams;
+ nodessection_t *n = rig->nodes;
+
+ //parse hydros
+ int id1, id2;
+ float ratio;
+ char options[50] = "n";
+ float startDelay=0;
+ float stopDelay=0;
+ char startFunction[50]="";
+ char stopFunction[50]="";
+
+ int result = sscanf(line, "%i, %i, %f, %s %f, %f, %s
%s",&id1,&id2,&ratio,options,&startDelay,&stopDelay,startFunction,stopFunction);
+ if (result < 3 || result == EOF)
+ {
+ //LogManager::getSingleton().logMessage("Error parsing
File (Hydro) " + String(fname) +" line " +
StringConverter::toString(linecounter) + ". trying to continue ...");
+ return 0;
+ }
+
+ int htype = BEAM_HYDRO;
+
+ // FIXME: separate init_beam and setup_beam to be able to set
all parameters after creation
+ // this is just ugly:
+ char *options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ if(*options_pointer=='i')
+ {
+ htype = BEAM_INVISIBLE_HYDRO;
+ break;
+ }
+ options_pointer++;
+ }
+
+ if (id1 >= n->free_node || id2 >= n->free_node)
+ {
+ LogManager::getSingleton().logMessage("Error: unknown
node number in hydros section
("+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+ exit(6);
+ };
+
+ if(b->free_beam >= MAX_BEAMS)
+ {
+ //LogManager::getSingleton().logMessage("beams limit
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line "
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+ if(h->free_hydro >= MAX_HYDROS)
+ {
+ //LogManager::getSingleton().logMessage("hydros limit
reached ("+StringConverter::toString(MAX_HYDROS)+"): " + String(fname) +" line
" + StringConverter::toString(linecounter) + ". trying to continue ...");
+ return -1;
+ }
+
+ int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], htype,
b->default_break * b->default_break_scale, b->default_spring *
b->default_spring_scale, b->default_damp * b->default_damp_scale);
+ h->hydro[h->free_hydro]=pos;
+ h->free_hydro++;
+ b->beams[pos].Lhydro = b->beams[pos].L;
+ b->beams[pos].hydroRatio = ratio;
+ b->beams[pos].animOption = 0;
+
+
+ // now 'parse' the options
+ options_pointer = options;
+ while (*options_pointer != 0)
+ {
+ switch (*options_pointer)
+ {
+ case 'i': // invisible
+ b->beams[pos].type =
BEAM_INVISIBLE_HYDRO;
+ break;
+ case 'n': // normal
+ b->beams[pos].type = BEAM_HYDRO;
+ b->beams[pos].hydroFlags |=
HYDRO_FLAG_DIR;
+ break;
+ case 's': // speed changing hydro
+ b->beams[pos].hydroFlags |=
HYDRO_FLAG_SPEED;
+ break;
+ case 'a':
+ b->beams[pos].hydroFlags |=
HYDRO_FLAG_AILERON;
+ break;
+ case 'r':
+ b->beams[pos].hydroFlags |=
HYDRO_FLAG_RUDDER;
+ break;
+ case 'e':
+ b->beams[pos].hydroFlags |=
HYDRO_FLAG_ELEVATOR;
+ break;
+ case 'u':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR);
+ break;
+ case 'v':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR);
+ break;
+ case 'x':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER);
+ break;
+ case 'y':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER);
+ break;
+ case 'g':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER);
+ break;
+ case 'h':
+ b->beams[pos].hydroFlags |=
(HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER);
+ break;
+ }
+ options_pointer++;
+ // if you use the i flag on its own, add the direction
to it
+ if(b->beams[pos].type == BEAM_INVISIBLE_HYDRO &&
!b->beams[pos].hydroFlags)
+ b->beams[pos].hydroFlags |= HYDRO_FLAG_DIR;
+ }
+ return result;
+ }
+ int serialize(char *line, rig_t *rig)
+ {
+ // XXX: TODO
+ return -1;
+ }
+};
+
+
+
+
+
+
+//////// HELPER functions below
+int add_beam(rig_t *rig, node_t *p1, node_t *p2, int type, float strength,
float spring, float damp, float length, float shortbound, float longbound,
float precomp, float diameter)
+{
+ // shortcuts
+ nodessection_t *n = rig->nodes;
+ beamssection_t *b = rig->beams;
+
+ int pos = b->free_beam;
+
+ b->beams[pos].p1 = p1;
+ b->beams[pos].p2 = p2;
+ b->beams[pos].p2truck = 0;
+ b->beams[pos].type = type;
+ if (length < 0)
+ {
+ //calculate the length
+ Vector3 t = p1->RelPosition - p2->RelPosition;
+ b->beams[pos].L = precomp * t.length();
+ } else
+ {
+ b->beams[pos].L = length;
+ }
+ b->beams[pos].k = spring;
+ b->beams[pos].d = damp;
+ b->beams[pos].broken = 0;
+ b->beams[pos].Lhydro = b->beams[pos].L;
+ b->beams[pos].refL = b->beams[pos].L;
+ b->beams[pos].hydroRatio = 0;
+ b->beams[pos].hydroFlags = 0;
+ b->beams[pos].animFlags = 0;
+ b->beams[pos].stress = 0;
+ b->beams[pos].lastforce = Vector3::ZERO;
+ b->beams[pos].iscentering = false;
+ b->beams[pos].isOnePressMode = 0;
+ b->beams[pos].isforcerestricted = false;
+ b->beams[pos].autoMovingMode = 0;
+ b->beams[pos].autoMoveLock = false;
+ b->beams[pos].pressedCenterMode = false;
+ b->beams[pos].disabled = false;
+ b->beams[pos].shock = 0;
+ if (b->default_deform < b->beam_creak)
+ b->default_deform = b->beam_creak;
+ b->beams[pos].default_deform = b->default_deform *
b->default_deform_scale;
+ b->beams[pos].minmaxposnegstress = b->default_deform *
b->default_deform_scale;
+ b->beams[pos].maxposstress = b->default_deform *
b->default_deform_scale;
+ b->beams[pos].maxnegstress = - b->beams[pos].maxposstress;
+ b->beams[pos].plastic_coef = b->default_plastic_coef;
+ b->beams[pos].default_plastic_coef = b->default_plastic_coef;
+ b->beams[pos].strength = strength;
+ b->beams[pos].iStrength = strength;
+ b->beams[pos].diameter = b->default_beam_diameter;
+ b->beams[pos].minendmass = 1;
+ b->beams[pos].diameter = diameter;
+ b->beams[pos].scale = 0;
+ if (shortbound != -1.0)
+ {
+ b->beams[pos].bounded = SHOCK1;
+ b->beams[pos].shortbound = shortbound;
+ b->beams[pos].longbound = longbound;
+
+ } else
+ {
+ b->beams[pos].bounded = NOSHOCK;
+ }
+
+ // no visuals here
+ b->beams[pos].mSceneNode = 0;
+ b->beams[pos].mEntity = 0;
+
+ b->free_beam++;
+ return pos;
+}
+
+void init_node(rig_t *rig, int pos, float x, float y, float z, int type, float
m, int iswheel, float friction, int id, int wheelid, float nfriction, float
nvolume, float nsurface, float nloadweight)
+{
+ nodessection *n = rig->nodes;
+ n->nodes[pos].AbsPosition = Vector3(x, y, z);
+ n->nodes[pos].RelPosition = Vector3(x, y, z) - n->origin;
+ n->nodes[pos].smoothpos = n->nodes[pos].AbsPosition;
+ n->nodes[pos].iPosition = Vector3(x, y, z);
+ if(pos != 0)
+ n->nodes[pos].iDistance = (n->nodes[0].AbsPosition -
Vector3(x, y, z)).squaredLength();
+ else
+ n->nodes[pos].iDistance = 0;
+ n->nodes[pos].Velocity = Vector3::ZERO;
+ n->nodes[pos].Forces = Vector3::ZERO;
+ n->nodes[pos].locked = m < 0.0;
+ n->nodes[pos].mass = m;
+ n->nodes[pos].iswheel = iswheel;
+ n->nodes[pos].wheelid = wheelid;
+ n->nodes[pos].friction_coef = nfriction;
+ n->nodes[pos].volume_coef = nvolume;
+ n->nodes[pos].surface_coef = nsurface;
+ if (nloadweight >= 0.0f)
+ {
+ n->nodes[pos].masstype = NODE_LOADED;
+ n->nodes[pos].overrideMass = true;
+ n->nodes[pos].mass = nloadweight;
+ }
+ n->nodes[pos].disable_particles = false;
+ n->nodes[pos].masstype = type;
+ n->nodes[pos].contactless = 0;
+ n->nodes[pos].contacted = 0;
+ n->nodes[pos].lockednode = 0;
+ n->nodes[pos].buoyanceForce = Vector3::ZERO;
+ n->nodes[pos].buoyancy = rig->globals->truckmass /
15.0f;//DEFAULT_BUOYANCY;
+ n->nodes[pos].lastdrag = Vector3(0,0,0);
+ // XXX: TOFIX
+ //n->nodes[pos].gravimass = Vector3(0,
RoRFrameListener::getGravity()*m, 0);
+ n->nodes[pos].gravimass = Vector3(0, n->gravitation * m, 0);
+ n->nodes[pos].wetstate = DRY;
+ n->nodes[pos].isHot = false;
+ n->nodes[pos].overrideMass = false;
+ n->nodes[pos].id = id;
+ n->nodes[pos].colltesttimer = 0;
+ n->nodes[pos].iIsSkin = false;
+ n->nodes[pos].isSkin = n->nodes[pos].iIsSkin;
+ n->nodes[pos].pos = pos;
+ if (type == NODE_LOADED)
+ n->masscount++;
+}
\ No newline at end of file
Added: trunk/source/serializer/serializer.cpp
===================================================================
--- trunk/source/serializer/serializer.cpp (rev 0)
+++ trunk/source/serializer/serializer.cpp 2010-05-08 22:13:25 UTC (rev
1381)
@@ -0,0 +1,137 @@
+
+#include "string.h"
+
+#include "serializer.h"
+#include "BeamData.h"
+#include "rormemory.h"
+#include "serializationmodules.h"
+
+#include "OgreResourceGroupManager.h"
+
+using namespace Ogre;
+
+
+RoRSerializer::RoRSerializer()
+{
+ // register all available modules :)
+ new GlobalsSerializer(this);
+ new NodeSerializer(this);
+ new BeamSerializer(this);
+
+ new FileInfoSerializer(this);
+ new AuthorSerializer(this);
+ new EngineSerializer(this);
+ new CamerasSerializer(this);
+ new ShocksSerializer(this);
+ new HydrosSerializer(this);
+}
+
+RoRSerializer::~RoRSerializer()
+{
+}
+
+int RoRSerializer::loadRig(Ogre::DataStreamPtr ds, rig_t *rig)
+{
+ //log(INFO, "loading Rig from %s ...", filename);
+ if(!rig) return 1;
+
+ // clear rig
+ memset(rig, 0, sizeof(rig_t));
+
+ // file things
+ char line[1024];
+ int linecounter = 0;
+ std::string activeSection;
+
+ // first: init rig
+ // TODO: IMPORTANT: FIX the rig_t initialization
+ rig->patchEngineTorque = false;
+ rig->forwardcommands = 0;
+ rig->importcommands = 0;
+ rig->wheel_contact_requested = false;
+ rig->rescuer = false;
+ rig->disable_default_sounds = false;
+
+ // read in truckname
+ ds->readLine(line, 1023);
+ strncpy(rig->realtruckname, line, 255);
+
+ // loop through all the files lines
+ SerializationContext ctx("foobar", 0);
+
+ while (!ds->eof())
+ {
+ size_t ll = ds->readLine(line, 1023);
+ linecounter++;
+ // ignore comments and empty lines
+ if (ll==0 || line[0]==';' || line[0]=='/')
+ continue;
+
+ // update context
+ ctx.lineNo = linecounter;
+
+ // now process the modules and try to parse the line
+ // -1 = no match
+ int res = processModules(line, rig, &ctx, activeSection);
+ if(!activeSection.empty() && res == 0)
+ {
+ LogManager::getSingleton().logMessage("line section
parsing with no result: " + String(line));
+ }
+ if(res == -1)
+ {
+ LogManager::getSingleton().logMessage("line with no
match: " + String(line));
+ }
+
+ }
+ LogManager::getSingleton().logMessage("done loading");
+ return 0;
+}
+
+int RoRSerializer::saveRig(std::string filename, rig_t *rig)
+{
+ // XXX: TODO
+ return 0;
+}
+
+int RoRSerializer::registerModuleSerializer(RoRSerializationModule *module)
+{
+ modules[module->getName()] = module;
+ return 0;
+}
+
+int RoRSerializer::processModules(char *line, rig_t *rig, SerializationContext
*ctx, std::string &activeSection)
+{
+ // parse for commands or other sections
+ std::map < std::string, RoRSerializationModule *>::iterator it;
+ for(it = modules.begin(); it != modules.end() ; it++)
+ {
+ // check if that command is matched
+ std::string *cmd = &it->second->commandTrigger;
+ if(cmd->size() && !strncmp(cmd->c_str(), line, cmd->size()))
+ {
+ // match, using this module
+ return it->second->deserialize(line, rig);
+ }
+
+ // check for a new section
+ std::string *sec = &it->second->sectionTrigger;
+ if(sec->size() && !strcmp(sec->c_str(), line))
+ {
+ // match, using this module
+ //set section as active
+ activeSection = it->first;
+ // parse this as well, could be that the section header
contains information as well
+ return it->second->deserialize(line, rig);
+ }
+ }
+
+ // if we are in a section, parse it in its module handler
+ if(!activeSection.empty())
+ {
+ // just try to use that section and ignore the others
+ return modules[activeSection]->deserialize(line, rig);
+ }
+
+ // no match
+ return -1;
+}
\ No newline at end of file
Added: trunk/source/serializer/serializer.h
===================================================================
--- trunk/source/serializer/serializer.h (rev 0)
+++ trunk/source/serializer/serializer.h 2010-05-08 22:13:25 UTC (rev
1381)
@@ -0,0 +1,105 @@
+/*
+This source file is part of Rigs of Rods
+Copyright 2005,2006,2007,2008,2009 Pierre-Michel Ricordel
+Copyright 2007,2008,2009 Thomas Fischer
+
+For more information, see http://www.rigsofrods.com/
+
+Rigs of Rods is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 3, as
+published by the Free Software Foundation.
+
+Rigs of Rods is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SERIALIZER_H__
+#define SERIALIZER_H__
+
+#include <string>
+#include <map>
+#include "RoRPrerequisites.h"
+
+#include "OgreDataStream.h"
+#include "OgreLogManager.h"
+
+class RoRSerializer;
+class RoRSerializationModule;
+
+// TODO: make this class more independend from Ogre
+
+class SerializationContext
+{
+public:
+ SerializationContext(std::string filename, int lineNo) :
+ filename(filename), lineNo(lineNo)
+ {
+ }
+
+ std::string filename;
+ int lineNo;
+};
+
+class RoRSerializer
+{
+ friend class RoRSerializationModule;
+public:
+ RoRSerializer();
+ ~RoRSerializer();
+
+ int loadRig(Ogre::DataStreamPtr ds, rig_t *rig);
+ int saveRig(std::string filename, rig_t *rig);
+
+ int registerModuleSerializer(RoRSerializationModule *module);
+protected:
+ int processModules(char *line, rig_t *rig, SerializationContext *ctx,
std::string &activeSection);
+
+ std::map < std::string, RoRSerializationModule *> modules;
+};
+
+class RoRSerializationModule
+{
+ friend class RoRSerializer;
+public:
+ RoRSerializationModule(RoRSerializer *s) :
+ s(s),
+ name(),
+ commandTrigger(),
+ sectionTrigger(),
+ initiated(false)
+ {
+ }
+
+ ~RoRSerializationModule() {}
+
+ virtual int deserialize(char *line, rig_t *rig) = 0;
+ virtual int serialize(char *line, rig_t *rig) = 0;
+
+ std::string getName() { return name; };
+protected:
+ RoRSerializer *s;
+ std::string name;
+ std::string commandTrigger;
+ std::string sectionTrigger;
+ bool initiated;
+
+ // some utils
+ int checkRes(int minArgs, int result)
+ {
+ if (result < 1 || result == EOF)
+ {
+ Ogre::LogManager::getSingleton().logMessage("Error
parsing " + this->getName() + "");
+ // TODO output more info about the problem
+ }
+ return result;
+ }
+
+ virtual void initData(rig_t *rig) = 0;
+
+};
+
+#endif // SERIALIZER_H__
Added: trunk/source/serializer/tests/main.cpp
===================================================================
--- trunk/source/serializer/tests/main.cpp (rev 0)
+++ trunk/source/serializer/tests/main.cpp 2010-05-08 22:13:25 UTC (rev
1381)
@@ -0,0 +1,35 @@
+
+// example program to test the serializer
+
+#include "serializer.h"
+#include "BeamData.h"
+#include "Ogre.h"
+
+using namespace std;
+using namespace Ogre;
+
+int main(int argc, char **argv)
+{
+ String filename = "b6b0UID-semi.truck";
+
+ // start ogre
+ Ogre::Root* root = new Ogre::Root("", "", "ogre.log");
+
+ // add resource dir
+
ResourceGroupManager::getSingleton().addResourceLocation("streams/dev/dafsemi.zip",
"Zip");
+ ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+ // load the file
+ DataStreamPtr ds =
ResourceGroupManager::getSingleton().openResource(filename);
+
+ // root struct
+ rig_t rig;
+
+ // create the serializer
+ RoRSerializer *s = new RoRSerializer();
+ int result = s->loadRig(ds, &rig);
+ printf("result: %d\n", result);
+
+ delete root;
+}
+
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
_______________________________________________
Rigsofrods-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel