[Sandy] [sandy commit] r661 - in trunk/sandy/as3/trunk/src/sandy: parser primitive
codesite-noreply at google.com
codesite-noreply at google.com
Tue Jun 3 02:40:48 PDT 2008
Author: makc.the.great
Date: Tue Jun 3 02:39:42 2008
New Revision: 661
Added:
trunk/sandy/as3/trunk/src/sandy/parser/MD2Parser.as
trunk/sandy/as3/trunk/src/sandy/primitive/MD2.as
Modified:
trunk/sandy/as3/trunk/src/sandy/parser/Parser.as
Log:
1st vworking version of MD2 parser and primitive
Added: trunk/sandy/as3/trunk/src/sandy/parser/MD2Parser.as
==============================================================================
--- (empty file)
+++ trunk/sandy/as3/trunk/src/sandy/parser/MD2Parser.as Tue Jun 3 02:39:42 2008
@@ -0,0 +1,86 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+Copyright the original author or authors.
+Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/MPL-1.1.html
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+# ***** END LICENSE BLOCK *****
+*/
+
+package sandy.parser
+{
+ import flash.events.Event;
+ import flash.net.URLLoaderDataFormat;
+ import flash.utils.ByteArray;
+
+ import sandy.materials.Appearance;
+ import sandy.primitive.MD2;
+
+ /**
+ * Transforms an MD2 file into Sandy MD2 primitive.
+ * <p>Creates a Group as rootnode with MD2 primitive as its only child.
+ *
+ * @author makc
+ * @version 3.0.3
+ * @date 03.06.2008
+ *
+ * @example To parse an MD2 file at runtime:
+ *
+ * <listing version="3.0">
+ * var parser:IParser = Parser.create( "/path/to/my/md2file.md2", Parser.MD2 );
+ * </listing>
+ *
+ * @example To parse an embedded MD2 object:
+ *
+ * <listing version="3.0">
+ * [Embed( source="/path/to/my/md2file.md2", mimeType="application/octet-stream" )]
+ * private var MyMD2:Class;
+ *
+ * ...
+ *
+ * var parser:IParser = Parser.create( new MyMD2(), Parser.MD2 );
+ * </listing>
+ */
+
+ public final class MD2Parser extends AParser implements IParser
+ {
+ /**
+ * Creates a new MD2Parser instance
+ *
+ * @param p_sUrl This can be either a String containing an URL or a
+ * an embedded object
+ * @param p_nScale The scale factor
+ */
+ public function MD2Parser( p_sUrl:*, p_nScale:Number )
+ {
+ super( p_sUrl, p_nScale );
+ m_sDataFormat = URLLoaderDataFormat.BINARY;
+ }
+
+ /**
+ * @private
+ * Starts the parsing process
+ *
+ * @param e The Event object
+ */
+ protected override function parseData( e:Event=null ):void
+ {
+ super.parseData( e );
+ // make MD2 object
+ var md2:MD2 = new MD2 ( "animation", ByteArray( m_oFile ), m_nScale );
+ // we are not quite done yet, so we dispatch less than 100% :)
+ var event:ParserEvent = new ParserEvent( ParserEvent.PARSING ); event.percent = 80; dispatchEvent( event );
+ // --
+ md2.appearance = m_oStandardAppearance; m_oGroup.addChild( md2 );
+ // -- Parsing is finished
+ var l_eOnInit:ParserEvent = new ParserEvent( ParserEvent.INIT ); l_eOnInit.group = m_oGroup; dispatchEvent( l_eOnInit );
+ }
+ }
+}
Modified: trunk/sandy/as3/trunk/src/sandy/parser/Parser.as
==============================================================================
--- trunk/sandy/as3/trunk/src/sandy/parser/Parser.as (original)
+++ trunk/sandy/as3/trunk/src/sandy/parser/Parser.as Tue Jun 3 02:39:42 2008
@@ -74,6 +74,10 @@
*/
public static const ASE:String = "ASE";
/**
+ * Specifies that the MD2 (Quake II model) parser should be used.
+ */
+ public static const MD2:String = "MD2";
+ /**
* Specifies that the 3DS (3D Studio) parser should be used.
*/
public static const MAX_3DS:String = "3DS";
@@ -116,6 +120,9 @@
{
case "ASE":
l_iParser = new ASEParser( p_sFile, p_nScale );
+ break;
+ case "MD2":
+ l_iParser = new MD2Parser( p_sFile, p_nScale );
break;
case "OBJ":
break;
Added: trunk/sandy/as3/trunk/src/sandy/primitive/MD2.as
==============================================================================
--- (empty file)
+++ trunk/sandy/as3/trunk/src/sandy/primitive/MD2.as Tue Jun 3 02:39:42 2008
@@ -0,0 +1,217 @@
+package sandy.primitive
+{
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+
+ import sandy.core.data.*;
+ import sandy.core.scenegraph.Geometry3D;
+ import sandy.core.scenegraph.Shape3D;
+ import sandy.primitive.Primitive3D;
+
+ /**
+ * MD2 primitive.
+ *
+ * @author Philippe Ajoux (philippe.ajoux at gmail.com)
+ */
+ public class MD2 extends Shape3D implements Primitive3D
+ {
+ /**
+ * Creates MD2 primitive.
+ *
+ * @param p_sName Shape instance name.
+ * @param data MD2 binary data.
+ * @param scale Adjusts model scale.
+ */
+ public function MD2 ( p_sName:String, data:ByteArray, scale:Number = 1 )
+ {
+ super (p_sName); scaling = scale; geometry = generate (data); frame = 0;
+ }
+
+ /**
+ * Generates the geometry for MD2. Sandy never actually calls this method,
+ * but we still implement it according to Primitive3D, just in case :)
+ *
+ * @return The geometry object.
+ */
+ public function generate (... arguments):Geometry3D
+ {
+ var i:int, j:int;
+ var uvs:Array = [];
+ var mesh:Geometry3D = new Geometry3D ();
+
+ // okay, let's read out header 1st
+ var data:ByteArray = ByteArray (arguments [0]);
+ data.endian = Endian.LITTLE_ENDIAN;
+
+ ident = data.readInt();
+ version = data.readInt();
+
+ 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();
+
+ // UV coordinates
+ data.position = offset_st;
+ for (i = 0; i < num_st; i++)
+ uvs.push (new UVCoord (data.readShort() / skinwidth, data.readShort() / skinheight ));
+
+ // Faces
+ data.position = offset_tris;
+ for (i = 0, j = 0; i < num_tris; i++, j+=3)
+ {
+ 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();
+
+ // create placeholder vertices (actual coordinates are set later)
+ mesh.setVertex (a, 1, 0, 0);
+ mesh.setVertex (b, 0, 1, 0);
+ mesh.setVertex (c, 0, 0, 1);
+
+ mesh.setUVCoords (j, uvs [ta].u, uvs [ta].v);
+ mesh.setUVCoords (j + 1, uvs [tb].u, uvs [tb].v);
+ mesh.setUVCoords (j + 2, uvs [tc].u, uvs [tc].v);
+
+ mesh.setFaceVertexIds (i, a, b, c);
+ mesh.setFaceUVCoordsIds (i, j, j + 1, j + 2);
+ }
+
+ // Frame animation data
+ for (i = 0; i < num_frames; i++)
+ {
+ 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();
+
+ // store frame names as pointers to frame numbers
+ var name:String = "", wasNotZero:Boolean = true;
+ for (j = 0; j < 16; j++)
+ {
+ var char:int = data.readUnsignedByte ();
+ wasNotZero &&= (char != 0);
+ if (wasNotZero)
+ name += String.fromCharCode (char);
+ }
+ frames [name] = i;
+
+ // store vertices for every frame
+ var vi:Array = [];
+ vertices [i] = vi;
+ for (j = 0; j < num_vertices; j++)
+ {
+ var vec:Vector = new Vector ();
+
+ // order of assignment is important here because of data reads...
+ vec.x = ((sx * data.readUnsignedByte()) + tx) * scaling;
+ vec.z = ((sy * data.readUnsignedByte()) + ty) * scaling;
+ vec.y = ((sz * data.readUnsignedByte()) + tz) * scaling;
+
+ vi [j] = vec;
+
+ // ignore "vertex normal index"
+ data.readUnsignedByte ();
+ }
+ }
+
+ return mesh;
+ }
+
+ /**
+ * Frames map. This maps frame names to frame numbers.
+ */
+ public var frames:Array = [];
+
+ /**
+ * Frame number. You can tween this value to play MD2 animation.
+ */
+ public function get frame ():Number { return t; }
+
+ /**
+ * @private (setter)
+ */
+ public function set frame (value:Number):void
+ {
+ t = value;
+
+ // interpolation frames
+ var f1:Array = vertices [int (t) % num_frames];
+ var f2:Array = vertices [(int (t) + 1) % num_frames];
+
+ // interpolation coef-s
+ var c2:Number = t - int (t), c1:Number = 1 - c2;
+
+ // loop through vertices
+ for (var i:int = 0; i < num_vertices; i++)
+ {
+ var v0:Vertex = Vertex (geometry.aVertex [i]);
+ var v1:Vector = Vector (f1 [i]);
+ var v2:Vector = Vector (f2 [i]);
+
+ // interpolate
+ v0.x = v1.x * c1 + v2.x * c2; v0.wx = v0.x;
+ v0.y = v1.y * c1 + v2.y * c2; v0.wy = v0.y;
+ v0.z = v1.z * c1 + v2.z * c2; v0.wz = v0.z;
+ }
+
+ // update face normals
+ for each (var l_oPoly:Polygon in aPolygons)
+ {
+ v.x = l_oPoly.b.x - l_oPoly.a.x; v.y = l_oPoly.b.y - l_oPoly.a.y; v.z = l_oPoly.b.z - l_oPoly.a.z;
+ w.x = l_oPoly.b.x - l_oPoly.c.x; w.y = l_oPoly.b.y - l_oPoly.c.y; w.z = l_oPoly.b.z - l_oPoly.c.z;
+ w.crossWith (v); w.normalize ();
+ l_oPoly.normal.x = w.x; l_oPoly.normal.y = w.y; l_oPoly.normal.z = w.z;
+ }
+ }
+
+ // animation "time" (frame number)
+ private var t:Number;
+
+ // vertices list for every frame
+ private var vertices:Array = [];
+
+ // vars for quick normal computation
+ private var v:Vector = new Vector (), w:Vector = new Vector ();
+
+ // original Philippe vars
+ 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 scaling:Number;
+ }
+}
\ No newline at end of file
More information about the Sandy
mailing list