does anyone have any note on rewriting C/C++ programs in Python??
google and bing give me the exact opposite, and I've got a headache from searching...

please note that I can't read C++

if you need the program I'm rewriting, please let me know

So you can't read C++, and want to convert some C++ files to Python?

How about leaking the C++ files so we can help you?

Meanwhile, i'll google for tools. ;)

KK
IDK if this works or not...
but I used js based knowledge to get about 9 files into one...

the program is an MDL0 to collada converter written bt William Hane
just so I don't get in trouble for posting someone elses code...

#include <iostream>

#include <dae.h>
#include <dom/domCOLLADA.h>
#include <ctime>
#include <sstream>

#include <iostream>
#include <string>
#include <fstream>

#include <cmath>


typedef unsigned char uchar;
typedef unsigned int uint;

class Vec3 {
public:
	Vec3() {
		this->x = 0;
		this->y = 0;
		this->z = 0;
	}
	Vec3(float x, float y, float z) {
		this->x = x;
		this->y = y;
		this->z = z;
	}
	float X() {
		return x;
	}
	float Y() {
		return y;
	}
	float Z() {
		return z;
	}
protected:
	float x;
	float y;
	float z;
};

class Vec2 {
public:
	Vec2() {
		this->u = 0;
		this->v = 0;
	}
	Vec2(float u, float v) {
		this->u = u;
		this->v = v;
	}
	float U() {
		return u;
	}
	float V() {
		return v;
	}
protected:
	float u;
	float v;
};

class RGBA {
public:
	RGBA(uchar r, uchar g, uchar b, uchar a) {
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}
	uchar R() {
		return r;
	}
	uchar G() {
		return g;
	}
	uchar B() {
		return b;
	}
	uchar A() {
		return a;
	}
protected:
	uchar r;
	uchar g;
	uchar b;
	uchar a;
};

class Vec3Group: public std::vector<Vec3> {
public:
	Vec3Group() {
		set = false;
	}
	void SetBound(Vec3 min, Vec3 max) {
		if (!set) {
			this->min = min;
			this->max = max;
			set = true;
		}
	}
	Vec3 BoundingMin() {
		return min;
	}
	Vec3 BoundingMax() {
		return max;
	}
protected:
	bool set;
	Vec3 min;
	Vec3 max;
};

class Vec2Group: public std::vector<Vec2> {
public:
	Vec2Group() {
		set = false;
	}
	void SetBound(Vec2 min, Vec2 max) {
		if (!set) {
			this->min = min;
			this->max = max;
			set = true;
		}
	}
	Vec2 BoundingMin() {
		return min;
	}
	Vec2 BoundingMax() {
		return max;
	}
protected:
	bool set;
	Vec2 min;
	Vec2 max;
};

typedef std::vector<RGBA> RGBAGroup;

class Vertex {
public:
	Vertex() {
		vertex = 0;
		normal = 0;
		color = 0;
		//uv = NULL;
		uvCount = 0;
	}
	~Vertex() {
		/*if (uv != NULL) {
		 delete[] uv;
		 uv = NULL;
		 }*/
	}

	void Set(uint16_t vertex, uint16_t normal, uint16_t color, uint16_t uv[],
			int numUV) {
		this->vertex = vertex;
		this->normal = normal;
		this->color = color;

		//this->uv = new uint16_t[numUV];
		for (int i = 0; i < numUV; i++) {
			this->uv[i] = uv[i];
		}
		this->uvCount = numUV;
	}

	uint16_t GetVertex() {
		return vertex;
	}
	uint16_t GetNormal() {
		return normal;
	}
	uint16_t GetColor() {
		return color;
	}
	uint16_t GetUV(int id) {
		if (id >= 0 && id < uvCount) {
			return uv[id];
		}
		else
			return 0;
	}
	int UVCount() {
		return uvCount;
	}
private:
	uint16_t vertex;
	uint16_t normal;
	uint16_t color;
	uint16_t uv[8];
	int uvCount;
};

class TriangleStrip {
public:
	TriangleStrip() {
		locked = false;
	}

	~TriangleStrip() {

	}

	Vertex& operator[](size_t index) {
		return verts[index];
	}

	void Add(Vertex vert) {
		if (!locked) {
			verts.push_back(vert);
		}
	}

	void Lock() {
		locked = true;
	}

	size_t Count() {
		return verts.size();
	}
private:
	bool locked;
	std::vector<Vertex> verts;
};

class TriangleFan {
public:
	TriangleFan(Vertex origin) {
		this->origin = origin;
		locked = false;
	}

	~TriangleFan() {

	}

	Vertex& operator[](size_t index) {
		return verts[index];
	}

	void Add(Vertex vert) {
		if (!locked) {
			verts.push_back(vert);
		}
	}

	void Lock() {
		locked = true;
	}

	size_t Count() {
		return verts.size();
	}

	Vertex GetOriginVertex() {
		return origin;
	}
private:
	bool locked;
	Vertex origin;
	std::vector<Vertex> verts;
};

class Triangle {
public:
	Triangle(Vertex p1, Vertex p2, Vertex p3) {
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
	}

	~Triangle() {

	}

	Vertex& operator[](size_t index) {
		switch (index) {
		case 0:
			return p1;
		case 1:
			return p2;
		case 2:
			return p3;
		default:
			return p3;
		}
	}
private:
	Vertex p1;
	Vertex p2;
	Vertex p3;
};

class Quad {
public:
	Quad(Vertex p1, Vertex p2, Vertex p3, Vertex p4) {
		this->p1 = p1;
		this->p2 = p2;
		this->p3 = p3;
		this->p4 = p4;
	}

	~Quad() {

	}

	Vertex& operator[](size_t index) {
		switch (index) {
		case 0:
			return p1;
		case 1:
			return p2;
		case 2:
			return p3;
		case 3:
			return p4;
		default:
			return p4;
		}
	}
private:
	Vertex p1;
	Vertex p2;
	Vertex p3;
	Vertex p4;
};

class PolyGroup {
public:
	PolyGroup() {
		locked = false;

		vertex = 0;
		vertexPtr = NULL;
		normal = 0;
		normalPtr = NULL;
		color = 0;
		colorPtr = NULL;
	}

	~PolyGroup() {

	}

	void SetVertex(uint16_t vertex, Vec3Group* vertexPtr) {
		if (!locked) {
			this->vertex = vertex;
			this->vertexPtr = vertexPtr;
		}
	}

	void SetNormal(uint16_t normal, Vec3Group* normalPtr) {
		if (!locked) {
			this->normal = normal;
			this->normalPtr = normalPtr;
		}
	}

	void SetColor(uint16_t color, RGBAGroup* colorPtr) {
		if (!locked) {
			this->color = color;
			this->colorPtr = colorPtr;
		}
	}

	void AddUV(uint16_t uvid, Vec2Group* uvPtr) {
		if (!locked) {
			this->uvIDs.push_back(uvid);
			this->uvPtrs.push_back(uvPtr);
		}
	}

	void Lock() {
		locked = true;
	}

	void AddTriangleStrip(TriangleStrip tristrip) {
		if (!locked) {
			triangleStrips.push_back(tristrip);
		}
	}

	void AddTriangleFan(TriangleFan trifan) {
		if (!locked) {
			triangleFans.push_back(trifan);
		}
	}

	void AddTriangle(Triangle triangle) {
		if (!locked) {
			triangles.push_back(triangle);
		}
	}

