/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

  1. package away3d.extrusions
  2. {
  3. import away3d.bounds.BoundingVolumeBase;
  4. import away3d.core.base.Geometry;
  5. import away3d.core.base.SubGeometry;
  6. import away3d.core.base.SubMesh;
  7. import away3d.core.base.data.UV;
  8. import away3d.core.base.data.Vertex;
  9. import away3d.entities.Mesh;
  10. import away3d.materials.MaterialBase;
  11. import away3d.tools.helpers.MeshHelper;
  12. import flash.geom.Vector3D;
  13. public class SkinExtrude extends Mesh
  14. {
  15. private const LIMIT:uint = 196605;
  16. private var _tmpVectors:Vector.<Number>;
  17. private var _subGeometry:SubGeometry;
  18. private var _indice:uint;
  19. private var _uva:UV;
  20. private var _uvb:UV;
  21. private var _uvc:UV;
  22. private var _uvd:UV;
  23. private var _va:Vertex;
  24. private var _vb:Vertex;
  25. private var _vc:Vertex;
  26. private var _vd:Vertex;
  27. private var _uvs:Vector.<Number>;
  28. private var _vertices:Vector.<Number>;
  29. private var _indices:Vector.<uint>;
  30. private var _geomDirty:Boolean = true;
  31. private var _profiles:Vector.<Vector.<Vector3D>>;
  32. private var _subdivision:uint;
  33. private var _centerMesh:Boolean;
  34. private var _closeShape:Boolean;
  35. private var _coverAll:Boolean;
  36. private var _flip:Boolean;
  37. /*
  38. * Class SkinExtrude generates (and becomes) a mesh from a multidimentional vector of vector3D's . <code>SkinExtrude</code>
  39. *@param material MaterialBase. The SkinExtrude (Mesh) material
  40. *@param profiles Vector.&;t;Vector.&lt;Vector3D&gt;&gt; Multidimentional vector of vectors holding the vector3d's defining the shape. &lt; &lt;va0, va1&gt;, &lt;vb0, vb1&gt; &gt;
  41. *@param subdivision [optional] uint. The _subdivision between vectors. Default is 1.
  42. *@param centerMesh [optional] Boolean. If the final mesh must be _centerMeshed. Default is false.
  43. *@param closeShape [optional] Boolean. If the last vector must be linked to the first vector. Default is false.
  44. *@param coverAll [optional] Boolean. If the mapping is stretched over the entire mesh or from vector to vector. Default is false.
  45. *@param flip [optional] Boolean. If the faces need to be inverted. Default is false.
  46. */
  47. public function SkinExtrude(material:MaterialBase, profiles:Vector.<Vector.<Vector3D>>, subdivision:uint = 1, centerMesh:Boolean = false, closeShape:Boolean = false, coverAll:Boolean = false, flip:Boolean = false)
  48. {
  49. var geom:Geometry = new Geometry();
  50. _subGeometry = new SubGeometry();
  51. geom.addSubGeometry(_subGeometry);
  52. super(geom, material);
  53. _profiles = profiles;
  54. _subdivision = subdivision;
  55. _centerMesh = centerMesh;
  56. _closeShape = closeShape;
  57. _coverAll = coverAll;
  58. _flip = flip;
  59. }
  60. /**
  61. * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
  62. */
  63. public function get profiles():Vector.<Vector.<Vector3D>>
  64. {
  65. return _profiles;
  66. }
  67. public function set profiles(val:Vector.<Vector.<Vector3D>>):void
  68. {
  69. _profiles = val;
  70. invalidateGeometry();
  71. }
  72. /**
  73. * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
  74. */
  75. public function get coverAll():Boolean
  76. {
  77. return _coverAll;
  78. }
  79. public function set coverAll(val:Boolean):void
  80. {
  81. if (_coverAll == val)
  82. return;
  83. _coverAll = val;
  84. invalidateGeometry();
  85. }
  86. /**
  87. * Defines if the last vector of Vector3D are joined to the first one, closing the shape. works from 3 vector.&lt;Vector3D&gt; entered.
  88. */
  89. public function get closeShape():Boolean
  90. {
  91. return _closeShape;
  92. }
  93. public function set closeShape(val:Boolean):void
  94. {
  95. if (_closeShape == val)
  96. return;
  97. _closeShape = val;
  98. invalidateGeometry();
  99. }
  100. /**
  101. * Defines if the face orientatio needs to be inverted
  102. */
  103. public function get flip():Boolean
  104. {
  105. return _flip;
  106. }
  107. public function set flip(val:Boolean):void
  108. {
  109. if (_flip == val)
  110. return;
  111. _flip = val;
  112. invalidateGeometry();
  113. }
  114. /**
  115. * Defines whether the mesh is _centerMeshed of not after generation
  116. */
  117. public function get centerMesh():Boolean
  118. {
  119. return _centerMesh;
  120. }
  121. public function set centerMesh(val:Boolean):void
  122. {
  123. if (_centerMesh == val)
  124. return;
  125. _centerMesh = val;
  126. if (_centerMesh && _subGeometry.vertexData.length > 0)
  127. MeshHelper.applyPosition(this, (this.minX + this.maxX)*.5, (this.minY + this.maxY)*.5, (this.minZ + this.maxZ)*.5);
  128. else
  129. invalidateGeometry();
  130. }
  131. public function get subdivision():Number
  132. {
  133. return _subdivision;
  134. }
  135. public function set subdivision(val:Number):void
  136. {
  137. if (_subdivision == val)
  138. return;
  139. _subdivision = val;
  140. invalidateGeometry();
  141. }
  142. // building
  143. private function buildExtrude():void
  144. {
  145. _geomDirty = false;
  146. if (_profiles.length > 1 && _profiles[0].length > 1 && _profiles[1].length > 1) {
  147. initHolders();
  148. if (_closeShape && _profiles.length < 3)
  149. _closeShape = false;
  150. generate();
  151. } else
  152. throw new Error("SkinExtrude: 1 multidimentional Vector.<Vector.<Vector3D>> with minimum 2 children Vector.<Vector3D>. Each child Vector must hold at least 2 Vector3D.");
  153. if (_centerMesh)
  154. MeshHelper.recenter(this);
  155. _tmpVectors = null;
  156. }
  157. private function generate():void
  158. {
  159. var uvlength:int = (_closeShape)? _profiles.length : _profiles.length - 1;
  160. for (var i:int = 0; i < _profiles.length - 1; ++i) {
  161. _tmpVectors = new Vector.<Number>();
  162. extrude(_profiles[i], _profiles[i + 1], (1/uvlength)*i, uvlength);
  163. }
  164. if (_closeShape) {
  165. _tmpVectors = new Vector.<Number>();
  166. extrude(_profiles[_profiles.length - 1], _profiles[0], (1/uvlength)*i, uvlength);
  167. }
  168. _subGeometry.updateVertexData(_vertices);
  169. _subGeometry.updateIndexData(_indices);
  170. _subGeometry.updateUVData(_uvs);
  171. _uva = _uvb = _uvc = _uvd = null;
  172. _va = _vb = _vc = _vd = null;
  173. _uvs = _vertices = null;
  174. _indices = null;
  175. }
  176. private function extrude(vectsA:Vector.<Vector3D>, vectsB:Vector.<Vector3D>, vscale:Number, indexv:int):void
  177. {
  178. var i:int;
  179. var j:int;
  180. var k:int;
  181. var stepx:Number;
  182. var stepy:Number;
  183. var stepz:Number;
  184. var u1:Number;
  185. var u2:Number;
  186. var index:int = 0;
  187. var vertIndice:uint;
  188. var bu:Number = 0;
  189. var bincu:Number = 1/(vectsA.length - 1);
  190. var v1:Number = 0;
  191. var v2:Number = 0;
  192. for (i = 0; i < vectsA.length; ++i) {
  193. stepx = (vectsB[i].x - vectsA[i].x)/_subdivision;
  194. stepy = (vectsB[i].y - vectsA[i].y)/_subdivision;
  195. stepz = (vectsB[i].z - vectsA[i].z)/_subdivision;
  196. for (j = 0; j < _subdivision + 1; ++j)
  197. _tmpVectors.push(vectsA[i].x + (stepx*j), vectsA[i].y + (stepy*j), vectsA[i].z + (stepz*j));
  198. }
  199. for (i = 0; i < vectsA.length - 1; ++i) {
  200. u1 = bu;
  201. bu += bincu;
  202. u2 = bu;
  203. for (j = 0; j < _subdivision; ++j) {
  204. v1 = (_coverAll)? vscale + ((j/_subdivision)/indexv) : j/_subdivision;
  205. v2 = (_coverAll)? vscale + (( (j + 1)/_subdivision)/indexv) : (j + 1)/_subdivision;
  206. _uva.v = u1;
  207. _uva.u = v1;
  208. _uvb.v = u1;
  209. _uvb.u = v2;
  210. _uvc.v = u2;
  211. _uvc.u = v2;
  212. _uvd.v = u2;
  213. _uvd.u = v1;
  214. _va.x = _tmpVectors[vertIndice = (index + j)*3];
  215. _va.y = _tmpVectors[vertIndice + 1];
  216. _va.z = _tmpVectors[vertIndice + 2];
  217. _vb.x = _tmpVectors[vertIndice = (index + j + 1)*3];
  218. _vb.y = _tmpVectors[vertIndice + 1];
  219. _vb.z = _tmpVectors[vertIndice + 2];
  220. _vc.x = _tmpVectors[vertIndice = (index + j + _subdivision + 2 )*3];
  221. _vc.y = _tmpVectors[vertIndice + 1];
  222. _vc.z = _tmpVectors[vertIndice + 2];
  223. _vd.x = _tmpVectors[vertIndice = (index + j + _subdivision + 1 )*3];
  224. _vd.y = _tmpVectors[vertIndice + 1];
  225. _vd.z = _tmpVectors[vertIndice + 2];
  226. if (_vertices.length == LIMIT) {
  227. _subGeometry.updateVertexData(_vertices);
  228. _subGeometry.updateIndexData(_indices);
  229. _subGeometry.updateUVData(_uvs);
  230. _subGeometry = new SubGeometry();
  231. this.geometry.addSubGeometry(_subGeometry);
  232. _subGeometry.autoDeriveVertexNormals = true;
  233. _subGeometry.autoDeriveVertexTangents = true;
  234. _uvs = new Vector.<Number>();
  235. _vertices = new Vector.<Number>();
  236. _indices = new Vector.<uint>();
  237. _indice = 0;
  238. }
  239. if (_flip) {
  240. _vertices.push(_va.x, _va.y, _va.z, _vb.x, _vb.y, _vb.z, _vc.x, _vc.y, _vc.z);
  241. _uvs.push(_uva.u, _uva.v, _uvb.u, _uvb.v, _uvc.u, _uvc.v);
  242. _vertices.push(_va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z, _vd.x, _vd.y, _vd.z);
  243. _uvs.push(_uva.u, _uva.v, _uvc.u, _uvc.v, _uvd.u, _uvd.v);
  244. } else {
  245. _vertices.push(_vb.x, _vb.y, _vb.z, _va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z);
  246. _uvs.push(_uvb.u, _uvb.v, _uva.u, _uva.v, _uvc.u, _uvc.v);
  247. _vertices.push(_vc.x, _vc.y, _vc.z, _va.x, _va.y, _va.z, _vd.x, _vd.y, _vd.z);
  248. _uvs.push(_uvc.u, _uvc.v, _uva.u, _uva.v, _uvd.u, _uvd.v);
  249. }
  250. for (k = 0; k < 6; ++k) {
  251. _indices[_indice] = _indice;
  252. _indice++;
  253. }
  254. }
  255. index += _subdivision + 1;
  256. }
  257. }
  258. private function initHolders():void
  259. {
  260. _indice = 0;
  261. _uva = new UV(0, 0);
  262. _uvb = new UV(0, 0);
  263. _uvc = new UV(0, 0);
  264. _uvd = new UV(0, 0);
  265. _va = new Vertex(0, 0, 0);
  266. _vb = new Vertex(0, 0, 0);
  267. _vc = new Vertex(0, 0, 0);
  268. _vd = new Vertex(0, 0, 0);
  269. _uvs = new Vector.<Number>();
  270. _vertices = new Vector.<Number>();
  271. _indices = new Vector.<uint>();
  272. _subGeometry.autoDeriveVertexNormals = true;
  273. _subGeometry.autoDeriveVertexTangents = true;
  274. }
  275. /**
  276. * @inheritDoc
  277. */
  278. override public function get bounds():BoundingVolumeBase
  279. {
  280. if (_geomDirty)
  281. buildExtrude();
  282. return super.bounds;
  283. }
  284. /**
  285. * @inheritDoc
  286. */
  287. override public function get geometry():Geometry
  288. {
  289. if (_geomDirty)
  290. buildExtrude();
  291. return super.geometry;
  292. }
  293. /**
  294. * @inheritDoc
  295. */
  296. override public function get subMeshes():Vector.<SubMesh>
  297. {
  298. if (_geomDirty)
  299. buildExtrude();
  300. return super.subMeshes;
  301. }
  302. /**
  303. * Invalidates the geometry, causing it to be rebuillded when requested.
  304. */
  305. private function invalidateGeometry():void
  306. {
  307. _geomDirty = true;
  308. invalidateBounds();
  309. }
  310. }
  311. }