Go Back   AC3D Forums > Technical > AC3D Developers
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Display Modes
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
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



All times are GMT -4. The time now is 12:14 PM.


AC3D Forum
(C) Inivis Limited 2020