package away3d.loaders { import away3d.arcane; import away3d.core.base.*; import away3d.core.utils.*; import flash.utils.*; use namespace arcane; /** * File loader for the Md2 file format (non-animated version). * * @author Philippe Ajoux (philippe.ajoux@gmail.com) */ public class Md2still extends AbstractParser { private var ini:Init; private var ident:int; private var version:int; private var skinwidth:int; private var skinheight:int; private var framesize:int; private var num_skins:int; private var num_vertices:int; private var num_st:int; private var num_tris:int; private var num_glcmds:int; private var num_frames:int; private var offset_skins:int; private var offset_st:int; private var offset_tris:int; private var offset_frames:int; private var offset_glcmds:int; private var offset_end:int; private var mesh:Mesh; private var scaling:Number; private function parseMd2still(data:ByteArray):void { data.endian = Endian.LITTLE_ENDIAN; var vertices:Array = []; var uvs:Array = []; ident = data.readInt(); version = data.readInt(); // Make sure it is valid MD2 file if (ident != 844121161 || version != 8) throw new Error("Error loading MD2 file: Not a valid MD2 file/bad version"); skinwidth = data.readInt(); skinheight = data.readInt(); framesize = data.readInt(); num_skins = data.readInt(); num_vertices = data.readInt(); num_st = data.readInt(); num_tris = data.readInt(); num_glcmds = data.readInt(); num_frames = data.readInt(); offset_skins = data.readInt(); offset_st = data.readInt(); offset_tris = data.readInt(); offset_frames = data.readInt(); offset_glcmds = data.readInt(); offset_end = data.readInt(); var i:int; // Vertice setup // Be sure to allocate memory for the vertices to the object // These vertices will be updated each frame with the proper coordinates for (i = 0; i < num_vertices; i++) vertices.push(new Vertex()); // UV coordinates data.position = offset_st; for (i = 0; i < num_st; i++) uvs.push(new UV(data.readShort() / skinwidth, 1 - ( data.readShort() / skinheight) )); // Faces data.position = offset_tris; for (i = 0; i < num_tris; i++) { var a:int = data.readUnsignedShort(); var b:int = data.readUnsignedShort(); var c:int = data.readUnsignedShort(); var ta:int = data.readUnsignedShort(); var tb:int = data.readUnsignedShort(); var tc:int = data.readUnsignedShort(); mesh.addFace(new Face(vertices[a], vertices[b], vertices[c], null, uvs[ta], uvs[tb], uvs[tc])); } // Frame animation data // This part is a little funky. data.position = offset_frames; readFrames(data, vertices, num_frames); mesh.type = ".Md2"; } private function readFrames(data:ByteArray, vertices:Array, num_frames:int):void { for (var i:int = 0; i < num_frames; i++) { var frame:Object = {name:""}; var sx:Number = data.readFloat(); var sy:Number = data.readFloat(); var sz:Number = data.readFloat(); var tx:Number = data.readFloat(); var ty:Number = data.readFloat(); var tz:Number = data.readFloat(); for (var j:int = 0; j < 16; j++) { var char:int = data.readUnsignedByte(); if (char != 0) frame.name += String.fromCharCode(char); } for (var h:int = 0; h < vertices.length; h++) { vertices[h].x = -((sx * data.readUnsignedByte()) + tx) * scaling; vertices[h].z = ((sy * data.readUnsignedByte()) + ty) * scaling; vertices[h].y = ((sz * data.readUnsignedByte()) + tz) * scaling; data.readUnsignedByte(); // "vertex normal index" } break; // only 1st frame for now } } /** * Creates a new Md2Still object. Not intended for direct use, use the static parse or load methods. * * @param data The binary data of a loaded file. * @param init [optional] An initialisation object for specifying default instance properties. * * @see away3d.loaders.Md2Still#parse() * @see away3d.loaders.Md2Still#load() */ public function Md2still(data:*, init:Object = null) { ini = Init.parse(init); scaling = ini.getNumber("scaling", 1) * 100; mesh = (container = new Mesh(ini)) as Mesh; parseMd2still(Cast.bytearray(data)); } /** * Creates a 3d mesh object from the raw xml data of an md2 file. * * @param data The binary data of a loaded file. * @param init [optional] An initialisation object for specifying default instance properties. * * @return A 3d mesh object representation of the md2 file. */ public static function parse(data:*, init:Object = null):Mesh { return Object3DLoader.parseGeometry(data, Md2still, init).handle as Mesh; } /** * Loads and parses an md2 file into a 3d mesh object. * * @param url The url location of the file to load. * @param init [optional] An initialisation object for specifying default instance properties. * @return A 3d loader object that can be used as a placeholder in a scene while the file is loading. */ public static function load(url:String, init:Object = null):Object3DLoader { return Object3DLoader.loadGeometry(url, Md2still, true, init); } } }