PageRenderTime 426ms CodeModel.GetById 242ms app.highlight 17ms RepoModel.GetById 164ms app.codeStats 0ms

/src/away3d/primitives/Sphere.as

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