View Single Post
Old 11th May 2006, 02:40 AM   #1
Gernot
Member
Expert member
 
Gernot's Avatar
 
Join Date: Mar 2004
Location: Germany
Posts: 75
Default 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
Gernot is offline   Reply With Quote