What's new

Blender MDL0 importer/exporter (help needed)

Tcll

Complexity == Fun >:3
you will need Blender to help...

I currently have 2 codes:

the actual MDL0 importer:
Code:
#!BPY
""" 
Name: 'Brawl (.mdl0)...'
Blender: 248
Group: 'Import'
Tooltip: 'Import a Brawl model file (.mdl0)'
"""
__author__= ['Tcll']
__url__ = ("")
__version__= '0.015'
__bpydoc__= '''\
mdl0 Importer
'''
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Bob Holcomb 
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Importing modules
import struct as S
import Blender
def HexToDec(n):
 return float(S.unpack("<h", S.pack("<H", int((n.encode('hex')), 16)))[0])
def readvert(v):
 x, y, z = (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001)
 v = v - 1
 return x, y, z
 
   
def import_mdl0(path):
 Blender.Window.WaitCursor(1)
 name = path.split('\\')[-1].split('/')[-1]
 mesh = Blender.NMesh.New( name ) # create a new mesh
 # parse the file
 mdl0 = open(path, 'rb')
 
 if (mdl0.read(4).__str__() == "MDL0"):#MDL0 Magic
  print "mdl0 is vald"
  
  h02 = mdl0.read(4) #0x04(4)  MDL0 Size
  h03 = mdl0.read(4) #0x08(4)  Sections
  h04 = mdl0.read(4) #0x0C(4)  Model Nodes Offset
  h05 = mdl0.read(4) #0x10(4)  Definitions List
  h06 = mdl0.read(4) #0x14(4)  Bones List
  h07 = mdl0.read(4) #0x18(4)  Vertices List
  h08 = mdl0.read(4) #0x1C(4)  Normals List
  h09 = mdl0.read(4) #0x20(4)  Colors List
  h10 = mdl0.read(4) #0x24(4)  UV Points List
  h11 = mdl0.read(4) #0x28(4)  Materials 1 List
  h12 = mdl0.read(4) #0x2C(4)  Materials 2 List
  h13 = mdl0.read(4) #0x30(4)  Polygons List
  h14 = mdl0.read(4) #0x34(4)  Textures 1 List
  h15 = mdl0.read(4) #0x38(4)  Textures 2 List
  h16 = mdl0.read(4) #0x3C(4)  Model Name Offset
  h17 = mdl0.read(4) #0x40(4)  Header Length
  h18 = mdl0.read(4) #0x44(4)  Header Offset
  h19 = mdl0.read(4) #0x48(4)  Unknown 1
  h20 = mdl0.read(4) #0x4C(4)  Unknown 2
  h21 = mdl0.read(4) #0x50(4)  # of Vertices
  h22 = mdl0.read(4) #0x54(4)  # of Faces
  h23 = mdl0.read(4) #0x58(4)  Unknown 3
  h24 = mdl0.read(4) #0x5C(4)  # of Nodes
  h25 = mdl0.read(4) #0x60(4)  Version
  h26 = mdl0.read(2) #0x62(2)  Unknown 4
  h27 = mdl0.read(2) #0x64(2)  Unknown 5
  h28 = mdl0.read(4) #0x68(4)  Box Min. X
  h29 = mdl0.read(4) #0x6C(4)  Box Min. Y
  h30 = mdl0.read(4) #0x70(4)  Box Min. Z
  h31 = mdl0.read(4) #0x74(4)  Box Max. X
  h32 = mdl0.read(4) #0x78(4)  Box Max. Y
  h33 = mdl0.read(4) #0x7C(4)  Box Max. Z
  h34 = mdl0.read(4) #0x80(4)  # of Nodes (Copy?)
  
  a = 0
  while(a==0):
   x, y, z = (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001)
   v = "v "+(x).__str__()+" "+(y).__str__()+" "+(z).__str__()
   if (v == 'v 0.0 0.0 0.0'):
    a = 1
   mesh.verts.append(Blender.NMesh.Vert(x, y, z))
 else:
  print "file is not in mdl0 fomat"
  mdl0.close()
 
 # link the mesh to a new object
 ob = Blender.Object.New('Mesh', name) # Mesh must be spelled just this--it is a specific type
 ob.link(mesh) # tell the object to use the mesh we just made
 scn = Blender.Scene.GetCurrent()
 for o in scn.getChildren():
  o.sel = 0
 scn.link(ob) # link the object to the current scene
 ob.sel= 1
 ob.Layers = scn.Layers
 Blender.Window.WaitCursor(0)
 Blender.Window.RedrawAll()
Blender.Window.FileSelector(import_mdl0, 'Import')


and what I use to test the verts:
(need a better conversion method)
what am I doing wrong D:>
Code:
#!BPY
""" 
Name: 'Brawl (.mdl0)...'
Blender: 248
Group: 'Import'
Tooltip: 'Import a Brawl model file (.mdl0)'
"""
__author__= ['Tcll']
__url__ = ("")
__version__= '0.015'
__bpydoc__= '''\
mdl0 Importer
'''
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Bob Holcomb 
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Importing modules
import struct as S
import Blender
def HexToDec(n):
 h = float(S.unpack("<h", S.pack("<H", int((n.encode('hex')), 16)))[0])