	void AddQuad(Quad quad) {
		if (!locked) {
			quads.push_back(quad);
		}
	}

	size_t TriangleStripCount() {
		return triangleStrips.size();
	}

	size_t TriangleFanCount() {
		return triangleFans.size();
	}

	size_t TriangleCount() {
		return triangles.size();
	}

	size_t QuadCount() {
		return quads.size();
	}

	TriangleStrip GetTriangleStrip(size_t index) {
		return triangleStrips[index];
	}

	TriangleFan GetTriangleFan(size_t index) {
		return triangleFans[index];
	}

	Triangle GetTriangle(size_t index) {
		return triangles[index];
	}

	Quad GetQuad(size_t index) {
		return quads[index];
	}

	uint16_t VertexGroup() {
		return vertex;
	}
	Vec3Group* VertexGroupPtr() {
		return vertexPtr;
	}
	uint16_t NormalGroup() {
		return normal;
	}
	Vec3Group* NormalGroupPtr() {
		return normalPtr;
	}
	uint16_t ColorGroup() {
		return color;
	}
	RGBAGroup* ColorGroupPtr() {
		return colorPtr;
	}
	uint16_t UVGroup(uint id) {
		if (id < uvIDs.size())
			return uvIDs[id];
	}

	Vec2Group* UVGroupPtr(uint id) {
		if (id < uvPtrs.size())
			return uvPtrs[id];
		else
			return NULL;
	}

	int UVGroupCount() {
		return uvIDs.size();
	}
private:
	bool locked;
	uint16_t vertex;
	Vec3Group* vertexPtr;
	uint16_t normal;
	Vec3Group* normalPtr;
	uint16_t color;
	RGBAGroup* colorPtr;
	std::vector<uint16_t> uvIDs;
	std::vector<Vec2Group*> uvPtrs;

	std::vector<TriangleStrip> triangleStrips;
	std::vector<TriangleFan> triangleFans;
	std::vector<Triangle> triangles;
	std::vector<Quad> quads;
};








extern float BigFloat(const char* data, unsigned int offset=0);
extern uint32_t BigUInt32(const char* data, unsigned int offset=0);
extern uint16_t BigUInt16(const char* data, unsigned int offset=0);
extern int16_t BigSInt16(const char* data, unsigned int offset=0); 







float BigFloat(const char* data, unsigned int offset) {
	union {
		float f;
		unsigned char b[4];
	} dat;

	dat.b[0] = data[offset + 3];
	dat.b[1] = data[offset + 2];
	dat.b[2] = data[offset + 1];
	dat.b[3] = data[offset];
	return dat.f;
}

uint32_t BigUInt32(const char* data, unsigned int offset) {
	union {
		uint32_t u;
		unsigned char b[4];
	} dat;

	dat.b[0] = data[offset + 3];
	dat.b[1] = data[offset + 2];
	dat.b[2] = data[offset + 1];
	dat.b[3] = data[offset];
	return dat.u;
}

uint16_t BigUInt16(const char* data, unsigned int offset) {
	union {
		uint16_t u;
		unsigned char b[2];
	} dat;

	dat.b[0] = data[offset + 1];
	dat.b[1] = data[offset];
	return dat.u;
}

int16_t BigSInt16(const char* data, unsigned int offset) {
	union {
		int16_t u;
		unsigned char b[2];
	} dat;

	dat.b[0] = data[offset + 1];
	dat.b[1] = data[offset];
	return dat.u;
}







typedef enum {
	LO_CONV_TO_TRIS = 1 // converts all triangle strips/fans and quads to triangles
} LoadOptions;

class MDL0File {
public:
	MDL0File();
	virtual ~MDL0File();

	/**
	 * Load an MDL0 file.
	 *
	 * @param data An array containing the all the data in the file.
	 * @return True on a success, false on failure.
	 */
	bool Load(const char* data, uint length, uint options);
	void Unload();

	PolyGroup* GetPolygonGroup(int id);
	int PolygonGroupCount();
	Vec3Group* GetVertexGroup(int id);
	int VertexGroupCount();
	RGBAGroup* GetColorGroup(int id);
	int ColorGroupCount();
	Vec3Group* GetNormalGroup(int id);
	int NormalGroupCount();
	Vec2Group* GetUVGroup(int id);
	int UVGroupCount();

private:
	bool loadGroup(const char* data, int type);
	bool loadVec3Group(const char* data, Vec3Group* group);
	bool loadVec2Group(const char* data, Vec2Group* group);
	bool loadRGBAGroup(const char* data, RGBAGroup* group);
	bool loadPolyGroup(const char* data, PolyGroup* group);
	Vertex loadVertex(const char* data, int offset, std::vector<int> fmt,
			bool hasNormal, bool hasColor, int unknown, int uv, int& outLength);

	bool loaded;
	uint options;

	PolyGroup* polyGroups;
	int polyGroupCount;
	Vec3Group* vertexGroups;
	int vertexGroupCount;
	RGBAGroup* colorGroups;
	int colorGroupCount;
	Vec3Group* normalGroups;
	int normalGroupCount;
	Vec2Group* uvGroups;
	int uvGroupCount;
};







MDL0File::MDL0File() {
	loaded = false;

	polyGroups = NULL;
	polyGroupCount = 0;
	vertexGroups = NULL;
	vertexGroupCount = 0;
	colorGroups = NULL;
	colorGroupCount = 0;
	normalGroups = NULL;
	normalGroupCount = 0;
	uvGroups = NULL;
	uvGroupCount = 0;
	options = 0;
}

MDL0File::~MDL0File() {
	if (vertexGroups != NULL) {
		delete[] vertexGroups;
		vertexGroups = NULL;
	}
	if (normalGroups != NULL) {
		delete[] normalGroups;
		normalGroups = NULL;
	}
	if (colorGroups != NULL) {
		delete[] colorGroups;
		colorGroups = NULL;
	}
	if (uvGroups != NULL) {
		delete[] uvGroups;
		uvGroups = NULL;
	}
	if (polyGroups != NULL) {
		delete[] polyGroups;
		polyGroups = NULL;
	}
}

bool MDL0File::Load(const char* data, uint length, uint convToTris) {
	if (data == NULL) {
		return false;
	}

	// we need the array to be at least as long as the header
	if (length < 64)
		return false;

	// check for "MDL0"
	if (data[0] != 'M' || data[1] != 'D' || data[2] != 'L' || data[3] != '0')
		return false;

	this->options = options;

	const char *groupPtrs[11];
	for (int i = 0; i < 11; i++) {
		uint32_t ptr = BigUInt32(data, 16 + i * 4);

		if (ptr >= length)
			return false; // pointer is out of range

		if (ptr == 0)
			groupPtrs[i] = NULL;
		else
			groupPtrs[i] = data + ptr;
	}

	for (int i = 0; i < 11; i++) {
		if (groupPtrs[i] != NULL) {
			loadGroup(groupPtrs[i], i);
		}
	}

	loaded = true;

	return true;
}

void MDL0File::Unload() {}

PolyGroup* MDL0File::GetPolygonGroup(int id) {
	if (id < polyGroupCount)
		return &polyGroups[id];
	else
		return NULL;
}

int MDL0File::PolygonGroupCount() {
	return polyGroupCount;
}

Vec3Group* MDL0File::GetVertexGroup(int id) {
	if (id < vertexGroupCount)
		return &vertexGroups[id];
	else
		return NULL;
}

int MDL0File::VertexGroupCount() {
	return vertexGroupCount;
}

RGBAGroup* MDL0File::GetColorGroup(int id) {
	if (id < colorGroupCount)
		return &colorGroups[id];
	else
		return NULL;
}

int MDL0File::ColorGroupCount() {
	return colorGroupCount;
}

Vec3Group* MDL0File::GetNormalGroup(int id) {
	if (id < normalGroupCount)
		return &normalGroups[id];
	else
		return NULL;
}

int MDL0File::NormalGroupCount() {
	return normalGroupCount;
}

Vec2Group* MDL0File::GetUVGroup(int id) {
	if (id < uvGroupCount)
		return &uvGroups[id];
	else
		return NULL;
}

int MDL0File::UVGroupCount() {
	return uvGroupCount;
}

bool MDL0File::loadGroup(const char* data, int type) {
	uint32_t itemcount = BigUInt32(data, 4);

	switch (type) {
	case 0: // unknown
		break;
	case 1: // probably bones, don't know how to load yet
		break;
	case 2: // vertices
		vertexGroups = new Vec3Group[itemcount];
		vertexGroupCount = itemcount;
		break;
	case 3: // normals
		normalGroups = new Vec3Group[itemcount];
		normalGroupCount = itemcount;
		break;
	case 4: // colors
		colorGroups = new RGBAGroup[itemcount];
		colorGroupCount = itemcount;
		break;
	case 5: // uv coordinates
		uvGroups = new Vec2Group[itemcount];
		uvGroupCount = itemcount;
		break;
	case 6: // unknown
		break;
	case 7: // unknown
		break;
	case 8: // polygon groups
		polyGroups = new PolyGroup[itemcount];
		polyGroupCount = itemcount;
		break;
	case 9: // unknown
		break;
	case 10: // unknown
		break;
	}

	for (uint i = 0; i < itemcount; i++) {
		uint32_t dataoffset = BigUInt32(data, 36 + 16 * i);

		switch (type) {
		case 0: // unknown
			break;
		case 1: // probably bones, don't know how to load yet
			break;
		case 2: // vertices
			if (!loadVec3Group(data + dataoffset, &vertexGroups[i]))
				return false;
			break;
		case 3: // normals
			if (!loadVec3Group(data + dataoffset, &normalGroups[i]))
				return false;
			break;
		case 4: // colors
			if (!loadRGBAGroup(data + dataoffset, &colorGroups[i]))
				return false;
			break;
		case 5: // uv coordinates
			if (!loadVec2Group(data + dataoffset, &uvGroups[i]))
				return false;
			break;
		case 6: // unknown
			break;
		case 7: // unknown
			break;
		case 8: // polygon groups
			if (!loadPolyGroup(data + dataoffset, &polyGroups[i]))
				return false;
			break;
		case 9: // unknown
			break;
		case 10: // unknown
			break;
		}
	}

	return true;
}

bool MDL0File::loadVec3Group(const char* data, Vec3Group* group) {
	bool boundingbox = data[23];
	char datatype = data[27];
	char fixedpointbits = data[28];
	uint16_t datacount = BigUInt16(data, 30);

	int datastart = 32;
	if (boundingbox) {
		float minx = BigFloat(data, 32);
		float miny = BigFloat(data, 36);
		float minz = BigFloat(data, 40);
		float maxx = BigFloat(data, 44);
		float maxy = BigFloat(data, 48);
		float maxz = BigFloat(data, 52);

		group->SetBound(Vec3(minx, miny, minz), Vec3(maxx, maxy, maxz));

		datastart = 64;
	} else {
		group->SetBound(Vec3(0, 0, 0), Vec3(0, 0, 0));
	}

	switch (datatype) {
	case 0: // fixed point u8
		for (int i = 0; i < datacount; i++) {
			float x = (unsigned char) data[datastart + i * 6] / pow(2.0f,
					fixedpointbits);
			float y = (unsigned char) data[datastart + 1 + i * 6] / pow(2.0f,
					fixedpointbits);
			float z = (unsigned char) data[datastart + 2 + i * 6] / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec3(x, y, z));
		}
		break;
	case 1: // fixed point s8
		for (int i = 0; i < datacount; i++) {
			float x = data[datastart + i * 6] / pow(2.0f, fixedpointbits);
			float y = data[datastart + 1 + i * 6] / pow(2.0f, fixedpointbits);
			float z = data[datastart + 2 + i * 6] / pow(2.0f, fixedpointbits);
			group->push_back(Vec3(x, y, z));
		}
		break;
	case 2: // fixed point u16
		for (int i = 0; i < datacount; i++) {
			float x = BigUInt16(data, datastart + i * 6) / pow(2.0f,
					fixedpointbits);
			float y = BigUInt16(data, datastart + 2 + i * 6) / pow(2.0f,
					fixedpointbits);
			float z = BigUInt16(data, datastart + 4 + i * 6) / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec3(x, y, z));
		}
		break;
	case 3: // fixed point s16
		for (int i = 0; i < datacount; i++) {
			float x = BigSInt16(data, datastart + i * 6) / pow(2.0f,
					fixedpointbits);
			float y = BigSInt16(data, datastart + 2 + i * 6) / pow(2.0f,
					fixedpointbits);
			float z = BigSInt16(data, datastart + 4 + i * 6) / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec3(x, y, z));
		}
		break;
	case 4: // floating point
		for (int i = 0; i < datacount; i++) {
			float x = BigFloat(data, datastart + i * 12);
			float y = BigFloat(data, datastart + 4 + i * 12);
			float z = BigFloat(data, datastart + 8 + i * 12);
			group->push_back(Vec3(x, y, z));
		}
		break;
	default:
		return false;
	}

	return true;
}

bool MDL0File::loadVec2Group(const char* data, Vec2Group* group) {
	bool boundingbox = data[23];
	char datatype = data[27];
	char fixedpointbits = data[28];
	uint16_t datacount = BigUInt16(data, 30);

	int datastart = 32;
	if (boundingbox) {
		float minu = BigFloat(data, 32);
		float minv = BigFloat(data, 36);
		float maxu = BigFloat(data, 40);
		float maxv = BigFloat(data, 44);

		group->SetBound(Vec2(minu, minv), Vec2(maxu, maxv));

		datastart = 64;
	} else {
		group->SetBound(Vec2(0, 0), Vec2(0, 0));
	}

	switch (datatype) {
	case 0: // fixed point u8
		for (int i = 0; i < datacount; i++) {
			float u = (unsigned char) data[datastart + i * 6] / pow(2.0f,
					fixedpointbits);
			float v = (unsigned char) data[datastart + 1 + i * 6] / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec2(u, v));
		}
		break;
	case 1: // fixed point s8
		for (int i = 0; i < datacount; i++) {
			float u = data[datastart + i * 6] / pow(2.0f, fixedpointbits);
			float v = data[datastart + 1 + i * 6] / pow(2.0f, fixedpointbits);
			group->push_back(Vec2(u, v));
		}
		break;
	case 2: // fixed point u16
		for (int i = 0; i < datacount; i++) {
			float u = BigUInt16(data, datastart + i * 4) / pow(2.0f,
					fixedpointbits);
			float v = BigUInt16(data, datastart + 2 + i * 4) / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec2(u, v));
		}
	case 3: // fixed point s16
		for (int i = 0; i < datacount; i++) {
			float u = BigSInt16(data, datastart + i * 4) / pow(2.0f,
					fixedpointbits);
			float v = BigSInt16(data, datastart + 2 + i * 4) / pow(2.0f,
					fixedpointbits);
			group->push_back(Vec2(u, v));
		}
		break;
	case 4: // floating point
		for (int i = 0; i < datacount; i++) {
			float u = BigFloat(data, datastart + i * 8);
			float v = BigFloat(data, datastart + 4 + i * 8);
			group->push_back(Vec2(u, v));
		}
		break;
	default:
		return false;
	}

	return true;
}

bool MDL0File::loadRGBAGroup(const char* data, RGBAGroup* group) {
	char datatype = data[27];
	uint16_t datacount = BigUInt16(data, 30);

	int datastart = 32;

	switch (datatype) {
	case 0: // RGB565
		for (int i = 0; i < datacount; i++) {
			char r = ((data[datastart + 2 * i] & 0xF8) >> 3) / 0x1F * 0xFF;
			char g = (((data[datastart + 2 * i] & 0x7) << 3) | ((data[datastart
					+ 1 + 2 * i] & 0xE0) >> 5)) / 0x3F * 0xFF;
			char b = (data[datastart + 1 + 2 * i] & 0x1F) / 0x1F * 0xFF;
			group->push_back(RGBA(r, g, b, 0xFF));
		}
		break;
	case 1: // RGB8
		for (int i = 0; i < datacount; i++) {
			char r = data[datastart + 3 * i];
			char g = data[datastart + 1 + 3 * i];
			char b = data[datastart + 2 + 3 * i];
			group->push_back(RGBA(r, g, b, 0xFF));
		}
		break;
	case 2: // RGBX8
		for (int i = 0; i < datacount; i++) {
			char r = data[datastart + 4 * i];
			char g = data[datastart + 1 + 4 * i];
			char b = data[datastart + 2 + 4 * i];
			group->push_back(RGBA(r, g, b, 0xFF));
		}
		break;
	case 3: // RGBA4
		for (int i = 0; i < datacount; i++) {
			char r = (data[datastart + 2 * i] >> 4) * 0x11;
			char g = data[datastart + 2 * i] * 0x11;
			char b = (data[datastart + 1 + 2 * i] >> 4) * 0x11;
			char a = data[datastart + 1 + 2 * i] * 0x11;
			group->push_back(RGBA(r, g, b, a));
		}
		break;
	case 4: // RGBA6
		for (int i = 0; i < datacount; i++) {
			char r = ((data[datastart + 3 * i] & 0x3F) >> 2) / 0x3F * 0xFF;
			char g = (((data[datastart + 3 * i] & 0x3) << 4) | ((data[datastart
					+ 1 + 3 * i] & 0xF0) >> 4)) / 0x3F * 0xFF;
			char b = (((data[datastart + 1 + 3 * i] & 0xF) << 4)
					| ((data[datastart + 2 + 3 * i] & 0xC0) >> 6)) / 0x3F
					* 0xFF;
			char a = (data[datastart + 2 + 3 * i] & 0x3F) / 0x3F * 0xFF;
			group->push_back(RGBA(r, g, b, a));
		}
		break;
	case 5: // RGBA8
		for (int i = 0; i < datacount; i++) {
			unsigned char r = data[datastart + 4 * i];
			unsigned char g = data[datastart + 1 + 4 * i];
			unsigned char b = data[datastart + 2 + 4 * i];
			unsigned char a = data[datastart + 3 + 4 * i];
			group->push_back(RGBA(r, g, b, a));
		}
		break;
	default:
		return false;
	}

	return true;
}

bool MDL0File::loadPolyGroup(const char* data, PolyGroup* group) {
	uint16_t vertexid = BigUInt16(data, 72);
	uint16_t normalid = BigUInt16(data, 74);
	uint16_t colorid = BigUInt16(data, 76);
	uint16_t texcoordid[8];
	for (int i = 0; i < 8; i++)
		texcoordid[i] = BigUInt16(data, 80 + 2 * i);

	uint16_t unknowncount = BigUInt16(data, 102);

	// find the start of the array format
	int loc = 104 + unknowncount * 2;
	while (data[loc] == 0) {
		loc++;
	}

	// read array format
	std::vector<int> fmt;
	bool normalfmt = false;
	bool colorfmt = false;
	int unknownfmt = 0;
	int uvfmt = 0;
	int tempfmt = 0;

	if (data[loc] != 0x08 && data[loc + 1] != 0x50)
		return false;

	tempfmt = data[loc + 5] & 3;
	if (tempfmt) {
		unknownfmt = 1;
	}
	tempfmt = (data[loc + 5] & 12) >> 2;
	if (tempfmt) {
		unknownfmt++;
	}
	tempfmt = (data[loc + 5] & 48) >> 4;
	if (tempfmt) {
		unknownfmt++;
	}
	tempfmt = (data[loc + 5] & 192) >> 6;
	if (tempfmt) {
		unknownfmt++;
	}

	tempfmt = (data[loc + 4] & 6) >> 1;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 4] & 24) >> 3;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 4] & 96) >> 5;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);

	if (data[loc + 6] != 0x08 && data[loc + 7] != 0x60)
		return false;

	tempfmt = data[loc + 11] & 3;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 11] & 12) >> 2;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 11] & 48) >> 4;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 11] & 192) >> 6;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = data[loc + 10] & 3;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 10] & 12) >> 2;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 10] & 48) >> 4;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);
	tempfmt = (data[loc + 10] & 192) >> 6;
	if (tempfmt)
		fmt.push_back(tempfmt - 1);

	if (data[loc + 16] != 0x08 && data[loc + 17] != 0x00)
		return false;

	colorfmt = data[loc + 20] & 3;
	normalfmt = (data[loc + 20] & 12) >> 2;
	uvfmt = (data[loc + 20] & 240) >> 4;

	// find the start of the data
	loc += 40;
	while (data[loc] == 0) {
		loc++;
	}

	// read data
	bool reading = true;
	do {
		char type = data[loc];
		loc++;
		switch (type) {
		case 0x30:
			loc += 4;
			break;
		case 0x20:
			loc += 4;
			break;
		case 0x28:
			loc += 4;
			break;
		case 0x98: {
			uint16_t count = BigUInt16(data, loc);
			loc += 2;

			if (options & LO_CONV_TO_TRIS) {
				int length;
				for (int i = 0; i < count - 2; i++) {
					Vertex p1, p2, p3;
					if (i % 2) {
						p3 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc += length;
						p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc += length;
						p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc -= length;
					} else {
						p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc += length;
						p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc += length;
						p3 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
								unknownfmt, uvfmt, length);
						loc -= length;
					}
					Triangle tri(p1, p2, p3);
					group->AddTriangle(tri);
				}
				loc += length * 2;
			} else {
				TriangleStrip strip;
				for (int i = 0; i < count; i++) {
					int length;
					strip.Add(loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length));
					loc += length;
				}
				strip.Lock();
				group->AddTriangleStrip(strip);
			}
		}
			break;
		case 0x90: {
			uint16_t count = BigUInt16(data, loc);
			loc += 2;

			for (int i = 0; i < count; i += 3) {
				int length;
				Vertex p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
						unknownfmt, uvfmt, length);
				loc += length;
				Vertex p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
						unknownfmt, uvfmt, length);
				loc += length;
				Vertex p3 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
						unknownfmt, uvfmt, length);
				loc += length;
				Triangle tri(p1, p2, p3);
				group->AddTriangle(tri);
			}
		}
			break;
		case 0xA0: {
			uint16_t count = BigUInt16(data, loc);
			loc += 2;

			if (options & LO_CONV_TO_TRIS) {
				int length;
				Vertex origin = loadVertex(data, loc, fmt, normalfmt, colorfmt,
						unknownfmt, uvfmt, length);
				loc += length;

				for (int i = 1; i < count - 1; i++) {

					Vertex p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					Triangle tri(origin, p1, p2);
					group->AddTriangle(tri);
				}
				loc += length;
			} else {
				int length;
				Vertex origin = loadVertex(data, loc, fmt, normalfmt, colorfmt,
						unknownfmt, uvfmt, length);
				loc += length;
				TriangleFan fan(origin);
				for (int i = 1; i < count; i++) {

					fan.Add(loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length));
					loc += length;
				}
				fan.Lock();
				group->AddTriangleFan(fan);
			}
		}
			break;
		case 0x80: {
			uint16_t count = BigUInt16(data, loc);
			loc += 2;

			if (options & LO_CONV_TO_TRIS) {
				for (int i = 0; i < count; i += 4) {
					int length;
					Vertex p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p3 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p4 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Triangle tri1(p1, p2, p3);
					Triangle tri2(p1, p3, p4);
					group->AddTriangle(tri1);
					group->AddTriangle(tri2);
				}
			} else {
				for (int i = 0; i < count; i += 4) {
					int length;
					Vertex p1 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p2 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p3 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Vertex p4 = loadVertex(data, loc, fmt, normalfmt, colorfmt,
							unknownfmt, uvfmt, length);
					loc += length;
					Quad quad(p1, p2, p3, p4);
					group->AddQuad(quad);
				}
			}
		}
			break;
		case 0x00:
			reading = false;
			break;
		default:
			return false;
		}
	} while (reading);

	group->SetVertex(vertexid, &vertexGroups[vertexid]);

	if (normalid != 0xFFFF)
		group->SetNormal(normalid, &normalGroups[normalid]);

	if (colorid != 0xFFFF)
		group->SetColor(colorid, &colorGroups[colorid]);

	for (int i = 0; i < 8; i++) {
		if (texcoordid[i] != 0xFFFF) {
			group->AddUV(texcoordid[i], &uvGroups[texcoordid[i]]);
		}
	}

	group->Lock();

	return true;
}

