
Код AS3:
package alternativa.engine3d.loaders
{
import flash.geom.Vector3D;
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.materials.TextureMaterial;
import alternativa.engine3d.objects.Mesh;
import alternativa.engine3d.core.Face;
import alternativa.engine3d.core.Vertex;
import alternativa.engine3d.materials.Material;
import alternativa.engine3d.core.Wrapper;
import alternativa.engine3d.materials.FillMaterial;
import flash.utils.ByteArray;
import flash.geom.Matrix;
import flash.utils.Endian;
use namespace alternativa3d;
public class Parser3DS
{
private static const CHUNK_MAPPINGCOORDS:int = 16704;
private static const CHUNK_VERTICES:int = 16656;
private static const CHUNK_TRIMESH:int = 16640;
private static const CHUNK_TRANSFORMATION:int = 16736;
private static const CHUNK_MAIN:int = 19789;
private static const CHUNK_VERSION:int = 2;
private static const CHUNK_OBJECT:int = 16384;
private static const CHUNK_ANIMATION:int = 45056;
private static const CHUNK_FACESMATERIAL:int = 16688;
private static const CHUNK_MATERIAL:int = 45055;
private static const CHUNK_SCENE:int = 15677;
private static const CHUNK_FACES:int = 16672;
public var parents:Vector.<Object3D>;
public var textureMaterials:Vector.<TextureMaterial>;
public var objects:Vector.<Object3D>;
private var objectDatas:Object;
private var materialDatas:Object;
private var animationDatas:Array;
private var data:ByteArray;
public var materials:Vector.<Material>;
public function Parser3DS()
{
super();
}
private function parseMainChunk(dataPosition:int, bytesAvailable:int) : void
{
if(bytesAvailable < 6)
{
return;
}
var chunkInfo:ChunkInfo = this.readChunkInfo(dataPosition);
switch(chunkInfo.id)
{
case CHUNK_VERSION:
break;
case CHUNK_SCENE:
this.parse3DChunk(chunkInfo.dataPosition,chunkInfo.dataSize);
break;
case CHUNK_ANIMATION:
this.parseAnimationChunk(chunkInfo.dataPosition,chunkInfo.dataSize);
}
this.parseMainChunk(chunkInfo.nextChunkPosition,bytesAvailable - chunkInfo.size);
}
private function parseObjectAnimationChunk(animation:AnimationData, dataPosition:int, bytesAvailable:int) : void
{
if(bytesAvailable < 6)
{
return;
}
var chunkInfo:ChunkInfo = this.readChunkInfo(dataPosition);
switch(chunkInfo.id)
{
case 45072:
animation.objectName = this.getString(this.data.position);
this.data.position = this.data.position + 4;
animation.parentIndex = this.data.readUnsignedShort();
break;
case 45073:
animation.objectName = this.getString(this.data.position);
break;
case 45075:
animation.pivot = new Vector3D(this.data.readFloat(),this.data.readFloat(),this.data.readFloat());
break;
case 45088:
this.data.position = this.data.position + 20;
animation.position = new Vector3D(this.data.readFloat(),this.data.readFloat(),this.data.readFloat());
break;
case 45089:
this.data.position = this.data.position + 20;
animation.rotation = this.getRotationFrom3DSAngleAxis(this.data.readFloat(),this.data.readFloat(),this.data.readFloat(),this.data.readFloat());
break;
case 45090:
this.data.position = this.data.position + 20;
animation.scale = new Vector3D(this.data.readFloat(),this.data.readFloat(),this.data.readFloat());
}
this.parseObjectAnimationChunk(animation,chunkInfo.nextChunkPosition,bytesAvailable - chunkInfo.size);
}
private function parseFaces(_arg1:ObjectData, _arg2:ChunkInfo):void{
var _local3:int = this.data.readUnsignedShort();
_arg1.faces = new Vector.<int>();
var _local4:int;
var _local5:int;
while (_local4 < _local3) {
var _temp1 = _local5;
_local5 = (_local5 + 1);
var _local7 = _temp1;
_arg1.faces[_local7] = this.data.readUnsignedShort();
var _temp2 = _local5;
_local5 = (_local5 + 1);
var _local8 = _temp2;
_arg1.faces[_local8] = this.data.readUnsignedShort();
var _temp3 = _local5;
_local5 = (_local5 + 1);
var _local9 = _temp3;
_arg1.faces[_local9] = this.data.readUnsignedShort();
this.data.position = (this.data.position + 2);
_local4++;
};
var _local6:int = (2 + (8 * _local3));
this.parseFacesChunk(_arg1, (_arg2.dataPosition + _local6), (_arg2.dataSize - _local6));
}
private function readChunkInfo(dataPosition:int) : ChunkInfo
{
this.data.position = dataPosition;
var chunkInfo:ChunkInfo = new ChunkInfo();
chunkInfo.id = this.data.readUnsignedShort();
chunkInfo.size = this.data.readUnsignedInt();
chunkInfo.dataSize = chunkInfo.size - 6;
chunkInfo.dataPosition = this.data.position;
chunkInfo.nextChunkPosition = dataPosition + chunkInfo.size;
return chunkInfo;
}
private function getString(index:int) : String
{
var charCode:int = 0;
this.data.position = index;
for(var res:String = ""; (charCode = int(this.data.readByte())) != 0; )
{
res = res + String.fromCharCode(charCode);
}
return res;
}
private function parseMapChunk(materialName:String, map:MapData, dataPosition:int, bytesAvailable:int) : void
{
if(bytesAvailable < 6)
{
return;
}
var chunkInfo:ChunkInfo = this.readChunkInfo(dataPosition);
switch(chunkInfo.id)
{
case 41728:
map.filename = this.getString(chunkInfo.dataPosition).toLowerCase();
break;
case 41809:
break;
case 41812:
map.scaleU = this.data.readFloat();
break;
case 41814:
map.scaleV = this.data.readFloat();
break;
case 41816:
map.offsetU = this.data.readFloat();
break;
case 41818:
map.offsetV = this.data.readFloat();
break;
case 41820:
map.rotation = this.data.readFloat();
}
this.parseMapChunk(materialName,map,chunkInfo.nextChunkPosition,bytesAvailable - chunkInfo.size);
}
private function parseVertices(_arg1:ObjectData):void{
var _local2:int = this.data.readUnsignedShort();
_arg1.vertices = new Vector.<Number>();
var _local3:int;
var _local4:int;
while (_local3 < _local2) {
var _temp1 = _local4;
_local4 = (_local4 + 1);
var _local5 = _temp1;
_arg1.vertices[_local5] = this.data.readFloat();
var _temp2 = _local4;
_local4 = (_local4 + 1);
var _local6 = _temp2;
_arg1.vertices[_local6] = this.data.readFloat();
var _temp3 = _local4;
_local4 = (_local4 + 1);
var _local7 = _temp3;
_arg1.vertices[_local7] = this.data.readFloat();
_local3++;
};
}
private function parseMeshChunk(object:ObjectData, dataPosition:int, bytesAvailable:int) : void
{
if(bytesAvailable < 6)
{
return;
}
var chunkInfo:ChunkInfo = this.readChunkInfo(dataPosition);
switch(chunkInfo.id)
{
case CHUNK_VERTICES:
this.parseVertices(object);
break;
case CHUNK_MAPPINGCOORDS:
this.parseUVs(object);
break;
case CHUNK_TRANSFORMATION:
this.parseMatrix(object);
break;
case CHUNK_FACES:
this.parseFaces(object,chunkInfo);
}
this.parseMeshChunk(object,chunkInfo.nextChunkPosition,bytesAvailable - chunkInfo.size);
}
private function parseMaterialChunk(material:MaterialData, dataPosition:int, bytesAvailable:int) : void
{
if(bytesAvailable < 6)
{
return;
}
var chunkInfo:ChunkInfo = this.readChunkInfo(dataPosition);
switch(chunkInfo.id)
{
case 40960:
this.parseMaterialName(material);
break;
case 40976:
break;
case 40992:
this.data.position = chunkInfo.dataPosition + 6;
material.color = (this.data.readUnsignedByte() << 16) + (this.data.readUnsignedByte() << 8) + this.data.readUnsignedByte();
break;
case 41008:
break;
case 41024:
this.data.position = chunkInfo.dataPosition + 6;
material.glossiness = this.data.readUnsignedShort();
break;
case 41025:
this.data.position = chunkInfo.dataPosition + 6;
material.specular = this.data.readUnsignedShort();
break;
case 41040:
this.data.position = chunkInfo.dataPosition + 6;
material.transparency = this.data.readUnsignedShort();
break;
case 41472:
material.diffuseMap = new MapData();
this.parseMapChunk(material.name,material.diffuseMap,chunkInfo.dataPosition,chunkInfo.dataSize);
break;
case 41786:
break;
case 41488:
material.opacityMap = new MapData();
this.parseMapChunk(material.name,material.opacityMap,chunkInfo.dataPosition,chunkInfo.dataSize);
break;
case 41520:
break;
case 41788:
break;
case 41476:
break;
case 41789:
break;
case 41504:
}
this.parseMaterialChunk(material,chunkInfo.nextChunkPosition,bytesAvailable - chunkInfo.size);
}
public function getObjectByName(name:String) : Object3D
{
var object:* = null;
for each(object in this.objects)
{
if(object.name == name)
{
return object;
}
}
return null;
}
private function parseAnimationChunk(_arg1:int, _arg2:int):void{
var _local3:ChunkInfo;
var _local4:AnimationData;
while (_arg2 >= 6) {
_local3 = this.readChunkInfo(_arg1);
switch (_local3.id){
case 45057:
case 45058:
case 45059:
case 45060:
case 45061:
case 45062:
case 45063:
if (this.animationDatas == null){
this.animationDatas = new Array();
};
_local4 = new AnimationData();
this.animationDatas.push(_local4);
this.parseObjectAnimationChunk(_local4, _local3.dataPosition, _local3.dataSize);
break;
case 45064:
break;
};
_arg1 = _local3.nextChunkPosition;
_arg2 = (_arg2 - _local3.size);
};
}