# while (h > 127): # uncomment this code for better results:
#  h = h*(1/256)
  
 return h

def import_mdl0(path):
 Blender.Window.WaitCursor(1)
 name = path.split('\\')[-1].split('/')[-1]
 mesh = Blender.NMesh.New( name ) # create a new mesh
 # parse the file
 mdl0 = open(path, 'rb')
 
 a = 0
 while(a==0):
  x, y, z = (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001), (HexToDec(mdl0.read(2))* 0.001)
  v = "v "+(x).__str__()+" "+(y).__str__()+" "+(z).__str__()
  if (v == 'v 0.0 0.0 0.0'):
   a = 1
  mesh.verts.append(Blender.NMesh.Vert(x, y, z))
 
 # link the mesh to a new object
 ob = Blender.Object.New('Mesh', name) # Mesh must be spelled just this--it is a specific type
 ob.link(mesh) # tell the object to use the mesh we just made
 scn = Blender.Scene.GetCurrent()
 for o in scn.getChildren():
  o.sel = 0
 scn.link(ob) # link the object to the current scene
 ob.sel= 1
 ob.Layers = scn.Layers
 Blender.Window.WaitCursor(0)
 Blender.Window.RedrawAll()
Blender.Window.FileSelector(import_mdl0, 'Import')

the commented code shows you all the verts (jumbled), while uncommenting it shows you about 10 verts (clean).

export a vert selection from an mdl0, and impoort that file...
(make sure to add about 2 lines of '00' to the end of the file in a hex editor before importing)

you will see the results.
 
OP
Tcll

Tcll

Complexity == Fun >:3
can someone compile this code for me??
part1:
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;
}
 
OP
Tcll

Tcll

Complexity == Fun >:3
part2:
Code:
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;
}

it's the code for williams converter
I'm sure some of you already know how this works...
I just put all the seperate source files into a single file and want to know if it works...

please note that I have no knowledge in C++
I used my knowledge in js to do this...

I expect there to be alot of errors.
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
can someone check these notes for me??
Code:
META note: these notes are kind of out of date.
All data is big endian.
BRES header:
 u32 magic = 'bres'
 u32 unknown
 u32 filesize
 u32 unknown
 u32 other_magic = 'root'
 u32 root directory length
BRES root directory @0x18:
 u32 unknown 
 u32 ndirents
 16 bytes unknown = ff ff 00 00 00 01 00 00
 ndirents * struct {
  u16 unknown[2]
  u16 unknown[2]
  u32 offset to dirname from start of directory
   dirname is a null terminated string
  u32 offset to data for entry from start of dir
  
  
 }
 
MDL0 header:
 u32 magic = 'MDL0'
 u32 filesize
 u32 (one less than offset index count?)
 u32 unknown
 u32 offsets to data block index blocks[]
data block index block { (0x260)
 u32 index block length
 u32 entry count (10 @ 0x264)
 u32 unknown[2]
 u32 zero[2]
 0x278 - 0x378: array {
  u16 model_id -- maps position blocks to normal blocks?
  u16 zero
  u16 unknown
  u16 unknown
  uint32 unknown (like 0x001a2f34):
   model id? when added to start offset of this data block -- consistent between positions and normals...
  uint32 offset to vertex position data block from start of this data block
 } [10]
}
another data block index at 0x118, unknown0 = 0x0148, count=13
NodeMix block {
 stream:
 u8 nexttype {
  00: done
  02: mapping data, u16 -> u16
  03: weighting data
 }
 nexttype == 02: {
  u16 unknown1
  u16 unknown2
 }
 nexttype == 03: {
  u16 (some id?)
  u8 number of weights
  struct {
   u16 transform_id
   float weight
  }[] weight_set
 }
}
vertex position data block {
 0x40 byte header {
  uint32_t length of this block
  int32_t offset to beginning of file (always negative)
  ...
  uint32_t at 0x10:
   index # of block (starts at 0, should be no gaps)
  uint32_t at 0x14: {
   0x01 = positions, has bounding box + zero pad
   0x00 = normals, no bounding box data + zero pad
  }
  ...
  uint16_t at 0x1c: bytes per vertex (0x04 * #components) {
   0x08 = UVs
   0x0c = vertex and normal data
  }
  uint16_t at 0x1e = number of vertices to follow
  0x20 {
  float[6] (bounding box?)
  uint32_t[2] zero
  } (not present for normals)
 } 
 component data follows: #vertices * #components float32
}