Vertex MDL0File::loadVertex(const char* data, int offset, std::vector<int> fmt,
		bool hasNormal, bool hasColor, int unknown, int uv, int& outLength) {
	uint16_t vert = 0;
	uint16_t norm = 0;
	uint16_t color = 0;
	uint16_t uvs[8];

	int length = 0;

	// assuming all unknowns are one byte long for now.
	length += unknown;

	if (fmt[0] == 1) {
		vert = (unsigned char) data[offset + length];
		length += 1;
	} else {
		vert = BigUInt16(data, offset + length);
		length += 2;
	}

	if (hasNormal) {
		if (fmt[1] == 1) {
			norm = (unsigned char) data[offset + length];
			length += 1;
		} else {
			norm = BigUInt16(data, offset + length);
			length += 2;
		}
	}

	if (hasColor) {
		if (fmt[1 + hasNormal] == 1) {
			color = (unsigned char) data[offset + length];
			length += 1;
		} else {
			color = BigUInt16(data, offset + length);
			length += 2;
		}
	}

	for (int i = 0; i < uv; i++) {
		if (fmt[1 + hasNormal + hasColor + i] == 1) {
			uvs[i] = (unsigned char) data[offset + length];
			length += 1;
		} else {
			uvs[i] = BigUInt16(data, offset + length);
			length += 2;
		}
	}

	Vertex outvert;
	outvert.Set(vert, norm, color, uvs, uv);

	outLength = length;

	return outvert;
}








using namespace std;

class COLLADAExport {
public:
	COLLADAExport();
	virtual ~COLLADAExport();

	bool Export(MDL0File* mdl0, const char* destfilename);

private:
	void addMetadata(domCOLLADA* root);
	void addLibraryGeometry(domCOLLADA* root, MDL0File* mdl0);
	void addPositionArray(daeElement* mesh, Vec3Group* group, string geomName);
	void addTexcoordArray(daeElement* mesh, Vec2Group* group, string geomName);
	void addTriangleStrips(daeElement* mesh, PolyGroup* group, string name);
	void addTriangleFans(daeElement* mesh, PolyGroup* group, string name);
	void addTriangles(daeElement* mesh, PolyGroup* group, string name);
	void addQuads(daeElement* mesh, PolyGroup* group, string name);
	void addInputs(daeElement* parent, PolyGroup* group, string name);
	string intToString(int num);


};







COLLADAExport::COLLADAExport() {
	// TODO Auto-generated constructor stub

}

COLLADAExport::~COLLADAExport() {
	// TODO Auto-generated destructor stub
}

bool COLLADAExport::Export(MDL0File* mdl0, const char* destfilename) {
	DAE dae;

	domCOLLADA* root = dae.add(destfilename);

	if (root == NULL)
		return false;

	addMetadata(root);

	addLibraryGeometry(root, mdl0);

	dae.writeAll();

	return true;
}

void COLLADAExport::addMetadata(domCOLLADA* root) {
	daeElement* asset = root->add("asset");

	// add contributer
	daeElement* contributor = asset->add("contributor");
	//daeElement* author = asset->add("author");
	daeElement* authoring_tool = contributor->add("authoring_tool");
	authoring_tool->setCharData("MDL0 to COLLADA converter");
	daeElement* comments = contributor->add("comments");
	comments->setCharData(
			"This file was created by the mdl0converter, written by William Hahne. The copyright of this file belongs to the creator of the original input file.");

	// get the current time and then format it correctly for XML
	ostringstream strm;
	time_t t = time(NULL);
	struct tm* lt = localtime(&t);
	strm << lt->tm_year + 1900 << "-" << lt->tm_mon << "-" << lt->tm_mday
			<< "T" << lt->tm_hour << ":" << lt->tm_min << ":" << lt->tm_sec
			<< "Z";
	string current_time = strm.str();

	// set created and modified time
	daeElement* created = asset->add("created");
	created->setCharData(current_time);
	daeElement* modified = asset->add("modified");
	modified->setCharData(current_time);
}

void COLLADAExport::addLibraryGeometry(domCOLLADA* root, MDL0File* mdl0) {
	daeElement* library_geometries = root->add("library_geometries");

	for (int i = 0; i < mdl0->PolygonGroupCount(); i++) {
		PolyGroup* group = mdl0->GetPolygonGroup(i);
		daeElement* geometry = library_geometries->add("geometry");

		ostringstream strm;
		strm << "Polygon" << i;
		string name = strm.str();

		geometry->setAttribute("id", name.c_str());

		daeElement* mesh = geometry->add("mesh");

		addPositionArray(mesh, group->VertexGroupPtr(), name + "-position");
		addPositionArray(mesh, group->NormalGroupPtr(), name + "-normal");
		for (int i = 0; i < group->UVGroupCount(); i++)
			addTexcoordArray(mesh, group->UVGroupPtr(i), name + "-texcoord"
					+ intToString(i));

		daeElement* vertices = mesh->add("vertices");
		string vertName(name + "-vertex");
		vertices->setAttribute("id", vertName.c_str());
		daeElement* input = vertices->add("input");
		input->setAttribute("semantic", "POSITION");
		string sourceName("#" + name + "-position");
		input->setAttribute("source", sourceName.c_str());

		if (group->TriangleStripCount() > 0)
			addTriangleStrips(mesh, group, name);

		if (group->TriangleFanCount() > 0)
			addTriangleFans(mesh, group, name);

		if (group->TriangleCount() > 0)
			addTriangles(mesh, group, name);
	}

	// temporary until I (hopefully) find a better solution
	daeElement* visual_scene = root->add("library_visual_scenes visual_scene");
	visual_scene->setAttribute("id", "testscene");
	for (int i = 0; i < mdl0->PolygonGroupCount(); i++) {
		daeElement* instance_geometry = visual_scene->add(
				"node instance_geometry");
		string name("#Polygon" + intToString(i));
		instance_geometry->setAttribute("url", name.c_str());
	}

	daeElement* instance_visual_scene =
			root->add("scene instance_visual_scene");
	instance_visual_scene->setAttribute("url", "#testscene");
}

