/src/away3d/extrusions/SkinExtrude.as
http://github.com/away3d/away3d-core-fp11 · ActionScript · 376 lines · 273 code · 65 blank · 38 comment · 32 complexity · a86fbfdc480b1771fafbc4092ee1810f MD5 · raw file
- package away3d.extrusions
- {
- import away3d.bounds.BoundingVolumeBase;
- import away3d.core.base.Geometry;
- import away3d.core.base.SubGeometry;
- import away3d.core.base.SubMesh;
- import away3d.core.base.data.UV;
- import away3d.core.base.data.Vertex;
- import away3d.entities.Mesh;
- import away3d.materials.MaterialBase;
- import away3d.tools.helpers.MeshHelper;
-
- import flash.geom.Vector3D;
-
- public class SkinExtrude extends Mesh
- {
- private const LIMIT:uint = 196605;
- private var _tmpVectors:Vector.<Number>;
- private var _subGeometry:SubGeometry;
- private var _indice:uint;
- private var _uva:UV;
- private var _uvb:UV;
- private var _uvc:UV;
- private var _uvd:UV;
- private var _va:Vertex;
- private var _vb:Vertex;
- private var _vc:Vertex;
- private var _vd:Vertex;
- private var _uvs:Vector.<Number>;
- private var _vertices:Vector.<Number>;
- private var _indices:Vector.<uint>;
- private var _geomDirty:Boolean = true;
-
- private var _profiles:Vector.<Vector.<Vector3D>>;
- private var _subdivision:uint;
- private var _centerMesh:Boolean;
- private var _closeShape:Boolean;
- private var _coverAll:Boolean;
- private var _flip:Boolean;
-
- /*
- * Class SkinExtrude generates (and becomes) a mesh from a multidimentional vector of vector3D's . <code>SkinExtrude</code>
- *@param material MaterialBase. The SkinExtrude (Mesh) material
- *@param profiles Vector.&;t;Vector.<Vector3D>> Multidimentional vector of vectors holding the vector3d's defining the shape. < <va0, va1>, <vb0, vb1> >
- *@param subdivision [optional] uint. The _subdivision between vectors. Default is 1.
- *@param centerMesh [optional] Boolean. If the final mesh must be _centerMeshed. Default is false.
- *@param closeShape [optional] Boolean. If the last vector must be linked to the first vector. Default is false.
- *@param coverAll [optional] Boolean. If the mapping is stretched over the entire mesh or from vector to vector. Default is false.
- *@param flip [optional] Boolean. If the faces need to be inverted. Default is false.
- */
- public function SkinExtrude(material:MaterialBase, profiles:Vector.<Vector.<Vector3D>>, subdivision:uint = 1, centerMesh:Boolean = false, closeShape:Boolean = false, coverAll:Boolean = false, flip:Boolean = false)
- {
- var geom:Geometry = new Geometry();
- _subGeometry = new SubGeometry();
- geom.addSubGeometry(_subGeometry);
- super(geom, material);
-
- _profiles = profiles;
- _subdivision = subdivision;
- _centerMesh = centerMesh;
- _closeShape = closeShape;
- _coverAll = coverAll;
- _flip = flip;
- }
-
- /**
- * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
- */
- public function get profiles():Vector.<Vector.<Vector3D>>
- {
- return _profiles;
- }
-
- public function set profiles(val:Vector.<Vector.<Vector3D>>):void
- {
- _profiles = val;
- invalidateGeometry();
- }
-
- /**
- * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
- */
- public function get coverAll():Boolean
- {
- return _coverAll;
- }
-
- public function set coverAll(val:Boolean):void
- {
- if (_coverAll == val)
- return;
-
- _coverAll = val;
- invalidateGeometry();
- }
-
- /**
- * Defines if the last vector of Vector3D are joined to the first one, closing the shape. works from 3 vector.<Vector3D> entered.
- */
- public function get closeShape():Boolean
- {
- return _closeShape;
- }
-
- public function set closeShape(val:Boolean):void
- {
- if (_closeShape == val)
- return;
-
- _closeShape = val;
- invalidateGeometry();
- }
-
- /**
- * Defines if the face orientatio needs to be inverted
- */
- public function get flip():Boolean
- {
- return _flip;
- }
-
- public function set flip(val:Boolean):void
- {
- if (_flip == val)
- return;
-
- _flip = val;
- invalidateGeometry();
- }
-
- /**
- * Defines whether the mesh is _centerMeshed of not after generation
- */
- public function get centerMesh():Boolean
- {
- return _centerMesh;
- }
-
- public function set centerMesh(val:Boolean):void
- {
- if (_centerMesh == val)
- return;
-
- _centerMesh = val;
-
- if (_centerMesh && _subGeometry.vertexData.length > 0)
- MeshHelper.applyPosition(this, (this.minX + this.maxX)*.5, (this.minY + this.maxY)*.5, (this.minZ + this.maxZ)*.5);
- else
- invalidateGeometry();
- }
-
- public function get subdivision():Number
- {
- return _subdivision;
- }
-
- public function set subdivision(val:Number):void
- {
- if (_subdivision == val)
- return;
-
- _subdivision = val;
- invalidateGeometry();
- }
-
- // building
- private function buildExtrude():void
- {
- _geomDirty = false;
- if (_profiles.length > 1 && _profiles[0].length > 1 && _profiles[1].length > 1) {
- initHolders();
- if (_closeShape && _profiles.length < 3)
- _closeShape = false;
- generate();
- } else
- throw new Error("SkinExtrude: 1 multidimentional Vector.<Vector.<Vector3D>> with minimum 2 children Vector.<Vector3D>. Each child Vector must hold at least 2 Vector3D.");
-
- if (_centerMesh)
- MeshHelper.recenter(this);
-
- _tmpVectors = null;
- }
-
- private function generate():void
- {
- var uvlength:int = (_closeShape)? _profiles.length : _profiles.length - 1;
- for (var i:int = 0; i < _profiles.length - 1; ++i) {
- _tmpVectors = new Vector.<Number>();
- extrude(_profiles[i], _profiles[i + 1], (1/uvlength)*i, uvlength);
- }
-
- if (_closeShape) {
- _tmpVectors = new Vector.<Number>();
- extrude(_profiles[_profiles.length - 1], _profiles[0], (1/uvlength)*i, uvlength);
- }
-
- _subGeometry.updateVertexData(_vertices);
- _subGeometry.updateIndexData(_indices);
- _subGeometry.updateUVData(_uvs);
- _uva = _uvb = _uvc = _uvd = null;
- _va = _vb = _vc = _vd = null;
- _uvs = _vertices = null;
- _indices = null;
- }
-
- private function extrude(vectsA:Vector.<Vector3D>, vectsB:Vector.<Vector3D>, vscale:Number, indexv:int):void
- {
- var i:int;
- var j:int;
- var k:int;
- var stepx:Number;
- var stepy:Number;
- var stepz:Number;
-
- var u1:Number;
- var u2:Number;
- var index:int = 0;
- var vertIndice:uint;
-
- var bu:Number = 0;
- var bincu:Number = 1/(vectsA.length - 1);
- var v1:Number = 0;
- var v2:Number = 0;
-
- for (i = 0; i < vectsA.length; ++i) {
- stepx = (vectsB[i].x - vectsA[i].x)/_subdivision;
- stepy = (vectsB[i].y - vectsA[i].y)/_subdivision;
- stepz = (vectsB[i].z - vectsA[i].z)/_subdivision;
-
- for (j = 0; j < _subdivision + 1; ++j)
- _tmpVectors.push(vectsA[i].x + (stepx*j), vectsA[i].y + (stepy*j), vectsA[i].z + (stepz*j));
-
- }
-
- for (i = 0; i < vectsA.length - 1; ++i) {
-
- u1 = bu;
- bu += bincu;
- u2 = bu;
-
- for (j = 0; j < _subdivision; ++j) {
-
- v1 = (_coverAll)? vscale + ((j/_subdivision)/indexv) : j/_subdivision;
- v2 = (_coverAll)? vscale + (( (j + 1)/_subdivision)/indexv) : (j + 1)/_subdivision;
-
- _uva.v = u1;
- _uva.u = v1;
- _uvb.v = u1;
- _uvb.u = v2;
- _uvc.v = u2;
- _uvc.u = v2;
- _uvd.v = u2;
- _uvd.u = v1;
-
- _va.x = _tmpVectors[vertIndice = (index + j)*3];
- _va.y = _tmpVectors[vertIndice + 1];
- _va.z = _tmpVectors[vertIndice + 2];
-
- _vb.x = _tmpVectors[vertIndice = (index + j + 1)*3];
- _vb.y = _tmpVectors[vertIndice + 1];
- _vb.z = _tmpVectors[vertIndice + 2];
-
- _vc.x = _tmpVectors[vertIndice = (index + j + _subdivision + 2 )*3];
- _vc.y = _tmpVectors[vertIndice + 1];
- _vc.z = _tmpVectors[vertIndice + 2];
-
- _vd.x = _tmpVectors[vertIndice = (index + j + _subdivision + 1 )*3];
- _vd.y = _tmpVectors[vertIndice + 1];
- _vd.z = _tmpVectors[vertIndice + 2];
-
- if (_vertices.length == LIMIT) {
- _subGeometry.updateVertexData(_vertices);
- _subGeometry.updateIndexData(_indices);
- _subGeometry.updateUVData(_uvs);
-
- _subGeometry = new SubGeometry();
- this.geometry.addSubGeometry(_subGeometry);
- _subGeometry.autoDeriveVertexNormals = true;
- _subGeometry.autoDeriveVertexTangents = true;
- _uvs = new Vector.<Number>();
- _vertices = new Vector.<Number>();
- _indices = new Vector.<uint>();
- _indice = 0;
- }
-
- if (_flip) {
-
- _vertices.push(_va.x, _va.y, _va.z, _vb.x, _vb.y, _vb.z, _vc.x, _vc.y, _vc.z);
- _uvs.push(_uva.u, _uva.v, _uvb.u, _uvb.v, _uvc.u, _uvc.v);
-
- _vertices.push(_va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z, _vd.x, _vd.y, _vd.z);
- _uvs.push(_uva.u, _uva.v, _uvc.u, _uvc.v, _uvd.u, _uvd.v);
-
- } else {
-
- _vertices.push(_vb.x, _vb.y, _vb.z, _va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z);
- _uvs.push(_uvb.u, _uvb.v, _uva.u, _uva.v, _uvc.u, _uvc.v);
-
- _vertices.push(_vc.x, _vc.y, _vc.z, _va.x, _va.y, _va.z, _vd.x, _vd.y, _vd.z);
- _uvs.push(_uvc.u, _uvc.v, _uva.u, _uva.v, _uvd.u, _uvd.v);
- }
-
- for (k = 0; k < 6; ++k) {
- _indices[_indice] = _indice;
- _indice++;
- }
-
- }
-
- index += _subdivision + 1;
- }
- }
-
- private function initHolders():void
- {
- _indice = 0;
- _uva = new UV(0, 0);
- _uvb = new UV(0, 0);
- _uvc = new UV(0, 0);
- _uvd = new UV(0, 0);
- _va = new Vertex(0, 0, 0);
- _vb = new Vertex(0, 0, 0);
- _vc = new Vertex(0, 0, 0);
- _vd = new Vertex(0, 0, 0);
- _uvs = new Vector.<Number>();
- _vertices = new Vector.<Number>();
- _indices = new Vector.<uint>();
-
- _subGeometry.autoDeriveVertexNormals = true;
- _subGeometry.autoDeriveVertexTangents = true;
- }
-
- /**
- * @inheritDoc
- */
- override public function get bounds():BoundingVolumeBase
- {
- if (_geomDirty)
- buildExtrude();
-
- return super.bounds;
- }
-
- /**
- * @inheritDoc
- */
- override public function get geometry():Geometry
- {
- if (_geomDirty)
- buildExtrude();
-
- return super.geometry;
- }
-
- /**
- * @inheritDoc
- */
- override public function get subMeshes():Vector.<SubMesh>
- {
- if (_geomDirty)
- buildExtrude();
-
- return super.subMeshes;
- }
-
- /**
- * Invalidates the geometry, causing it to be rebuillded when requested.
- */
- private function invalidateGeometry():void
- {
- _geomDirty = true;
- invalidateBounds();
- }
-
- }
- }