Brawlbox Resources & History

Started by BlackJax96, December 14, 2010, 03:39:11 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

heh...

yea...
I'm trying to find out if there's a 0, 1, or 4 :/
I could post the template, but if I do, you can expect errors galore XD
including I disabled the definitions (they take too long to load in edit mode)

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

Is the plan still to make a converter, or an exporter?

Also, I apparently stumbled upon a .pmd importer for 3DS, but unfortunately when I went to download it, the link was broken. However, apparently MarioKart had worked on that site before so... perhaps he has a copy?

Quote from: Roo on December 17, 2010, 01:15:02 AM
Is the plan still to make a converter, or an exporter?
lol I'm building this template for a reason :P

QuoteAlso, I apparently stumbled upon a .pmd importer for 3DS, but unfortunately when I went to download it, the link was broken. However, apparently MarioKart had worked on that site before so... perhaps he has a copy?

ah nice :D
if it works, let me know

I have a Yoko model sent to me that's waiting to be extracted :)

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

You mean the Resident Evil PMD importer? Yeah I saw that >.>
http://z6.invisionfree.com/Resident_Evil_4_PC/index.php?showtopic=1494

Too bad he didn't put mirrors -_-

December 17, 2010, 01:44:13 AM #64 Last Edit: December 17, 2010, 01:45:55 AM by Roo
RRRRRRRRRAAAAAAAAAAAAAAAAAAAAGGGGGGGGGGGGGEEEEEEEEEEEEEEE!!!

Also, Tech, you do Realize that if you make a video tutorial for hexing Pika's final smash, you're going to get featured on KC-MM blog. Check the "Featured" thread.

yea... I know...
I have to PM him

I'm sick right now though,
and I don't think anyone wants to hear a cold :P

colds suck... don't catch one
especially if you're like me where everything lasts twice as long... DX

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

Sound worth it if living counts as twice as long.


Quote from: Roo on December 17, 2010, 02:13:10 AM
Sound worth it if living counts as twice as long.

lol
*trollface* Problem logic

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

December 17, 2010, 06:55:22 PM #69 Last Edit: December 17, 2010, 07:00:41 PM by Tcll
hmm...
this has baffled me even more...
my template freezez with Pika...
but I tried it with Pachi and it worked...

but look what I found on a type 3:

98 00 1F
0F 2D 01 E6 01 DD 01 4F
0F 2D 01 F8 01 EE 01 61
0C 2A 01 F7 01 ED 01 60
03 21 01 F6 01 EC 01 5F
03 21 01 E0 01 D7 01 49
03 21 02 0F 02 05 01 78
03 21 01 E1 01 D8 01 4A
03 21 02 08 01 FE 01 71
03 21 01 E2 01 D9 01 4B
03 21 02 07 01 FD 01 70
03 21 02 0E 02 04 01 77
03 21 01 D0 01 C9 01 39
03 21 01 B9 01 B4 01 22
03 21 01 BD 01 B7 01 26
03 21 01 BA 01 B5 01 23
03 21 01 BB 01 B6 01 24
03 21 01 BC 00 B2 01 25
03 21 01 C2 01 BC 01 2B
03 21 01 C3 01 BD 01 2C
03 21 01 C6 01 C0 01 2F
03 21 02 6F 02 62 01 2B
03 21 02 70 02 63 01 2D
03 21 02 6B 02 5E 01 24
03 21 02 6D 02 60 01 27
03 21 02 6C 02 5F 01 26
03 21 02 6E 02 61 01 28
03 21 02 77 02 69 01 39
03 21 02 79 02 6B 01 3C
03 21 02 A4 02 95 01 70
03 21 02 A5 02 96 01 71
03 21 02 7F 02 71 01 4B

the length is 8... (not 9)
why must poly's be so tough DX

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

hey...
can anyone read/id this:
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;
}

I know it's a C-type code :/

anyways...
this'll help me figure out the polygon structure
(code taken from will's converter)

can anyone comment on that??
thanx

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

Let me look at the code for a bit, I'll see what I can get from it

kk

if you need anything else from will's src, let me know :/

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

Got the whole source
I'm prepared :D

Except neither AiS nor Will's converter will build... too many errors
idk why the released source would have errors but I'll have to fix them

lol
I did manage to take the whole src and put it in 1 document :P
here:


#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;
}


[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.