void COLLADAExport::addPositionArray(daeElement* mesh, Vec3Group* group,
		string posName) {
	daeElement* source = mesh->add("source");
	source->setAttribute("id", posName.c_str());

	daeElement* float_array = source->add("float_array");
	string arrayPosName(posName + "-array");
	float_array->setAttribute("id", arrayPosName.c_str());
	float_array->setAttribute("count", intToString(group->size() * 3).c_str());

	ostringstream strm;
	for (uint i = 0; i < group->size(); i++) {
		Vec3 vec = (*group)[i];
		strm << -vec.X() << " " << vec.Y() << " " << vec.Z() << "\n";
	}
	float_array->setCharData(strm.str());

	daeElement* accessor = source->add("technique_common accessor");

	string arrayPosSourceName("#" + arrayPosName);
	accessor->setAttribute("source", arrayPosSourceName.c_str());
	accessor->setAttribute("count", intToString(group->size()).c_str());
	accessor->setAttribute("stride", "3");
	daeElement* paramX = accessor->add("param");
	paramX->setAttribute("name", "X");
	paramX->setAttribute("type", "float");
	daeElement* paramY = accessor->add("param");
	paramY->setAttribute("name", "Y");
	paramY->setAttribute("type", "float");
	daeElement* paramZ = accessor->add("param");
	paramZ->setAttribute("name", "Z");
	paramZ->setAttribute("type", "float");

}

void COLLADAExport::addTexcoordArray(daeElement* mesh, Vec2Group* group,
		string posName) {
	daeElement* source = mesh->add("source");
	source->setAttribute("id", posName.c_str());

	daeElement* float_array = source->add("float_array");
	string arrayPosName(posName + "-array");
	float_array->setAttribute("id", arrayPosName.c_str());
	float_array->setAttribute("count", intToString(group->size() * 2).c_str());

	ostringstream strm;
	for (uint i = 0; i < group->size(); i++) {
		Vec2 vec = (*group)[i];
		strm << vec.U() << " " << vec.V() << " ";
	}
	float_array->setCharData(strm.str());

	daeElement* accessor = source->add("technique_common accessor");

	string arrayPosSourceName("#" + arrayPosName);
	accessor->setAttribute("source", arrayPosSourceName.c_str());
	accessor->setAttribute("count", intToString(group->size()).c_str());
	accessor->setAttribute("stride", "2");
	daeElement* paramU = accessor->add("param");
	paramU->setAttribute("name", "U");
	paramU->setAttribute("type", "float");
	daeElement* paramV = accessor->add("param");
	paramV->setAttribute("name", "V");
	paramV->setAttribute("type", "float");

}

void COLLADAExport::addTriangleStrips(daeElement* mesh, PolyGroup* group,
		string name) {
	daeElement* tristrips = mesh->add("tristrips");
	tristrips->setAttribute("count",
			intToString(group->TriangleStripCount()).c_str());

	addInputs(tristrips, group, name);

	for (uint i = 0; i < group->TriangleStripCount(); i++) {
		daeElement* p = tristrips->add("p");

		TriangleStrip strip = group->GetTriangleStrip(i);

		ostringstream strm;
		for (uint j = 0; j < strip.Count(); j++) {
			Vertex vert = strip[j];
			if (vert.GetVertex() >= group->VertexGroupPtr()->size())
				std::cout << "WARNING: Tristrip vertex out of range in "
						<< name << endl;
			if (vert.GetNormal() >= group->NormalGroupPtr()->size())
				std::cout << "WARNING: Tristrip normal out of range in "
						<< name << endl;
			strm << vert.GetVertex() << " " << vert.GetNormal() << "  ";

			for (int k = 0; k < vert.UVCount(); k++) {
				strm << vert.GetUV(k) << " ";
			}
		}
		p->setCharData(strm.str());
	}
}
void COLLADAExport::addTriangleFans(daeElement* mesh, PolyGroup* group,
		string name) {
	daeElement* trifans = mesh->add("trifans");
	trifans->setAttribute("count",
			intToString(group->TriangleFanCount()).c_str());

	addInputs(trifans, group, name);

	for (uint i = 0; i < group->TriangleFanCount(); i++) {
		daeElement* p = trifans->add("p");

		TriangleFan fan = group->GetTriangleFan(i);

		ostringstream strm;
		Vertex origin = fan.GetOriginVertex();
		strm << origin.GetVertex() << " " << origin.GetNormal() << "  ";
		for (uint j = 0; j < fan.Count(); j++) {
			Vertex vert = fan[j];
			if (vert.GetVertex() >= group->VertexGroupPtr()->size())
				std::cout << "WARNING: Triangle Fan vertex out of range in "
						<< name << endl;
			if (vert.GetNormal() >= group->NormalGroupPtr()->size())
				std::cout << "WARNING: Triangle Fan normal out of range in "
						<< name << endl;
			strm << vert.GetVertex() << " " << vert.GetNormal() << " ";

			for (int k = 0; k < vert.UVCount(); k++) {
				strm << vert.GetUV(k) << " ";
			}
		}
		p->setCharData(strm.str());
	}
}
void COLLADAExport::addTriangles(daeElement* mesh, PolyGroup* group,
		string name) {
	daeElement* tris = mesh->add("triangles");
	tris->setAttribute("count", intToString(group->TriangleCount()).c_str());

	addInputs(tris, group, name);

	daeElement* p = tris->add("p");
	ostringstream strm;
	for (uint i = 0; i < group->TriangleCount(); i++) {
		Triangle tri = group->GetTriangle(i);

		for (int j = 0; j < 3; j++) {
			Vertex vert = tri[j];
			if (vert.GetVertex() >= group->VertexGroupPtr()->size())
				std::cout << "TRIANGLE WARNING: Vertex out of range in "
						<< name << endl;
			if (vert.GetNormal() >= group->NormalGroupPtr()->size())
				std::cout << "TRIANGLE WARNING: Normal out of range in "
						<< name << endl;
			strm << vert.GetVertex() << " " << vert.GetNormal() << " ";

			for (int k = 0; k < vert.UVCount(); k++) {
				strm << vert.GetUV(k) << " ";
			}
		}
		strm << "\n";
	}
	p->setCharData(strm.str());
}
void COLLADAExport::addQuads(daeElement* mesh, PolyGroup* group, string name) {

}

