Just some example code to load 3DS files into flash. Not really finished, what is missing is to seperate map loading (Texture, Specular, Reflection), also it would eb nice to implement the keyframe loader, but that in some time to come. Oh and one more thing, the code for Mesh, Model objects is not published, it will be in time later:
package Lib.Mesh
{
import __AS3__.vec.Vector;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Vector3D;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
public class MeshLoader extends EventDispatcher
{
public static var MESH_LOADED:String = “mesh_loaded”;
private var loader:URLLoader = null;
public var mesh:Mesh = null; // My own class for holding all the mesh data
public function MeshLoader() // Constructor
{
}
public function Load3DS(mURL:String):void { // The start loading function, notice no error checking, assuming all ok
var urlR:URLRequest = new URLRequest(mURL);
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, MeshLoaded);
loader.load(urlR);
}
private function MeshLoaded(e:Event):void { // Actual loading function
var ChunkID:int = 0;
var ChunkLength:int = 0;
var ColorMode:String = “Ambient”;
var MaterialMapMode:String = “Texture”;
var currMeshObject:int = -1;
var currMeshMaterial:int = -1;
var MObj:MeshObject = null; // generic MeshObject to be used
var MFace:MeshFace = null; // generic MeshFace to be used
var MVertex:MeshVertex = null; // generic MeshVertex to be used
var MTexcoord:MeshTexCoord = null; // generic MeshTexCoord to be used
var MMaterial:MeshMaterial = null; // generic MeshMaterial to be used
try { // lets give it a shot
var data:ByteArray = loader.data;
data.endian = “littleEndian”; // Make sure we use little endian
var tmpData:ByteArray = new ByteArray();
while(data.bytesAvailable > 0) {
// read the chunkID
ChunkID = data.readUnsignedShort();
// read the Chunk length
ChunkLength = data.readUnsignedInt();
switch(ChunkID) {
case 0x4D4D: // Main Chunk
mesh = new Mesh();
break;
case 0x3D3D: // 3D Editor Chunk
break;
case 0x4000: // Object Chunk
currMeshObject++;
// here load the name of the object
var obi:uint = 0;
var name:String = “”;
var rc:String = “”;
var rb:int = 0;
do {
rb = data.readByte();
rc = String.fromCharCode(rb);
name += rc;
obi++;
} while(rb != 0 && obi<20);
var MObject:MeshObject = new MeshObject();
MObject.setName(name);
mesh.addObject(MObject);
break;
case 0x4100: // Triangular Mesh Chunk
break;
case 0x4110: // Mesh Vertex Chunk
var NumVertices:uint = 0;
NumVertices = data.readUnsignedShort();
var VerticesArray:Vector.<MeshVertex> = new Vector.<MeshVertex>();
for(var vi:uint = 0; vi < NumVertices; vi++) {
var x:Number = data.readFloat();
var y:Number = data.readFloat();
var z:Number = data.readFloat();
MVertex = new MeshVertex();
MVertex.setPosition(new Vector3D(x, y, z, 0));
VerticesArray.push(MVertex);
}
MObj = mesh.getObjectList()[currMeshObject];
MObj.setVertexList(VerticesArray);
break;
case 0x4120: // Mesh Face Chunk
var NumFaces:uint = 0;
NumFaces = data.readUnsignedShort();
var FacesArray:Vector.<MeshFace> = new Vector.<MeshFace>();
MObj = mesh.getObjectList()[currMeshObject];
for(var fi:uint = 0; fi < NumFaces; fi++) {
var fa:Number = data.readUnsignedShort();
var fb:Number = data.readUnsignedShort();
var fc:Number = data.readUnsignedShort();
var FaceFlags:Number = data.readUnsignedShort();
var VList:Vector.<MeshVertex> = new Vector.<MeshVertex>();
VList.push(MObj.getVertexList()[fa]);
VList.push(MObj.getVertexList()[fb]);
VList.push(MObj.getVertexList()[fc]);
MFace = new MeshFace();
MFace.setFaceVertices(VList);
MFace.setFaceIndices(new Vector3D(fa, fb, fc, FaceFlags));
FacesArray.push(MFace);
}
MObj.setFaceList(FacesArray);
break;
case 0x4130: // Mesh Face Material Chunk
var mi:uint = 0;
var mname:String = “”;
var mrc:String = “”;
var mrb:int = 0;
do {
mrb = data.readByte();
mrc = String.fromCharCode(mrb);
mname += mrc;
mi++;
} while(mrb != 0 && mi<20);
mname = mname.substr(0, mname.length-1);
MMaterial = mesh.getMaterialByName(mname);
var NumMaterialFaces:uint = 0;
var MaterialFacesArray:Vector.<Number> = new Vector.<Number>();
NumMaterialFaces = data.readUnsignedShort();
MObj = mesh.getObjectList()[currMeshObject];
for(var mfi:uint=0; mfi < NumMaterialFaces; mfi++) {
var mfIndex:Number = data.readUnsignedShort();
MFace = MObj.getFaceList()[mfIndex];
MFace.setFaceMaterialName(mname);
MFace.setFaceMaterialIndex(MMaterial.getMaterialIndex());
}
break;
case 0x4140: // Mesh Vertex TexCoord Chunk
var NumUVs:uint = 0;
NumUVs = data.readUnsignedShort();
var UVsArray:Vector.<MeshTexCoord> = new Vector.<MeshTexCoord>();
for(var uvi:uint = 0; uvi < NumUVs; uvi++) {
var u:Number = data.readFloat();
var v:Number = data.readFloat();
var MTexCoord:MeshTexCoord = new MeshTexCoord();
MTexCoord.setTexCoord(new Vector3D(u, v, 0, 0));
VerticesArray[uvi].setTexCoord(new Vector3D(u, v, 0, 0));
UVsArray.push(MTexCoord);
}
break;
case 0x4160: // Mesh Object Pivot Chunk
var TMV:Vector.<Number> = new Vector.<Number>();
for(var tmvi:uint=0; tmvi<12; tmvi++) {
TMV.push(data.readFloat());
}
var V:Vector.<Number> = Vector.<Number>([TMV[0], TMV[1], TMV[2], new Number(0), TMV[3], TMV[4], TMV[5], new Number(0), TMV[6], TMV[7], TMV[8], new Number(0), TMV[9], TMV[10], TMV[11], new Number(1)]);
var M:flash.geom.Matrix3D = new flash.geom.Matrix3D(V);
mesh.getObjectList()[currMeshObject].setTransformMatrix(M);
var tmviC:uint = 0;
break;
case 0xAFFF: // Material Chunk
currMeshMaterial++;
MMaterial = new MeshMaterial();
MMaterial.setMaterialIndex(currMeshMaterial);
mesh.addMaterial(MMaterial);
break;
case 0xA000: // Material Name Chunk
var mti:uint = 0;
var mtname:String = “”;
var mtrc:String = “”;
var mtrb:int = 0;
do {
mtrb = data.readByte();
mtrc = String.fromCharCode(mtrb);
mtname += mtrc;
mti++;
} while(mtrb != 0 && mti<20);
mtname = mtname.substr(0, mtname.length-1);
MMaterial = mesh.getMaterialList()[currMeshMaterial];
MMaterial.setMaterialName(mtname);
break;
case 0xA010: // Material Color Type Chunk (In our case)
ColorMode = “Ambient”;
break;
case 0xA020:
ColorMode = “Diffuse”;
break;
case 0xA030:
ColorMode = “Specular”;
break;
case 0x0011: // Color Chunk
var matRed:uint = data.readUnsignedByte();
var matGreen:uint = data.readUnsignedByte();
var matBlue:uint = data.readUnsignedByte();
MMaterial = mesh.getMaterialList()[currMeshMaterial];
switch(ColorMode) {
case “Ambient”:
MMaterial.setMaterialAmbientColor(new Vector3D(matRed, matGreen, matBlue));
break;
case “Diffuse”:
MMaterial.setMaterialDiffuseColor(new Vector3D(matRed, matGreen, matBlue));
break;
case “Specular”:
MMaterial.setMaterialSpecularColor(new Vector3D(matRed, matGreen, matBlue));
break;
}
break;
case 0xA200: // Material TextureMapChunk
break;
case 0xA300: // Material Map Name (In our case Texture Map, Dont use other texture Maps, otherwise implement other maps)
var mtmi:uint = 0;
var mtmurl:String = “”;
var mtmrc:String = “”;
var mtmrb:int = 0;
do {
mtmrb = data.readByte();
mtmrc = String.fromCharCode(mtmrb);
mtmurl += mtmrc;
mtmi++;
} while(mtmrb != 0 && mtmi<20);
mtmurl = mtmurl.substr(0, mtmurl.length-1);
MMaterial = mesh.getMaterialList()[currMeshMaterial];
switch(MaterialMapMode) {
case “Texture”:
MMaterial = mesh.getMaterialList()[currMeshMaterial];
MMaterial.setMaterialTextureMapURL(mtmurl);
break;
}
break;
default:
for(var di:uint=0; di<ChunkLength-6; di++)
data.readByte();
}
}
} catch(te:TypeError) {
trace(te.toString());
}
dispatchEvent(new Event(MESH_LOADED));
}
}
}