智慧水务管理系统 - 精河县供水工程综合管理平台

PrimitiveLoadPlan.js 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. import Check from "../Core/Check.js";
  2. import ComponentDatatype from "../Core/ComponentDatatype.js";
  3. import defined from "../Core/defined.js";
  4. import IndexDatatype from "../Core/IndexDatatype.js";
  5. import Buffer from "../Renderer/Buffer.js";
  6. import BufferUsage from "../Renderer/BufferUsage.js";
  7. import AttributeType from "./AttributeType.js";
  8. import ModelComponents from "./ModelComponents.js";
  9. import PrimitiveOutlineGenerator from "./Model/PrimitiveOutlineGenerator.js";
  10. /**
  11. * Simple struct for tracking whether an attribute will be loaded as a buffer
  12. * or typed array after post-processing.
  13. *
  14. * @alias PrimitiveLoadPlan.AttributeLoadPlan
  15. * @constructor
  16. *
  17. * @param {ModelComponents.Attribute} attribute The attribute to be updated
  18. *
  19. * @private
  20. */
  21. function AttributeLoadPlan(attribute) {
  22. //>>includeStart('debug', pragmas.debug);
  23. Check.typeOf.object("attribute", attribute);
  24. //>>includeEnd('debug');
  25. /**
  26. * The attribute to track.
  27. *
  28. * @type {ModelComponents.Attribute}
  29. * @readonly
  30. * @private
  31. */
  32. this.attribute = attribute;
  33. /**
  34. * Whether the attribute will be loaded as a GPU buffer by the time
  35. * {@link PrimitiveLoadPlan#postProcess} is finished.
  36. *
  37. * @type {boolean}
  38. * @private
  39. */
  40. this.loadBuffer = false;
  41. /**
  42. * Whether the attribute will be loaded as a packed typed array by the time
  43. * {@link PrimitiveLoadPlan#postProcess} is finished.
  44. *
  45. * @type {boolean}
  46. * @private
  47. */
  48. this.loadTypedArray = false;
  49. }
  50. /**
  51. * Simple struct for tracking whether an index buffer will be loaded as a buffer
  52. * or typed array after post-processing.
  53. *
  54. * @alias PrimitiveLoadPlan.IndicesLoadPlan
  55. * @constructor
  56. *
  57. * @param {ModelComponents.Indices} indices The indices to be updated
  58. *
  59. * @private
  60. */
  61. function IndicesLoadPlan(indices) {
  62. //>>includeStart('debug', pragmas.debug);
  63. Check.typeOf.object("indices", indices);
  64. //>>includeEnd('debug');
  65. /**
  66. * The indices to track.
  67. *
  68. * @type {ModelComponents.Indices}
  69. * @readonly
  70. * @private
  71. */
  72. this.indices = indices;
  73. /**
  74. * Whether the indices will be loaded as a GPU buffer by the time
  75. * {@link PrimitiveLoadPlan#postProcess} is finished.
  76. *
  77. * @type {boolean}
  78. * @private
  79. */
  80. this.loadBuffer = false;
  81. /**
  82. * Whether the indices will be loaded as a typed array copy of the GPU
  83. * buffer by the time {@link PrimitiveLoadPlan#postProcess} is finished.
  84. *
  85. * @type {boolean}
  86. * @private
  87. */
  88. this.loadTypedArray = false;
  89. }
  90. /**
  91. * Primitives may need post-processing steps after their attributes and indices
  92. * have loaded, such as generating outlines for the CESIUM_primitive_outline glTF
  93. * extension. This object tracks what indices and attributes need to be
  94. * post-processed.
  95. *
  96. * @alias PrimitiveLoadPlan
  97. * @constructor
  98. *
  99. * @param {ModelComponents.Primitive} primitive The primitive to track
  100. *
  101. * @private
  102. */
  103. function PrimitiveLoadPlan(primitive) {
  104. //>>includeStart('debug', pragmas.debug);
  105. Check.typeOf.object("primitive", primitive);
  106. //>>includeEnd('debug');
  107. /**
  108. * The primitive to track.
  109. *
  110. * @type {ModelComponents.Primitive}
  111. * @readonly
  112. * @private
  113. */
  114. this.primitive = primitive;
  115. /**
  116. * A flat list of attributes that need to be post-processed. This includes
  117. * both regular attributes and morph target attributes.
  118. *
  119. * @type {PrimitiveLoadPlan.AttributeLoadPlan[]}
  120. * @private
  121. */
  122. this.attributePlans = [];
  123. /**
  124. * Information about the triangle indices that need to be post-processed,
  125. * if they exist.
  126. *
  127. * @type {PrimitiveLoadPlan.IndicesLoadPlan}
  128. * @private
  129. */
  130. this.indicesPlan = undefined;
  131. /**
  132. * Set this true to indicate that the primitive has the
  133. * CESIUM_primitive_outline extension and needs to be post-processed
  134. *
  135. * @type {boolean}
  136. * @private
  137. */
  138. this.needsOutlines = false;
  139. /**
  140. * The outline edge indices from the CESIUM_primitive_outline extension
  141. *
  142. * @type {number[]}
  143. * @private
  144. */
  145. this.outlineIndices = undefined;
  146. /**
  147. * Set this true to indicate that the primitive has the
  148. * KHR_gaussian_splatting and KHR_gaussian_splatting_compression_spz_2 extension and needs to be post-processed
  149. *
  150. * @type {boolean}
  151. * @private
  152. */
  153. this.needsGaussianSplats = false;
  154. }
  155. /**
  156. * Apply post-processing steps that may modify geometry such as generating
  157. * outline coordinates. If no post-processing steps are needed, this function
  158. * is a no-op.
  159. *
  160. * @param {Context} context The context for generating buffers on the GPU
  161. */
  162. PrimitiveLoadPlan.prototype.postProcess = function (context) {
  163. // Handle CESIUM_primitive_outline. This modifies indices and attributes and
  164. // also generates a new attribute for the outline coordinates. These steps
  165. // are synchronous.
  166. if (this.needsOutlines) {
  167. generateOutlines(this);
  168. generateBuffers(this, context);
  169. }
  170. if (this.needsGaussianSplats) {
  171. setupGaussianSplatBuffers(this, context);
  172. }
  173. };
  174. function generateOutlines(loadPlan) {
  175. const primitive = loadPlan.primitive;
  176. const indices = primitive.indices;
  177. const vertexCount = primitive.attributes[0].count;
  178. const generator = new PrimitiveOutlineGenerator({
  179. triangleIndices: indices.typedArray,
  180. outlineIndices: loadPlan.outlineIndices,
  181. originalVertexCount: vertexCount,
  182. });
  183. // The generator modifies/adds indices. In some uncommon cases it may have
  184. // to upgrade to 16- or 32-bit indices so the datatype may change.
  185. indices.typedArray = generator.updatedTriangleIndices;
  186. indices.indexDatatype = IndexDatatype.fromTypedArray(indices.typedArray);
  187. // The outline generator creates a new attribute for the outline coordinates
  188. // that are used with a lookup texture.
  189. const outlineCoordinates = makeOutlineCoordinatesAttribute(
  190. generator.outlineCoordinates,
  191. );
  192. const outlineCoordinatesPlan = new AttributeLoadPlan(outlineCoordinates);
  193. outlineCoordinatesPlan.loadBuffer = true;
  194. outlineCoordinatesPlan.loadTypedArray = false;
  195. loadPlan.attributePlans.push(outlineCoordinatesPlan);
  196. primitive.outlineCoordinates = outlineCoordinatesPlan.attribute;
  197. // Some vertices may be copied due to the addition of the new attribute
  198. // which may have multiple values at a vertex depending on the face
  199. const attributePlans = loadPlan.attributePlans;
  200. const attributesLength = loadPlan.attributePlans.length;
  201. for (let i = 0; i < attributesLength; i++) {
  202. const attribute = attributePlans[i].attribute;
  203. attribute.typedArray = generator.updateAttribute(attribute.typedArray);
  204. }
  205. }
  206. function makeOutlineCoordinatesAttribute(outlineCoordinatesTypedArray) {
  207. const attribute = new ModelComponents.Attribute();
  208. attribute.name = "_OUTLINE_COORDINATES";
  209. attribute.typedArray = outlineCoordinatesTypedArray;
  210. attribute.componentDatatype = ComponentDatatype.FLOAT;
  211. attribute.type = AttributeType.VEC3;
  212. attribute.normalized = false;
  213. attribute.count = outlineCoordinatesTypedArray.length / 3;
  214. return attribute;
  215. }
  216. function setupGaussianSplatBuffers(loadPlan, context) {
  217. const attributePlans = loadPlan.attributePlans;
  218. const attrLen = attributePlans.length;
  219. for (let i = 0; i < attrLen; i++) {
  220. const attributePlan = attributePlans[i];
  221. attributePlan.loadBuffer = false;
  222. attributePlan.loadTypedArray = true;
  223. }
  224. }
  225. function generateBuffers(loadPlan, context) {
  226. generateAttributeBuffers(loadPlan.attributePlans, context);
  227. if (defined(loadPlan.indicesPlan)) {
  228. generateIndexBuffers(loadPlan.indicesPlan, context);
  229. }
  230. }
  231. function generateAttributeBuffers(attributePlans, context) {
  232. const attributesLength = attributePlans.length;
  233. for (let i = 0; i < attributesLength; i++) {
  234. const attributePlan = attributePlans[i];
  235. const attribute = attributePlan.attribute;
  236. const typedArray = attribute.typedArray;
  237. if (attributePlan.loadBuffer) {
  238. const buffer = Buffer.createVertexBuffer({
  239. typedArray: typedArray,
  240. context: context,
  241. usage: BufferUsage.STATIC_DRAW,
  242. });
  243. buffer.vertexArrayDestroyable = false;
  244. attribute.buffer = buffer;
  245. }
  246. if (!attributePlan.loadTypedArray) {
  247. attribute.typedArray = undefined;
  248. }
  249. }
  250. }
  251. function generateIndexBuffers(indicesPlan, context) {
  252. const indices = indicesPlan.indices;
  253. if (indicesPlan.loadBuffer) {
  254. const buffer = Buffer.createIndexBuffer({
  255. typedArray: indices.typedArray,
  256. context: context,
  257. usage: BufferUsage.STATIC_DRAW,
  258. indexDatatype: indices.indexDatatype,
  259. });
  260. indices.buffer = buffer;
  261. buffer.vertexArrayDestroyable = false;
  262. }
  263. if (!indicesPlan.loadTypedArray) {
  264. indices.typedArray = undefined;
  265. }
  266. }
  267. PrimitiveLoadPlan.AttributeLoadPlan = AttributeLoadPlan;
  268. PrimitiveLoadPlan.IndicesLoadPlan = IndicesLoadPlan;
  269. export default PrimitiveLoadPlan;