void COLLADAExport::addInputs(daeElement* parent, PolyGroup* group, string name) {
	daeElement* inputVert = parent->add("input");
	inputVert->setAttribute("semantic", "VERTEX");
	string vertSourceName("#" + name + "-vertex");
	inputVert->setAttribute("source", vertSourceName.c_str());
	inputVert->setAttribute("offset", "0");
	daeElement* inputNorm = parent->add("input");
	inputNorm->setAttribute("semantic", "NORMAL");
	string normSourceName("#" + name + "-normal");
	inputNorm->setAttribute("source", normSourceName.c_str());
	inputNorm->setAttribute("offset", "1");

	for (int i = 0; i < group->UVGroupCount(); i++) {
		daeElement* inputTex = parent->add("input");
		inputTex->setAttribute("semantic", "TEXCOORD");
		string texSourceName("#" + name + "-texcoord" + intToString(i));
		inputTex->setAttribute("source", texSourceName.c_str());
		inputTex->setAttribute("offset", intToString(2 + i).c_str());
		inputTex->setAttribute("set", "0");
	}
}

string COLLADAExport::intToString(int num) {
	ostringstream strm;
	strm << num;
	return strm.str();
}










using namespace std;

void printUsage() {
	cout << "Usage:" << endl;
	cout << "mdl0converter [-t] input_file output_file" << endl << endl;
	cout << "Options:" << endl;
	cout << "   -t    Convert all triangle strips, triangle fans, and quads to triangles." << endl << endl;
	cout << "Copyright (C) 2008 William Hahne" << endl;
}

void printCredits() {
	// todo: add credits
}

int main(int argc, char *argv[]) {
	char* inputfile = NULL;
	char* outputfile = NULL;
	uint opts = 0;
	for (int i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			switch (argv[i][1]) {
			case 't':
				opts |= LO_CONV_TO_TRIS;
				break;
			default:
				cout << "Invalid option: " << argv[i] << endl;
				printUsage();
				return 0;
			}
		} else {
			if (inputfile == NULL) {
				inputfile = argv[i];
			}
			else if (inputfile != NULL && outputfile == NULL) {
				outputfile = argv[i];
			}
		}
	}

	if (inputfile == NULL || outputfile == NULL) {
		cout << "Not enough arguments." << endl;
		printUsage();
		return 0;
	}

	ifstream f;
	f.open(inputfile, ios::binary | ios::in);
	if (!f.good() || !f.is_open()) {
		cout << "Error opening file." << endl << endl;
		printUsage();
		return 0;
	}
	f.seekg(0, ios::beg);
	int begin = f.tellg();
	f.seekg(0, ios::end);
	int size = (int) f.tellg() - begin;

	f.seekg(0, ios::beg);
	char* data = new char[size];
	f.read(data, size);

	MDL0File file;
	file.Load(data, size, opts);

	// convert to collada
	COLLADAExport daeExport;
	outputfile = inputfile + ".DAE"
	if (!daeExport.Export(&file, outputfile)) {
		cout << "Error writing output file." << endl << endl;
		printUsage();
		return 0;
	}

	cout << "Success" << endl;

	return 0;
}

EDIT:
I was expecting this to scroll...

Edited 6 Years Ago by Tcll: n/a

it's not the collada I'm worried about...

I'm writing an import script for blender to import MDL0 files
as well as an export script...

but thanx for the referance

Edited 6 Years Ago by Tcll: n/a

wait wut...
my scripts??
you mean on Smashboards, emutalk, etc...??

and yea... that's right...

it's sad how I had to come here actually...

Edited 6 Years Ago by Tcll: n/a

Could be that that module you want would work with IronPython or what you say IronPython gurus?

Or the program could be complied to library (dll in Windows) and used as Python library with ctypes. Or you could see if shedskin could manage to turn all your code to C++ if you are in non-windows platform (or use version 0.3 for windows)

Edited 6 Years Ago by pyTony: n/a

already, I can say that's a no...
MDL0 files are not in ASCII

would anyone like some info I have on the mdl0 files??

Edited 6 Years Ago by Tcll: n/a

Maybe a sample file and some info would help mate.

I'm just trying to help, but I have litle insight on this.

And this?

Edited 6 Years Ago by Beat_Slayer: n/a

I understand... :)

you can look into the research that's been done:
http://www.smashboards.com/showpost.php?p=10716092&postcount=3 (most of the research)
http://emutalk.net/showpost.php?p=432680&postcount=2 (my research to add)

here's the mdl0 of the only char I was able to get imported into blender:
(using the old conversion methods and such)
[img]http://lh4.ggpht.com/_IteXPmeC6ek/S9zsZyqYhXI/AAAAAAAABDk/rDWHE9dPOwU/s640/Pikachu.PNG.jpg[/img]
look in the attached file...

Edited 6 Years Ago by Tcll: n/a

Maybe a sample file and some info would help mate.

I'm just trying to help, but I have litle insight on this.

And this?

lol
I just noticed the attachment containing the nsbmd.html file XD

I already had that...
the notes are more recent than that :)

but yea...

hope you guys have fun :)
I just wanna know how I can rewrite C++ into Py is all...
still keep finding the same old reverse results...
(rewriting py in C++)

Could be that that module you want would work with IronPython or what you say IronPython gurus?

Or the program could be complied to library (dll in Windows) and used as Python library with ctypes. Or you could see if shedskin could manage to turn all your code to C++ if you are in non-windows platform (or use version 0.3 for windows)

Well IronPython is only good if the foreign code is C# or VB.NET, or even IronRuby.

The reason why this code can't be directly translated line-by-line to Python is because it is C++, with its low-level/static pointers, private class members, etc

You could just go ahead and compile it, and use the dll with ctypes.
It is easier said than done, though. (You would need to create C interfaces... etc since ctypes is for C not C++)

Which is why I ultimately recommend Boost.Python.

C++ library that allows Python/C++ integration.

Edited 6 Years Ago by jcao219: n/a

Well IronPython is only good if the foreign code is C# or VB.NET, or even IronRuby.

The reason why this code can't be directly translated line-by-line to Python is because it is C++, with its low-level/static pointers, private class members, etc

You should just go ahead and compile it, and use the dll with ctypes.
It is easier said than done, though.

that doesn't help me with my importer...
the code has already been compiled by william Hane...

I'm trying to use his methods for my importer...
(along with methods from other converters)
but what good does it do me if reading the code is like trying to read chinese...

and I cant just import it as a module either...
the code is setup to convert...
I need to rewrite it to import, and blender doesn't read C++

Edited 6 Years Ago by Tcll: n/a

that doesn't help me with my importer...
the code has already been compiled by william Hane...

I'm trying to use his methods for my importer...
(along with methods from other converters)
but what good does it do me if reading the code is like trying to read chinese...

and I cant just import it as a module either...
the code is setup to convert...
I need to rewrite it to import, and blender doesn't read C++

I can read Chinese :P

I've never used Boost.Python, but it looks like it is able to make Python modules out of C++ files. So take a look there.

Comments
Congratulations on reading chinese (are you chinese ?)

KK sweet :D

I'll try it...

I'll be back I guess XD

thanx for the help (to everyone) :)

KK sweet :D

I'll try it...

I'll be back I guess XD

thanx for the help (to everyone) :)

well I wasn't as lucky as I thought I was...
it turns out, this is only a compiler IDE module that can allow mixing C++ and Py...
havn't found anything to do with conversion yet...

but I've noticed this C++ to Py conversion thing is starting to become big...

