/src/away3d/extrusions/PathExtrude.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 1313 lines · 978 code · 229 blank · 106 comment · 256 complexity · 87f41ec93c880755d1bf25ef196615a4 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.core.math.Vector3DUtils;
  10. import away3d.entities.Mesh;
  11. import away3d.materials.MaterialBase;
  12. import away3d.paths.IPath;
  13. import away3d.paths.IPathSegment;
  14. import away3d.tools.helpers.MeshHelper;
  15. import flash.geom.Matrix3D;
  16. import flash.geom.Vector3D;
  17. [Deprecated]
  18. public class PathExtrude extends Mesh
  19. {
  20. private var _varr:Vector.<Vertex>;
  21. private var _doubles:Vector.<Vertex> = new Vector.<Vertex>();
  22. private var _upAxis:Vector3D = new Vector3D(0, 1, 0);
  23. private var _trans:Matrix3D = new Matrix3D();
  24. private const LIMIT:uint = 196605;
  25. private const MAXRAD:Number = 1.2;
  26. private var _path:IPath;
  27. private var _profile:Vector.<Vector3D>;
  28. private var _centerMesh:Boolean;
  29. private var _scales:Vector.<Vector3D>;
  30. private var _rotations:Vector.<Vector3D>;
  31. private var _materials:Vector.<MaterialBase>;
  32. private var _activeMaterial:MaterialBase;
  33. private var _subdivision:uint;
  34. private var _coverAll:Boolean;
  35. private var _coverSegment:Boolean;
  36. private var _flip:Boolean;
  37. private var _mapFit:Boolean;
  38. private var _closePath:Boolean;
  39. private var _alignToPath:Boolean;
  40. private var _smoothScale:Boolean;
  41. private var _smoothSurface:Boolean;
  42. private var _isClosedProfile:Boolean;
  43. private var _maxIndProfile:uint;
  44. private var _matIndex:uint = 0;
  45. private var _segv:Number;
  46. private var _geomDirty:Boolean = true;
  47. private var _subGeometry:SubGeometry;
  48. private var _MaterialsSubGeometries:Vector.<SubGeometryList> = new Vector.<SubGeometryList>();
  49. private var _uva:UV;
  50. private var _uvb:UV;
  51. private var _uvc:UV;
  52. private var _uvd:UV;
  53. private var _uvs:Vector.<Number>;
  54. private var _vertices:Vector.<Number>;
  55. private var _indices:Vector.<uint>;
  56. private var _normals:Vector.<Number>;
  57. private var _normalTmp:Vector3D;
  58. private var _normal0:Vector3D;
  59. private var _normal1:Vector3D;
  60. private var _normal2:Vector3D;
  61. private var _keepExtremes:Boolean;
  62. private var _distribute:Boolean;
  63. private var _distributeU:Boolean;
  64. private var _distributedU:Vector.<Number>;
  65. private var _startPoints:Vector.<Vector3D>;
  66. private var _endPoints:Vector.<Vector3D>;
  67. /**
  68. * Creates a new <code>PathExtrude</code>
  69. *
  70. * @param material [optional] MaterialBase. The PathExtrude (Mesh) material. Optional in constructor, material must be set before PathExtrude object is rendered. Required for the class to work.
  71. * @param path [optional] Path. Defines the <code>Path</code> object representing path to extrude along. Required for the class to work.
  72. * @param profile [optional] Vector.&lt;Vector3D&gt;. Defines an Vector.&lt;Vector3D&gt; of Vector3D objects representing the profile information to be projected along the Path object. Required for the class to work.
  73. * @param subdivision [optional] uint. Howmany steps between each PathSegment. If the path holds curves, the higher this value, the higher the curve fidelity. Default and minimum is 2;
  74. * @param coverall [optional] Boolean. Defines the uv mapping, when true a unique material is stretched along the entire path/shape. Default is true.
  75. * @param coverSegment [optional] Boolean. Defines the uv mapping, when true and coverall is false a unique material is stretched along one PathSegment. Default is false.
  76. * @param alignToPath [optional] Boolean. If the profile must follow the path or keep its original orientation.
  77. * @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.
  78. * @param mapFit [optional] Boolean. The UV mapping is percentually spreaded over the width of the path, making texture looking nicer and edits for applications such as a race track, road, more easy. Affects the uv's u values and set distributeU to false. Default is false.
  79. * @param flip [optional] Boolean. If the faces must be reversed depending on Vector3D's orientation. Default is false.
  80. * @param closePath [optional] Boolean. If the last PathSegment entered must be welded back to first one. Executed in a straight manner, its recommanded to pass the first entry to the Path again, as last entry if curves are involved.
  81. * @param materials [optional] Vector.&lt;MaterialBase&gt;. An optional Vector.&lt;MaterialBase&gt; of different materials that can be alternated along the path if coverAll is false.
  82. * @param scales [optional] An optional Vector.&lt;Vector3D&gt; of <code>Vector3D</code> objects that defines a series of scales to be set on each PathSegment.
  83. * @param smoothScale [optional] Boolean. Defines if the scale must be interpolated between values or keep their full aspect on each PathSegment.
  84. * @param rotations [optional] An optional Vector.&lt;Vector3D&gt; of <code>Vector3D</code> objects that defines a series of rotations to be set on each PathSegment.
  85. * @param smoothSurface [optional] An optional Boolean. Defines if the surface of the mesh must be smoothed or not. Default is true.
  86. * @param distribute [optional] Boolean. If the mesh subdivision is evenly spreaded over the entire mesh. Depending on path definition, segments are possibly not having the same amount of subdivision.
  87. * @param distributeU [optional] Boolean. If the mesh uv' u value is procentually spreaded over the entire mesh surface. Prevents the source map to be stretched. Default is true.
  88. * @param keepExtremes [optional] Boolean. If the the first and last profile coordinates must be kept accessible, in order to feed classes such as DelaunayMesh. Default is false;
  89. */
  90. function PathExtrude(material:MaterialBase = null, path:IPath = null, profile:Vector.<Vector3D> = null, subdivision:uint = 2, coverAll:Boolean = true, coverSegment:Boolean = false, alignToPath:Boolean = true, centerMesh:Boolean = false, mapFit:Boolean = false, flip:Boolean = false, closePath:Boolean = false, materials:Vector.<MaterialBase> = null, scales:Vector.<Vector3D> = null, smoothScale:Boolean = true, rotations:Vector.<Vector3D> = null, smoothSurface:Boolean = true, distribute:Boolean = false, distributeU:Boolean = true, keepExtremes:Boolean = false)
  91. {
  92. distribute = distribute;
  93. var geom:Geometry = new Geometry();
  94. _subGeometry = new SubGeometry();
  95. super(geom, material);
  96. _activeMaterial = this.material;
  97. _path = path;
  98. this.profile = profile;
  99. this.subdivision = subdivision;
  100. _coverSegment = coverSegment;
  101. _coverAll = (_coverSegment)? false : coverAll;
  102. _alignToPath = alignToPath;
  103. _centerMesh = centerMesh;
  104. _mapFit = mapFit;
  105. _flip = flip;
  106. _closePath = closePath;
  107. _materials = (materials)? materials : new Vector.<MaterialBase>();
  108. _scales = scales;
  109. _smoothScale = smoothScale;
  110. _rotations = rotations;
  111. _smoothSurface = smoothSurface;
  112. _distributeU = distributeU;
  113. _keepExtremes = keepExtremes;
  114. }
  115. public function get upAxis():Vector3D
  116. {
  117. return _upAxis;
  118. }
  119. public function set upAxis(value:Vector3D):void
  120. {
  121. _upAxis = value;
  122. }
  123. /**
  124. * @inheritDoc
  125. */
  126. override public function get bounds():BoundingVolumeBase
  127. {
  128. if (_geomDirty)
  129. buildExtrude();
  130. return super.bounds;
  131. }
  132. /**
  133. * @inheritDoc
  134. */
  135. override public function get geometry():Geometry
  136. {
  137. if (_geomDirty)
  138. buildExtrude();
  139. return super.geometry;
  140. }
  141. /**
  142. * @inheritDoc
  143. */
  144. override public function get subMeshes():Vector.<SubMesh>
  145. {
  146. if (_geomDirty)
  147. buildExtrude();
  148. return super.subMeshes;
  149. }
  150. /**
  151. * Defines whether the mesh is recentered of not after generation
  152. */
  153. public function get centerMesh():Boolean
  154. {
  155. return _centerMesh;
  156. }
  157. public function set centerMesh(val:Boolean):void
  158. {
  159. if (_centerMesh == val)
  160. return;
  161. _centerMesh = val;
  162. if (_centerMesh && this.geometry.subGeometries.length > 0)
  163. MeshHelper.recenter(this);
  164. else
  165. invalidateGeometry();
  166. }
  167. /**
  168. * Defines the uv's u values are spreaded procentually over the entire surface to prevent the maps to be stretched.
  169. */
  170. public function get distributeU():Boolean
  171. {
  172. return _distributeU;
  173. }
  174. public function set distributeU(val:Boolean):void
  175. {
  176. if (_distributeU == val)
  177. return;
  178. _distributeU = val;
  179. if (val && _mapFit)
  180. _mapFit = false;
  181. if (!val && _distributedU)
  182. _distributedU = null;
  183. invalidateGeometry();
  184. }
  185. /**
  186. * Invalidates the geometry, causing it to be rebuillded when requested.
  187. */
  188. private function invalidateGeometry():void
  189. {
  190. _geomDirty = true;
  191. invalidateBounds();
  192. }
  193. /**
  194. * Defines the <code>Path</code> object representing path to extrude along. Required.
  195. */
  196. public function get path():IPath
  197. {
  198. return _path;
  199. }
  200. public function set path(val:IPath):void
  201. {
  202. _path = val;
  203. _geomDirty = true;
  204. }
  205. /**
  206. * Defines a Vector.&lt;Vector3D&gt; of Vector3D objects representing the profile information to be projected along the Path object. Required.
  207. */
  208. public function get profile():Vector.<Vector3D>
  209. {
  210. return _profile;
  211. }
  212. public function set profile(val:Vector.<Vector3D>):void
  213. {
  214. _profile = val;
  215. if (_profile != null)
  216. _isClosedProfile = (_profile[0].x == _profile[_profile.length - 1].x && _profile[0].y == _profile[_profile.length - 1].y && _profile[0].z == _profile[_profile.length - 1].z);
  217. _geomDirty = true;
  218. }
  219. /**
  220. * An optional Vector.&lt;Vector3D&gt; of <code>Vector3D</code> objects that defines a series of scales to be set on each PathSegment.
  221. */
  222. public function get scales():Vector.<Vector3D>
  223. {
  224. return _scales;
  225. }
  226. public function set scales(val:Vector.<Vector3D>):void
  227. {
  228. _scales = val;
  229. _geomDirty = true;
  230. }
  231. /**
  232. * An optional Vector.&lt;Vector3D&gt; of <code>Vector3D</code> objects that defines a series of rotations to be set on each PathSegment.
  233. */
  234. public function get rotations():Vector.<Vector3D>
  235. {
  236. return _rotations;
  237. }
  238. public function set rotations(val:Vector.<Vector3D>):void
  239. {
  240. _rotations = val;
  241. _geomDirty = true;
  242. }
  243. /**
  244. * An optional Vector.&lt;MaterialBase&gt;. It defines a series of materials to be set on each PathSegment if coverAll is set to false.
  245. */
  246. public function get materials():Vector.<MaterialBase>
  247. {
  248. return _materials;
  249. }
  250. public function set materials(val:Vector.<MaterialBase>):void
  251. {
  252. if (val == null)
  253. return;
  254. _materials = val;
  255. _geomDirty = true;
  256. }
  257. /**
  258. * Defines the subdivisions created in the mesh for each PathSegment. Defaults to 2, minimum 2.
  259. */
  260. public function get subdivision():int
  261. {
  262. return _subdivision;
  263. }
  264. public function set subdivision(val:int):void
  265. {
  266. val = (val < 2)? 2 : val;
  267. if (_subdivision == val)
  268. return;
  269. _subdivision = val;
  270. _geomDirty = true;
  271. }
  272. /**
  273. * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to true.
  274. */
  275. public function get coverAll():Boolean
  276. {
  277. return _coverAll;
  278. }
  279. public function set coverAll(val:Boolean):void
  280. {
  281. if (_coverAll == val)
  282. return;
  283. _coverAll = val;
  284. _geomDirty = true;
  285. }
  286. /**
  287. * Defines if the mesh subdivision is spread evenly over the entire geometry. Possibly resulting in uneven subdivision per segments.
  288. * Uv mapping is less distorted on complex shapes once applied. Depending on Path length, extra construct time might be significant.
  289. * Defaults to false.
  290. */
  291. public function get distribute():Boolean
  292. {
  293. return _distribute;
  294. }
  295. public function set distribute(val:Boolean):void
  296. {
  297. if (_distribute == val)
  298. return;
  299. _distribute = val;
  300. _geomDirty = true;
  301. }
  302. /**
  303. * Defines if the surface of the mesh must be smoothed or not.
  304. */
  305. public function get smoothSurface():Boolean
  306. {
  307. return _smoothSurface;
  308. }
  309. public function set smoothSurface(val:Boolean):void
  310. {
  311. if (_smoothSurface == val)
  312. return;
  313. _smoothSurface = val;
  314. _geomDirty = true;
  315. }
  316. /**
  317. * Defines if the texture(s) should applied per segment. Default false.
  318. */
  319. public function set coverSegment(b:Boolean):void
  320. {
  321. _coverSegment = b;
  322. }
  323. public function get coverSegment():Boolean
  324. {
  325. return _coverSegment;
  326. }
  327. /**
  328. * Defines if the texture(s) should be projected on the geometry evenly spreaded over the source bitmapdata or using distance/percent. Default is false.
  329. * The mapping considers first and last profile points are the most distant from each other. Most left and most right on the map.
  330. * Note that it is NOT suitable for most cases. It is helpfull for roads definition, usually seen from above with simple profile. It prevents then distorts and eases map designs.
  331. */
  332. public function get mapFit():Boolean
  333. {
  334. return _mapFit;
  335. }
  336. public function set mapFit(val:Boolean):void
  337. {
  338. if (_mapFit == val)
  339. return;
  340. if (val && _distributeU)
  341. _distributeU = false;
  342. _mapFit = val;
  343. _geomDirty = true;
  344. }
  345. /**
  346. * Defines if the generated faces should be inversed. Default false.
  347. */
  348. public function get flip():Boolean
  349. {
  350. return _flip;
  351. }
  352. public function set flip(val:Boolean):void
  353. {
  354. if (_flip == val)
  355. return;
  356. _flip = val;
  357. _geomDirty = true;
  358. }
  359. /**
  360. * Defines if the last PathSegment should join the first one and close the loop. Defaults to false.
  361. */
  362. public function get closePath():Boolean
  363. {
  364. return _closePath;
  365. }
  366. public function set closePath(val:Boolean):void
  367. {
  368. if (_closePath == val)
  369. return;
  370. _closePath = val;
  371. _geomDirty = true;
  372. }
  373. /**
  374. * Defines if the array of profile points should be orientated on path or not. Default true. Note that Path object's worldaxis property might need to be changed. default = 0,1,0.
  375. *
  376. * @see #profile
  377. */
  378. public function get aligntoPath():Boolean
  379. {
  380. return _alignToPath;
  381. }
  382. public function set alignToPath(val:Boolean):void
  383. {
  384. if (_alignToPath == val)
  385. return;
  386. _alignToPath = val;
  387. _geomDirty = true;
  388. }
  389. /**
  390. * Defines if a scaling of a PathSegment defined from the scales array of <code>Vector3D</code> objects should affect the whole PathSegment evenly or be smoothly interpolated from previous PathSegment scale. Defaults to true.
  391. */
  392. public function get smoothScale():Boolean
  393. {
  394. return _smoothScale;
  395. }
  396. public function set smoothScale(val:Boolean):void
  397. {
  398. if (_smoothScale == val)
  399. return;
  400. _smoothScale = val;
  401. _geomDirty = true;
  402. }
  403. /**
  404. * Defines if the first and last transformed vector3d's of the profile are kept.
  405. * For instance to be able to pass these coordinates to DelaunayMesh class, to close the extrude, if it was a tube.
  406. * @see getStartProfile
  407. * @see getEndProfile
  408. */
  409. public function get keepExtremes():Boolean
  410. {
  411. return _keepExtremes;
  412. }
  413. public function set keepExtremes(b:Boolean):void
  414. {
  415. _keepExtremes = b;
  416. }
  417. /**
  418. * returns a vector of vector3d's representing the transformed profile coordinates at the start of the extrude shape
  419. * null if "keepExtremes" is false or if the extrusion has not been builded yet.
  420. */
  421. public function get startProfile():Vector.<Vector3D>
  422. {
  423. if (!_path || !_startPoints)
  424. return null;
  425. return _startPoints;
  426. }
  427. /**
  428. * returns a vector of vector3d's representing the transformed profile coordinates at the end of the extrude shape
  429. * null if "keepExtremes" is false or if the extrusion has not been builded yet.
  430. */
  431. public function get endProfile():Vector.<Vector3D>
  432. {
  433. if (!_path || !_endPoints)
  434. return null;
  435. return _endPoints;
  436. }
  437. private function orientateAt(target:Vector3D, position:Vector3D):void
  438. {
  439. var xAxis:Vector3D;
  440. var yAxis:Vector3D;
  441. var zAxis:Vector3D = target.subtract(position);
  442. zAxis.normalize();
  443. if (zAxis.length > 0.1) {
  444. xAxis = _upAxis.crossProduct(zAxis);
  445. xAxis.normalize();
  446. yAxis = xAxis.crossProduct(zAxis);
  447. yAxis.normalize();
  448. var rawData:Vector.<Number> = _trans.rawData;
  449. rawData[0] = xAxis.x;
  450. rawData[1] = xAxis.y;
  451. rawData[2] = xAxis.z;
  452. rawData[4] = -yAxis.x;
  453. rawData[5] = -yAxis.y;
  454. rawData[6] = -yAxis.z;
  455. rawData[8] = zAxis.x;
  456. rawData[9] = zAxis.y;
  457. rawData[10] = zAxis.z;
  458. _trans.rawData = rawData;
  459. }
  460. }
  461. private function generate(points:Vector.<Vector.<Vector3D>>, offsetV:int = 0, closedata:Boolean = false):void
  462. {
  463. var uvlength:int = (points.length - 1) + offsetV;
  464. var offset:uint;
  465. for (var i:uint = 0; i < points.length - 1; ++i) {
  466. _varr = new Vector.<Vertex>();
  467. offset = (closedata)? i + uvlength : i;
  468. extrudePoints(points[i], points[i + 1], (1/uvlength)*offset, uvlength, offset/(_subdivision - 1));
  469. if (i == 0 && _isClosedProfile)
  470. _doubles = _varr.concat();
  471. }
  472. _varr = _doubles = null;
  473. }
  474. private function extrudePoints(points1:Vector.<Vector3D>, points2:Vector.<Vector3D>, vscale:Number, indexv:int, indexp:Number):void
  475. {
  476. var i:int;
  477. var j:int;
  478. var stepx:Number;
  479. var stepy:Number;
  480. var stepz:Number;
  481. var va:Vertex;
  482. var vb:Vertex;
  483. var vc:Vertex;
  484. var vd:Vertex;
  485. var u1:Number;
  486. var u2:Number;
  487. var index:uint = 0;
  488. var v1:Number = 0;
  489. var v2:Number = 0;
  490. var countloop:int = points1.length;
  491. var mat:MaterialBase;
  492. if (_mapFit) {
  493. var dist:Number = 0;
  494. var tdist:Number;
  495. var bleft:Vector3D;
  496. for (i = 0; i < countloop; ++i) {
  497. for (j = 0; j < countloop; ++j) {
  498. if (i != j) {
  499. tdist = Vector3D.distance(points1[i], points1[j]);
  500. if (tdist > dist) {
  501. dist = tdist;
  502. bleft = points1[i];
  503. }
  504. }
  505. }
  506. }
  507. } else {
  508. var bu:Number = 0;
  509. var bincu:Number = 1/(countloop - 1);
  510. }
  511. function getDouble(x:Number, y:Number, z:Number):Vertex
  512. {
  513. for (var i:int = 0; i < _doubles.length; ++i) {
  514. if (_doubles[i].x == x && _doubles[i].y == y && _doubles[i].z == z) {
  515. return _doubles[i];
  516. }
  517. }
  518. return new Vertex(x, y, z);
  519. }
  520. for (i = 0; i < countloop; ++i) {
  521. stepx = points2[i].x - points1[i].x;
  522. stepy = points2[i].y - points1[i].y;
  523. stepz = points2[i].z - points1[i].z;
  524. for (j = 0; j < 2; ++j) {
  525. if (_isClosedProfile && _doubles.length > 0)
  526. _varr.push(getDouble(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j)));
  527. else
  528. _varr.push(new Vertex(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j)));
  529. }
  530. }
  531. var floored:uint = _coverSegment? indexp : 0;
  532. if (_materials && _materials.length > 0) {
  533. if (_coverSegment && indexp - floored == 0)
  534. _matIndex = (_matIndex + 1 > _materials.length - 1)? 0 : _matIndex + 1;
  535. else if (!coverAll && !_coverSegment)
  536. _matIndex = (_matIndex + 1 > _materials.length - 1)? 0 : _matIndex + 1;
  537. }
  538. mat = ( _coverAll || !_materials || _materials.length == 0)? this.material : _materials[_matIndex];
  539. var covSub:Boolean = _coverAll && _subdivision > 1;
  540. var cosegSub:Boolean = _coverSegment && _subdivision > 1;
  541. for (i = 0; i < countloop - 1; ++i) {
  542. if (_distributeU) {
  543. u1 = _distributedU[i];
  544. u2 = _distributedU[i + 1];
  545. } else if (_mapFit) {
  546. u1 = 1 - Vector3D.distance(points1[i], bleft)/dist;
  547. u2 = 1 - Vector3D.distance(points1[i + 1], bleft)/dist;
  548. } else {
  549. u1 = 1 - bu;
  550. bu += bincu;
  551. u2 = 1 - bu;
  552. }
  553. v1 = (covSub)? vscale : ( (cosegSub)? indexp - floored : 0 );
  554. v2 = (covSub)? vscale + (1/indexv) : ( (cosegSub)? v1 + _segv : 1 );
  555. _uva.u = u1;
  556. _uva.v = v1;
  557. _uvb.u = u1;
  558. _uvb.v = v2;
  559. _uvc.u = u2;
  560. _uvc.v = v2;
  561. _uvd.u = u2;
  562. _uvd.v = v1;
  563. va = _varr[index];
  564. vb = _varr[index + 1];
  565. vc = _varr[index + 3];
  566. vd = _varr[index + 2];
  567. if (_flip) {
  568. addFace(vb, va, vc, _uvb, _uva, _uvc, mat);
  569. addFace(vc, va, vd, _uvc, _uva, _uvd, mat);
  570. } else {
  571. addFace(va, vb, vc, _uva, _uvb, _uvc, mat);
  572. addFace(va, vc, vd, _uva, _uvc, _uvd, mat);
  573. }
  574. if (_mapFit)
  575. u1 = u2;
  576. index += 2;
  577. }
  578. }
  579. private function initHolders():void
  580. {
  581. if (!_uva) {
  582. _uva = new UV(0, 0);
  583. _uvb = new UV(0, 0);
  584. _uvc = new UV(0, 0);
  585. _uvd = new UV(0, 0);
  586. _normal0 = new Vector3D(0.0, 0.0, 0.0);
  587. _normal1 = new Vector3D(0.0, 0.0, 0.0);
  588. _normal2 = new Vector3D(0.0, 0.0, 0.0);
  589. _normalTmp = new Vector3D(0.0, 0.0, 0.0);
  590. }
  591. if (_materials && _materials.length > 0) {
  592. var sglist:SubGeometryList = new SubGeometryList();
  593. _MaterialsSubGeometries.push(sglist);
  594. sglist.subGeometry = new SubGeometry();
  595. _subGeometry = sglist.subGeometry;
  596. sglist.uvs = _uvs = new Vector.<Number>();
  597. sglist.vertices = _vertices = new Vector.<Number>();
  598. if (_smoothSurface)
  599. sglist.normals = _normals = new Vector.<Number>();
  600. sglist.indices = _indices = new Vector.<uint>();
  601. sglist.material = this.material;
  602. if (sglist.material.name == null)
  603. sglist.material.name = "baseMaterial";
  604. _matIndex = _materials.length;
  605. } else {
  606. _uvs = new Vector.<Number>();
  607. _vertices = new Vector.<Number>();
  608. _indices = new Vector.<uint>();
  609. if (_smoothSurface)
  610. _normals = new Vector.<Number>();
  611. else
  612. _subGeometry.autoDeriveVertexNormals = true;
  613. _subGeometry.autoDeriveVertexTangents = true;
  614. }
  615. }
  616. private function getSubGeometryListFromMaterial(mat:MaterialBase):SubGeometryList
  617. {
  618. var sglist:SubGeometryList;
  619. for (var i:uint = 0; i < _MaterialsSubGeometries.length; ++i) {
  620. if (_MaterialsSubGeometries[i].material == mat) {
  621. sglist = _MaterialsSubGeometries[i];
  622. break;
  623. }
  624. }
  625. if (!sglist) {
  626. sglist = new SubGeometryList();
  627. _MaterialsSubGeometries.push(sglist);
  628. sglist.subGeometry = new SubGeometry();
  629. sglist.uvs = new Vector.<Number>();
  630. sglist.vertices = new Vector.<Number>();
  631. sglist.indices = new Vector.<uint>();
  632. sglist.material = mat;
  633. if (_smoothSurface)
  634. sglist.normals = new Vector.<Number>();
  635. }
  636. return sglist;
  637. }
  638. private function calcNormal(v0:Vertex, v1:Vertex, v2:Vertex):void
  639. {
  640. var dx1:Number = v2.x - v0.x;
  641. var dy1:Number = v2.y - v0.y;
  642. var dz1:Number = v2.z - v0.z;
  643. var dx2:Number = v1.x - v0.x;
  644. var dy2:Number = v1.y - v0.y;
  645. var dz2:Number = v1.z - v0.z;
  646. var cx:Number = dz1*dy2 - dy1*dz2;
  647. var cy:Number = dx1*dz2 - dz1*dx2;
  648. var cz:Number = dy1*dx2 - dx1*dy2;
  649. var d:Number = 1/Math.sqrt(cx*cx + cy*cy + cz*cz);
  650. _normal0.x = _normal1.x = _normal2.x = cx*d;
  651. _normal0.y = _normal1.y = _normal2.y = cy*d;
  652. _normal0.z = _normal1.z = _normal2.z = cz*d;
  653. }
  654. private function addFace(v0:Vertex, v1:Vertex, v2:Vertex, uv0:UV, uv1:UV, uv2:UV, mat:MaterialBase):void
  655. {
  656. var subGeom:SubGeometry;
  657. var uvs:Vector.<Number>;
  658. var vertices:Vector.<Number>;
  659. var normals:Vector.<Number>;
  660. var indices:Vector.<uint>;
  661. var sglist:SubGeometryList;
  662. var startMat:Boolean;
  663. if (_activeMaterial != mat && _materials && _materials.length > 0) {
  664. _activeMaterial = mat;
  665. sglist = getSubGeometryListFromMaterial(mat);
  666. _subGeometry = subGeom = sglist.subGeometry;
  667. _uvs = uvs = sglist.uvs;
  668. _vertices = vertices = sglist.vertices;
  669. _indices = indices = sglist.indices;
  670. _normals = normals = sglist.normals;
  671. startMat = true;
  672. } else {
  673. subGeom = _subGeometry;
  674. uvs = _uvs;
  675. vertices = _vertices;
  676. indices = _indices;
  677. normals = _normals;
  678. }
  679. if (vertices.length + 9 > LIMIT) {
  680. subGeom.updateVertexData(vertices);
  681. subGeom.updateIndexData(indices);
  682. subGeom.updateUVData(uvs);
  683. if (_smoothSurface)
  684. subGeom.updateVertexNormalData(normals);
  685. this.geometry.addSubGeometry(subGeom);
  686. this.subMeshes[this.subMeshes.length - 1].material = mat;
  687. subGeom = new SubGeometry();
  688. subGeom.autoDeriveVertexTangents = true;
  689. if (!_smoothSurface)
  690. subGeom.autoDeriveVertexNormals = true;
  691. if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 1) {
  692. sglist = getSubGeometryListFromMaterial(mat);
  693. sglist.subGeometry = _subGeometry = subGeom;
  694. sglist.uvs = _uvs = uvs = new Vector.<Number>();
  695. sglist.vertices = _vertices = vertices = new Vector.<Number>();
  696. sglist.indices = _indices = indices = new Vector.<uint>();
  697. if (_smoothSurface)
  698. sglist.normals = _normals = normals = new Vector.<Number>();
  699. } else {
  700. _subGeometry = subGeom;
  701. uvs = _uvs = new Vector.<Number>();
  702. vertices = _vertices = new Vector.<Number>();
  703. indices = _indices = new Vector.<uint>();
  704. normals = _normals = new Vector.<Number>();
  705. }
  706. }
  707. var bv0:Boolean;
  708. var bv1:Boolean;
  709. var bv2:Boolean;
  710. var ind0:uint;
  711. var ind1:uint;
  712. var ind2:uint;
  713. if (_smoothSurface && !startMat) {
  714. var uvind:uint;
  715. var uvindV:uint;
  716. var vind:uint;
  717. var vindy:uint;
  718. var vindz:uint;
  719. var ind:uint;
  720. var indlength:uint = indices.length;
  721. calcNormal(v0, v1, v2);
  722. var ab:Number;
  723. if (indlength > 0) {
  724. var back:Number = indlength - _maxIndProfile;
  725. var limitBack:uint = (back < 0)? 0 : back;
  726. for (var i:uint = indlength - 1; i > limitBack; --i) {
  727. ind = indices[i];
  728. vind = ind*3;
  729. vindy = vind + 1;
  730. vindz = vind + 2;
  731. uvind = ind*2;
  732. uvindV = uvind + 1;
  733. if (bv0 && bv1 && bv2)
  734. break;
  735. if (!bv0 && vertices[vind] == v0.x && vertices[vindy] == v0.y && vertices[vindz] == v0.z) {
  736. _normalTmp.x = normals[vind];
  737. _normalTmp.y = normals[vindy];
  738. _normalTmp.z = normals[vindz];
  739. ab = Vector3D.angleBetween(_normalTmp, _normal0);
  740. if (ab < MAXRAD) {
  741. _normal0.x = (_normalTmp.x + _normal0.x)*.5;
  742. _normal0.y = (_normalTmp.y + _normal0.y)*.5;
  743. _normal0.z = (_normalTmp.z + _normal0.z)*.5;
  744. if (_coverAll || uvs[uvind] == uv0.u && uvs[uvindV] == uv0.v) {
  745. bv0 = true;
  746. ind0 = ind;
  747. continue;
  748. }
  749. }
  750. }
  751. if (!bv1 && vertices[vind] == v1.x && vertices[vindy] == v1.y && vertices[vindz] == v1.z) {
  752. _normalTmp.x = normals[vind];
  753. _normalTmp.y = normals[vindy];
  754. _normalTmp.z = normals[vindz];
  755. ab = Vector3D.angleBetween(_normalTmp, _normal1);
  756. if (ab < MAXRAD) {
  757. _normal1.x = (_normalTmp.x + _normal1.x)*.5;
  758. _normal1.y = (_normalTmp.y + _normal1.y)*.5;
  759. _normal1.z = (_normalTmp.z + _normal1.z)*.5;
  760. if (_coverAll || uvs[uvind] == uv1.u && uvs[uvindV] == uv1.v) {
  761. bv1 = true;
  762. ind1 = ind;
  763. continue;
  764. }
  765. }
  766. }
  767. if (!bv2 && vertices[vind] == v2.x && vertices[vindy] == v2.y && vertices[vindz] == v2.z) {
  768. _normalTmp.x = normals[vind];
  769. _normalTmp.y = normals[vindy];
  770. _normalTmp.z = normals[vindz];
  771. ab = Vector3D.angleBetween(_normalTmp, _normal2);
  772. if (ab < MAXRAD) {
  773. _normal2.x = (_normalTmp.x + _normal2.x)*.5;
  774. _normal2.y = (_normalTmp.y + _normal2.y)*.5;
  775. _normal2.z = (_normalTmp.z + _normal2.z)*.5;
  776. if (_coverAll || uvs[uvind] == uv2.u && uvs[uvindV] == uv2.v) {
  777. bv2 = true;
  778. ind2 = ind;
  779. continue;
  780. }
  781. }
  782. }
  783. }
  784. }
  785. }
  786. if (!bv0) {
  787. ind0 = vertices.length/3;
  788. vertices.push(v0.x, v0.y, v0.z);
  789. uvs.push(uv0.u, uv0.v);
  790. if (_smoothSurface)
  791. normals.push(_normal0.x, _normal0.y, _normal0.z);
  792. }
  793. if (!bv1) {
  794. ind1 = vertices.length/3;
  795. vertices.push(v1.x, v1.y, v1.z);
  796. uvs.push(uv1.u, uv1.v);
  797. if (_smoothSurface)
  798. normals.push(_normal1.x, _normal1.y, _normal1.z);
  799. }
  800. if (!bv2) {
  801. ind2 = vertices.length/3;
  802. vertices.push(v2.x, v2.y, v2.z);
  803. uvs.push(uv2.u, uv2.v);
  804. if (_smoothSurface)
  805. normals.push(_normal2.x, _normal2.y, _normal2.z);
  806. }
  807. indices.push(ind0, ind1, ind2);
  808. }
  809. private function distributeVectors():Vector.<Vector.<Vector3D>>
  810. {
  811. var segs:Vector.<Vector.<Vector3D>> = _path.getPointsOnCurvePerSegment(_subdivision);
  812. var nSegs:Vector.<Vector.<Vector3D>> = new Vector.<Vector.<Vector3D>>();
  813. var seg:Vector.<Vector3D>;
  814. var j:uint;
  815. var estLength:Number = 0;
  816. var vCount:uint;
  817. var v:Vector3D;
  818. var tmpV:Vector3D = new Vector3D();
  819. var prevV:Vector3D;
  820. for (var i:uint = 0; i < segs.length; ++i) {
  821. seg = segs[i];
  822. for (j = 0; j < _subdivision; ++j) {
  823. if (prevV)
  824. estLength += Vector3D.distance(prevV, seg[j]);
  825. prevV = seg[j];
  826. vCount++;
  827. }
  828. }
  829. var step:Number = estLength/vCount;
  830. var tPrecision:Number = 0.001;
  831. var t:Number = 0;
  832. var ps:IPathSegment;
  833. var tmpVDist:Number = 0;
  834. var diff:Number = 0;
  835. var ignore:Boolean;
  836. for (i = 0; i < segs.length; ++i) {
  837. ps = _path.getSegmentAt(i);
  838. ignore = false;
  839. t = diff;
  840. seg = new Vector.<Vector3D>();
  841. while (t < 1) {
  842. if (segs.length == 0) {
  843. v = segs[i][0];
  844. seg.push(v);
  845. prevV = v;
  846. continue;
  847. }
  848. tmpVDist = 0;
  849. while (tmpVDist < step) {
  850. t += tPrecision;
  851. if (t > 1 && i < segs.length - 1) {
  852. ignore = true;
  853. break;
  854. } else {
  855. tmpV = ps.getPointOnSegment(t, tmpV);
  856. tmpVDist = Vector3D.distance(prevV, tmpV);
  857. }
  858. }
  859. diff = 1 - t;
  860. if (!ignore) {
  861. v = new Vector3D(tmpV.x, tmpV.y, tmpV.z);
  862. prevV = v;
  863. seg.push(v);
  864. }
  865. }
  866. nSegs.push(seg);
  867. }
  868. segs = null;
  869. return nSegs;
  870. }
  871. private function generateUlist():void
  872. {
  873. _distributedU = Vector.<Number>([0]);
  874. var tdist:Number = 0;
  875. var dist:Number = 0;
  876. var tmpDists:Vector.<Number> = new Vector.<Number>();
  877. for (var i:uint = 0; i < _profile.length - 1; ++i) {
  878. tmpDists[i] = Vector3D.distance(_profile[i], _profile[i + 1]);
  879. tdist += tmpDists[i];
  880. }
  881. for (i = 1; i < _profile.length; ++i) {
  882. _distributedU[i] = (tmpDists[i - 1] + dist)/tdist;
  883. dist += tmpDists[i - 1];
  884. }
  885. tmpDists = null;
  886. }
  887. private function buildExtrude():void
  888. {
  889. if (_path == null || _path.numSegments == 0 || _profile == null || _profile.length < 2)
  890. throw new Error("PathExtrude error: invalid Path or profile with unsufficient data");
  891. _geomDirty = false;
  892. initHolders();
  893. _maxIndProfile = _profile.length*9;
  894. var vSegPts:Vector.<Vector.<Vector3D>>;
  895. if (_distribute)
  896. vSegPts = distributeVectors();
  897. else
  898. vSegPts = _path.getPointsOnCurvePerSegment(_subdivision);
  899. if (_distributeU)
  900. generateUlist();
  901. var vPtsList:Vector.<Vector3D> = new Vector.<Vector3D>();
  902. var vSegResults:Vector.<Vector.<Vector3D>> = new Vector.<Vector.<Vector3D>>();
  903. var atmp:Vector.<Vector3D>;
  904. var tmppt:Vector3D = new Vector3D(0, 0, 0);
  905. var i:uint;
  906. var j:uint;
  907. var k:uint;
  908. var nextpt:Vector3D;
  909. if (_coverSegment)
  910. _segv = 1/(_subdivision - 1);
  911. var lastP:Vector.<Vector3D>
  912. if (_closePath)
  913. lastP = new Vector.<Vector3D>();
  914. var rescale:Boolean = (_scales != null);
  915. var lastscale:Vector3D;
  916. if (rescale)
  917. lastscale = (_scales[0] == null)? new Vector3D(1, 1, 1) : _scales[0];
  918. var rotate:Boolean = (_rotations != null);
  919. if (rotate && _rotations.length > 0) {
  920. var lastrotate:Vector3D = _rotations[0];
  921. var nextrotate:Vector3D;
  922. var rotation:Vector.<Vector3D> = new Vector.<Vector3D>();
  923. var tweenrot:Vector3D;
  924. }
  925. if (_smoothScale && rescale) {
  926. var nextscale:Vector3D = new Vector3D(1, 1, 1);
  927. var vScales:Vector.<Vector3D> = Vector.<Vector3D>([lastscale]);
  928. if (_scales.length != _path.numSegments + 2) {
  929. var lastScl:Vector3D = _scales[_scales.length - 1];
  930. while (_scales.length != _path.numSegments + 2)
  931. _scales.push(lastScl);
  932. }
  933. }
  934. var tmploop:uint = _profile.length;
  935. for (i = 0; i < vSegPts.length; ++i) {
  936. if (rotate) {
  937. lastrotate = (_rotations[i] == null)? lastrotate : _rotations[i];
  938. nextrotate = (_rotations[i + 1] == null)? lastrotate : _rotations[i + 1];
  939. rotation = Vector.<Vector3D>([lastrotate]);
  940. rotation = rotation.concat(Vector3DUtils.subdivide(lastrotate, nextrotate, _subdivision));
  941. }
  942. if (rescale)
  943. lastscale = (!_scales[i])? lastscale : _scales[i];
  944. if (_smoothScale && rescale) {
  945. nextscale = (!_scales[i + 1])? (!_scales[i])? lastscale : _scales[i] : _scales[i + 1];
  946. vScales = vScales.concat(Vector3DUtils.subdivide(lastscale, nextscale, _subdivision));
  947. }
  948. for (j = 0; j < vSegPts[i].length; ++j) {
  949. atmp = new Vector.<Vector3D>();
  950. atmp = atmp.concat(_profile);
  951. vPtsList = new Vector.<Vector3D>();
  952. if (rotate)
  953. tweenrot = rotation[j];
  954. if (_alignToPath) {
  955. _trans = new Matrix3D();
  956. if (i == vSegPts.length - 1 && j == vSegPts[i].length - 1) {
  957. if (_closePath) {
  958. nextpt = vSegPts[0][0];
  959. orientateAt(nextpt, vSegPts[i][j]);
  960. } else {
  961. nextpt = vSegPts[i][j - 1];
  962. orientateAt(vSegPts[i][j], nextpt);
  963. }
  964. } else {
  965. nextpt = (j < vSegPts[i].length - 1)? vSegPts[i][j + 1] : vSegPts[i + 1][0];
  966. orientateAt(nextpt, vSegPts[i][j]);
  967. }
  968. }
  969. for (k = 0; k < tmploop; ++k) {
  970. if (rescale && !_smoothScale) {
  971. atmp[k].x *= lastscale.x;
  972. atmp[k].y *= lastscale.y;
  973. atmp[k].z *= lastscale.z;
  974. }
  975. if (_alignToPath) {
  976. tmppt = new Vector3D();
  977. tmppt.x = atmp[k].x*_trans.rawData[0] + atmp[k].y*_trans.rawData[4] + atmp[k].z*_trans.rawData[8] + _trans.rawData[12];
  978. tmppt.y = atmp[k].x*_trans.rawData[1] + atmp[k].y*_trans.rawData[5] + atmp[k].z*_trans.rawData[9] + _trans.rawData[13];
  979. tmppt.z = atmp[k].x*_trans.rawData[2] + atmp[k].y*_trans.rawData[6] + atmp[k].z*_trans.rawData[10] + _trans.rawData[14];
  980. if (rotate)
  981. tmppt = Vector3DUtils.rotatePoint(tmppt, tweenrot);
  982. tmppt.x += vSegPts[i][j].x;
  983. tmppt.y += vSegPts[i][j].y;
  984. tmppt.z += vSegPts[i][j].z;
  985. } else
  986. tmppt = new Vector3D(atmp[k].x + vSegPts[i][j].x, atmp[k].y + vSegPts[i][j].y, atmp[k].z + vSegPts[i][j].z);
  987. vPtsList.push(tmppt);
  988. }
  989. if (_closePath && i == vSegPts.length - 1 && j == vSegPts[i].length - 1)
  990. break;
  991. if (_closePath)
  992. lastP = vPtsList;
  993. vSegResults.push(vPtsList);
  994. }
  995. }
  996. if (rescale && _smoothScale) {
  997. for (i = 0; i < vScales.length; ++i) {
  998. for (j = 0; j < vSegResults[i].length; ++j) {
  999. vSegResults[i][j].x *= vScales[i].x;
  1000. vSegResults[i][j].y *= vScales[i].y;
  1001. vSegResults[i][j].z *= vScales[i].z;
  1002. }
  1003. }
  1004. vScales = null;
  1005. }
  1006. if (rotate)
  1007. rotation = null;
  1008. if (_closePath) {
  1009. var stepx:Number;
  1010. var stepy:Number;
  1011. var stepz:Number;
  1012. var c:Vector.<Vector3D>;
  1013. var c2:Vector.<Vector.<Vector3D>> = new Vector.<Vector.<Vector3D>>();
  1014. for (i = 1; i < _subdivision + 1; ++i) {
  1015. c = new Vector.<Vector3D>();
  1016. for (j = 0; j < lastP.length; ++j) {
  1017. stepx = (vSegResults[0][j].x - lastP[j].x)/_subdivision;
  1018. stepy = (vSegResults[0][j].y - lastP[j].y)/_subdivision;
  1019. stepz = (vSegResults[0][j].z - lastP[j].z)/_subdivision;
  1020. c.push(new Vector3D(lastP[j].x + (stepx*i), lastP[j].y + (stepy*i), lastP[j].z + (stepz*i)));
  1021. }
  1022. c2.push(c);
  1023. }
  1024. c2[0] = lastP;
  1025. generate(c2, (_coverAll)? vSegResults.length : 0, _coverAll);
  1026. c = null;
  1027. c2 = null;
  1028. }
  1029. if (_keepExtremes) {
  1030. _startPoints = new Vector.<Vector3D>();
  1031. _endPoints = new Vector.<Vector3D>();
  1032. var offsetEnd:uint = vSegResults.length - 1;
  1033. for (i = 0; i < tmploop; ++i) {
  1034. _startPoints[i] = vSegResults[0][i];
  1035. _endPoints[i] = vSegResults[offsetEnd][i];
  1036. }
  1037. } else if (_startPoints) {
  1038. for (i = 0; i < tmploop; ++i)
  1039. _startPoints[i] = _endPoints[i] = null;
  1040. _startPoints = _endPoints = null;
  1041. }
  1042. generate(vSegResults, (_closePath && _coverAll)? 1 : 0, (_closePath && !_coverAll));
  1043. vSegPts = null;
  1044. _varr = null;
  1045. if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
  1046. var sglist:SubGeometryList;
  1047. var sg:SubGeometry;
  1048. for (i = 0; i < _MaterialsSubGeometries.length; ++i) {
  1049. sglist = _MaterialsSubGeometries[i];
  1050. sg = sglist.subGeometry;
  1051. if (sg && sglist.vertices.length > 0) {
  1052. this.geometry.addSubGeometry(sg);
  1053. this.subMeshes[this.subMeshes.length - 1].material = sglist.material;
  1054. sg.updateVertexData(sglist.vertices);
  1055. sg.updateIndexData(sglist.indices);
  1056. sg.updateUVData(sglist.uvs);
  1057. if (_smoothSurface)
  1058. sg.updateVertexNormalData(sglist.normals);
  1059. }
  1060. }
  1061. } else {
  1062. _subGeometry.updateVertexData(_vertices);
  1063. _subGeometry.updateIndexData(_indices);
  1064. _subGeometry.updateUVData(_uvs);
  1065. if (_smoothSurface)
  1066. _subGeometry.updateVertexNormalData(_normals);
  1067. this.geometry.addSubGeometry(_subGeometry);
  1068. }
  1069. if (_centerMesh)
  1070. MeshHelper.recenter(this);
  1071. }
  1072. }
  1073. }
  1074. import away3d.core.base.SubGeometry;
  1075. import away3d.materials.MaterialBase;
  1076. class SubGeometryList
  1077. {
  1078. public var uvs:Vector.<Number>;
  1079. public var vertices:Vector.<Number>;
  1080. public var normals:Vector.<Number>;
  1081. public var indices:Vector.<uint>;
  1082. public var subGeometry:SubGeometry;
  1083. public var material:MaterialBase;
  1084. }