#include #include #include #include #include #include #include #include #include #include #include using namespace std; int main(int argc, char *argv[]) { if (argc < 2) { cerr << "not enough arguments\n"; return 1; } ifstream dff(argv[1], ios::binary); if (dff.fail()) { cerr << "couldn't open file " << argv[1] << endl; return 1; } rw::Clump clump; clump.read(dff); dff.close(); string textureDir = "textures/"; if (argc >= 3) textureDir = argv[2]; osg::ref_ptr root = new osg::Group(); // build MatrixTransform tree osg::MatrixTransform **frames = new osg::MatrixTransform*[ clump.frameList.size()]; for (uint i = 0; i < clump.frameList.size(); i++) { frames[i] = new osg::MatrixTransform(); rw::Frame *rwframe = &clump.frameList[i]; osg::Matrix mat; #define M(i,j) rwframe->rotationMatrix[(i)*3+(j)] mat.set(M(0,0), M(0,1), M(0,2), 0, M(1,0), M(1,1), M(1,2), 0, M(2,0), M(2,1), M(2,2), 0, 0, 0, 0, 1); #undef M frames[i]->setMatrix(mat); mat.makeTranslate(osg::Vec3(rwframe->position[0], rwframe->position[1], rwframe->position[2])); frames[i]->postMult(mat); if (rwframe->parent != -1) frames[rwframe->parent]->addChild(frames[i]); else root->addChild(frames[i]); } // associate geometries for (uint i = 0; i < clump.atomicList.size(); i++) { rw::Geometry *rwgeo = &clump.geometryList[ clump.atomicList[i].geometryIndex]; rw::Frame *rwframe = &clump.frameList[ clump.atomicList[i].frameIndex]; // if (rwframe->name == "chassis_vlo" || // strstr(rwframe->name.c_str(), "_dam") != 0) // continue; osg::ref_ptr geode = new osg::Geode(); // vertices osg::Vec3Array *vertices = new osg::Vec3Array; for (uint j = 0; j < rwgeo->vertices.size()/3; j++) { vertices->push_back(osg::Vec3(rwgeo->vertices[j*3+0], rwgeo->vertices[j*3+1], rwgeo->vertices[j*3+2])); } // normals osg::Vec3Array *normals; if (rwgeo->flags & rw::FLAGS_NORMALS) { normals = new osg::Vec3Array; for (uint j = 0; j < rwgeo->vertices.size()/3; j++) { normals->push_back(osg::Vec3( rwgeo->normals[j*3+0], rwgeo->normals[j*3+1], rwgeo->normals[j*3+2])); } } // texcoords osg::Vec2Array *texCoords; if (rwgeo->flags & rw::FLAGS_TEXTURED || rwgeo->flags & rw::FLAGS_TEXTURED2) { texCoords = new osg::Vec2Array; for (uint j = 0; j < rwgeo->vertices.size()/3; j++) { texCoords->push_back(osg::Vec2( rwgeo->texCoords[0][j*2+0], -rwgeo->texCoords[0][j*2+1])); } } // colors osg::Vec4Array *colors; if (rwgeo->flags & rw::FLAGS_PRELIT) { colors = new osg::Vec4Array; for (uint j = 0; j < rwgeo->vertices.size()/3; j++) { colors->push_back(osg::Vec4( rwgeo->vertexColors[j*4+0]/255.0f, rwgeo->vertexColors[j*4+1]/255.0f, rwgeo->vertexColors[j*4+2]/255.0f, rwgeo->vertexColors[j*4+3]/255.0f)); } } // make one geometry per material split for (uint s = 0; s < rwgeo->splits.size(); s++) { osg::ref_ptr geo = new osg::Geometry(); geo->setVertexArray(vertices); if (rwgeo->flags & rw::FLAGS_NORMALS) { geo->setNormalArray(normals); geo->setNormalBinding( osg::Geometry::BIND_PER_VERTEX); geo->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON); } else { geo->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); } if (rwgeo->flags & rw::FLAGS_TEXTURED || rwgeo->flags & rw::FLAGS_TEXTURED2) geo->setTexCoordArray(0, texCoords); if (rwgeo->flags & rw::FLAGS_PRELIT) { geo->setColorArray(colors); geo->setColorBinding( osg::Geometry::BIND_PER_VERTEX); } // faces osg::DrawElementsUInt *indices; if (rwgeo->faceType == FACETYPE_STRIP) indices = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLE_STRIP, 0); else indices = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0); for (uint k = 0; k < rwgeo->splits[s].indices.size(); k++) indices->push_back(rwgeo->splits[s].indices[k]); geo->addPrimitiveSet(indices); // associate texture string textureName = textureDir + rwgeo->materialList[ rwgeo->splits[s].matIndex].texture.name + ".tga"; osg::Image *image = osgDB::readImageFile(textureName); if (image) { osg::Texture2D *tex = new osg::Texture2D; tex->setDataVariance(osg::Object::DYNAMIC); tex->setImage(image); tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); osg::StateSet *stateSet = geo->getOrCreateStateSet(); stateSet->ref(); stateSet->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON); } geode->addDrawable(geo); } frames[clump.atomicList[i].frameIndex]->addChild(geode); } // write file osgDB::Registry::instance()->writeNode(*root,"out.osg", osgDB::Registry::instance()->getOptions()); return 0; }