PageRenderTime 265ms CodeModel.GetById 110ms app.highlight 18ms RepoModel.GetById 133ms app.codeStats 0ms

/src/away3d/primitives/Capsule.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 243 lines | 184 code | 26 blank | 33 comment | 17 complexity | b1a4b782c1cda4a3126f16a6df7bacfc MD5 | raw file
  1package away3d.primitives
  2{
  3
  4	import away3d.core.base.SubGeometry;
  5	import away3d.materials.MaterialBase;
  6
  7	/**
  8	 * A UV Capsule primitive mesh.
  9	 */
 10	public class Capsule extends PrimitiveBase
 11	{
 12		private var _radius:Number;
 13		private var _height:Number;
 14		private var _segmentsW:uint;
 15		private var _segmentsH:uint;
 16		private var _yUp:Boolean;
 17
 18		/**
 19		 * Creates a new Capsule object.
 20		 * @param material The material with which to render the capsule.
 21		 * @param radius The radius of the capsule.
 22		 * @param height The height of the capsule.
 23		 * @param segmentsW Defines the number of horizontal segments that make up the capsule. Defaults to 16.
 24		 * @param segmentsH Defines the number of vertical segments that make up the capsule. Defaults to 12.
 25		 * @param yUp Defines whether the capsule poles should lay on the Y-axis (true) or on the Z-axis (false).
 26		 */
 27		public function Capsule(material:MaterialBase, radius:Number = 50, height:Number = 100, segmentsW:uint = 16, segmentsH:uint = 12, yUp:Boolean = true)
 28		{
 29			super(material);
 30
 31			_radius = radius;
 32			_height = height;
 33			_segmentsW = segmentsW;
 34			_segmentsH = segmentsH;
 35			_yUp = yUp;
 36		}
 37
 38		/**
 39		 * @inheritDoc
 40		 */
 41		protected override function buildGeometry(target:SubGeometry):void
 42		{
 43			var vertices:Vector.<Number>;
 44			var vertexNormals:Vector.<Number>;
 45			var vertexTangents:Vector.<Number>;
 46			var indices:Vector.<uint>;
 47			var i:uint, j:uint, triIndex:uint;
 48			var numVerts:uint = (_segmentsH + 1)*(_segmentsW + 1);
 49
 50			if(numVerts == target.numVertices)
 51			{
 52				vertices = target.vertexData;
 53				vertexNormals = target.vertexNormalData;
 54				vertexTangents = target.vertexTangentData;
 55				indices = target.indexData;
 56			}
 57			else
 58			{
 59				vertices = new Vector.<Number>(numVerts*3, true);
 60				vertexNormals = new Vector.<Number>(numVerts*3, true);
 61				vertexTangents = new Vector.<Number>(numVerts*3, true);
 62				indices = new Vector.<uint>((_segmentsH - 1)*_segmentsW*6, true);
 63			}
 64
 65			numVerts = 0;
 66			for(j = 0; j <= _segmentsH; ++j)
 67			{
 68				var horangle:Number = Math.PI*j/_segmentsH;
 69				var z:Number = -_radius*Math.cos(horangle);
 70				var ringradius:Number = _radius*Math.sin(horangle);
 71
 72				for(i = 0; i <= _segmentsW; ++i)
 73				{
 74					var verangle:Number = 2*Math.PI*i/_segmentsW;
 75					var x:Number = ringradius*Math.cos(verangle);
 76					var offset:Number = j > _segmentsH/2 ? _height/2 : -_height/2;
 77					var y:Number = ringradius*Math.sin(verangle);
 78					var normLen:Number = 1/Math.sqrt(x*x + y*y + z*z);
 79					var tanLen:Number = Math.sqrt(y*y + x*x);
 80
 81					if(_yUp)
 82					{
 83						vertexNormals[numVerts] = x*normLen;
 84						vertexTangents[numVerts] = tanLen > .007 ? -y/tanLen : 1;
 85						vertices[numVerts++] = x;
 86						vertexNormals[numVerts] = -z*normLen;
 87						vertexTangents[numVerts] = 0;
 88						vertices[numVerts++] = -z - offset;
 89						vertexNormals[numVerts] = y*normLen;
 90						vertexTangents[numVerts] = tanLen > .007 ? x/tanLen : 0;
 91						vertices[numVerts++] = y;
 92					}
 93					else
 94					{
 95						vertexNormals[numVerts] = x*normLen;
 96						vertexTangents[numVerts] = tanLen > .007 ? -y/tanLen : 1;
 97						vertices[numVerts++] = x;
 98						vertexNormals[numVerts] = y*normLen;
 99						vertexTangents[numVerts] = tanLen > .007 ? x/tanLen : 0;
100						vertices[numVerts++] = y;
101						vertexNormals[numVerts] = z*normLen;
102						vertexTangents[numVerts] = 0;
103						vertices[numVerts++] = z + offset;
104					}
105
106					if(i > 0 && j > 0)
107					{
108						var a:int = (_segmentsW + 1)*j + i;
109						var b:int = (_segmentsW + 1)*j + i - 1;
110						var c:int = (_segmentsW + 1)*(j - 1) + i - 1;
111						var d:int = (_segmentsW + 1)*(j - 1) + i;
112
113						if(j == _segmentsH)
114						{
115							indices[triIndex++] = a;
116							indices[triIndex++] = c;
117							indices[triIndex++] = d;
118						}
119						else if(j == 1)
120						{
121							indices[triIndex++] = a;
122							indices[triIndex++] = b;
123							indices[triIndex++] = c;
124						}
125						else
126						{
127							indices[triIndex++] = a;
128							indices[triIndex++] = b;
129							indices[triIndex++] = c;
130							indices[triIndex++] = a;
131							indices[triIndex++] = c;
132							indices[triIndex++] = d;
133						}
134					}
135				}
136			}
137
138			target.updateVertexData(vertices);
139			target.updateVertexNormalData(vertexNormals);
140			target.updateVertexTangentData(vertexTangents);
141			target.updateIndexData(indices);
142		}
143
144		/**
145		 * @inheritDoc
146		 */
147		protected override function buildUVs(target:SubGeometry):void
148		{
149			var i:int, j:int;
150			var numUvs:uint = (_segmentsH + 1)*(_segmentsW + 1)*2;
151			var uvData:Vector.<Number>;
152
153			if(target.UVData && numUvs == target.UVData.length)
154				uvData = target.UVData;
155			else
156				uvData = new Vector.<Number>(numUvs, true);
157
158			numUvs = 0;
159			for(j = 0; j <= _segmentsH; ++j)
160			{
161				for(i = 0; i <= _segmentsW; ++i)
162				{
163					uvData[numUvs++] = i/_segmentsW;
164					uvData[numUvs++] = j/_segmentsH;
165				}
166			}
167
168			target.updateUVData(uvData);
169		}
170
171		/**
172		 * The radius of the capsule.
173		 */
174		public function get radius():Number
175		{
176			return _radius;
177		}
178
179		public function set radius(value:Number):void
180		{
181			_radius = value;
182			invalidateGeometry();
183		}
184
185		/**
186		 * The height of the capsule.
187		 */
188		public function get height():Number
189		{
190			return _height;
191		}
192
193		public function set height(value:Number):void
194		{
195			_height = value;
196			invalidateGeometry();
197		}
198
199		/**
200		 * Defines the number of horizontal segments that make up the capsule. Defaults to 16.
201		 */
202		public function get segmentsW():uint
203		{
204			return _segmentsW;
205		}
206
207		public function set segmentsW(value:uint):void
208		{
209			_segmentsW = value;
210			invalidateGeometry();
211			invalidateUVs();
212		}
213
214		/**
215		 * Defines the number of vertical segments that make up the capsule. Defaults to 12.
216		 */
217		public function get segmentsH():uint
218		{
219			return _segmentsH;
220		}
221
222		public function set segmentsH(value:uint):void
223		{
224			_segmentsH = value;
225			invalidateGeometry();
226			invalidateUVs();
227		}
228
229		/**
230		 * Defines whether the capsule poles should lay on the Y-axis (true) or on the Z-axis (false).
231		 */
232		public function get yUp():Boolean
233		{
234			return _yUp;
235		}
236
237		public function set yUp(value:Boolean):void
238		{
239			_yUp = value;
240			invalidateGeometry();
241		}
242	}
243}