EllipsoidGeometry-6d9d226b.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /**
  2. * Cesium - https://github.com/CesiumGS/cesium
  3. *
  4. * Copyright 2011-2020 Cesium Contributors
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Columbus View (Pat. Pend.)
  19. *
  20. * Portions licensed separately.
  21. * See https://github.com/CesiumGS/cesium/blob/master/LICENSE.md for full licensing details.
  22. */
  23. define(['exports', './when-8d13db60', './Check-70bec281', './Math-61ede240', './Cartographic-fe4be337', './arrayFill-9766fb2e', './Cartesian2-85064f09', './BoundingSphere-8f8a682c', './ComponentDatatype-5862616f', './GeometryAttribute-ed9d707f', './PrimitiveType-97893bc7', './GeometryAttributes-aacecde6', './GeometryOffsetAttribute-999fc023', './VertexFormat-fe4db402', './IndexDatatype-9435b55f'], function (exports, when, Check, _Math, Cartographic, arrayFill, Cartesian2, BoundingSphere, ComponentDatatype, GeometryAttribute, PrimitiveType, GeometryAttributes, GeometryOffsetAttribute, VertexFormat, IndexDatatype) { 'use strict';
  24. var scratchPosition = new Cartographic.Cartesian3();
  25. var scratchNormal = new Cartographic.Cartesian3();
  26. var scratchTangent = new Cartographic.Cartesian3();
  27. var scratchBitangent = new Cartographic.Cartesian3();
  28. var scratchNormalST = new Cartographic.Cartesian3();
  29. var defaultRadii = new Cartographic.Cartesian3(1.0, 1.0, 1.0);
  30. var cos = Math.cos;
  31. var sin = Math.sin;
  32. /**
  33. * A description of an ellipsoid centered at the origin.
  34. *
  35. * @alias EllipsoidGeometry
  36. * @constructor
  37. *
  38. * @param {Object} [options] Object with the following properties:
  39. * @param {Cartesian3} [options.radii=Cartesian3(1.0, 1.0, 1.0)] The radii of the ellipsoid in the x, y, and z directions.
  40. * @param {Cartesian3} [options.innerRadii=options.radii] The inner radii of the ellipsoid in the x, y, and z directions.
  41. * @param {Number} [options.minimumClock=0.0] The minimum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.
  42. * @param {Number} [options.maximumClock=2*PI] The maximum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.
  43. * @param {Number} [options.minimumCone=0.0] The minimum angle measured from the positive z-axis and toward the negative z-axis.
  44. * @param {Number} [options.maximumCone=PI] The maximum angle measured from the positive z-axis and toward the negative z-axis.
  45. * @param {Number} [options.stackPartitions=64] The number of times to partition the ellipsoid into stacks.
  46. * @param {Number} [options.slicePartitions=64] The number of times to partition the ellipsoid into radial slices.
  47. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  48. *
  49. * @exception {DeveloperError} options.slicePartitions cannot be less than three.
  50. * @exception {DeveloperError} options.stackPartitions cannot be less than three.
  51. *
  52. * @see EllipsoidGeometry#createGeometry
  53. *
  54. * @example
  55. * var ellipsoid = new Cesium.EllipsoidGeometry({
  56. * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,
  57. * radii : new Cesium.Cartesian3(1000000.0, 500000.0, 500000.0)
  58. * });
  59. * var geometry = Cesium.EllipsoidGeometry.createGeometry(ellipsoid);
  60. */
  61. function EllipsoidGeometry(options) {
  62. options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
  63. var radii = when.defaultValue(options.radii, defaultRadii);
  64. var innerRadii = when.defaultValue(options.innerRadii, radii);
  65. var minimumClock = when.defaultValue(options.minimumClock, 0.0);
  66. var maximumClock = when.defaultValue(options.maximumClock, _Math.CesiumMath.TWO_PI);
  67. var minimumCone = when.defaultValue(options.minimumCone, 0.0);
  68. var maximumCone = when.defaultValue(options.maximumCone, _Math.CesiumMath.PI);
  69. var stackPartitions = Math.round(when.defaultValue(options.stackPartitions, 64));
  70. var slicePartitions = Math.round(when.defaultValue(options.slicePartitions, 64));
  71. var vertexFormat = when.defaultValue(options.vertexFormat, VertexFormat.VertexFormat.DEFAULT);
  72. //>>includeStart('debug', pragmas.debug);
  73. if (slicePartitions < 3) {
  74. throw new Check.DeveloperError('options.slicePartitions cannot be less than three.');
  75. }
  76. if (stackPartitions < 3) {
  77. throw new Check.DeveloperError('options.stackPartitions cannot be less than three.');
  78. }
  79. //>>includeEnd('debug');
  80. this._radii = Cartographic.Cartesian3.clone(radii);
  81. this._innerRadii = Cartographic.Cartesian3.clone(innerRadii);
  82. this._minimumClock = minimumClock;
  83. this._maximumClock = maximumClock;
  84. this._minimumCone = minimumCone;
  85. this._maximumCone = maximumCone;
  86. this._stackPartitions = stackPartitions;
  87. this._slicePartitions = slicePartitions;
  88. this._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat);
  89. this._offsetAttribute = options.offsetAttribute;
  90. this._workerName = 'createEllipsoidGeometry';
  91. }
  92. /**
  93. * The number of elements used to pack the object into an array.
  94. * @type {Number}
  95. */
  96. EllipsoidGeometry.packedLength = 2 * (Cartographic.Cartesian3.packedLength) + VertexFormat.VertexFormat.packedLength + 7;
  97. /**
  98. * Stores the provided instance into the provided array.
  99. *
  100. * @param {EllipsoidGeometry} value The value to pack.
  101. * @param {Number[]} array The array to pack into.
  102. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  103. *
  104. * @returns {Number[]} The array that was packed into
  105. */
  106. EllipsoidGeometry.pack = function(value, array, startingIndex) {
  107. //>>includeStart('debug', pragmas.debug);
  108. if (!when.defined(value)) {
  109. throw new Check.DeveloperError('value is required');
  110. }
  111. if (!when.defined(array)) {
  112. throw new Check.DeveloperError('array is required');
  113. }
  114. //>>includeEnd('debug');
  115. startingIndex = when.defaultValue(startingIndex, 0);
  116. Cartographic.Cartesian3.pack(value._radii, array, startingIndex);
  117. startingIndex += Cartographic.Cartesian3.packedLength;
  118. Cartographic.Cartesian3.pack(value._innerRadii, array, startingIndex);
  119. startingIndex += Cartographic.Cartesian3.packedLength;
  120. VertexFormat.VertexFormat.pack(value._vertexFormat, array, startingIndex);
  121. startingIndex += VertexFormat.VertexFormat.packedLength;
  122. array[startingIndex++] = value._minimumClock;
  123. array[startingIndex++] = value._maximumClock;
  124. array[startingIndex++] = value._minimumCone;
  125. array[startingIndex++] = value._maximumCone;
  126. array[startingIndex++] = value._stackPartitions;
  127. array[startingIndex++] = value._slicePartitions;
  128. array[startingIndex] = when.defaultValue(value._offsetAttribute, -1);
  129. return array;
  130. };
  131. var scratchRadii = new Cartographic.Cartesian3();
  132. var scratchInnerRadii = new Cartographic.Cartesian3();
  133. var scratchVertexFormat = new VertexFormat.VertexFormat();
  134. var scratchOptions = {
  135. radii : scratchRadii,
  136. innerRadii : scratchInnerRadii,
  137. vertexFormat : scratchVertexFormat,
  138. minimumClock : undefined,
  139. maximumClock : undefined,
  140. minimumCone : undefined,
  141. maximumCone : undefined,
  142. stackPartitions : undefined,
  143. slicePartitions : undefined,
  144. offsetAttribute : undefined
  145. };
  146. /**
  147. * Retrieves an instance from a packed array.
  148. *
  149. * @param {Number[]} array The packed array.
  150. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  151. * @param {EllipsoidGeometry} [result] The object into which to store the result.
  152. * @returns {EllipsoidGeometry} The modified result parameter or a new EllipsoidGeometry instance if one was not provided.
  153. */
  154. EllipsoidGeometry.unpack = function(array, startingIndex, result) {
  155. //>>includeStart('debug', pragmas.debug);
  156. if (!when.defined(array)) {
  157. throw new Check.DeveloperError('array is required');
  158. }
  159. //>>includeEnd('debug');
  160. startingIndex = when.defaultValue(startingIndex, 0);
  161. var radii = Cartographic.Cartesian3.unpack(array, startingIndex, scratchRadii);
  162. startingIndex += Cartographic.Cartesian3.packedLength;
  163. var innerRadii = Cartographic.Cartesian3.unpack(array, startingIndex, scratchInnerRadii);
  164. startingIndex += Cartographic.Cartesian3.packedLength;
  165. var vertexFormat = VertexFormat.VertexFormat.unpack(array, startingIndex, scratchVertexFormat);
  166. startingIndex += VertexFormat.VertexFormat.packedLength;
  167. var minimumClock = array[startingIndex++];
  168. var maximumClock = array[startingIndex++];
  169. var minimumCone = array[startingIndex++];
  170. var maximumCone = array[startingIndex++];
  171. var stackPartitions = array[startingIndex++];
  172. var slicePartitions = array[startingIndex++];
  173. var offsetAttribute = array[startingIndex];
  174. if (!when.defined(result)) {
  175. scratchOptions.minimumClock = minimumClock;
  176. scratchOptions.maximumClock = maximumClock;
  177. scratchOptions.minimumCone = minimumCone;
  178. scratchOptions.maximumCone = maximumCone;
  179. scratchOptions.stackPartitions = stackPartitions;
  180. scratchOptions.slicePartitions = slicePartitions;
  181. scratchOptions.offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
  182. return new EllipsoidGeometry(scratchOptions);
  183. }
  184. result._radii = Cartographic.Cartesian3.clone(radii, result._radii);
  185. result._innerRadii = Cartographic.Cartesian3.clone(innerRadii, result._innerRadii);
  186. result._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat, result._vertexFormat);
  187. result._minimumClock = minimumClock;
  188. result._maximumClock = maximumClock;
  189. result._minimumCone = minimumCone;
  190. result._maximumCone = maximumCone;
  191. result._stackPartitions = stackPartitions;
  192. result._slicePartitions = slicePartitions;
  193. result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
  194. return result;
  195. };
  196. /**
  197. * Computes the geometric representation of an ellipsoid, including its vertices, indices, and a bounding sphere.
  198. *
  199. * @param {EllipsoidGeometry} ellipsoidGeometry A description of the ellipsoid.
  200. * @returns {Geometry|undefined} The computed vertices and indices.
  201. */
  202. EllipsoidGeometry.createGeometry = function(ellipsoidGeometry) {
  203. var radii = ellipsoidGeometry._radii;
  204. if ((radii.x <= 0) || (radii.y <= 0) || (radii.z <= 0)) {
  205. return;
  206. }
  207. var innerRadii = ellipsoidGeometry._innerRadii;
  208. if ((innerRadii.x <= 0) || (innerRadii.y <= 0) || innerRadii.z <= 0) {
  209. return;
  210. }
  211. var minimumClock = ellipsoidGeometry._minimumClock;
  212. var maximumClock = ellipsoidGeometry._maximumClock;
  213. var minimumCone = ellipsoidGeometry._minimumCone;
  214. var maximumCone = ellipsoidGeometry._maximumCone;
  215. var vertexFormat = ellipsoidGeometry._vertexFormat;
  216. // Add an extra slice and stack so that the number of partitions is the
  217. // number of surfaces rather than the number of joints
  218. var slicePartitions = ellipsoidGeometry._slicePartitions + 1;
  219. var stackPartitions = ellipsoidGeometry._stackPartitions + 1;
  220. slicePartitions = Math.round(slicePartitions * Math.abs(maximumClock - minimumClock) / _Math.CesiumMath.TWO_PI);
  221. stackPartitions = Math.round(stackPartitions * Math.abs(maximumCone - minimumCone) / _Math.CesiumMath.PI);
  222. if (slicePartitions < 2) {
  223. slicePartitions = 2;
  224. }
  225. if (stackPartitions < 2) {
  226. stackPartitions = 2;
  227. }
  228. var i;
  229. var j;
  230. var index = 0;
  231. // Create arrays for theta and phi. Duplicate first and last angle to
  232. // allow different normals at the intersections.
  233. var phis = [minimumCone];
  234. var thetas = [minimumClock];
  235. for (i = 0; i < stackPartitions; i++) {
  236. phis.push(minimumCone + i * (maximumCone - minimumCone) / (stackPartitions - 1));
  237. }
  238. phis.push(maximumCone);
  239. for (j = 0; j < slicePartitions; j++) {
  240. thetas.push(minimumClock + j * (maximumClock - minimumClock) / (slicePartitions - 1));
  241. }
  242. thetas.push(maximumClock);
  243. var numPhis = phis.length;
  244. var numThetas = thetas.length;
  245. // Allow for extra indices if there is an inner surface and if we need
  246. // to close the sides if the clock range is not a full circle
  247. var extraIndices = 0;
  248. var vertexMultiplier = 1.0;
  249. var hasInnerSurface = ((innerRadii.x !== radii.x) || (innerRadii.y !== radii.y) || innerRadii.z !== radii.z);
  250. var isTopOpen = false;
  251. var isBotOpen = false;
  252. var isClockOpen = false;
  253. if (hasInnerSurface) {
  254. vertexMultiplier = 2.0;
  255. if (minimumCone > 0.0) {
  256. isTopOpen = true;
  257. extraIndices += (slicePartitions - 1);
  258. }
  259. if (maximumCone < Math.PI) {
  260. isBotOpen = true;
  261. extraIndices += (slicePartitions - 1);
  262. }
  263. if ((maximumClock - minimumClock) % _Math.CesiumMath.TWO_PI) {
  264. isClockOpen = true;
  265. extraIndices += ((stackPartitions - 1) * 2) + 1;
  266. } else {
  267. extraIndices += 1;
  268. }
  269. }
  270. var vertexCount = numThetas * numPhis * vertexMultiplier;
  271. var positions = new Float64Array(vertexCount * 3);
  272. var isInner = arrayFill.arrayFill(new Array(vertexCount), false);
  273. var negateNormal = arrayFill.arrayFill(new Array(vertexCount), false);
  274. // Multiply by 6 because there are two triangles per sector
  275. var indexCount = slicePartitions * stackPartitions * vertexMultiplier;
  276. var numIndices = 6 * (indexCount + extraIndices + 1 - (slicePartitions + stackPartitions) * vertexMultiplier);
  277. var indices = IndexDatatype.IndexDatatype.createTypedArray(indexCount, numIndices);
  278. var normals = (vertexFormat.normal) ? new Float32Array(vertexCount * 3) : undefined;
  279. var tangents = (vertexFormat.tangent) ? new Float32Array(vertexCount * 3) : undefined;
  280. var bitangents = (vertexFormat.bitangent) ? new Float32Array(vertexCount * 3) : undefined;
  281. var st = (vertexFormat.st) ? new Float32Array(vertexCount * 2) : undefined;
  282. // Calculate sin/cos phi
  283. var sinPhi = new Array(numPhis);
  284. var cosPhi = new Array(numPhis);
  285. for (i = 0; i < numPhis; i++) {
  286. sinPhi[i] = sin(phis[i]);
  287. cosPhi[i] = cos(phis[i]);
  288. }
  289. // Calculate sin/cos theta
  290. var sinTheta = new Array(numThetas);
  291. var cosTheta = new Array(numThetas);
  292. for (j = 0; j < numThetas; j++) {
  293. cosTheta[j] = cos(thetas[j]);
  294. sinTheta[j] = sin(thetas[j]);
  295. }
  296. // Create outer surface
  297. for (i = 0; i < numPhis; i++) {
  298. for (j = 0; j < numThetas; j++) {
  299. positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
  300. positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
  301. positions[index++] = radii.z * cosPhi[i];
  302. }
  303. }
  304. // Create inner surface
  305. var vertexIndex = vertexCount / 2.0;
  306. if (hasInnerSurface) {
  307. for (i = 0; i < numPhis; i++) {
  308. for (j = 0; j < numThetas; j++) {
  309. positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
  310. positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
  311. positions[index++] = innerRadii.z * cosPhi[i];
  312. // Keep track of which vertices are the inner and which ones
  313. // need the normal to be negated
  314. isInner[vertexIndex] = true;
  315. if (i > 0 && i !== (numPhis - 1) && j !== 0 && j !== (numThetas - 1)) {
  316. negateNormal[vertexIndex] = true;
  317. }
  318. vertexIndex++;
  319. }
  320. }
  321. }
  322. // Create indices for outer surface
  323. index = 0;
  324. var topOffset;
  325. var bottomOffset;
  326. for (i = 1; i < (numPhis - 2); i++) {
  327. topOffset = i * numThetas;
  328. bottomOffset = (i + 1) * numThetas;
  329. for (j = 1; j < numThetas - 2; j++) {
  330. indices[index++] = bottomOffset + j;
  331. indices[index++] = bottomOffset + j + 1;
  332. indices[index++] = topOffset + j + 1;
  333. indices[index++] = bottomOffset + j;
  334. indices[index++] = topOffset + j + 1;
  335. indices[index++] = topOffset + j;
  336. }
  337. }
  338. // Create indices for inner surface
  339. if (hasInnerSurface) {
  340. var offset = numPhis * numThetas;
  341. for (i = 1; i < (numPhis - 2); i++) {
  342. topOffset = offset + i * numThetas;
  343. bottomOffset = offset + (i + 1) * numThetas;
  344. for (j = 1; j < numThetas - 2; j++) {
  345. indices[index++] = bottomOffset + j;
  346. indices[index++] = topOffset + j;
  347. indices[index++] = topOffset + j + 1;
  348. indices[index++] = bottomOffset + j;
  349. indices[index++] = topOffset + j + 1;
  350. indices[index++] = bottomOffset + j + 1;
  351. }
  352. }
  353. }
  354. var outerOffset;
  355. var innerOffset;
  356. if (hasInnerSurface) {
  357. if (isTopOpen) {
  358. // Connect the top of the inner surface to the top of the outer surface
  359. innerOffset = numPhis * numThetas;
  360. for (i = 1; i < numThetas - 2; i++) {
  361. indices[index++] = i;
  362. indices[index++] = i + 1;
  363. indices[index++] = innerOffset + i + 1;
  364. indices[index++] = i;
  365. indices[index++] = innerOffset + i + 1;
  366. indices[index++] = innerOffset + i;
  367. }
  368. }
  369. if (isBotOpen) {
  370. // Connect the bottom of the inner surface to the bottom of the outer surface
  371. outerOffset = numPhis * numThetas - numThetas;
  372. innerOffset = numPhis * numThetas * vertexMultiplier - numThetas;
  373. for (i = 1; i < numThetas - 2; i++) {
  374. indices[index++] = outerOffset + i + 1;
  375. indices[index++] = outerOffset + i;
  376. indices[index++] = innerOffset + i;
  377. indices[index++] = outerOffset + i + 1;
  378. indices[index++] = innerOffset + i;
  379. indices[index++] = innerOffset + i + 1;
  380. }
  381. }
  382. }
  383. // Connect the edges if clock is not closed
  384. if (isClockOpen) {
  385. for (i = 1; i < numPhis - 2; i++) {
  386. innerOffset = numThetas * numPhis + (numThetas * i);
  387. outerOffset = numThetas * i;
  388. indices[index++] = innerOffset;
  389. indices[index++] = outerOffset + numThetas;
  390. indices[index++] = outerOffset;
  391. indices[index++] = innerOffset;
  392. indices[index++] = innerOffset + numThetas;
  393. indices[index++] = outerOffset + numThetas;
  394. }
  395. for (i = 1; i < numPhis - 2; i++) {
  396. innerOffset = numThetas * numPhis + (numThetas * (i + 1)) - 1;
  397. outerOffset = numThetas * (i + 1) - 1;
  398. indices[index++] = outerOffset + numThetas;
  399. indices[index++] = innerOffset;
  400. indices[index++] = outerOffset;
  401. indices[index++] = outerOffset + numThetas;
  402. indices[index++] = innerOffset + numThetas;
  403. indices[index++] = innerOffset;
  404. }
  405. }
  406. var attributes = new GeometryAttributes.GeometryAttributes();
  407. if (vertexFormat.position) {
  408. attributes.position = new GeometryAttribute.GeometryAttribute({
  409. componentDatatype : ComponentDatatype.ComponentDatatype.DOUBLE,
  410. componentsPerAttribute : 3,
  411. values : positions
  412. });
  413. }
  414. var stIndex = 0;
  415. var normalIndex = 0;
  416. var tangentIndex = 0;
  417. var bitangentIndex = 0;
  418. var vertexCountHalf = vertexCount / 2.0;
  419. var ellipsoid;
  420. var ellipsoidOuter = Cartesian2.Ellipsoid.fromCartesian3(radii);
  421. var ellipsoidInner = Cartesian2.Ellipsoid.fromCartesian3(innerRadii);
  422. if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
  423. for (i = 0; i < vertexCount; i++) {
  424. ellipsoid = (isInner[i]) ? ellipsoidInner : ellipsoidOuter;
  425. var position = Cartographic.Cartesian3.fromArray(positions, i * 3, scratchPosition);
  426. var normal = ellipsoid.geodeticSurfaceNormal(position, scratchNormal);
  427. if (negateNormal[i]) {
  428. Cartographic.Cartesian3.negate(normal, normal);
  429. }
  430. if (vertexFormat.st) {
  431. var normalST = Cartesian2.Cartesian2.negate(normal, scratchNormalST);
  432. st[stIndex++] = (Math.atan2(normalST.y, normalST.x) / _Math.CesiumMath.TWO_PI) + 0.5;
  433. st[stIndex++] = (Math.asin(normal.z) / Math.PI) + 0.5;
  434. }
  435. if (vertexFormat.normal) {
  436. normals[normalIndex++] = normal.x;
  437. normals[normalIndex++] = normal.y;
  438. normals[normalIndex++] = normal.z;
  439. }
  440. if (vertexFormat.tangent || vertexFormat.bitangent) {
  441. var tangent = scratchTangent;
  442. // Use UNIT_X for the poles
  443. var tangetOffset = 0;
  444. var unit;
  445. if (isInner[i]) {
  446. tangetOffset = vertexCountHalf;
  447. }
  448. if ((!isTopOpen && (i >= tangetOffset && i < (tangetOffset + numThetas * 2)))) {
  449. unit = Cartographic.Cartesian3.UNIT_X;
  450. } else {
  451. unit = Cartographic.Cartesian3.UNIT_Z;
  452. }
  453. Cartographic.Cartesian3.cross(unit, normal, tangent);
  454. Cartographic.Cartesian3.normalize(tangent, tangent);
  455. if (vertexFormat.tangent) {
  456. tangents[tangentIndex++] = tangent.x;
  457. tangents[tangentIndex++] = tangent.y;
  458. tangents[tangentIndex++] = tangent.z;
  459. }
  460. if (vertexFormat.bitangent) {
  461. var bitangent = Cartographic.Cartesian3.cross(normal, tangent, scratchBitangent);
  462. Cartographic.Cartesian3.normalize(bitangent, bitangent);
  463. bitangents[bitangentIndex++] = bitangent.x;
  464. bitangents[bitangentIndex++] = bitangent.y;
  465. bitangents[bitangentIndex++] = bitangent.z;
  466. }
  467. }
  468. }
  469. if (vertexFormat.st) {
  470. attributes.st = new GeometryAttribute.GeometryAttribute({
  471. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  472. componentsPerAttribute : 2,
  473. values : st
  474. });
  475. }
  476. if (vertexFormat.normal) {
  477. attributes.normal = new GeometryAttribute.GeometryAttribute({
  478. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  479. componentsPerAttribute : 3,
  480. values : normals
  481. });
  482. }
  483. if (vertexFormat.tangent) {
  484. attributes.tangent = new GeometryAttribute.GeometryAttribute({
  485. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  486. componentsPerAttribute : 3,
  487. values : tangents
  488. });
  489. }
  490. if (vertexFormat.bitangent) {
  491. attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  492. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  493. componentsPerAttribute : 3,
  494. values : bitangents
  495. });
  496. }
  497. }
  498. if (when.defined(ellipsoidGeometry._offsetAttribute)) {
  499. var length = positions.length;
  500. var applyOffset = new Uint8Array(length / 3);
  501. var offsetValue = ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.NONE ? 0 : 1;
  502. arrayFill.arrayFill(applyOffset, offsetValue);
  503. attributes.applyOffset = new GeometryAttribute.GeometryAttribute({
  504. componentDatatype : ComponentDatatype.ComponentDatatype.UNSIGNED_BYTE,
  505. componentsPerAttribute : 1,
  506. values : applyOffset
  507. });
  508. }
  509. return new GeometryAttribute.Geometry({
  510. attributes : attributes,
  511. indices : indices,
  512. primitiveType : PrimitiveType.PrimitiveType.TRIANGLES,
  513. boundingSphere : BoundingSphere.BoundingSphere.fromEllipsoid(ellipsoidOuter),
  514. offsetAttribute : ellipsoidGeometry._offsetAttribute
  515. });
  516. };
  517. var unitEllipsoidGeometry;
  518. /**
  519. * Returns the geometric representation of a unit ellipsoid, including its vertices, indices, and a bounding sphere.
  520. * @returns {Geometry} The computed vertices and indices.
  521. *
  522. * @private
  523. */
  524. EllipsoidGeometry.getUnitEllipsoid = function() {
  525. if (!when.defined(unitEllipsoidGeometry)) {
  526. unitEllipsoidGeometry = EllipsoidGeometry.createGeometry((new EllipsoidGeometry({
  527. radii : new Cartographic.Cartesian3(1.0, 1.0, 1.0),
  528. vertexFormat : VertexFormat.VertexFormat.POSITION_ONLY
  529. })));
  530. }
  531. return unitEllipsoidGeometry;
  532. };
  533. exports.EllipsoidGeometry = EllipsoidGeometry;
  534. });