home *** CD-ROM | disk | FTP | other *** search
- #include "xentax.h"
-
- bool GeometryToOBJ(const char* path, const char* name, const deque<VERTEX_BUFFER>& vd, const deque<INDEX_BUFFER>& fd)
- {
- // create OBJ file
- stringstream ss;
- ss << path << name << ".obj";
- ofstream objfile(ss.str().c_str());
- if(!objfile) return error("OBJ EXPORT: Error creating output file.");
-
- // OBJ file header
- objfile << "o " << name << ".obj" << endl;
- objfile << "mtllib " << name << ".mtl" << endl;
-
- struct OBJOFFSETINFO {
- uint32 vertex_base;
- uint32 normal_base;
- uint32 texmap_base;
- };
-
- // index to each vertex buffer
- OBJOFFSETINFO ooi = { 0, 0, 0 };
- deque<OBJOFFSETINFO> offset_list;
- for(size_t i = 0; i < vd.size(); i++) {
- offset_list.push_back(ooi);
- if(vd[i].flags & VERTEX_POSITION) ooi.vertex_base += vd[i].elem;
- if(vd[i].flags & VERTEX_NORMAL) ooi.normal_base += vd[i].elem;
- if(vd[i].flags & VERTEX_UV) ooi.texmap_base += vd[i].elem;
- }
-
- // output vertices
- for(size_t i = 0; i < vd.size(); i++) {
- if(vd[i].flags & VERTEX_POSITION) {
- objfile << "# POSITION BUFFER " << i << endl;
- for(size_t j = 0; j < vd[i].elem; j++)
- objfile << "v " << vd[i].data[j].vx << " " << vd[i].data[j].vy << " " << vd[i].data[j].vz << endl;
- }
- }
- for(size_t i = 0; i < vd.size(); i++) {
- if(vd[i].flags & VERTEX_NORMAL) {
- objfile << "# NORMAL BUFFER " << i << endl;
- for(size_t j = 0; j < vd[i].elem; j++)
- objfile << "vn " << vd[i].data[j].nx << " " << vd[i].data[j].ny << " " << vd[i].data[j].nz << endl;
- }
- }
- for(size_t i = 0; i < vd.size(); i++) {
- if(vd[i].flags & VERTEX_UV) {
- objfile << "# UV BUFFER " << i << endl;
- for(size_t j = 0; j < vd[i].elem; j++)
- objfile << "vt " << vd[i].data[j].tu << " " << vd[i].data[j].tv << endl;
- }
- }
-
- // output faces
- for(size_t i = 0; i < fd.size(); i++)
- {
- objfile << "# INDEX BUFFER " << i << endl;
- objfile << "g " << fd[i].name.c_str() << endl;
- objfile << "usemtl " << fd[i].name.c_str() << endl;
-
- // set vertex buffer reference index
- uint32 vertex_buffer_index = fd[i].reference;
- if(!(vertex_buffer_index < offset_list.size())) return error("OBJ EXPORT: Invalid vertex buffer reference.");
-
- // set vertex buffer properties
- bool has_vertex = (vd[vertex_buffer_index].flags & VERTEX_POSITION) != 0;
- bool has_normal = (vd[vertex_buffer_index].flags & VERTEX_NORMAL) != 0;
- bool has_texmap = (vd[vertex_buffer_index].flags & VERTEX_UV) != 0;
-
- // set base vertex
- uint32 base_vertex = offset_list[vertex_buffer_index].vertex_base;
- uint32 base_normal = offset_list[vertex_buffer_index].normal_base;
- uint32 base_texmap = offset_list[vertex_buffer_index].texmap_base;
-
- // tri-strips
- if(fd[i].type == FACE_TYPE_TRISTRIP)
- {
- // validate
- if(fd[i].elem < 3) return error("OBJ EXPORT: Tri-strips require at least three points.");
-
- if(fd[i].format == FACE_FORMAT_UINT_16)
- {
- // first triangle
- const uint16* data = reinterpret_cast<uint16*>(fd[i].data.get());
- uint32 va = base_vertex + data[0] + 1;
- uint32 vb = base_vertex + data[1] + 1;
- uint32 vc = base_vertex + data[2] + 1;
- uint32 na = base_normal + data[0] + 1;
- uint32 nb = base_normal + data[1] + 1;
- uint32 nc = base_normal + data[2] + 1;
- uint32 ta = base_texmap + data[0] + 1;
- uint32 tb = base_texmap + data[1] + 1;
- uint32 tc = base_texmap + data[2] + 1;
-
- // first triangle (draw only if not degenerate)
- if(!(va == vb || va == vc || vb == vc)) {
- if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
- else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- else if(!has_texmap && has_normal) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
- }
-
- // other triangles
- for(size_t j = 3; j < fd[i].elem; j++)
- {
- // update position
- va = vb;
- vb = vc;
- vc = base_vertex + data[j] + 1;
-
- // update normal
- if(has_normal) {
- na = nb;
- nb = nc;
- nc = base_normal + data[j] + 1;
- }
-
- // update UV
- if(has_texmap) {
- ta = tb;
- tb = tc;
- tc = base_texmap + data[j] + 1;
- }
-
- // skip degenerate triangles
- if(va == vb || va == vc || vb == vc) continue;
-
- if(!has_normal && !has_texmap) {
- if(j % 2) objfile << "f " << va << " " << vc << " " << vb << endl;
- else objfile << "f " << va << " " << vb << " " << vc << endl;
- }
- else if(!has_normal && has_texmap) {
- if(j % 2) objfile << "f " << va << "/" << ta << " " << vc << "/" << tc << " " << vb << "/" << tb << endl;
- else objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- }
- else if(has_normal && !has_texmap) {
- if(j % 2) objfile << "f " << va << "//" << na << " " << vc << "//" << nc << " " << vb << "//" << nb << endl;
- else objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- }
- else {
- if(j % 2) objfile << "f " << va << "/" << ta << "/" << na << " " << vc << "/" << tc << "/" << nc << " " << vb << "/" << tb << "/" << nb << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
- }
- }
- }
- else if(fd[i].format == FACE_FORMAT_UINT_32)
- {
- // first triangle
- const uint32* data = reinterpret_cast<uint32*>(fd[i].data.get());
- uint32 va = base_vertex + data[0] + 1;
- uint32 vb = base_vertex + data[1] + 1;
- uint32 vc = base_vertex + data[2] + 1;
- uint32 na = base_normal + data[0] + 1;
- uint32 nb = base_normal + data[1] + 1;
- uint32 nc = base_normal + data[2] + 1;
- uint32 ta = base_texmap + data[0] + 1;
- uint32 tb = base_texmap + data[1] + 1;
- uint32 tc = base_texmap + data[2] + 1;
- if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
- else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- else if(!has_texmap && has_normal) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
-
- // other triangles
- for(size_t j = 3; j < fd[i].elem; j++)
- {
- va = vb;
- vb = vc;
- vc = base_vertex + data[j] + 1;
-
- if(has_normal) {
- na = nb;
- nb = nc;
- nc = base_normal + data[j] + 1;
- }
- if(has_texmap) {
- ta = tb;
- tb = tc;
- tc = base_texmap + data[j] + 1;
- }
-
- if(!has_normal && !has_texmap) {
- if(j % 2) objfile << "f " << va << " " << vc << " " << vb << endl;
- else objfile << "f " << va << " " << vb << " " << vc << endl;
- }
- else if(!has_normal && has_texmap) {
- if(j % 2) objfile << "f " << va << "/" << ta << " " << vc << "/" << tc << " " << vb << "/" << tb << endl;
- else objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- }
- else if(has_normal && !has_texmap) {
- if(j % 2) objfile << "f " << va << "//" << na << " " << vc << "//" << nc << " " << vb << "//" << nb << endl;
- else objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- }
- else {
- if(j % 2) objfile << "f " << va << "/" << ta << "/" << na << " " << vc << "/" << tc << "/" << nc << " " << vb << "/" << tb << "/" << nb << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
- }
- }
- }
- else
- return error("OBJ EXPORT: Invalid index buffer data format.");
- }
- // triangles
- else if(fd[i].type == FACE_TYPE_TRIANGLES)
- {
- if(fd[i].format == FACE_FORMAT_UINT_16)
- {
- size_t n_triangles = fd[i].elem/3;
- for(size_t j = 0; j < n_triangles; j++)
- {
- // base OBJ indices
- const uint16* ib_data = reinterpret_cast<uint16*>(fd[i].data.get());
- uint32 va = base_vertex + ib_data[(3*j + 0)] + 1;
- uint32 vb = base_vertex + ib_data[(3*j + 1)] + 1;
- uint32 vc = base_vertex + ib_data[(3*j + 2)] + 1;
- uint32 na = base_normal + ib_data[(3*j + 0)] + 1;
- uint32 nb = base_normal + ib_data[(3*j + 1)] + 1;
- uint32 nc = base_normal + ib_data[(3*j + 2)] + 1;
- uint32 ta = base_texmap + ib_data[(3*j + 0)] + 1;
- uint32 tb = base_texmap + ib_data[(3*j + 1)] + 1;
- uint32 tc = base_texmap + ib_data[(3*j + 2)] + 1;
-
- // write triangle
- if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
- else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- else if(has_normal && !has_texmap) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
- }
- }
- else if(fd[i].format == FACE_FORMAT_UINT_32)
- {
- size_t n_triangles = fd[i].elem/3;
- for(size_t j = 0; j < n_triangles; j++)
- {
- // base OBJ indices
- const uint32* ib_data = reinterpret_cast<uint32*>(fd[i].data.get());
- uint32 va = base_vertex + ib_data[(3*j + 0)] + 1;
- uint32 vb = base_vertex + ib_data[(3*j + 1)] + 1;
- uint32 vc = base_vertex + ib_data[(3*j + 2)] + 1;
- uint32 na = base_normal + ib_data[(3*j + 0)] + 1;
- uint32 nb = base_normal + ib_data[(3*j + 1)] + 1;
- uint32 nc = base_normal + ib_data[(3*j + 2)] + 1;
- uint32 ta = base_texmap + ib_data[(3*j + 0)] + 1;
- uint32 tb = base_texmap + ib_data[(3*j + 1)] + 1;
- uint32 tc = base_texmap + ib_data[(3*j + 2)] + 1;
-
- // write triangle
- if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
- else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
- else if(has_normal && !has_texmap) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
- else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
- }
- }
- }
- }
-
- // create MTL file
- stringstream mtlfilename;
- mtlfilename << path << name << ".mtl" << ends;
- ofstream mtlfile(mtlfilename.str().c_str());
- if(!mtlfile) return error("OBJ EXPORT: Error creating material file.");
-
- // save materials
- for(size_t i = 0; i < fd.size(); i++)
- {
- mtlfile << "newmtl " << fd[i].name.c_str() << endl;
- mtlfile << "Ka 0 0 0" << endl;
- mtlfile << "Kd 0.784314 0.784314 0.784314" << endl;
- mtlfile << "Ks 0 0 0" << endl;
- mtlfile << "Ni 1" << endl;
- mtlfile << "Ns 400" << endl;
- mtlfile << "Tf 1 1 1" << endl;
- mtlfile << "d 1" << endl;
- //if(fd[i].basemap.length()) mtlfile << "map_Ka " << fd[i].basemap << endl;
- //if(fd[i].basemap.length()) mtlfile << "map_Kd " << fd[i].basemap << endl;
- //if(fd[i].specmap.length()) mtlfile << "map_Ks " << fd[i].specmap << endl;
- //if(fd[i].basemap.length()) mtlfile << "map_d " << fd[i].basemap << endl;
- mtlfile << endl;
- }
-
- return true;
- }