11th May 2006, 02:40 AM | #1 |
Member
Expert member
Join Date: Mar 2004
Location: Germany
Posts: 75
|
OpenGL to AC3D class
Hi,
here's a simple class that lets you create AC3D .ac files. The input is generated as if you were draing the model/world with OpenGL. So, if you can draw it, now you can save it It's just a header in std C++, so it should compile pretty much anywhere. Code:
#ifndef AC3D_H_INC #define AC3D_H_INC // a AC3D export/creation class // very handy for exporting 3D data from anywhere. // Written by Gernot Frisch : www.glbasic.com // this file is public domain, do whatever you want with it. #if 0 useage: GF_AC3D ac3d; // texture if you want some ac3d.glBindTexture("test.bmp"); // new "object" ac3d.glBegin(GL_TRIANGLE_STIP); // all OpenGL modes supported! // surfaces ac3d.glColor(); // color ac3d.glTexCoo();// texture coordiante ac3d.glVertex();// vertex position ... ac3d.glEnd(); // end + store object ac3d.Write("out.ac"); // save world ac3d.clear(); #endif // VC6 gives funny warnings ;) #pragma warning(disable:4710) #pragma warning(disable:4100) #pragma warning(disable:4786) #include <vector> #include <string> #include <fstream> #include <map> class GF_AC3D { public: void clear() { m_cur_col = COLO(); m_cur_uv[0]=0; m_cur_uv[1] = 0; m_gl_texname=""; m_gl_nodes.clear(); m_objects.clear(); } bool Write(const char* filename) { std::ofstream os(filename); if(!os.good()) return false; os << "AC3Db" << std::endl; int o; std::map<COLO> mats; int ncolo=0; for(o=0; o<(int)m_objects.size(); ++o) { OBJ& ob = m_objects[o]; if(mats.find(ob.rgb) == mats.end() ) mats[ob.rgb] = ncolo++; } for(std::map<COLO>::iterator it = mats.begin(); it!=mats.end(); ++it) { const COLO& ob = it->first; os << "MATERIAL \"\" rgb " <<ob.r<<" " <<ob.g<<" "<<ob.b<<" amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0"<<std::endl; } os << "OBJECT world" << std::endl; os << "kids "<< (int)m_objects.size()<< std::endl; for(o=0; o<(int)m_objects.size(); ++o) { OBJ& ob = m_objects[o]; os << "OBJECT poly" << std::endl; if (ob.texture.length()) { os << "texture " << ob.texture << std::endl; } os << "numvert " << ob.triangles.size() * 3 << std::endl; int i; char tmp[1024]; for(i=0; i<(int)ob.triangles.size(); ++i) { for(int j=0; j<3; ++j) { sprintf(tmp, "%.2f %.2f %.2f", ob.triangles[i].nodes[j].pos[0], ob.triangles[i].nodes[j].pos[1],ob.triangles[i].nodes[j].pos[2]); os << tmp <<std::endl; } } os << "numsurf " << ob.triangles.size() << std::endl; for(i=0; i<(int)ob.triangles.size(); ++i) { os << "SURF 0x20" <<std::endl; os << "mat " << (int)mats[ob.rgb] << std::endl; os << "refs 3"<< std::endl; int first = i*3; for(int j=0; j<3; ++j) { os << (first+j) << " " << ob.triangles[i].nodes[j].uv[0] << " " << ob.triangles[i].nodes[j].uv[1] << std::endl; } } os << "kids 0"<< std::endl; } return true; } class COLO { public: COLO() {r=g=b=1.0f;} COLO(const COLO& c) {*this = c;} COLO& operator=(const COLO& c) {r=c.r; g=c.g; b=c.b;return *this;} bool operator<(const COLO& c) const {return r*100000+g*1000+b < c.r*100000+c.g*1000+c.b ? true:false;} float r,g,b; }; class NODE { public: NODE() {pos[0]=pos[1]=pos[2]=0; uv[0]=uv[1]=0;} NODE(const NODE& t) {*this = t;} NODE& operator=(const NODE& t) {pos[0]=t.pos[0]; pos[1]=t.pos[1]; pos[2]=t.pos[2]; uv[0]=t.uv[0]; uv[1]=t.uv[1]; return *this;} float pos[3]; float uv[2]; }; class TRI { public: TRI() {} TRI(const TRI& t) {*this = t;} TRI& operator=(const TRI& t) {nodes[0]=t.nodes[0]; nodes[1]=t.nodes[1]; nodes[2]=t.nodes[2]; return *this;} NODE nodes[3]; }; class OBJ { public: OBJ() {imat=0;} OBJ(const OBJ& o){*this=o;} OBJ& operator=(const OBJ& o) {rgb=o.rgb; triangles=o.triangles; texture = o.texture; return *this;} COLO rgb; int imat; std::vector<TRI> triangles; std::string texture; }; std::vector<OBJ> m_objects; // OpenGL-Style Interface int m_glmode; COLO m_cur_col; std::vector<NODE> m_gl_nodes; float m_cur_uv[2]; std::string m_gl_texname; bool m_gl_good; void glBindTexture(const char* filename) { m_gl_texname=filename; } void glColor(float r, float g, float b) { m_cur_col.r = r; m_cur_col.g=g; m_cur_col.b = b; } void glBegin(int mode) { m_gl_good=true; m_glmode = mode; } void glTexCoo(float u, float v) { m_cur_uv[0] = u; m_cur_uv[1]=v; } void glVertex(float x, float y, float z) { #define GF_GL_MAX 10000 if(x>GF_GL_MAX || y>GF_GL_MAX || z>GF_GL_MAX || x<-GF_GL_MAX || y<-GF_GL_MAX || z<-GF_GL_MAX) { m_gl_good=false; } else { NODE n; n.pos[0] = x; n.pos[1] = y; n.pos[2] = z; n.uv[0] = m_cur_uv[0]; n.uv[1] = m_cur_uv[1]; m_gl_nodes.push_back(n); } } void glEnd() { #define GF_GL_POINTS 0x0000 #define GF_GL_LINES 0x0001 #define GF_GL_LINE_LOOP 0x0002 #define GF_GL_LINE_STRIP 0x0003 #define GF_GL_TRIANGLES 0x0004 #define GF_GL_TRIANGLE_STRIP 0x0005 #define GF_GL_TRIANGLE_FAN 0x0006 #define GF_GL_QUADS 0x0007 #define GF_GL_QUAD_STRIP 0x0008 #define GF_GL_POLYGON 0x0009 OBJ o; int num_tri=0; switch(m_glmode) { case GF_GL_TRIANGLES: num_tri = m_gl_nodes.size()/3; break; case GF_GL_TRIANGLE_STRIP: num_tri = m_gl_nodes.size()-2; break; case GF_GL_TRIANGLE_FAN: case GF_GL_POLYGON: num_tri = m_gl_nodes.size()-2; break; // case GF_GL_QUADS: // num_tri = (m_gl_nodes.size()/4) * 2; break; } if(num_tri && m_gl_good) { for(int n=0; n<num_tri; ++n) { int a,b,c; switch(m_glmode) { case GF_GL_TRIANGLES: a=3*n+2; b=3*n+1; c=3*n; break; case GF_GL_TRIANGLE_STRIP: if(n%2) { a=n+1; b=n; c=n+2; } else { a=n; b=n+1; c=n+2; } break; case GF_GL_TRIANGLE_FAN: case GF_GL_POLYGON: a=0; b=n+1; c=n+2; break; case GF_GL_QUADS: if(n%2) { a=4*n; b=4*n-1; c=4*n; } else { a=3+4*n; b=3+4*n-3; c=3+4*n-1; } break; } TRI t; t.nodes[0] = m_gl_nodes[a]; t.nodes[1] = m_gl_nodes[b]; t.nodes[2] = m_gl_nodes[c]; NODE n1, n2, n3; n1 = m_gl_nodes[a]; n2 = m_gl_nodes[b]; n3 = m_gl_nodes[c]; o.triangles.push_back(t); } o.texture = m_gl_texname; o.rgb=m_cur_col; m_objects.push_back(o); } m_gl_nodes.clear(); } }; #endif // AC3D_H_INC
__________________
www.GLBasic.com |
|
|