|
@@ -1,9 +1,10 @@
|
|
|
import { Nullable } from "../types";
|
|
|
import { VertexBuffer } from "../Meshes/buffer";
|
|
|
import { AbstractMesh } from "../Meshes/abstractMesh";
|
|
|
+import { Mesh } from "../Meshes/mesh";
|
|
|
import { LinesMesh, InstancedLinesMesh } from "../Meshes/linesMesh";
|
|
|
-import { Vector3, TmpVectors } from "../Maths/math.vector";
|
|
|
-import { IDisposable } from "../scene";
|
|
|
+import { Vector3, TmpVectors, Matrix } from "../Maths/math.vector";
|
|
|
+import { IDisposable, Scene } from "../scene";
|
|
|
import { Observer } from "../Misc/observable";
|
|
|
import { Effect } from "../Materials/effect";
|
|
|
import { Material } from "../Materials/material";
|
|
@@ -15,6 +16,14 @@ import { Node } from "../node";
|
|
|
import "../Shaders/line.fragment";
|
|
|
import "../Shaders/line.vertex";
|
|
|
import { DataBuffer } from '../Meshes/dataBuffer';
|
|
|
+import { SmartArray } from '../Misc/smartArray';
|
|
|
+
|
|
|
+declare module "../scene" {
|
|
|
+ export interface Scene {
|
|
|
+ /** @hidden */
|
|
|
+ _edgeRenderLineShader: Nullable<ShaderMaterial>;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
declare module "../Meshes/abstractMesh" {
|
|
|
export interface AbstractMesh {
|
|
@@ -114,6 +123,11 @@ export interface IEdgesRenderer extends IDisposable {
|
|
|
* @return true if ready, otherwise false.
|
|
|
*/
|
|
|
isReady(): boolean;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * List of instances to render in case the source mesh has instances
|
|
|
+ */
|
|
|
+ customInstances: SmartArray<Matrix>;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -141,6 +155,7 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
protected _lineShader: ShaderMaterial;
|
|
|
protected _ib: DataBuffer;
|
|
|
protected _buffers: { [key: string]: Nullable<VertexBuffer> } = {};
|
|
|
+ protected _buffersForInstances: { [key: string]: Nullable<VertexBuffer> } = {};
|
|
|
protected _checkVerticesInsteadOfIndices = false;
|
|
|
|
|
|
private _meshRebuildObserver: Nullable<Observer<AbstractMesh>>;
|
|
@@ -150,6 +165,28 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
public isEnabled = true;
|
|
|
|
|
|
/**
|
|
|
+ * List of instances to render in case the source mesh has instances
|
|
|
+ */
|
|
|
+ public customInstances = new SmartArray<Matrix>(32);
|
|
|
+
|
|
|
+ private static GetShader(scene: Scene): ShaderMaterial {
|
|
|
+ if (!scene._edgeRenderLineShader) {
|
|
|
+ const shader = new ShaderMaterial("lineShader", scene, "line",
|
|
|
+ {
|
|
|
+ attributes: ["position", "normal"],
|
|
|
+ uniforms: ["world", "viewProjection", "color", "width", "aspectRatio"]
|
|
|
+ });
|
|
|
+
|
|
|
+ shader.disableDepthWrite = true;
|
|
|
+ shader.backFaceCulling = false;
|
|
|
+
|
|
|
+ scene._edgeRenderLineShader = shader;
|
|
|
+ }
|
|
|
+
|
|
|
+ return scene._edgeRenderLineShader;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Creates an instance of the EdgesRenderer. It is primarily use to display edges of a mesh.
|
|
|
* Beware when you use this class with complex objects as the adjacencies computation can be really long
|
|
|
* @param source Mesh used to create edges
|
|
@@ -182,14 +219,7 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- this._lineShader = new ShaderMaterial("lineShader", this._source.getScene(), "line",
|
|
|
- {
|
|
|
- attributes: ["position", "normal"],
|
|
|
- uniforms: ["worldViewProjection", "color", "width", "aspectRatio"]
|
|
|
- });
|
|
|
-
|
|
|
- this._lineShader.disableDepthWrite = true;
|
|
|
- this._lineShader.backFaceCulling = false;
|
|
|
+ this._lineShader = EdgesRenderer.GetShader(this._source.getScene());
|
|
|
}
|
|
|
|
|
|
/** @hidden */
|
|
@@ -437,6 +467,9 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
this._buffers[VertexBuffer.PositionKind] = new VertexBuffer(engine, this._linesPositions, VertexBuffer.PositionKind, false);
|
|
|
this._buffers[VertexBuffer.NormalKind] = new VertexBuffer(engine, this._linesNormals, VertexBuffer.NormalKind, false, false, 4);
|
|
|
|
|
|
+ this._buffersForInstances[VertexBuffer.PositionKind] = this._buffers[VertexBuffer.PositionKind];
|
|
|
+ this._buffersForInstances[VertexBuffer.NormalKind] = this._buffers[VertexBuffer.NormalKind];
|
|
|
+
|
|
|
this._ib = engine.createIndexBuffer(this._linesIndices);
|
|
|
|
|
|
this._indicesCount = this._linesIndices.length;
|
|
@@ -447,7 +480,7 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
* @return true if ready, otherwise false.
|
|
|
*/
|
|
|
public isReady(): boolean {
|
|
|
- return this._lineShader.isReady();
|
|
|
+ return this._lineShader.isReady(this._source, (this._source.hasInstances && this.customInstances.length > 0) || this._source.hasThinInstances);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -469,8 +502,39 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
engine.setAlphaMode(Constants.ALPHA_DISABLE);
|
|
|
}
|
|
|
|
|
|
+ const hasInstances = this._source.hasInstances && this.customInstances.length > 0;
|
|
|
+ const useBuffersWithInstances = hasInstances || this._source.hasThinInstances;
|
|
|
+
|
|
|
+ let instanceCount = 0;
|
|
|
+
|
|
|
+ if (useBuffersWithInstances) {
|
|
|
+ this._buffersForInstances["world0"] = (this._source as Mesh).getVertexBuffer("world0");
|
|
|
+ this._buffersForInstances["world1"] = (this._source as Mesh).getVertexBuffer("world1");
|
|
|
+ this._buffersForInstances["world2"] = (this._source as Mesh).getVertexBuffer("world2");
|
|
|
+ this._buffersForInstances["world3"] = (this._source as Mesh).getVertexBuffer("world3");
|
|
|
+
|
|
|
+ if (hasInstances) {
|
|
|
+ let instanceStorage = (this._source as Mesh)._instanceDataStorage;
|
|
|
+
|
|
|
+ instanceCount = this.customInstances.length;
|
|
|
+
|
|
|
+ if (!instanceStorage.isFrozen) {
|
|
|
+ let offset = 0;
|
|
|
+
|
|
|
+ for (let i = 0; i < instanceCount; ++i) {
|
|
|
+ this.customInstances.data[i].copyToArray(instanceStorage.instancesData, offset);
|
|
|
+ offset += 16;
|
|
|
+ }
|
|
|
+
|
|
|
+ instanceStorage.instancesBuffer!.updateDirectly(instanceStorage.instancesData, 0, instanceCount);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ instanceCount = (this._source as Mesh).thinInstanceCount;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// VBOs
|
|
|
- engine.bindBuffers(this._buffers, this._ib, <Effect>this._lineShader.getEffect());
|
|
|
+ engine.bindBuffers(useBuffersWithInstances ? this._buffersForInstances : this._buffers, this._ib, <Effect>this._lineShader.getEffect());
|
|
|
|
|
|
scene.resetCachedMaterial();
|
|
|
this._lineShader.setColor4("color", this._source.edgesColor);
|
|
@@ -485,8 +549,10 @@ export class EdgesRenderer implements IEdgesRenderer {
|
|
|
this._lineShader.bind(this._source.getWorldMatrix());
|
|
|
|
|
|
// Draw order
|
|
|
- engine.drawElementsType(Material.TriangleFillMode, 0, this._indicesCount);
|
|
|
+ engine.drawElementsType(Material.TriangleFillMode, 0, this._indicesCount, instanceCount);
|
|
|
this._lineShader.unbind();
|
|
|
+
|
|
|
+ this.customInstances.reset();
|
|
|
}
|
|
|
}
|
|
|
|