diff --git a/src/away3d/core/base/Geometry.as b/src/away3d/core/base/Geometry.as index 456f3bd..da75639 100644 --- a/src/away3d/core/base/Geometry.as +++ b/src/away3d/core/base/Geometry.as @@ -8,7 +8,9 @@ import away3d.library.assets.IAsset; import away3d.library.assets.NamedAssetBase; - use namespace arcane; +import flash.geom.Matrix3D; + +use namespace arcane; /** * Geometry is a collection of SubGeometries, each of which contain the actual geometrical data such as vertices, @@ -34,6 +36,14 @@ _subGeometries = new Vector.(); _animation = new NullAnimation(); } + + public function applyTransformation(transform:Matrix3D):void + { + var len : uint = _subGeometries.length; + for (var i : int = 0; i < len; ++i) { + _subGeometries[i].applyTransformation(transform); + } + } public function get assetType() : String diff --git a/src/away3d/core/base/SubGeometry.as b/src/away3d/core/base/SubGeometry.as index 17c5b9b..c37e132 100644 --- a/src/away3d/core/base/SubGeometry.as +++ b/src/away3d/core/base/SubGeometry.as @@ -8,8 +8,10 @@ package away3d.core.base import flash.display3D.Context3D; import flash.display3D.IndexBuffer3D; import flash.display3D.VertexBuffer3D; +import flash.geom.Matrix3D; +import flash.geom.Vector3D; - use namespace arcane; +use namespace arcane; /** * The SubGeometry class is a collections of geometric data that describes a triangle mesh. It is owned by a @@ -190,6 +192,26 @@ package away3d.core.base return _uvBuffer[contextIndex]; } + public function applyTransformation(transform:Matrix3D):void + { + var len : uint = _vertices.length/3; + var i:uint, index:uint; + var v3:Vector3D = new Vector3D(); + for (i = 0; i < len; ++i) { + + index = 3 * i; + v3.x = _vertices[index]; + v3.y = _vertices[index + 1]; + v3.z = _vertices[index + 2]; + + v3 = transform.transformVector(v3); + + _vertices[index] = v3.x; + _vertices[index + 1] = v3.y; + _vertices[index + 2] = v3.z; + } + } + public function getSecondaryUVBuffer(stage3DProxy : Stage3DProxy) : VertexBuffer3D { var contextIndex : int = stage3DProxy._stage3DIndex; diff --git a/src/away3d/primitives/Capsule.as b/src/away3d/primitives/Capsule.as new file mode 100644 index 0000000..27f54ab --- /dev/null +++ b/src/away3d/primitives/Capsule.as @@ -0,0 +1,243 @@ +package away3d.primitives +{ + +import away3d.core.base.SubGeometry; +import away3d.materials.MaterialBase; + +/** + * A UV Capsule primitive mesh. + */ +public class Capsule extends PrimitiveBase +{ + private var _radius:Number; + private var _height:Number; + private var _segmentsW:uint; + private var _segmentsH:uint; + private var _yUp:Boolean; + + /** + * Creates a new Capsule object. + * @param material The material with which to render the capsule. + * @param radius The radius of the capsule. + * @param height The height of the capsule. + * @param segmentsW Defines the number of horizontal segments that make up the capsule. Defaults to 16. + * @param segmentsH Defines the number of vertical segments that make up the capsule. Defaults to 12. + * @param yUp Defines whether the capsule poles should lay on the Y-axis (true) or on the Z-axis (false). + */ + public function Capsule(material:MaterialBase, radius:Number = 50, height:Number = 100, segmentsW:uint = 16, segmentsH:uint = 12, yUp:Boolean = true) + { + super(material); + + _radius = radius; + _height = height; + _segmentsW = segmentsW; + _segmentsH = segmentsH; + _yUp = yUp; + } + + /** + * @inheritDoc + */ + protected override function buildGeometry(target:SubGeometry):void + { + var vertices:Vector.; + var vertexNormals:Vector.; + var vertexTangents:Vector.; + var indices:Vector.; + var i:uint, j:uint, triIndex:uint; + var numVerts:uint = (_segmentsH + 1)*(_segmentsW + 1); + + if(numVerts == target.numVertices) + { + vertices = target.vertexData; + vertexNormals = target.vertexNormalData; + vertexTangents = target.vertexTangentData; + indices = target.indexData; + } + else + { + vertices = new Vector.(numVerts*3, true); + vertexNormals = new Vector.(numVerts*3, true); + vertexTangents = new Vector.(numVerts*3, true); + indices = new Vector.((_segmentsH - 1)*_segmentsW*6, true); + } + + numVerts = 0; + for(j = 0; j <= _segmentsH; ++j) + { + var horangle:Number = Math.PI*j/_segmentsH; + var z:Number = -_radius*Math.cos(horangle); + var ringradius:Number = _radius*Math.sin(horangle); + + for(i = 0; i <= _segmentsW; ++i) + { + var verangle:Number = 2*Math.PI*i/_segmentsW; + var x:Number = ringradius*Math.cos(verangle); + var offset:Number = j > _segmentsH/2 ? _height/2 : -_height/2; + var y:Number = ringradius*Math.sin(verangle); + var normLen:Number = 1/Math.sqrt(x*x + y*y + z*z); + var tanLen:Number = Math.sqrt(y*y + x*x); + + if(_yUp) + { + vertexNormals[numVerts] = x*normLen; + vertexTangents[numVerts] = tanLen > .007 ? -y/tanLen : 1; + vertices[numVerts++] = x; + vertexNormals[numVerts] = -z*normLen; + vertexTangents[numVerts] = 0; + vertices[numVerts++] = -z - offset; + vertexNormals[numVerts] = y*normLen; + vertexTangents[numVerts] = tanLen > .007 ? x/tanLen : 0; + vertices[numVerts++] = y; + } + else + { + vertexNormals[numVerts] = x*normLen; + vertexTangents[numVerts] = tanLen > .007 ? -y/tanLen : 1; + vertices[numVerts++] = x; + vertexNormals[numVerts] = y*normLen; + vertexTangents[numVerts] = tanLen > .007 ? x/tanLen : 0; + vertices[numVerts++] = y; + vertexNormals[numVerts] = z*normLen; + vertexTangents[numVerts] = 0; + vertices[numVerts++] = z + offset; + } + + if(i > 0 && j > 0) + { + var a:int = (_segmentsW + 1)*j + i; + var b:int = (_segmentsW + 1)*j + i - 1; + var c:int = (_segmentsW + 1)*(j - 1) + i - 1; + var d:int = (_segmentsW + 1)*(j - 1) + i; + + if(j == _segmentsH) + { + indices[triIndex++] = a; + indices[triIndex++] = c; + indices[triIndex++] = d; + } + else if(j == 1) + { + indices[triIndex++] = a; + indices[triIndex++] = b; + indices[triIndex++] = c; + } + else + { + indices[triIndex++] = a; + indices[triIndex++] = b; + indices[triIndex++] = c; + indices[triIndex++] = a; + indices[triIndex++] = c; + indices[triIndex++] = d; + } + } + } + } + + target.updateVertexData(vertices); + target.updateVertexNormalData(vertexNormals); + target.updateVertexTangentData(vertexTangents); + target.updateIndexData(indices); + } + + /** + * @inheritDoc + */ + protected override function buildUVs(target:SubGeometry):void + { + var i:int, j:int; + var numUvs:uint = (_segmentsH + 1)*(_segmentsW + 1)*2; + var uvData:Vector.; + + if(target.UVData && numUvs == target.UVData.length) + uvData = target.UVData; + else + uvData = new Vector.(numUvs, true); + + numUvs = 0; + for(j = 0; j <= _segmentsH; ++j) + { + for(i = 0; i <= _segmentsW; ++i) + { + uvData[numUvs++] = i/_segmentsW; + uvData[numUvs++] = j/_segmentsH; + } + } + + target.updateUVData(uvData); + } + + /** + * The radius of the capsule. + */ + public function get radius():Number + { + return _radius; + } + + public function set radius(value:Number):void + { + _radius = value; + invalidateGeometry(); + } + + /** + * The height of the capsule. + */ + public function get height():Number + { + return _height; + } + + public function set height(value:Number):void + { + _height = value; + invalidateGeometry(); + } + + /** + * Defines the number of horizontal segments that make up the capsule. Defaults to 16. + */ + public function get segmentsW():uint + { + return _segmentsW; + } + + public function set segmentsW(value:uint):void + { + _segmentsW = value; + invalidateGeometry(); + invalidateUVs(); + } + + /** + * Defines the number of vertical segments that make up the capsule. Defaults to 12. + */ + public function get segmentsH():uint + { + return _segmentsH; + } + + public function set segmentsH(value:uint):void + { + _segmentsH = value; + invalidateGeometry(); + invalidateUVs(); + } + + /** + * Defines whether the capsule poles should lay on the Y-axis (true) or on the Z-axis (false). + */ + public function get yUp():Boolean + { + return _yUp; + } + + public function set yUp(value:Boolean):void + { + _yUp = value; + invalidateGeometry(); + } +} +}