I don't think you can translate C++ into python if you don't understand C++. Your program does not seem too difficult to translate for someone who knows both C++ and python. The good way to translate is to understand precisely what the C++ code does and to achieve the same effect in python. Note that the C++ code uses different low level types, for example uint32_t uint16_t int16_t uint uchar int. In python, there is only one integer type. The effect of the code on these low level types must be examined attentively for code translation.

As far as I know, there is no automated tool to translate C++ in python, because the semantics of C++ code is too difficult.

So, learn C++, or find an expert to translate the code for you.

Edited 6 Years Ago by Gribouillis: n/a

well I wasn't as lucky as I thought I was...
it turns out, this is only a compiler IDE module that can allow mixing C++ and Py...
havn't found anything to do with conversion yet...

but I've noticed this C++ to Py conversion thing is starting to become big...

Exactly, very big because it's not quite possible. You'll have to rewrite the entire thing in Python instead of (line-by-line) converting it. C++ is much lower-level than Python.
Additionally, you would have to write Python versions of the C++ header domCOLLADA.h, or find another way to do that.

The point of the Boost.Python thing is to allow you to use that C++ file from Python.

Edited 6 Years Ago by jcao219: n/a

Exactly, very big because it's not quite possible. You'll have to rewrite the entire thing in Python instead of (line-by-line) converting it. C++ is much lower-level than Python.
Additionally, you would have to write Python versions of the C++ header domCOLLADA.h, or find another way to do that.

The point of the Boost.Python thing is to allow you to use that C++ file from Python.

Here seems to be one description of that header file use.
http://gadgetweb.de/programming/usingcolladadom.html

So, learn C++, or find an expert to translate the code for you.

well, I've tried learning, and still can't understand the tutorials for crap...
(tried to do what the tutorials told me and failed miserably)

so I've been looking for someone who can translate,
or at least give me a guide to translate the C++ classes and whatever...

The point of the Boost.Python thing is to allow you to use that C++ file from Python.

if only the C++ headers were rewritten in python to be able to be used as modules...

well, I've tried learning, and still can't understand the tutorials for crap...
(tried to do what the tutorials told me and failed miserably)

so I've been looking for someone who can translate,
or at least give me a guide to translate the C++ classes and whatever...

if only the C++ headers were rewritten in python to be able to be used as modules...

There are lots of us who would be happy to 'translate' modest amounts of C, C++, etc code to Python code that does the equivalent.
It's just that your code is really, really big, and plus, there are the dae.h and domCollada.h files which may even be bigger.

would it help if I told you I don't need the collada part of the code :)
I just want anything that deals with mdl0...

I can get you the source for Will's converter if you like :)
(meaning the seprate files)

go ahead ant traslate :)
just ignore anything to do with collada...

I just need to know how to convert the values in an mdl0 file...

thanx for all your help :)
and if there are any referances on how to translate,
please let me know...

Edited 6 Years Ago by Tcll: n/a

go ahead ant traslate :)
just ignore anything to do with collada...

I just need to know how to convert the values in an mdl0 file...

thanx for all your help :)
and if there are any referances on how to translate,
please let me know...

Alright, I'll do my best.

@jcao219

how's progress coming??
just curious #_#

anything useful yet?

@jcao219

how's progress coming??
just curious #_#

anything useful yet?

when you try to directly translate C++ to Python, you end up writing horrible unidiomatic code.

I don't think I can do this,
especially when I saw the Union thing, there's really no equivalent in Python*
here's what I got though:

class Vec3(object):
	def __init__(self, x = 0.0, y = 0.0, z = 0.0):
		self.__x = x
		self.__y = y
		self.__z = y
		
	@property
	def X(self):
		return self.__x
	
	@property
	def Y(self):
		return self.__y
		
	@property
	def Z(self):
		return self.__y
		
		

class Vec2(object):
	def __init__(self, x = 0.0, y = 0.0):
		self.__x = x
		self.__y = y
		
	@property
	def X(self):
		return self.__x
	
	@property
	def Y(self):
		return self.__y
		
		
class RGBA(object):
	def __init__(self, r, g, b, a):
		if not all([0 =< val <= 255 for val in (r,g,b,a)]):
			raise TypeError("r, g, b, and a arguments must be from 0 to 255!")
		try:
			self.__r, self.__g, self.__b, self.__a = int(r), int(g), int(b), int(a)  #Follow duck typing
		except ValueError:
			TypeError("Arguments can only be numbers!")
			
	@property
	def R(self):
		return self.__r
		
	@property
	def G(self):
		return self.__g
		
	def B(self):
		return self.__b
		
	def A(self):
		return self__a
		
		
class VecGroup(list):
	"""A list of Vecs"""
	
	def __init__(self, *args, **kwargs):
		super(VecGroup, self).__init__(*args, **kwargs)
		self.set = False
		
	def SetBound(self, min, max):  
	"""Although this is supposed to be as close to the cpp as possible,
	I don't want to go to the trouble of enforcing all things in this collection are 
	Vecs"""
		if not self.set:
			self.__min = min
			self.__max = max
			self.__set = True
			
	@property
	def BoundingMin(self):
		return self.__min
		
	@property
	def BoundingMax(self):
		return self.__max
		

class Vec3Group(VecGroup): pass
class Vec2Group(VecGroup): pass
class RGBAGroup(list): pass

class Vertex(object):
	def __init__(self):
		self.__vertex = 0
		self__normal = 0
		self.__color = 0
		self.__uvCount = 0
		self.__uv = []
		
	def Set(vertex, normal, color, uv, numUV):
		"""vertex, normal, color, and numUV are integers, uv is a collection of ints"""
		self.__vertex = int(vertex)  #uint16 is integer from 0~65535
		self.__normal = int(normal)
		self.__color = int(color)
		self.__uv = list(uv)
		self.__numUV = numUV
		
	def GetVertex(self):  #I like to make methods that start with "Get" as methods
		return self.__vertex
		
	def GetNormal(self):
		return self.__normal
		
	def GetColor(self):
		return self.__color
		
	def GetUV(self):
		return self.__uv
		
	@property
	def UVCount(self):  #and those that don't, I make them as properties
		return self.__numUV
		

def TriangleStrip(self):
	def __init__(self):
		self.__locked = False
		self.verts = []
		
	def __getitem__(self, index):
		return self.verts[index]
		
	def Add(self, vertex):
		if not self.__locked:
			self.verts.append(vertex)
			
	def Lock(self):
		self.locked = True
		
	@property
	def Count(self):
		return len(self.verts)

then I figured out it was impractical
very sorry,
the best way is to identify exactly what this code is doing,
and write it idiomatically in Python.
there's so many pointers and C/C++ish low-level memory stuff in there, so making a python version of that may be hard.

*there probably is, but I'm not experienced in that area
I could probably translate the mdl0file class, since that's the most important one, but i'll have to wait a few days, right now I'm too busy with my vacation :D

Edited 6 Years Ago by jcao219: n/a

that's ok :)

hey, you gave it your best
and it looks close enough to the C++ code
(since I can't read C++, I can only look at it) =3=

I'll see what I can gather from this...
thanx a bunch...

maybe I'll use this thread to develope my import/export script...
nah... I'll make a new thread when I get around to posting it...

Edited 6 Years Ago by Tcll: n/a

I see...
you just rewrote the main classes

however, I noticed you only got to the triangle strips when you couldn't work with it anymore...

one thing I've had much trouble with is accessing coords stored in a variable...
I can't for the life of me, figure out how to store a file in a var...

This question has already been answered. Start a new discussion instead.