/home/lindsay/xeolabs/xeogl-next/xeogl/src/geometry/cylinderGeometry.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/geometry/cylinderGeometry.js

  1. /**
  2. A **CylinderGeometry** is a parameterized {{#crossLink "Geometry"}}{{/crossLink}} that defines a cylinder-shaped mesh for attached {{#crossLink "Mesh"}}Meshes{{/crossLink}}.
  3.  
  4. <a href="../../examples/#geometry_primitives_cylinder"><img src="../../assets/images/screenshots/CylinderGeometry.png"></img></a>
  5.  
  6. ## Examples
  7.  
  8. * [Textured CylinderGeometry](../../examples/#geometry_primitives_cylinder)
  9.  
  10. ## Usage
  11.  
  12. An {{#crossLink "Mesh"}}{{/crossLink}} with a CylinderGeometry and a {{#crossLink "PhongMaterial"}}{{/crossLink}} with
  13. diffuse {{#crossLink "Texture"}}{{/crossLink}}:
  14.  
  15. ````javascript
  16. new xeogl.Mesh({
  17.  
  18. geometry: new xeogl.CylinderGeometry({
  19. center: [0,0,0],
  20. radiusTop: 2.0,
  21. radiusBottom: 2.0,
  22. height: 5.0,
  23. radialSegments: 20,
  24. heightSegments: 1,
  25. openEnded: false
  26. }),
  27.  
  28. material: new xeogl.PhongMaterial({
  29. diffuseMap: new xeogl.Texture({
  30. src: "textures/diffuse/uvGrid2.jpg"
  31. })
  32. })
  33. });
  34. ````
  35.  
  36. @class CylinderGeometry
  37. @module xeogl
  38. @submodule geometry
  39. @constructor
  40. @param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "Scene"}}{{/crossLink}} when omitted.
  41. @param [cfg] {*} Configs
  42. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
  43. generated automatically when omitted.
  44. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this CylinderGeometry.
  45. @param [cfg.primitive="triangles"] {String} The primitive type. Accepted values for a CylinderGeometry are 'points', 'lines' and 'triangles'.
  46. @param [cfg.center] {Float32Array} 3D point indicating the center position of the CylinderGeometry.
  47. @param [cfg.radiusTop=1] {Number} Radius of top.
  48. @param [cfg.radiusBottom=1] {Number} Radius of bottom.
  49. @param [cfg.height=1] {Number} Height.
  50. @param [cfg.radialSegments=60] {Number} Number of segments around the CylinderGeometry.
  51. @param [cfg.heightSegments=1] {Number} Number of vertical segments.
  52. @param [cfg.openEnded=false] {Boolean} Whether or not the CylinderGeometry has solid caps on the ends.
  53. @param [cfg.lod=1] {Number} Level-of-detail, in range [0..1].
  54. @extends Geometry
  55. */
  56. import {utils} from '../utils.js';
  57. import {Geometry} from './geometry.js';
  58. import {componentClasses} from "./../componentClasses.js";
  59.  
  60. const type = "xeogl.CylinderGeometry";
  61.  
  62. class CylinderGeometry extends Geometry {
  63.  
  64. /**
  65. JavaScript class name for this Component.
  66.  
  67. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  68.  
  69. @property type
  70. @type String
  71. @final
  72. */
  73. get type() {
  74. return type;
  75. }
  76.  
  77. init(cfg) {
  78.  
  79. let radiusTop = cfg.radiusTop || 1;
  80. if (radiusTop < 0) {
  81. this.error("negative radiusTop not allowed - will invert");
  82. radiusTop *= -1;
  83. }
  84.  
  85. let radiusBottom = cfg.radiusBottom || 1;
  86. if (radiusBottom < 0) {
  87. this.error("negative radiusBottom not allowed - will invert");
  88. radiusBottom *= -1;
  89. }
  90.  
  91. let height = cfg.height || 1;
  92. if (height < 0) {
  93. this.error("negative height not allowed - will invert");
  94. height *= -1;
  95. }
  96.  
  97. let radialSegments = cfg.radialSegments || 32;
  98. if (radialSegments < 0) {
  99. this.error("negative radialSegments not allowed - will invert");
  100. radialSegments *= -1;
  101. }
  102. if (radialSegments < 3) {
  103. radialSegments = 3;
  104. }
  105.  
  106. let heightSegments = cfg.heightSegments || 1;
  107. if (heightSegments < 0) {
  108. this.error("negative heightSegments not allowed - will invert");
  109. heightSegments *= -1;
  110. }
  111. if (heightSegments < 1) {
  112. heightSegments = 1;
  113. }
  114.  
  115. const openEnded = !!cfg.openEnded;
  116.  
  117. let center = cfg.center;
  118. const centerX = center ? center[0] : 0;
  119. const centerY = center ? center[1] : 0;
  120. const centerZ = center ? center[2] : 0;
  121.  
  122. const heightHalf = height / 2;
  123. const heightLength = height / heightSegments;
  124. const radialAngle = (2.0 * Math.PI / radialSegments);
  125. const radialLength = 1.0 / radialSegments;
  126. //var nextRadius = this._radiusBottom;
  127. const radiusChange = (radiusTop - radiusBottom) / heightSegments;
  128.  
  129. const positions = [];
  130. const normals = [];
  131. const uvs = [];
  132. const indices = [];
  133.  
  134. let h;
  135. let i;
  136.  
  137. let x;
  138. let z;
  139.  
  140. let currentRadius;
  141. let currentHeight;
  142.  
  143. let first;
  144. let second;
  145.  
  146. let startIndex;
  147. let tu;
  148. let tv;
  149.  
  150. // create vertices
  151. const normalY = (90.0 - (Math.atan(height / (radiusBottom - radiusTop))) * 180 / Math.PI) / 90.0;
  152.  
  153. for (h = 0; h <= heightSegments; h++) {
  154. currentRadius = radiusTop - h * radiusChange;
  155. currentHeight = heightHalf - h * heightLength;
  156.  
  157. for (i = 0; i <= radialSegments; i++) {
  158. x = Math.sin(i * radialAngle);
  159. z = Math.cos(i * radialAngle);
  160.  
  161. normals.push(currentRadius * x);
  162. normals.push(normalY); //todo
  163. normals.push(currentRadius * z);
  164.  
  165. uvs.push((i * radialLength));
  166. uvs.push(h * 1 / heightSegments);
  167.  
  168. positions.push((currentRadius * x) + centerX);
  169. positions.push((currentHeight) + centerY);
  170. positions.push((currentRadius * z) + centerZ);
  171. }
  172. }
  173.  
  174. // create faces
  175. for (h = 0; h < heightSegments; h++) {
  176. for (i = 0; i <= radialSegments; i++) {
  177.  
  178. first = h * (radialSegments + 1) + i;
  179. second = first + radialSegments;
  180.  
  181. indices.push(first);
  182. indices.push(second);
  183. indices.push(second + 1);
  184.  
  185. indices.push(first);
  186. indices.push(second + 1);
  187. indices.push(first + 1);
  188. }
  189. }
  190.  
  191. // create top cap
  192. if (!openEnded && radiusTop > 0) {
  193. startIndex = (positions.length / 3);
  194.  
  195. // top center
  196. normals.push(0.0);
  197. normals.push(1.0);
  198. normals.push(0.0);
  199.  
  200. uvs.push(0.5);
  201. uvs.push(0.5);
  202.  
  203. positions.push(0 + centerX);
  204. positions.push(heightHalf + centerY);
  205. positions.push(0 + centerZ);
  206.  
  207. // top triangle fan
  208. for (i = 0; i <= radialSegments; i++) {
  209. x = Math.sin(i * radialAngle);
  210. z = Math.cos(i * radialAngle);
  211. tu = (0.5 * Math.sin(i * radialAngle)) + 0.5;
  212. tv = (0.5 * Math.cos(i * radialAngle)) + 0.5;
  213.  
  214. normals.push(radiusTop * x);
  215. normals.push(1.0);
  216. normals.push(radiusTop * z);
  217.  
  218. uvs.push(tu);
  219. uvs.push(tv);
  220.  
  221. positions.push((radiusTop * x) + centerX);
  222. positions.push((heightHalf) + centerY);
  223. positions.push((radiusTop * z) + centerZ);
  224. }
  225.  
  226. for (i = 0; i < radialSegments; i++) {
  227. center = startIndex;
  228. first = startIndex + 1 + i;
  229.  
  230. indices.push(first);
  231. indices.push(first + 1);
  232. indices.push(center);
  233. }
  234. }
  235.  
  236. // create bottom cap
  237. if (!openEnded && radiusBottom > 0) {
  238.  
  239. startIndex = (positions.length / 3);
  240.  
  241. // top center
  242. normals.push(0.0);
  243. normals.push(-1.0);
  244. normals.push(0.0);
  245.  
  246. uvs.push(0.5);
  247. uvs.push(0.5);
  248.  
  249. positions.push(0 + centerX);
  250. positions.push(0 - heightHalf + centerY);
  251. positions.push(0 + centerZ);
  252.  
  253. // top triangle fan
  254. for (i = 0; i <= radialSegments; i++) {
  255.  
  256. x = Math.sin(i * radialAngle);
  257. z = Math.cos(i * radialAngle);
  258.  
  259. tu = (0.5 * Math.sin(i * radialAngle)) + 0.5;
  260. tv = (0.5 * Math.cos(i * radialAngle)) + 0.5;
  261.  
  262. normals.push(radiusBottom * x);
  263. normals.push(-1.0);
  264. normals.push(radiusBottom * z);
  265.  
  266. uvs.push(tu);
  267. uvs.push(tv);
  268.  
  269. positions.push((radiusBottom * x) + centerX);
  270. positions.push((0 - heightHalf) + centerY);
  271. positions.push((radiusBottom * z) + centerZ);
  272. }
  273.  
  274. for (i = 0; i < radialSegments; i++) {
  275.  
  276. center = startIndex;
  277. first = startIndex + 1 + i;
  278.  
  279. indices.push(center);
  280. indices.push(first + 1);
  281. indices.push(first);
  282. }
  283. }
  284.  
  285. super.init(utils.apply(cfg, {
  286. positions: positions,
  287. normals: normals,
  288. uv: uvs,
  289. indices: indices
  290. }));
  291. }
  292. }
  293.  
  294. componentClasses[type] = CylinderGeometry;
  295.  
  296. export{CylinderGeometry};
  297.