123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- var BABYLON;
- (function (BABYLON) {
- var FaceAdjacencies = (function () {
- function FaceAdjacencies() {
- this.edges = new Array();
- this.edgesConnectedCount = 0;
- }
- return FaceAdjacencies;
- })();
- var EdgesRenderer = (function () {
- // Beware when you use this class with complex objects as the adjacencies computation can be really long
- function EdgesRenderer(source, epsilon) {
- if (epsilon === void 0) { epsilon = 0.95; }
- this._linesPositions = new Array();
- this._linesNormals = new Array();
- this._linesIndices = new Array();
- this._buffers = new Array();
- this._source = source;
- this._epsilon = epsilon;
- this._prepareRessources();
- this._generateEdgesLines();
- }
- EdgesRenderer.prototype._prepareRessources = function () {
- if (this._lineShader) {
- return;
- }
- this._lineShader = new BABYLON.ShaderMaterial("lineShader", this._source.getScene(), "line", {
- attributes: ["position", "normal"],
- uniforms: ["worldViewProjection", "color", "width"]
- });
- this._lineShader.disableDepthWrite = true;
- this._lineShader.backFaceCulling = false;
- };
- EdgesRenderer.prototype.dispose = function () {
- this._vb0.dispose();
- this._vb1.dispose();
- this._source.getScene().getEngine()._releaseBuffer(this._ib);
- this._lineShader.dispose();
- };
- EdgesRenderer.prototype._processEdgeForAdjacencies = function (pa, pb, p0, p1, p2) {
- if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
- return 0;
- }
- if (pa === p1 && pb === p2 || pa === p2 && pb === p1) {
- return 1;
- }
- if (pa === p2 && pb === p0 || pa === p0 && pb === p2) {
- return 2;
- }
- return -1;
- };
- EdgesRenderer.prototype._checkEdge = function (faceIndex, edge, faceNormals, p0, p1) {
- var needToCreateLine;
- if (edge === undefined) {
- needToCreateLine = true;
- }
- else {
- var dotProduct = BABYLON.Vector3.Dot(faceNormals[faceIndex], faceNormals[edge]);
- needToCreateLine = dotProduct < this._epsilon;
- }
- if (needToCreateLine) {
- var offset = this._linesPositions.length / 3;
- var normal = p0.subtract(p1);
- normal.normalize();
- // Positions
- this._linesPositions.push(p0.x);
- this._linesPositions.push(p0.y);
- this._linesPositions.push(p0.z);
- this._linesPositions.push(p0.x);
- this._linesPositions.push(p0.y);
- this._linesPositions.push(p0.z);
- this._linesPositions.push(p1.x);
- this._linesPositions.push(p1.y);
- this._linesPositions.push(p1.z);
- this._linesPositions.push(p1.x);
- this._linesPositions.push(p1.y);
- this._linesPositions.push(p1.z);
- // Normals
- this._linesNormals.push(normal.x);
- this._linesNormals.push(normal.y);
- this._linesNormals.push(normal.z);
- this._linesNormals.push(-normal.x);
- this._linesNormals.push(-normal.y);
- this._linesNormals.push(-normal.z);
- this._linesNormals.push(-normal.x);
- this._linesNormals.push(-normal.y);
- this._linesNormals.push(-normal.z);
- this._linesNormals.push(normal.x);
- this._linesNormals.push(normal.y);
- this._linesNormals.push(normal.z);
- // Indices
- this._linesIndices.push(offset);
- this._linesIndices.push(offset + 1);
- this._linesIndices.push(offset + 2);
- this._linesIndices.push(offset);
- this._linesIndices.push(offset + 2);
- this._linesIndices.push(offset + 3);
- }
- };
- EdgesRenderer.prototype._generateEdgesLines = function () {
- var positions = this._source.getVerticesData(BABYLON.VertexBuffer.PositionKind);
- var indices = this._source.getIndices();
- // First let's find adjacencies
- var adjacencies = new Array();
- var faceNormals = new Array();
- var index;
- var faceAdjacencies;
- // Prepare faces
- for (index = 0; index < indices.length; index += 3) {
- faceAdjacencies = new FaceAdjacencies();
- var p0Index = indices[index];
- var p1Index = indices[index + 1];
- var p2Index = indices[index + 2];
- faceAdjacencies.p0 = new BABYLON.Vector3(positions[p0Index * 3], positions[p0Index * 3 + 1], positions[p0Index * 3 + 2]);
- faceAdjacencies.p1 = new BABYLON.Vector3(positions[p1Index * 3], positions[p1Index * 3 + 1], positions[p1Index * 3 + 2]);
- faceAdjacencies.p2 = new BABYLON.Vector3(positions[p2Index * 3], positions[p2Index * 3 + 1], positions[p2Index * 3 + 2]);
- var faceNormal = BABYLON.Vector3.Cross(faceAdjacencies.p1.subtract(faceAdjacencies.p0), faceAdjacencies.p2.subtract(faceAdjacencies.p1));
- faceNormal.normalize();
- faceNormals.push(faceNormal);
- adjacencies.push(faceAdjacencies);
- }
- // Scan
- for (index = 0; index < adjacencies.length; index++) {
- faceAdjacencies = adjacencies[index];
- for (var otherIndex = index + 1; otherIndex < adjacencies.length; otherIndex++) {
- var otherFaceAdjacencies = adjacencies[otherIndex];
- if (faceAdjacencies.edgesConnectedCount === 3) {
- break;
- }
- if (otherFaceAdjacencies.edgesConnectedCount === 3) {
- continue;
- }
- var otherP0 = indices[otherIndex * 3];
- var otherP1 = indices[otherIndex * 3 + 1];
- var otherP2 = indices[otherIndex * 3 + 2];
- for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) {
- var otherEdgeIndex;
- if (faceAdjacencies.edges[edgeIndex] !== undefined) {
- continue;
- }
- switch (edgeIndex) {
- case 0:
- otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3], indices[index * 3 + 1], otherP0, otherP1, otherP2);
- break;
- case 1:
- otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 1], indices[index * 3 + 2], otherP0, otherP1, otherP2);
- break;
- case 2:
- otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 2], indices[index * 3], otherP0, otherP1, otherP2);
- break;
- }
- if (otherEdgeIndex === -1) {
- continue;
- }
- faceAdjacencies.edges[edgeIndex] = otherIndex;
- otherFaceAdjacencies.edges[otherEdgeIndex] = index;
- faceAdjacencies.edgesConnectedCount++;
- otherFaceAdjacencies.edgesConnectedCount++;
- if (faceAdjacencies.edgesConnectedCount === 3) {
- break;
- }
- }
- }
- }
- // Create lines
- for (index = 0; index < adjacencies.length; index++) {
- // We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
- var current = adjacencies[index];
- this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
- this._checkEdge(index, current.edges[1], faceNormals, current.p1, current.p2);
- this._checkEdge(index, current.edges[2], faceNormals, current.p2, current.p0);
- }
- // Merge into a single mesh
- var engine = this._source.getScene().getEngine();
- this._vb0 = new BABYLON.VertexBuffer(engine, this._linesPositions, BABYLON.VertexBuffer.PositionKind, false);
- this._vb1 = new BABYLON.VertexBuffer(engine, this._linesNormals, BABYLON.VertexBuffer.NormalKind, false);
- this._buffers[BABYLON.VertexBuffer.PositionKind] = this._vb0;
- this._buffers[BABYLON.VertexBuffer.NormalKind] = this._vb1;
- this._ib = engine.createIndexBuffer(this._linesIndices);
- this._indicesCount = this._linesIndices.length;
- };
- EdgesRenderer.prototype.render = function () {
- if (!this._lineShader.isReady()) {
- return;
- }
- var scene = this._source.getScene();
- var engine = scene.getEngine();
- this._lineShader._preBind();
- // VBOs
- engine.bindMultiBuffers(this._buffers, this._ib, this._lineShader.getEffect());
- scene.resetCachedMaterial();
- this._lineShader.setColor4("color", this._source.edgesColor);
- this._lineShader.setFloat("width", this._source.edgesWidth / 100.0);
- this._lineShader.bind(this._source.getWorldMatrix());
- // Draw order
- engine.draw(true, 0, this._indicesCount);
- this._lineShader.unbind();
- engine.setDepthWrite(true);
- };
- return EdgesRenderer;
- })();
- BABYLON.EdgesRenderer = EdgesRenderer;
- })(BABYLON || (BABYLON = {}));
|