vertex array header: {
 0x140 bytes long, almost completely unknown
 u8 @ 0x0e {
  0x14 or 0x54 for u8 datas
  0x5e for u16 datas
 }
 u16 @ 0x1e (vertex count for a position data block) is:
  0x80 for a 4 or 7 byte vertex struct layout
  0xc0 for an 8 byte vertex struct layout
 u16 @ 0x94 = byte length of 3rd component in the struct
  only if @0x1e != 0xc0 and @0x0e != 0x14
}
vertex array data: {
 u8 list type to follow {
  0x00 == stop processing
  0xB8 == points
  0xA8 == lines
  0xB0 == line strip
  0x90 == triangles
  0x98 == triangle strip
  0xA0 == triangle fan
  0x80 == quads
 }
 u16 = #verts to follow
 if (@0x1e in header == 0xc0) {
  u8 position idx
  u8 unknown1
  u16 unknown2
  u8[4] more unknowns
 } else {
  component lengths defined in header (@0x0e, @0x94):
  position idx
  (uv or normal idx)
  (uv or normal idx)
 }
}
texture block: {
 u32 entry count
 entry (8 bytes) {
  u32 unknown
  u32 rel_offset to rel_offset to texture name (useless...)
 }
}

other notes to add:
MDL0 HEADER
Offset  Name
0x00(4)  MDL0 Identifier
0x04(4)  MDL0 Size
0x08(4)  Sections
0x0C(4)  Model Nodes Offset
0x10(4)  Definitions List
0x14(4)  Bones List
0x18(4)  Vertices List
0x1C(4)  Normals List
0x20(4)  Colors List
0x24(4)  UV Points List
0x28(4)  Materials 1 List
0x2C(4)  Materials 2 List
0x30(4)  Polygons List
0x34(4)  Textures 1 List
0x38(4)  Textures 2 List
0x3C(4)  Model Name Offset
0x40(4)  Header Length
0x44(4)  Header Offset
0x48(4)  Unknown 1
0x4C(4)  Unknown 2
0x50(4)  # of Vertices
0x54(4)  # of Faces
0x58(4)  Unknown 3
0x5C(4)  # of Nodes
0x60(4)  Version
0x62(2)  Unknown 4
0x64(2)  Unknown 5
0x68(4)  Box Min. X
0x6C(4)  Box Min. Y
0x70(4)  Box Min. Z
0x74(4)  Box Max. X
0x78(4)  Box Max. Y
0x7C(4)  Box Max. Z
0x80(4)  # of Nodes (Copy?)

MDL0 Bone data:
HEADER:
0x00 - Header Length (Usually 00D0)
0x04 - MDL0 Offset
0x08 - String Offset
0x0C - Bone Index
0x10 - Node ID
0x14 - Flags
0x18 - Pad 1
0x1C - Pad 2
0x20 - Scale X
0x24 - Scale Y
0x28 - Scale Z
0x2C - Rotation X
0x30 - Rotation Y
0x34 - Rotation Z
0x38 - Translation X
0x3C - Translation Y
0x40 - Translation Z
0x44 - Box Min. X
0x48 - Box Min. Y
0x4C - Box Min. Z
0x50 - Box Max. X
0x54 - Box Max. Y
0x58 - Box Max. Z
0x5C - Parent Offset
0x60 - First Child Offset
0x64 - Next Offset
0x68 - Previous Offset
0x6C - Bone Strings/Properties Offset
0x70 - FrameMatrix Set 1 Float 1
0x74 - FrameMatrix Set 2 Float 1
0x78 - FrameMatrix Set 3 Float 1
0x7C - FrameMatrix Set 4 Float 1
0x80 - FrameMatrix Set 1 Float 2
0x84 - FrameMatrix Set 2 Float 2
0x88 - FrameMatrix Set 3 Float 2
0x8C - FrameMatrix Set 4 Float 2
0x90 - FrameMatrix Set 1 Float 3
0x94 - FrameMatrix Set 2 Float 3
0x98 - FrameMatrix Set 3 Float 3
0x9C - FrameMatrix Set 4 Float 3
0xA0 - InverseBindMatrix Set 1 Float 1
0xA4 - InverseBindMatrix Set 2 Float 1
0xA8 - InverseBindMatrix Set 3 Float 1
0xAC - InverseBindMatrix Set 4 Float 1
0xB0 - InverseBindMatrix Set 1 Float 2
0xB4 - InverseBindMatrix Set 2 Float 2
0xB8 - InverseBindMatrix Set 3 Float 2
0xBC - InverseBindMatrix Set 4 Float 2
0xC0 - InverseBindMatrix Set 1 Float 3
0xC4 - InverseBindMatrix Set 2 Float 3
0xC8 - InverseBindMatrix Set 3 Float 3
0xCC - InverseBindMatrix Set 4 Float 3
FLAGS:
0x0001 - NoTransform
0x0002 - FixedTranslation
0x0004 - FixedRotation
0x0008 - FixedScale
0x0010 - Unk1
0x0100 - Unk2
0x0200 - HasGeometry
 
OP
Tcll

Tcll

Complexity == Fun >:3
OP
Tcll

Tcll

Complexity == Fun >:3
YO!
comon...
somebody...

I really need help with this... O_O

anyone >_> <_<
 

Top