/src/away3d/extrusions/LinearExtrude.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 1081 lines · 819 code · 190 blank · 72 comment · 176 complexity · fcd7ce76979ba7ef26553597aaed61b1 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.materials.utils.MultipleMaterials;
  12. import away3d.tools.helpers.MeshHelper;
  13. import flash.geom.Point;
  14. import flash.geom.Vector3D;
  15. public class LinearExtrude extends Mesh
  16. {
  17. public static const X_AXIS:String = "x";
  18. public static const Y_AXIS:String = "y";
  19. public static const Z_AXIS:String = "z";
  20. private const LIMIT:uint = 196605;
  21. private const EPS:Number = .0001;
  22. private var _varr:Vector.<Vertex>;
  23. private var _varr2:Vector.<Vertex>;
  24. private var _uvarr:Vector.<UV>;
  25. private var _subdivision:uint;
  26. private var _coverAll:Boolean;
  27. private var _flip:Boolean;
  28. private var _closePath:Boolean;
  29. private var _axis:String;
  30. private var _offset:Number;
  31. private var _materials:MultipleMaterials;
  32. private var _activeMaterial:MaterialBase;
  33. private var _centerMesh:Boolean;
  34. private var _thickness:Number;
  35. private var _thicknessSubdivision:uint;
  36. private var _ignoreSides:String;
  37. private var _geomDirty:Boolean = true;
  38. private var _subGeometry:SubGeometry;
  39. private var _MaterialsSubGeometries:Vector.<SubGeometryList>;
  40. private var _uva:UV;
  41. private var _uvb:UV;
  42. private var _uvc:UV;
  43. private var _uvd:UV;
  44. // TODO: not used
  45. // private var _va:Vertex;
  46. // private var _vb:Vertex;
  47. // private var _vc:Vertex;
  48. // private var _vd:Vertex;
  49. private var _maxIndProfile:uint;
  50. private var _uvs:Vector.<Number>;
  51. private var _vertices:Vector.<Number>;
  52. private var _indices:Vector.<uint>;
  53. private var _aVectors:Vector.<Vector3D>;
  54. private var _baseMax:Number;
  55. private var _baseMin:Number;
  56. /**
  57. * Class LinearExtrusion generates walls like meshes with or without thickness from a series of Vector3D's
  58. *
  59. *@param material [optional] MaterialBase. The LatheExtrude (Mesh) material. Optional in constructor, material must be set before LatheExtrude object is render.
  60. * @param vectors [optional] Vector.&lt;Vector3D&gt;. A series of Vector3D's representing the profile information to be repeated/rotated around a given axis.
  61. * @param axis [optional] String. The axis to elevate along: X_AXIS, Y_AXIS or Z_AXIS. Default is LinearExtrusion.Y_AXIS.
  62. * @param offset [optional] Number. The elevation offset along the defined axis.
  63. * @param subdivision [optional] uint. The subdivision of the geometry between 2 vector3D. Default is 32.
  64. * @param coverAll [optional] Boolean. The way the uv mapping is spreaded across the shape. True covers an entire side of the geometry while false covers per segments. Default is false.
  65. * @param thickness [optional] Number. If the shape must simulate a thickness. Default is 0.
  66. * @param thicknessSubdivision [optional] uint. If thickness is higher than 0. Defines the subdivision of the thickness (top, left, right, bottom). Default is 3;
  67. * @param materials [optional] MultipleMaterials. Allows multiple material support when thickness is set higher to 1. Default is null.
  68. * properties as MaterialBase are: bottom, top, left, right, front and back.
  69. * @param centerMesh [optional] Boolean. If the geometry needs to be recentered in its own object space. If the position after generation is set to 0,0,0, the object would be centered in worldspace. Default is false.
  70. * @param closePath [optional] Boolean. Defines if the last entered vector needs to be linked with the first one to form a closed shape. Default is false.
  71. * @param ignoreSides [optional] String. To prevent the generation of sides if thickness is set higher than 0. To avoid the bottom ignoreSides = "bottom", avoiding both top and bottom: ignoreSides = "bottom, top". Strings options: bottom, top, left, right, front and back. Default is "".
  72. * @param flip [optional] Boolean. If the faces must be reversed depending on Vector3D's orientation. Default is false.
  73. */
  74. public function LinearExtrude(material:MaterialBase = null, vectors:Vector.<Vector3D> = null, axis:String = LinearExtrude.Y_AXIS, offset:Number = 10, subdivision:uint = 3, coverAll:Boolean = false, thickness:Number = 0, thicknessSubdivision:uint = 3, materials:MultipleMaterials = null, centerMesh:Boolean = false, closePath:Boolean = false, ignoreSides:String = "", flip:Boolean = false)
  75. {
  76. var geom:Geometry = new Geometry();
  77. _subGeometry = new SubGeometry();
  78. if (!material && materials && materials.front)
  79. material = materials.front;
  80. super(geom, material);
  81. _aVectors = vectors;
  82. _axis = axis;
  83. _offset = offset;
  84. _coverAll = coverAll;
  85. _flip = flip;
  86. _centerMesh = centerMesh;
  87. _thickness = Math.abs(thickness);
  88. this.subdivision = subdivision;
  89. this.thicknessSubdivision = thicknessSubdivision;
  90. _ignoreSides = ignoreSides;
  91. _closePath = closePath;
  92. if (materials)
  93. this.materials = materials;
  94. if (_closePath && ignoreSides != "")
  95. this.ignoreSides = ignoreSides;
  96. }
  97. private function buildExtrude():void
  98. {
  99. if (!_aVectors.length || _aVectors.length < 2)
  100. throw new Error("LinearExtrusion error: at least 2 vector3D required!");
  101. if (_closePath)
  102. _aVectors.push(new Vector3D(_aVectors[0].x, _aVectors[0].y, _aVectors[0].z));
  103. _maxIndProfile = _aVectors.length*9;
  104. _MaterialsSubGeometries = null;
  105. _geomDirty = false;
  106. initHolders();
  107. generate();
  108. if (_vertices.length > 0) {
  109. _subGeometry.updateVertexData(_vertices);
  110. _subGeometry.updateIndexData(_indices);
  111. _subGeometry.updateUVData(_uvs);
  112. this.geometry.addSubGeometry(_subGeometry);
  113. }
  114. if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
  115. var sglist:SubGeometryList;
  116. var sg:SubGeometry;
  117. for (var i:uint = 1; i < _MaterialsSubGeometries.length; ++i) {
  118. sglist = _MaterialsSubGeometries[i];
  119. sg = sglist.subGeometry;
  120. if (sg && sglist.vertices.length > 0) {
  121. this.geometry.addSubGeometry(sg);
  122. this.subMeshes[this.subMeshes.length - 1].material = sglist.material;
  123. sg.updateVertexData(sglist.vertices);
  124. sg.updateIndexData(sglist.indices);
  125. sg.updateUVData(sglist.uvs);
  126. }
  127. }
  128. }
  129. if (_centerMesh)
  130. MeshHelper.recenter(this);
  131. _varr = _varr2 = null;
  132. _uvarr = null;
  133. }
  134. /**
  135. * Defines the axis used for the extrusion. Defaults to "y".
  136. */
  137. public function get axis():String
  138. {
  139. return _axis;
  140. }
  141. public function set axis(val:String):void
  142. {
  143. if (_axis == val)
  144. return;
  145. _axis = val;
  146. invalidateGeometry();
  147. }
  148. /**
  149. * An optional MultipleMaterials object that defines left, right, front, back, top and bottom materials to be set on the resulting lathe extrusion.
  150. */
  151. public function get materials():MultipleMaterials
  152. {
  153. return _materials;
  154. }
  155. public function set materials(val:MultipleMaterials):void
  156. {
  157. _materials = val;
  158. if (_materials.front && this.material != _materials.front)
  159. this.material = _materials.front;
  160. invalidateGeometry();
  161. }
  162. /**
  163. * Defines the subdivisions created in the mesh for the total number of revolutions. Defaults to 2, minimum 2.
  164. */
  165. public function get subdivision():uint
  166. {
  167. return _subdivision;
  168. }
  169. public function set subdivision(val:uint):void
  170. {
  171. val = (val < 3)? 3 : val;
  172. if (_subdivision == val)
  173. return;
  174. _subdivision = val;
  175. invalidateGeometry();
  176. }
  177. /**
  178. * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to true.
  179. */
  180. public function get coverAll():Boolean
  181. {
  182. return _coverAll;
  183. }
  184. public function set coverAll(val:Boolean):void
  185. {
  186. if (_coverAll == val)
  187. return;
  188. _coverAll = val;
  189. invalidateGeometry();
  190. }
  191. /**
  192. * Defines if the generated faces should be inversed. Default false.
  193. */
  194. public function get flip():Boolean
  195. {
  196. return _flip;
  197. }
  198. public function set flip(val:Boolean):void
  199. {
  200. if (_flip == val)
  201. return;
  202. _flip = val;
  203. invalidateGeometry();
  204. }
  205. /**
  206. * Defines whether the mesh is recentered of not after generation
  207. */
  208. public function get centerMesh():Boolean
  209. {
  210. return _centerMesh;
  211. }
  212. public function set centerMesh(val:Boolean):void
  213. {
  214. if (_centerMesh == val)
  215. return;
  216. _centerMesh = val;
  217. if (_centerMesh && _subGeometry.vertexData.length > 0)
  218. MeshHelper.recenter(this);
  219. else
  220. invalidateGeometry();
  221. }
  222. /**
  223. * Defines the _thickness of the resulting lathed geometry. Defaults to 0 (single face).
  224. */
  225. public function get thickness():Number
  226. {
  227. return _thickness;
  228. }
  229. public function set thickness(val:Number):void
  230. {
  231. val = Math.abs(val);
  232. if (_thickness == val)
  233. return;
  234. _thickness = val;
  235. invalidateGeometry();
  236. }
  237. /**
  238. * Defines the subdivision for the top, bottom, right and left if thickness is set higher to 0. Defaults to 1.
  239. */
  240. public function get thicknessSubdivision():uint
  241. {
  242. return _thicknessSubdivision;
  243. }
  244. public function set thicknessSubdivision(val:uint):void
  245. {
  246. val = (val < 3)? 3 : val;
  247. if (_thicknessSubdivision == val)
  248. return;
  249. _thicknessSubdivision = val;
  250. invalidateGeometry();
  251. }
  252. /**
  253. * Defines if the top, bottom, left, right, front or back of the the extrusion is left open.
  254. */
  255. public function get ignoreSides():String
  256. {
  257. return _ignoreSides;
  258. }
  259. public function set ignoreSides(val:String):void
  260. {
  261. _ignoreSides = val;
  262. if (_closePath) {
  263. if (_ignoreSides.indexOf("left") == -1)
  264. _ignoreSides += "left,";
  265. if (_ignoreSides.indexOf("right") == -1)
  266. _ignoreSides += "right";
  267. }
  268. invalidateGeometry();
  269. }
  270. /**
  271. * @inheritDoc
  272. */
  273. override public function get bounds():BoundingVolumeBase
  274. {
  275. if (_geomDirty)
  276. buildExtrude();
  277. return super.bounds;
  278. }
  279. /**
  280. * @inheritDoc
  281. */
  282. override public function get geometry():Geometry
  283. {
  284. if (_geomDirty)
  285. buildExtrude();
  286. return super.geometry;
  287. }
  288. /**
  289. * @inheritDoc
  290. */
  291. override public function get subMeshes():Vector.<SubMesh>
  292. {
  293. if (_geomDirty)
  294. buildExtrude();
  295. return super.subMeshes;
  296. }
  297. private function addFace(v0:Vertex, v1:Vertex, v2:Vertex, uv0:UV, uv1:UV, uv2:UV, mat:MaterialBase, invertU:Boolean = false):void
  298. {
  299. var subGeom:SubGeometry;
  300. var uvs:Vector.<Number>;
  301. var vertices:Vector.<Number>;
  302. // TODO: not used
  303. // var normals:Vector.<Number>;
  304. var indices:Vector.<uint>;
  305. var sglist:SubGeometryList;
  306. if (_activeMaterial != mat && _materials) {
  307. sglist = getSubGeometryListFromMaterial(mat);
  308. _subGeometry = subGeom = sglist.subGeometry;
  309. _uvs = uvs = sglist.uvs;
  310. _vertices = vertices = sglist.vertices;
  311. _indices = indices = sglist.indices;
  312. } else {
  313. subGeom = _subGeometry;
  314. uvs = _uvs;
  315. vertices = _vertices;
  316. indices = _indices;
  317. }
  318. if (vertices.length + 9 > LIMIT) {
  319. subGeom.updateVertexData(vertices);
  320. subGeom.updateIndexData(indices);
  321. subGeom.updateUVData(uvs);
  322. this.geometry.addSubGeometry(subGeom);
  323. this.subMeshes[this.subMeshes.length - 1].material = mat;
  324. subGeom = new SubGeometry();
  325. subGeom.autoDeriveVertexTangents = true;
  326. subGeom.autoDeriveVertexNormals = true;
  327. if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 1) {
  328. sglist = getSubGeometryListFromMaterial(mat);
  329. sglist.subGeometry = _subGeometry = subGeom;
  330. sglist.uvs = _uvs = uvs = new Vector.<Number>();
  331. sglist.vertices = _vertices = vertices = new Vector.<Number>();
  332. sglist.indices = _indices = indices = new Vector.<uint>();
  333. } else {
  334. _subGeometry = subGeom;
  335. uvs = _uvs = new Vector.<Number>();
  336. vertices = _vertices = new Vector.<Number>();
  337. indices = _indices = new Vector.<uint>();
  338. }
  339. }
  340. var ind:uint = vertices.length/3;
  341. if (invertU)
  342. uvs.push(1 - uv0.u, uv0.v, 1 - uv1.u, uv1.v, 1 - uv2.u, uv2.v);
  343. else
  344. uvs.push(uv0.u, uv0.v, uv1.u, uv1.v, uv2.u, uv2.v);
  345. vertices.push(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
  346. indices.push(ind, ind + 1, ind + 2);
  347. }
  348. private function generate():void
  349. {
  350. var i:uint;
  351. var j:uint;
  352. var increase:Number = _offset/_subdivision;
  353. var baseMaxX:Number = _aVectors[0].x;
  354. var baseMinX:Number = _aVectors[0].x;
  355. var baseMaxY:Number = _aVectors[0].y;
  356. var baseMinY:Number = _aVectors[0].y;
  357. var baseMaxZ:Number = _aVectors[0].z;
  358. var baseMinZ:Number = _aVectors[0].z;
  359. for (i = 1; i < _aVectors.length; i++) {
  360. baseMaxX = Math.max(_aVectors[i].x, baseMaxX);
  361. baseMinX = Math.min(_aVectors[i].x, baseMinX);
  362. baseMaxY = Math.max(_aVectors[i].y, baseMaxY);
  363. baseMinY = Math.min(_aVectors[i].y, baseMinY);
  364. baseMaxZ = Math.max(_aVectors[i].z, baseMaxZ);
  365. baseMinZ = Math.min(_aVectors[i].z, baseMinZ);
  366. }
  367. var offset:Number = 0;
  368. switch (_axis) {
  369. case X_AXIS:
  370. _baseMax = Math.abs(baseMaxX) - Math.abs(baseMinX);
  371. if (baseMinZ > 0 && baseMaxZ > 0) {
  372. _baseMin = baseMaxZ - baseMinZ;
  373. offset = -baseMinZ;
  374. } else if (baseMinZ < 0 && baseMaxZ < 0) {
  375. _baseMin = Math.abs(baseMinZ - baseMaxZ);
  376. offset = -baseMinZ;
  377. } else {
  378. _baseMin = Math.abs(baseMaxZ) + Math.abs(baseMinZ);
  379. offset = Math.abs(baseMinZ) + ((baseMaxZ < 0)? -baseMaxZ : 0);
  380. }
  381. break;
  382. case Y_AXIS:
  383. _baseMax = Math.abs(baseMaxY) - Math.abs(baseMinY);
  384. if (baseMinX > 0 && baseMaxX > 0) {
  385. _baseMin = baseMaxX - baseMinX;
  386. offset = -baseMinX;
  387. } else if (baseMinX < 0 && baseMaxX < 0) {
  388. _baseMin = Math.abs(baseMinX - baseMaxX);
  389. offset = -baseMinX;
  390. } else {
  391. _baseMin = Math.abs(baseMaxX) + Math.abs(baseMinX);
  392. offset = Math.abs(baseMinX) + ((baseMaxX < 0)? -baseMaxX : 0);
  393. }
  394. break;
  395. case Z_AXIS:
  396. _baseMax = Math.abs(baseMaxZ) - Math.abs(baseMinZ);
  397. if (baseMinY > 0 && baseMaxY > 0) {
  398. _baseMin = baseMaxY - baseMinY;
  399. offset = -baseMinY;
  400. } else if (baseMinY < 0 && baseMaxY < 0) {
  401. _baseMin = Math.abs(baseMinY - baseMaxY);
  402. offset = -baseMinY;
  403. } else {
  404. _baseMin = Math.abs(baseMaxY) + Math.abs(baseMinY);
  405. offset = Math.abs(baseMinY) + ((baseMaxY < 0)? -baseMaxY : 0);
  406. }
  407. break;
  408. }
  409. var aLines:Array;
  410. var prop1:String;
  411. var prop2:String;
  412. var prop3:String;
  413. var vector:Vertex = new Vertex();
  414. if (_thickness != 0) {
  415. var aListsides:Array = ["top", "bottom", "right", "left", "front", "back"];
  416. var renderSide:RenderSide = new RenderSide();
  417. for (i = 0; i < aListsides.length; ++i)
  418. renderSide[aListsides[i]] = (_ignoreSides.indexOf(aListsides[i]) == -1);
  419. switch (_axis) {
  420. case X_AXIS:
  421. prop1 = Z_AXIS;
  422. prop2 = Y_AXIS;
  423. prop3 = X_AXIS;
  424. break;
  425. case Y_AXIS:
  426. prop1 = X_AXIS;
  427. prop2 = Z_AXIS;
  428. prop3 = Y_AXIS;
  429. break;
  430. case Z_AXIS:
  431. prop1 = Y_AXIS;
  432. prop2 = X_AXIS;
  433. prop3 = Z_AXIS;
  434. }
  435. aLines = buildThicknessPoints(prop1, prop2);
  436. var points:FourPoints;
  437. var vector2:Vertex = new Vertex();
  438. var vector3:Vertex = new Vertex();
  439. var vector4:Vertex = new Vertex();
  440. for (i = 0; i < aLines.length; i++) {
  441. points = FourPoints(aLines[i]);
  442. if (i == 0) {
  443. vector[prop1] = points.pt2.x;
  444. vector[prop2] = points.pt2.y;
  445. vector[prop3] = _aVectors[0][prop3];
  446. _varr.push(new Vertex(vector.x, vector.y, vector.z));
  447. vector2[prop1] = points.pt1.x;
  448. vector2[prop2] = points.pt1.y;
  449. vector2[prop3] = _aVectors[0][prop3];
  450. _varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
  451. elevate(vector, vector2, increase);
  452. if (aLines.length == 1) {
  453. vector3[prop1] = points.pt4.x;
  454. vector3[prop2] = points.pt4.y;
  455. vector3[prop3] = _aVectors[0][prop3];
  456. _varr.push(new Vertex(vector3.x, vector3.y, vector3.z));
  457. vector4[prop1] = points.pt3.x;
  458. vector4[prop2] = points.pt3.y;
  459. vector4[prop3] = _aVectors[0][prop3];
  460. _varr2.push(new Vertex(vector4.x, vector4.y, vector4.z));
  461. elevate(vector3, vector4, increase);
  462. }
  463. } else if (i == aLines.length - 1) {
  464. vector[prop1] = points.pt2.x;
  465. vector[prop2] = points.pt2.y;
  466. vector[prop3] = _aVectors[i][prop3];
  467. _varr.push(new Vertex(vector.x, vector.y, vector.z));
  468. vector2[prop1] = points.pt1.x;
  469. vector2[prop2] = points.pt1.y;
  470. vector2[prop3] = _aVectors[i][prop3];
  471. _varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
  472. elevate(vector, vector2, increase);
  473. vector3[prop1] = points.pt4.x;
  474. vector3[prop2] = points.pt4.y;
  475. vector3[prop3] = _aVectors[i][prop3];
  476. _varr.push(new Vertex(vector3.x, vector3.y, vector3.z));
  477. vector4[prop1] = points.pt3.x;
  478. vector4[prop2] = points.pt3.y;
  479. vector4[prop3] = _aVectors[i][prop3];
  480. _varr2.push(new Vertex(vector4.x, vector4.y, vector4.z));
  481. elevate(vector3, vector4, increase);
  482. } else {
  483. vector[prop1] = points.pt2.x;
  484. vector[prop2] = points.pt2.y;
  485. vector[prop3] = _aVectors[i][prop3];
  486. _varr.push(new Vertex(vector.x, vector.y, vector.z));
  487. vector2[prop1] = points.pt1.x;
  488. vector2[prop2] = points.pt1.y;
  489. vector2[prop3] = _aVectors[i][prop3];
  490. _varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
  491. elevate(vector, vector2, increase);
  492. }
  493. }
  494. } else {
  495. for (i = 0; i < _aVectors.length; i++) {
  496. vector.x = _aVectors[i].x;
  497. vector.y = _aVectors[i].y;
  498. vector.z = _aVectors[i].z;
  499. _varr.push(new Vertex(vector.x, vector.y, vector.z));
  500. for (j = 0; j < _subdivision; j++) {
  501. vector[_axis] += increase;
  502. _varr.push(new Vertex(vector.x, vector.y, vector.z));
  503. }
  504. }
  505. }
  506. var index:uint = 0;
  507. var mat:MaterialBase;
  508. if (_thickness > 0) {
  509. var v1a:Vertex;
  510. var v1b:Vertex;
  511. var v1c:Vertex;
  512. var v2a:Vertex;
  513. var v2b:Vertex;
  514. var v2c:Vertex;
  515. var v3a:Vertex;
  516. var v3b:Vertex;
  517. var v3c:Vertex;
  518. var v4b:Vertex;
  519. var v4c:Vertex;
  520. }
  521. var step:Number = 1/(_aVectors.length - 1);
  522. var vindex:uint;
  523. for (i = 0; i < _aVectors.length - 1; ++i) {
  524. if (_coverAll) {
  525. _uva.u = _uvb.u = step*i;
  526. _uvc.u = _uvd.u = _uvb.u + step;
  527. } else {
  528. _uva.u = 0;
  529. _uvb.u = 0;
  530. _uvc.u = 1;
  531. _uvd.u = 1;
  532. }
  533. for (j = 0; j < _subdivision; ++j) {
  534. _uva.v = _uvd.v = 1 - (j/_subdivision);
  535. _uvb.v = _uvc.v = 1 - (j + 1)/_subdivision;
  536. vindex = index + j;
  537. if (_thickness == 0) {
  538. if (_flip) {
  539. addFace(_varr[ vindex + 1], _varr[vindex], _varr[vindex + _subdivision + 2], _uvb, _uva, _uvc, this.material);
  540. addFace(_varr[ vindex + _subdivision + 2], _varr[vindex], _varr[vindex + _subdivision + 1], _uvc, _uva, _uvd, this.material);
  541. } else {
  542. addFace(_varr[vindex], _varr[vindex + 1], _varr[vindex + _subdivision + 2], _uva, _uvb, _uvc, this.material);
  543. addFace(_varr[vindex], _varr[vindex + _subdivision + 2], _varr[vindex + _subdivision + 1], _uva, _uvc, _uvd, this.material);
  544. }
  545. } else {
  546. //half side 1
  547. v1a = _varr[vindex];
  548. v1b = _varr[vindex + 1];
  549. v1c = _varr[vindex + _subdivision + 2];
  550. v2a = _varr[vindex];
  551. v2b = _varr[vindex + _subdivision + 2];
  552. v2c = _varr[vindex + _subdivision + 1];
  553. //half side 2
  554. v3a = _varr2[vindex];
  555. v3b = _varr2[vindex + 1];
  556. v3c = _varr2[vindex + _subdivision + 2];
  557. v4b = _varr2[vindex + _subdivision + 2];
  558. v4c = _varr2[vindex + _subdivision + 1];
  559. //right
  560. if (renderSide.right) {
  561. mat = (materials && materials.right)? materials.right : this.material;
  562. if (_flip) {
  563. addFace(v1a, v1b, v1c, _uva, _uvb, _uvc, mat);
  564. addFace(v2a, v2b, v2c, _uva, _uvc, _uvd, mat);
  565. } else {
  566. addFace(v1b, v1a, v1c, _uvb, _uva, _uvc, mat);
  567. addFace(v2b, v2a, v2c, _uvc, _uva, _uvd, mat);
  568. }
  569. }
  570. //left
  571. if (renderSide.left) {
  572. mat = (materials && materials.left)? materials.left : this.material;
  573. if (_flip) {
  574. addFace(v4c, v3b, v3a, _uvd, _uvb, _uva, mat, true);
  575. addFace(v4c, v4b, v3b, _uvd, _uvc, _uvb, mat, true);
  576. } else {
  577. addFace(v3b, v4c, v3a, _uvb, _uvd, _uva, mat, true);
  578. addFace(v4b, v4c, v3b, _uvc, _uvd, _uvb, mat, true);
  579. }
  580. }
  581. //back
  582. if (i == 0 && renderSide.back) {
  583. mat = (materials && materials.back)? materials.back : this.material;
  584. if (_flip) {
  585. addFace(v3a, v3b, v1b, _uva, _uvb, _uvc, mat);
  586. addFace(v3a, v1b, v1a, _uva, _uvc, _uvd, mat);
  587. } else {
  588. addFace(v3b, v3a, v1b, _uvb, _uva, _uvc, mat);
  589. addFace(v1b, v3a, v1a, _uvc, _uva, _uvd, mat);
  590. }
  591. }
  592. //bottom
  593. if (j == 0 && renderSide.bottom) {
  594. mat = (materials && materials.bottom)? materials.bottom : this.material;
  595. addThicknessSubdivision([v4c, v3a], [v2c, v1a], _uvd.u, _uvb.u, mat);
  596. }
  597. //top
  598. if (j == _subdivision - 1 && renderSide.top) {
  599. mat = (materials && materials.top)? materials.top : this.material;
  600. addThicknessSubdivision([v3b, v3c], [v1b, v1c], _uva.u, _uvc.u, mat);
  601. }
  602. //front
  603. if (i == _aVectors.length - 2 && renderSide.front) {
  604. mat = (materials && materials.front)? materials.front : this.material;
  605. if (_flip) {
  606. addFace(v2c, v2b, v3c, _uva, _uvb, _uvc, mat);
  607. addFace(v2c, v3c, v4c, _uva, _uvc, _uvd, mat);
  608. } else {
  609. addFace(v2b, v2c, v3c, _uvb, _uva, _uvc, mat);
  610. addFace(v3c, v2c, v4c, _uvc, _uva, _uvd, mat);
  611. }
  612. }
  613. }
  614. }
  615. index += _subdivision + 1;
  616. }
  617. }
  618. private function addThicknessSubdivision(points1:Array, points2:Array, u1:Number, u2:Number, mat:MaterialBase):void
  619. {
  620. var i:uint;
  621. var j:uint;
  622. var stepx:Number;
  623. var stepy:Number;
  624. var stepz:Number;
  625. var va:Vertex;
  626. var vb:Vertex;
  627. var vc:Vertex;
  628. var vd:Vertex;
  629. var index:uint = 0;
  630. var v1:Number = 0;
  631. var v2:Number = 0;
  632. var tmp:Array = [];
  633. for (i = 0; i < points1.length; ++i) {
  634. stepx = (points2[i].x - points1[i].x)/_thicknessSubdivision;
  635. stepy = (points2[i].y - points1[i].y)/_thicknessSubdivision;
  636. stepz = (points2[i].z - points1[i].z)/_thicknessSubdivision;
  637. for (j = 0; j < _thicknessSubdivision + 1; ++j)
  638. tmp.push(new Vertex(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j)));
  639. }
  640. for (i = 0; i < points1.length - 1; ++i) {
  641. for (j = 0; j < _thicknessSubdivision; ++j) {
  642. v1 = j/_thicknessSubdivision;
  643. v2 = (j + 1)/_thicknessSubdivision;
  644. _uva.u = u1;
  645. _uva.v = v1;
  646. _uvb.u = u1;
  647. _uvb.v = v2;
  648. _uvc.u = u2;
  649. _uvc.v = v2;
  650. _uvd.u = u2;
  651. _uvd.v = v1;
  652. va = tmp[index + j];
  653. vb = tmp[(index + j) + 1];
  654. vc = tmp[((index + j) + (_thicknessSubdivision + 2))];
  655. vd = tmp[((index + j) + (_thicknessSubdivision + 1))];
  656. if (!_flip) {
  657. addFace(va, vb, vc, _uva, _uvb, _uvc, mat);
  658. addFace(va, vc, vd, _uva, _uvc, _uvd, mat);
  659. } else {
  660. addFace(vb, va, vc, _uvb, _uva, _uvc, mat);
  661. addFace(vc, va, vd, _uvc, _uva, _uvd, mat);
  662. }
  663. }
  664. index += _subdivision + 1;
  665. }
  666. }
  667. private function elevate(v0:Object, v1:Object, increase:Number):void
  668. {
  669. for (var i:uint = 0; i < _subdivision; ++i) {
  670. v0[_axis] += increase;
  671. v1[_axis] += increase;
  672. _varr.push(new Vertex(v0[X_AXIS], v0[Y_AXIS], v0[Z_AXIS]));
  673. _varr2.push(new Vertex(v1[X_AXIS], v1[Y_AXIS], v1[Z_AXIS]));
  674. }
  675. }
  676. private function buildThicknessPoints(prop1:String, prop2:String):Array
  677. {
  678. var anchors:Array = [];
  679. var lines:Array = [];
  680. for (var i:uint = 0; i < _aVectors.length - 1; ++i) {
  681. if (_aVectors[i][prop1] == 0 && _aVectors[i][prop2] == 0)
  682. _aVectors[i][prop1] = EPS;
  683. if (_aVectors[i + 1][prop2] && _aVectors[i][prop2] == _aVectors[i + 1][prop2])
  684. _aVectors[i + 1][prop2] += EPS;
  685. if (_aVectors[i][prop1] && _aVectors[i][prop1] == _aVectors[i + 1][prop1])
  686. _aVectors[i + 1][prop1] += EPS;
  687. anchors.push(defineAnchors(_aVectors[i], _aVectors[i + 1], prop1, prop2));
  688. }
  689. var totallength:uint = anchors.length;
  690. var pointResult:FourPoints;
  691. if (totallength > 1) {
  692. for (i = 0; i < totallength; ++i) {
  693. if (i < totallength)
  694. pointResult = definelines(i, anchors[i], anchors[i + 1], lines);
  695. else
  696. pointResult = definelines(i, anchors[i], anchors[i - 1], lines);
  697. if (pointResult != null)
  698. lines.push(pointResult);
  699. }
  700. } else {
  701. var fourPoints:FourPoints = new FourPoints();
  702. var anchorFP:FourPoints = anchors[0];
  703. fourPoints.pt1 = anchorFP.pt1;
  704. fourPoints.pt2 = anchorFP.pt2;
  705. fourPoints.pt3 = anchorFP.pt3;
  706. fourPoints.pt4 = anchorFP.pt4;
  707. lines = [fourPoints];
  708. }
  709. return lines;
  710. }
  711. private function definelines(index:uint, point1:FourPoints, point2:FourPoints = null, lines:Array = null):FourPoints
  712. {
  713. var tmppt:FourPoints;
  714. var fourPoints:FourPoints = new FourPoints();
  715. if (point2 == null) {
  716. tmppt = lines[index - 1];
  717. fourPoints.pt1 = tmppt.pt3;
  718. fourPoints.pt2 = tmppt.pt4;
  719. fourPoints.pt3 = point1.pt3;
  720. fourPoints.pt4 = point1.pt4;
  721. return fourPoints;
  722. }
  723. var line1:Line = buildObjectLine(point1.pt1.x, point1.pt1.y, point1.pt3.x, point1.pt3.y);
  724. var line2:Line = buildObjectLine(point1.pt2.x, point1.pt2.y, point1.pt4.x, point1.pt4.y);
  725. var line3:Line = buildObjectLine(point2.pt1.x, point2.pt1.y, point2.pt3.x, point2.pt3.y);
  726. var line4:Line = buildObjectLine(point2.pt2.x, point2.pt2.y, point2.pt4.x, point2.pt4.y);
  727. var cross1:Point = lineIntersect(line3, line1);
  728. var cross2:Point = lineIntersect(line2, line4);
  729. if (cross1 != null && cross2 != null) {
  730. if (index == 0) {
  731. fourPoints.pt1 = point1.pt1;
  732. fourPoints.pt2 = point1.pt2;
  733. fourPoints.pt3 = cross1;
  734. fourPoints.pt4 = cross2;
  735. return fourPoints;
  736. }
  737. tmppt = lines[index - 1];
  738. fourPoints.pt1 = tmppt.pt3;
  739. fourPoints.pt2 = tmppt.pt4;
  740. fourPoints.pt3 = cross1;
  741. fourPoints.pt4 = cross2;
  742. return fourPoints;
  743. } else
  744. return null;
  745. }
  746. private function defineAnchors(base:Vector3D, baseEnd:Vector3D, prop1:String, prop2:String):FourPoints
  747. {
  748. var angle:Number = (Math.atan2(base[prop2] - baseEnd[prop2], base[prop1] - baseEnd[prop1])*180)/Math.PI;
  749. angle -= 270;
  750. var angle2:Number = angle + 180;
  751. var fourPoints:FourPoints = new FourPoints();
  752. fourPoints.pt1 = new Point(base[prop1], base[prop2]);
  753. fourPoints.pt2 = new Point(base[prop1], base[prop2]);
  754. fourPoints.pt3 = new Point(baseEnd[prop1], baseEnd[prop2]);
  755. fourPoints.pt4 = new Point(baseEnd[prop1], baseEnd[prop2]);
  756. var radius:Number = _thickness*.5;
  757. fourPoints.pt1.x = fourPoints.pt1.x + Math.cos(-angle/180*Math.PI)*radius;
  758. fourPoints.pt1.y = fourPoints.pt1.y + Math.sin(angle/180*Math.PI)*radius;
  759. fourPoints.pt2.x = fourPoints.pt2.x + Math.cos(-angle2/180*Math.PI)*radius;
  760. fourPoints.pt2.y = fourPoints.pt2.y + Math.sin(angle2/180*Math.PI)*radius;
  761. fourPoints.pt3.x = fourPoints.pt3.x + Math.cos(-angle/180*Math.PI)*radius;
  762. fourPoints.pt3.y = fourPoints.pt3.y + Math.sin(angle/180*Math.PI)*radius;
  763. fourPoints.pt4.x = fourPoints.pt4.x + Math.cos(-angle2/180*Math.PI)*radius;
  764. fourPoints.pt4.y = fourPoints.pt4.y + Math.sin(angle2/180*Math.PI)*radius;
  765. return fourPoints;
  766. }
  767. private function buildObjectLine(origX:Number, origY:Number, endX:Number, endY:Number):Line
  768. {
  769. var line:Line = new Line();
  770. line.ax = origX;
  771. line.ay = origY;
  772. line.bx = endX - origX;
  773. line.by = endY - origY;
  774. return line;
  775. }
  776. private function lineIntersect(Line1:Line, Line2:Line):Point
  777. {
  778. Line1.bx = (Line1.bx == 0)? EPS : Line1.bx;
  779. Line2.bx = (Line2.bx == 0)? EPS : Line2.bx;
  780. var a1:Number = Line1.by/Line1.bx;
  781. var b1:Number = Line1.ay - a1*Line1.ax;
  782. var a2:Number = Line2.by/Line2.bx;
  783. var b2:Number = Line2.ay - a2*Line2.ax;
  784. var nzero:Number = ((a1 - a2) == 0)? EPS : a1 - a2;
  785. var ptx:Number = ( b2 - b1 )/(nzero);
  786. var pty:Number = a1*ptx + b1;
  787. if (isFinite(ptx) && isFinite(pty))
  788. return new Point(ptx, pty);
  789. else {
  790. trace("infinity");
  791. return null;
  792. }
  793. }
  794. private function initHolders():void
  795. {
  796. if (!_uva) {
  797. _uva = new UV(0, 0);
  798. _uvb = new UV(0, 0);
  799. _uvc = new UV(0, 0);
  800. _uvd = new UV(0, 0);
  801. }
  802. _varr = new Vector.<Vertex>();
  803. _varr2 = new Vector.<Vertex>();
  804. _uvarr = new Vector.<UV>();
  805. _uvs = new Vector.<Number>();
  806. _vertices = new Vector.<Number>();
  807. _indices = new Vector.<uint>();
  808. if (_materials) {
  809. _MaterialsSubGeometries = new Vector.<SubGeometryList>();
  810. var sglist:SubGeometryList = new SubGeometryList();
  811. _MaterialsSubGeometries.push(sglist);
  812. sglist.subGeometry = new SubGeometry();
  813. _subGeometry = sglist.subGeometry;
  814. sglist.uvs = _uvs = new Vector.<Number>();
  815. sglist.vertices = _vertices = new Vector.<Number>();
  816. sglist.indices = _indices = new Vector.<uint>();
  817. sglist.material = this.material;
  818. if (sglist.material.name == null)
  819. sglist.material.name = "baseMaterial";
  820. } else {
  821. _subGeometry.autoDeriveVertexNormals = true;
  822. _subGeometry.autoDeriveVertexTangents = true;
  823. }
  824. }
  825. private function getSubGeometryListFromMaterial(mat:MaterialBase):SubGeometryList
  826. {
  827. var sglist:SubGeometryList;
  828. for (var i:uint = 0; i < _MaterialsSubGeometries.length; ++i) {
  829. if (_MaterialsSubGeometries[i].material == mat) {
  830. sglist = _MaterialsSubGeometries[i];
  831. break;
  832. }
  833. }
  834. if (!sglist) {
  835. sglist = new SubGeometryList();
  836. _MaterialsSubGeometries.push(sglist);
  837. sglist.subGeometry = new SubGeometry();
  838. sglist.uvs = new Vector.<Number>();
  839. sglist.vertices = new Vector.<Number>();
  840. sglist.indices = new Vector.<uint>();
  841. sglist.material = mat;
  842. }
  843. return sglist;
  844. }
  845. /**
  846. * Invalidates the geometry, causing it to be rebuilded when requested.
  847. */
  848. private function invalidateGeometry():void
  849. {
  850. if (_geomDirty)
  851. return;
  852. _geomDirty = true;
  853. invalidateBounds();
  854. }
  855. }
  856. }
  857. import away3d.core.base.SubGeometry;
  858. import away3d.materials.MaterialBase;
  859. import flash.geom.Point;
  860. class SubGeometryList
  861. {
  862. public var id:uint;
  863. public var uvs:Vector.<Number>;
  864. public var vertices:Vector.<Number>;
  865. public var indices:Vector.<uint>;
  866. public var subGeometry:SubGeometry;
  867. public var material:MaterialBase;
  868. }
  869. class RenderSide
  870. {
  871. public var top:Boolean;
  872. public var bottom:Boolean;
  873. public var right:Boolean;
  874. public var left:Boolean;
  875. public var front:Boolean;
  876. public var back:Boolean;
  877. }
  878. class Line
  879. {
  880. public var ax:Number;
  881. public var ay:Number;
  882. public var bx:Number;
  883. public var by:Number;
  884. }
  885. class FourPoints
  886. {
  887. public var pt1:Point;
  888. public var pt2:Point;
  889. public var pt3:Point;
  890. public var pt4:Point;
  891. }