Home Gallery Resources The Team Rules chat Login Register
Pages:  1 2 3 4 [5] 6 7 8 ... 1046
Author Topic: Brawlbox Resources & History  (Read 3813408 times)
0 Members and 3 Guests are viewing this topic.
DarkPikachu
Angel Kitten
***
Offline Offline

Posts: 3069


complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #60 on: December 16, 2010, 05:51:42 PM »


    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)
    Logged


    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.

    Roo
    Lol Kitten
    *********
    Offline Offline

    Posts: 785


    Or WAS I?

  • Awards Fiery Topic Heart Container

  • View Profile Awards
    « Reply #61 on: December 16, 2010, 06:15:02 PM »


    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?
    Logged

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #62 on: December 16, 2010, 06:19:37 PM »


    Is the plan still to make a converter, or an exporter?
    lol I'm building this template for a reason Tongue

    Quote
    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?

    ah nice Cheesy
    if it works, let me know

    I have a Yoko model sent to me that's waiting to be extracted Smiley
    Logged


    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.

    BlackJax96
    Brawl Mod God
    Moderator
    ****
    Offline Offline

    Posts: 4612


  • Awards KCMM Veteran Sniper King for a Day Featured

  • View Profile Awards
    « Reply #63 on: December 16, 2010, 06:31:39 PM »


    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 -_-
    Logged

    Roo
    Lol Kitten
    *********
    Offline Offline

    Posts: 785


    Or WAS I?

  • Awards Fiery Topic Heart Container

  • View Profile Awards
    « Reply #64 on: December 16, 2010, 06:44:13 PM »


    RRRRRRRRRAAAAAAAAAAAAAAAAAAAAGGGGGGGGGGGGGEEEEEEE EEEEEEEE!!!

    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.
    « Last Edit: December 16, 2010, 06:45:55 PM by Roo » Logged

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #65 on: December 16, 2010, 07:08:07 PM »


    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 Tongue

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


    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.

    Roo
    Lol Kitten
    *********
    Offline Offline

    Posts: 785


    Or WAS I?

  • Awards Fiery Topic Heart Container

  • View Profile Awards
    « Reply #66 on: December 16, 2010, 07:13:10 PM »


    Sound worth it if living counts as twice as long.
    Logged

    BlackJax96
    Brawl Mod God
    Moderator
    ****
    Offline Offline

    Posts: 4612


  • Awards KCMM Veteran Sniper King for a Day Featured

  • View Profile Awards
    « Reply #67 on: December 16, 2010, 07:14:46 PM »


    Sound worth it if living counts as twice as long.

    Loophole ftw
    Logged

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #68 on: December 16, 2010, 07:29:50 PM »


    Sound worth it if living counts as twice as long.

    lol
    *trollface* Problem logic
    Logged


    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.

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #69 on: December 17, 2010, 11:55:22 AM »


    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
    « Last Edit: December 17, 2010, 12:00:41 PM by Tcll » Logged


    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.

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #70 on: December 17, 2010, 02:22:34 PM »


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


    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.

    BlackJax96
    Brawl Mod God
    Moderator
    ****
    Offline Offline

    Posts: 4612


  • Awards KCMM Veteran Sniper King for a Day Featured

  • View Profile Awards
    « Reply #71 on: December 17, 2010, 05:09:50 PM »


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

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #72 on: December 17, 2010, 05:36:32 PM »


    kk

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


    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.

    BlackJax96
    Brawl Mod God
    Moderator
    ****
    Offline Offline

    Posts: 4612


  • Awards KCMM Veteran Sniper King for a Day Featured

  • View Profile Awards
    « Reply #73 on: December 17, 2010, 05:47:00 PM »


    Got the whole source
    I'm prepared Cheesy

    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
    Logged

    DarkPikachu
    Angel Kitten
    ***
    Offline Offline

    Posts: 3069


    complexity == fun

  • Awards Super Saiyan Topic Heart Container KCMM Veteran Tutorial Writer

  • View Profile Awards
    « Reply #74 on: December 17, 2010, 06:14:00 PM »


    lol
    I did manage to take the whole src and put it in 1 document Tongue
    here:
    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;
    }

    Logged


    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.

    Pages:  1 2 3 4 [5] 6 7 8 ... 1046
    Print
    Jump to: