Reference Source

src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js

  1. import {ENTITY_FLAGS} from '../../../ENTITY_FLAGS.js';
  2. import {RENDER_PASSES} from '../../../RENDER_PASSES.js';
  3.  
  4. import {math} from "../../../../math/math.js";
  5. import {RenderState} from "../../../../webgl/RenderState.js";
  6. import {ArrayBuf} from "../../../../webgl/ArrayBuf.js";
  7. import {getRenderers} from "./renderers/VBOBatchingLinesRenderers.js";
  8. import {VBOBatchingLinesBuffer} from "./lib/VBOBatchingLinesBuffer.js";
  9. import {quantizePositions} from "../../../compression.js";
  10.  
  11. /**
  12. * @private
  13. */
  14. export class VBOBatchingLinesLayer {
  15.  
  16. /**
  17. * @param model
  18. * @param cfg
  19. * @param cfg.layerIndex
  20. * @param cfg.positionsDecodeMatrix
  21. * @param cfg.maxGeometryBatchSize
  22. * @param cfg.origin
  23. * @param cfg.scratchMemory
  24. */
  25. constructor(cfg) {
  26.  
  27. // console.info("Creating VBOBatchingLinesLayer");
  28.  
  29. /**
  30. * Index of this LinesBatchingLayer in {@link VBOSceneModel#_layerList}.
  31. * @type {Number}
  32. */
  33. this.layerIndex = cfg.layerIndex;
  34.  
  35. this._renderers = getRenderers(cfg.model.scene);
  36. this.model = cfg.model;
  37. this._buffer = new VBOBatchingLinesBuffer(cfg.maxGeometryBatchSize);
  38. this._scratchMemory = cfg.scratchMemory;
  39.  
  40. this._state = new RenderState({
  41. positionsBuf: null,
  42. offsetsBuf: null,
  43. colorsBuf: null,
  44. flagsBuf: null,
  45. indicesBuf: null,
  46. positionsDecodeMatrix: math.mat4(),
  47. origin: null
  48. });
  49.  
  50. // These counts are used to avoid unnecessary render passes
  51. this._numPortions = 0;
  52. this._numVisibleLayerPortions = 0;
  53. this._numTransparentLayerPortions = 0;
  54. this._numXRayedLayerPortions = 0;
  55. this._numSelectedLayerPortions = 0;
  56. this._numHighlightedLayerPortions = 0;
  57. this._numClippableLayerPortions = 0;
  58. this._numEdgesLayerPortions = 0;
  59. this._numPickableLayerPortions = 0;
  60. this._numCulledLayerPortions = 0;
  61.  
  62. this._modelAABB = math.collapseAABB3(); // Model-space AABB
  63. this._portions = [];
  64. this._meshes = [];
  65. this._numVerts = 0;
  66.  
  67. this._aabb = math.collapseAABB3();
  68. this.aabbDirty = true;
  69.  
  70. this._finalized = false;
  71.  
  72. if (cfg.positionsDecodeMatrix) {
  73. this._state.positionsDecodeMatrix.set(cfg.positionsDecodeMatrix);
  74. this._preCompressedPositionsExpected = true;
  75. } else {
  76. this._preCompressedPositionsExpected = false;
  77. }
  78.  
  79. if (cfg.origin) {
  80. this._state.origin = math.vec3(cfg.origin);
  81. }
  82.  
  83. /**
  84. * The type of primitives in this layer.
  85. */
  86. this.primitive = cfg.primitive;
  87. }
  88.  
  89. get aabb() {
  90. if (this.aabbDirty) {
  91. math.collapseAABB3(this._aabb);
  92. for (let i = 0, len = this._meshes.length; i < len; i++) {
  93. math.expandAABB3(this._aabb, this._meshes[i].aabb);
  94. }
  95. this.aabbDirty = false;
  96. }
  97. return this._aabb;
  98. }
  99.  
  100. /**
  101. * Tests if there is room for another portion in this LinesBatchingLayer.
  102. *
  103. * @param lenPositions Number of positions we'd like to create in the portion.
  104. * @param lenIndices Number of indices we'd like to create in this portion.
  105. * @returns {Boolean} True if OK to create another portion.
  106. */
  107. canCreatePortion(lenPositions, lenIndices) {
  108. if (this._finalized) {
  109. throw "Already finalized";
  110. }
  111. return ((this._buffer.positions.length + lenPositions) < (this._buffer.maxVerts * 3) && (this._buffer.indices.length + lenIndices) < (this._buffer.maxIndices));
  112. }
  113.  
  114. /**
  115. * Creates a new portion within this LinesBatchingLayer, returns the new portion ID.
  116. *
  117. * Gives the portion the specified geometry, color and matrix.
  118. *
  119. * @param mesh The SceneModelMesh that owns the portion
  120. * @param cfg.positions Flat float Local-space positions array.
  121. * @param cfg.positionsCompressed Flat quantized positions array - decompressed with TrianglesBatchingLayer positionsDecodeMatrix
  122. * @param cfg.indices Flat int indices array.
  123. * @param cfg.color Quantized RGB color [0..255,0..255,0..255,0..255]
  124. * @param cfg.opacity Opacity [0..255]
  125. * @param [cfg.meshMatrix] Flat float 4x4 matrix
  126. * @param cfg.aabb Flat float AABB World-space AABB
  127. * @param cfg.pickColor Quantized pick color
  128. * @returns {number} Portion ID
  129. */
  130. createPortion(mesh, cfg) {
  131.  
  132. if (this._finalized) {
  133. throw "Already finalized";
  134. }
  135.  
  136. const positions = cfg.positions;
  137. const positionsCompressed = cfg.positionsCompressed;
  138. const indices = cfg.indices;
  139. const color = cfg.color;
  140. const opacity = cfg.opacity;
  141.  
  142. const buffer = this._buffer;
  143. const positionsIndex = buffer.positions.length;
  144. const vertsIndex = positionsIndex / 3;
  145.  
  146. let numVerts;
  147.  
  148. math.expandAABB3(this._modelAABB, cfg.aabb);
  149.  
  150. if (this._preCompressedPositionsExpected) {
  151. if (!positionsCompressed) {
  152. throw "positionsCompressed expected";
  153. }
  154. numVerts = positionsCompressed.length / 3;
  155. for (let i = 0, len = positionsCompressed.length; i < len; i++) {
  156. buffer.positions.push(positionsCompressed[i]);
  157. }
  158. } else {
  159. if (!positions) {
  160. throw "positions expected";
  161. }
  162. numVerts = positions.length / 3;
  163. for (let i = 0, len = positions.length; i < len; i++) {
  164. buffer.positions.push(positions[i]);
  165. }
  166. }
  167.  
  168. if (color) {
  169.  
  170. const r = color[0]; // Color is pre-quantized by VBOSceneModel
  171. const g = color[1];
  172. const b = color[2];
  173. const a = opacity;
  174.  
  175. for (let i = 0; i < numVerts; i++) {
  176. buffer.colors.push(r);
  177. buffer.colors.push(g);
  178. buffer.colors.push(b);
  179. buffer.colors.push(a);
  180. }
  181. }
  182.  
  183. if (indices) {
  184. for (let i = 0, len = indices.length; i < len; i++) {
  185. buffer.indices.push(indices[i] + vertsIndex);
  186. }
  187. }
  188.  
  189. if (this.model.scene.entityOffsetsEnabled) {
  190. for (let i = 0; i < numVerts; i++) {
  191. buffer.offsets.push(0);
  192. buffer.offsets.push(0);
  193. buffer.offsets.push(0);
  194. }
  195. }
  196.  
  197. const portionId = this._portions.length / 2;
  198.  
  199. this._portions.push(vertsIndex);
  200. this._portions.push(numVerts);
  201.  
  202. this._numPortions++;
  203. this.model.numPortions++;
  204.  
  205. this._numVerts += numVerts;
  206.  
  207. this._meshes.push(mesh);
  208.  
  209. return portionId;
  210. }
  211.  
  212. /**
  213. * Builds batch VBOs from appended geometries.
  214. * No more portions can then be created.
  215. */
  216. finalize() {
  217.  
  218. if (this._finalized) {
  219. return;
  220. }
  221.  
  222. const state = this._state;
  223. const gl = this.model.scene.canvas.gl;
  224. const buffer = this._buffer;
  225.  
  226. if (buffer.positions.length > 0) {
  227. if (this._preCompressedPositionsExpected) {
  228. const positions = new Uint16Array(buffer.positions);
  229. state.positionsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, positions, buffer.positions.length, 3, gl.STATIC_DRAW);
  230. } else {
  231. const positions = new Float32Array(buffer.positions);
  232. const quantizedPositions = quantizePositions(positions, this._modelAABB, state.positionsDecodeMatrix);
  233. state.positionsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, buffer.positions.length, 3, gl.STATIC_DRAW);
  234. }
  235. }
  236.  
  237. if (buffer.colors.length > 0) {
  238. const colors = new Uint8Array(buffer.colors);
  239. let normalized = false;
  240. state.colorsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, colors, buffer.colors.length, 4, gl.DYNAMIC_DRAW, normalized);
  241. }
  242.  
  243. if (buffer.colors.length > 0) { // Because we build flags arrays here, get their length from the colors array
  244. const flagsLength = buffer.colors.length / 4;
  245. const flags = new Float32Array(flagsLength);
  246. let notNormalized = false;
  247. state.flagsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, flags, flags.length, 1, gl.DYNAMIC_DRAW, notNormalized);
  248. }
  249.  
  250. if (this.model.scene.entityOffsetsEnabled) {
  251. if (buffer.offsets.length > 0) {
  252. const offsets = new Float32Array(buffer.offsets);
  253. state.offsetsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, offsets, buffer.offsets.length, 3, gl.DYNAMIC_DRAW);
  254. }
  255. }
  256.  
  257. if (buffer.indices.length > 0) {
  258. const indices = new Uint32Array(buffer.indices);
  259. state.indicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, buffer.indices.length, 1, gl.STATIC_DRAW);
  260. }
  261.  
  262. this._buffer = null;
  263. this._finalized = true;
  264. }
  265.  
  266. initFlags(portionId, flags, meshTransparent) {
  267. if (flags & ENTITY_FLAGS.VISIBLE) {
  268. this._numVisibleLayerPortions++;
  269. this.model.numVisibleLayerPortions++;
  270. }
  271. if (flags & ENTITY_FLAGS.HIGHLIGHTED) {
  272. this._numHighlightedLayerPortions++;
  273. this.model.numHighlightedLayerPortions++;
  274. }
  275. if (flags & ENTITY_FLAGS.XRAYED) {
  276. this._numXRayedLayerPortions++;
  277. this.model.numXRayedLayerPortions++;
  278. }
  279. if (flags & ENTITY_FLAGS.SELECTED) {
  280. this._numSelectedLayerPortions++;
  281. this.model.numSelectedLayerPortions++;
  282. }
  283. if (flags & ENTITY_FLAGS.CLIPPABLE) {
  284. this._numClippableLayerPortions++;
  285. this.model.numClippableLayerPortions++;
  286. }
  287. if (flags & ENTITY_FLAGS.EDGES) {
  288. this._numEdgesLayerPortions++;
  289. this.model.numEdgesLayerPortions++;
  290. }
  291. if (flags & ENTITY_FLAGS.PICKABLE) {
  292. this._numPickableLayerPortions++;
  293. this.model.numPickableLayerPortions++;
  294. }
  295. if (flags & ENTITY_FLAGS.CULLED) {
  296. this._numCulledLayerPortions++;
  297. this.model.numCulledLayerPortions++;
  298. }
  299. if (meshTransparent) {
  300. this._numTransparentLayerPortions++;
  301. this.model.numTransparentLayerPortions++;
  302. }
  303. const deferred = true;
  304. this._setFlags(portionId, flags, meshTransparent, deferred);
  305. }
  306.  
  307. flushInitFlags() {
  308. this._setDeferredFlags();
  309. }
  310.  
  311. setVisible(portionId, flags, transparent) {
  312. if (!this._finalized) {
  313. throw "Not finalized";
  314. }
  315. if (flags & ENTITY_FLAGS.VISIBLE) {
  316. this._numVisibleLayerPortions++;
  317. this.model.numVisibleLayerPortions++;
  318. } else {
  319. this._numVisibleLayerPortions--;
  320. this.model.numVisibleLayerPortions--;
  321. }
  322. this._setFlags(portionId, flags, transparent);
  323. }
  324.  
  325. setHighlighted(portionId, flags, transparent) {
  326. if (!this._finalized) {
  327. throw "Not finalized";
  328. }
  329. if (flags & ENTITY_FLAGS.HIGHLIGHTED) {
  330. this._numHighlightedLayerPortions++;
  331. this.model.numHighlightedLayerPortions++;
  332. } else {
  333. this._numHighlightedLayerPortions--;
  334. this.model.numHighlightedLayerPortions--;
  335. }
  336. this._setFlags(portionId, flags, transparent);
  337. }
  338.  
  339. setXRayed(portionId, flags, transparent) {
  340. if (!this._finalized) {
  341. throw "Not finalized";
  342. }
  343. if (flags & ENTITY_FLAGS.XRAYED) {
  344. this._numXRayedLayerPortions++;
  345. this.model.numXRayedLayerPortions++;
  346. } else {
  347. this._numXRayedLayerPortions--;
  348. this.model.numXRayedLayerPortions--;
  349. }
  350. this._setFlags(portionId, flags, transparent);
  351. }
  352.  
  353. setSelected(portionId, flags, transparent) {
  354. if (!this._finalized) {
  355. throw "Not finalized";
  356. }
  357. if (flags & ENTITY_FLAGS.SELECTED) {
  358. this._numSelectedLayerPortions++;
  359. this.model.numSelectedLayerPortions++;
  360. } else {
  361. this._numSelectedLayerPortions--;
  362. this.model.numSelectedLayerPortions--;
  363. }
  364. this._setFlags(portionId, flags, transparent);
  365. }
  366.  
  367. setEdges(portionId, flags, transparent) {
  368. if (!this._finalized) {
  369. throw "Not finalized";
  370. }
  371. if (flags & ENTITY_FLAGS.EDGES) {
  372. this._numEdgesLayerPortions++;
  373. this.model.numEdgesLayerPortions++;
  374. } else {
  375. this._numEdgesLayerPortions--;
  376. this.model.numEdgesLayerPortions--;
  377. }
  378. this._setFlags(portionId, flags, transparent);
  379. }
  380.  
  381. setClippable(portionId, flags) {
  382. if (!this._finalized) {
  383. throw "Not finalized";
  384. }
  385. if (flags & ENTITY_FLAGS.CLIPPABLE) {
  386. this._numClippableLayerPortions++;
  387. this.model.numClippableLayerPortions++;
  388. } else {
  389. this._numClippableLayerPortions--;
  390. this.model.numClippableLayerPortions--;
  391. }
  392. this._setFlags(portionId, flags);
  393. }
  394.  
  395. setCulled(portionId, flags, transparent) {
  396. if (!this._finalized) {
  397. throw "Not finalized";
  398. }
  399. if (flags & ENTITY_FLAGS.CULLED) {
  400. this._numCulledLayerPortions++;
  401. this.model.numCulledLayerPortions++;
  402. } else {
  403. this._numCulledLayerPortions--;
  404. this.model.numCulledLayerPortions--;
  405. }
  406. this._setFlags(portionId, flags, transparent);
  407. }
  408.  
  409. setCollidable(portionId, flags) {
  410. if (!this._finalized) {
  411. throw "Not finalized";
  412. }
  413. }
  414.  
  415. setPickable(portionId, flags, transparent) {
  416. if (!this._finalized) {
  417. throw "Not finalized";
  418. }
  419. if (flags & ENTITY_FLAGS.PICKABLE) {
  420. this._numPickableLayerPortions++;
  421. this.model.numPickableLayerPortions++;
  422. } else {
  423. this._numPickableLayerPortions--;
  424. this.model.numPickableLayerPortions--;
  425. }
  426. this._setFlags(portionId, flags, transparent);
  427. }
  428.  
  429. setColor(portionId, color) {
  430. if (!this._finalized) {
  431. throw "Not finalized";
  432. }
  433. const portionsIdx = portionId * 2;
  434. const vertexBase = this._portions[portionsIdx];
  435. const numVerts = this._portions[portionsIdx + 1];
  436. const firstColor = vertexBase * 4;
  437. const lenColor = numVerts * 4;
  438. const tempArray = this._scratchMemory.getUInt8Array(lenColor);
  439. const r = color[0];
  440. const g = color[1];
  441. const b = color[2];
  442. const a = color[3];
  443. for (let i = 0; i < lenColor; i += 4) {
  444. tempArray[i + 0] = r;
  445. tempArray[i + 1] = g;
  446. tempArray[i + 2] = b;
  447. tempArray[i + 3] = a;
  448. }
  449. this._state.colorsBuf.setData(tempArray, firstColor, lenColor);
  450. }
  451.  
  452. setTransparent(portionId, flags, transparent) {
  453. if (transparent) {
  454. this._numTransparentLayerPortions++;
  455. this.model.numTransparentLayerPortions++;
  456. } else {
  457. this._numTransparentLayerPortions--;
  458. this.model.numTransparentLayerPortions--;
  459. }
  460. this._setFlags(portionId, flags, transparent);
  461. }
  462.  
  463. /**
  464. * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.
  465. */
  466. _setFlags(portionId, flags, transparent, deferred = false) {
  467.  
  468. if (!this._finalized) {
  469. throw "Not finalized";
  470. }
  471.  
  472. const portionsIdx = portionId * 2;
  473. const vertexBase = this._portions[portionsIdx];
  474. const numVerts = this._portions[portionsIdx + 1];
  475. const firstFlag = vertexBase;
  476. const lenFlags = numVerts;
  477.  
  478. const visible = !!(flags & ENTITY_FLAGS.VISIBLE);
  479. const xrayed = !!(flags & ENTITY_FLAGS.XRAYED);
  480. const highlighted = !!(flags & ENTITY_FLAGS.HIGHLIGHTED);
  481. const selected = !!(flags & ENTITY_FLAGS.SELECTED);
  482. // no edges
  483. const pickable = !!(flags & ENTITY_FLAGS.PICKABLE);
  484. const culled = !!(flags & ENTITY_FLAGS.CULLED);
  485.  
  486. let colorFlag;
  487. if (!visible || culled || xrayed
  488. || (highlighted && !this.model.scene.highlightMaterial.glowThrough)
  489. || (selected && !this.model.scene.selectedMaterial.glowThrough)) {
  490. colorFlag = RENDER_PASSES.NOT_RENDERED;
  491. } else {
  492. if (transparent) {
  493. colorFlag = RENDER_PASSES.COLOR_TRANSPARENT;
  494. } else {
  495. colorFlag = RENDER_PASSES.COLOR_OPAQUE;
  496. }
  497. }
  498.  
  499. let silhouetteFlag;
  500. if (!visible || culled) {
  501. silhouetteFlag = RENDER_PASSES.NOT_RENDERED;
  502. } else if (selected) {
  503. silhouetteFlag = RENDER_PASSES.SILHOUETTE_SELECTED;
  504. } else if (highlighted) {
  505. silhouetteFlag = RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;
  506. } else if (xrayed) {
  507. silhouetteFlag = RENDER_PASSES.SILHOUETTE_XRAYED;
  508. } else {
  509. silhouetteFlag = RENDER_PASSES.NOT_RENDERED;
  510. }
  511.  
  512. let pickFlag = (visible && !culled && pickable) ? RENDER_PASSES.PICK : RENDER_PASSES.NOT_RENDERED;
  513.  
  514. const clippableFlag = !!(flags & ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;
  515.  
  516. if (deferred) {
  517. // Avoid zillions of individual WebGL bufferSubData calls - buffer them to apply in one shot
  518. if (!this._deferredFlagValues) {
  519. this._deferredFlagValues = new Float32Array(this._numVerts);
  520. }
  521. for (let i = firstFlag, len = (firstFlag + lenFlags); i < len; i++) {
  522. let vertFlag = 0;
  523. vertFlag |= colorFlag;
  524. vertFlag |= silhouetteFlag << 4;
  525. // no edges
  526. vertFlag |= pickFlag << 12;
  527. vertFlag |= clippableFlag << 16;
  528.  
  529. this._deferredFlagValues[i] = vertFlag;
  530. }
  531. } else if (this._state.flagsBuf) {
  532. const tempArray = this._scratchMemory.getFloat32Array(lenFlags);
  533. for (let i = 0; i < lenFlags; i++) {
  534. let vertFlag = 0;
  535. vertFlag |= colorFlag;
  536. vertFlag |= silhouetteFlag << 4;
  537. // no edges
  538. vertFlag |= pickFlag << 12;
  539. vertFlag |= clippableFlag << 16;
  540.  
  541. tempArray[i] = vertFlag;
  542. }
  543. this._state.flagsBuf.setData(tempArray, firstFlag, lenFlags);
  544. }
  545. }
  546.  
  547. _setDeferredFlags() {
  548. if (this._deferredFlagValues) {
  549. this._state.flagsBuf.setData(this._deferredFlagValues);
  550. this._deferredFlagValues = null;
  551. }
  552. }
  553.  
  554. setOffset(portionId, offset) {
  555. if (!this._finalized) {
  556. throw "Not finalized";
  557. }
  558. if (!this.model.scene.entityOffsetsEnabled) {
  559. this.model.error("Entity#offset not enabled for this Viewer"); // See Viewer entityOffsetsEnabled
  560. return;
  561. }
  562. const portionsIdx = portionId * 2;
  563. const vertexBase = this._portions[portionsIdx];
  564. const numVerts = this._portions[portionsIdx + 1];
  565. const firstOffset = vertexBase * 3;
  566. const lenOffsets = numVerts * 3;
  567. const tempArray = this._scratchMemory.getFloat32Array(lenOffsets);
  568. const x = offset[0];
  569. const y = offset[1];
  570. const z = offset[2];
  571. for (let i = 0; i < lenOffsets; i += 3) {
  572. tempArray[i + 0] = x;
  573. tempArray[i + 1] = y;
  574. tempArray[i + 2] = z;
  575. }
  576. this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);
  577. }
  578.  
  579. //-- RENDERING ----------------------------------------------------------------------------------------------
  580.  
  581. drawColorOpaque(renderFlags, frameCtx) {
  582. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {
  583. return;
  584. }
  585. if (this._renderers.colorRenderer) {
  586. this._renderers.colorRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
  587. }
  588. }
  589.  
  590. drawColorTransparent(renderFlags, frameCtx) {
  591. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {
  592. return;
  593. }
  594. if (this._renderers.colorRenderer) {
  595. this._renderers.colorRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_TRANSPARENT);
  596. }
  597. }
  598.  
  599. drawDepth(renderFlags, frameCtx) {
  600. }
  601.  
  602. drawNormals(renderFlags, frameCtx) {
  603. }
  604.  
  605. drawSilhouetteXRayed(renderFlags, frameCtx) {
  606. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {
  607. return;
  608. }
  609. if (this._renderers.silhouetteRenderer) {
  610. this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, RENDER_PASSES.SILHOUETTE_XRAYED);
  611. }
  612. }
  613.  
  614. drawSilhouetteHighlighted(renderFlags, frameCtx) {
  615. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {
  616. return;
  617. }
  618. if (this._renderers.silhouetteRenderer) {
  619. this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);
  620. }
  621. }
  622.  
  623. drawSilhouetteSelected(renderFlags, frameCtx) {
  624. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {
  625. return;
  626. }
  627. if (this._renderers.silhouetteRenderer) {
  628. this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, RENDER_PASSES.SILHOUETTE_SELECTED);
  629. }
  630. }
  631.  
  632. drawEdgesColorOpaque(renderFlags, frameCtx) {
  633. }
  634.  
  635. drawEdgesColorTransparent(renderFlags, frameCtx) {
  636. }
  637.  
  638. drawEdgesHighlighted(renderFlags, frameCtx) {
  639. }
  640.  
  641. drawEdgesSelected(renderFlags, frameCtx) {
  642. }
  643.  
  644. drawEdgesXRayed(renderFlags, frameCtx) {
  645. }
  646.  
  647. drawPickMesh(frameCtx) {
  648. }
  649.  
  650. drawPickDepths(frameCtx) {
  651. }
  652.  
  653. drawPickNormals(frameCtx) {
  654. }
  655.  
  656. drawSnapInit(renderFlags, frameCtx) {
  657. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {
  658. return;
  659. }
  660. if (this._renderers.snapInitRenderer) {
  661. this._renderers.snapInitRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);
  662. }
  663. }
  664.  
  665. drawSnap(renderFlags, frameCtx) {
  666. if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {
  667. return;
  668. }
  669. if (this._renderers.snapRenderer) {
  670. this._renderers.snapRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);
  671. }
  672. }
  673.  
  674. drawOcclusion(frameCtx) {
  675. }
  676.  
  677. drawShadow(frameCtx) {
  678. }
  679.  
  680. destroy() {
  681. const state = this._state;
  682. if (state.positionsBuf) {
  683. state.positionsBuf.destroy();
  684. state.positionsBuf = null;
  685. }
  686. if (state.offsetsBuf) {
  687. state.offsetsBuf.destroy();
  688. state.offsetsBuf = null;
  689. }
  690. if (state.colorsBuf) {
  691. state.colorsBuf.destroy();
  692. state.colorsBuf = null;
  693. }
  694. if (state.flagsBuf) {
  695. state.flagsBuf.destroy();
  696. state.flagsBuf = null;
  697. }
  698. if (state.indicesBuf) {
  699. state.indicesBuf.destroy();
  700. state.indicesBuf = null;
  701. }
  702. state.destroy();
  703. }
  704. }