From 8303fd1810cbae3eaa417b42441a9086809bca9b Mon Sep 17 00:00:00 2001 From: Paul Graffam Date: Mon, 6 Jul 2020 17:23:59 -0400 Subject: [PATCH] Added vertex helper, fixed up mesh helper --- src/js/app/helpers/meshHelper.js | 47 +++++--- src/js/app/helpers/vertexNormalsHelper.js | 124 ++++++++++++++++++++++ 2 files changed, 156 insertions(+), 15 deletions(-) create mode 100644 src/js/app/helpers/vertexNormalsHelper.js diff --git a/src/js/app/helpers/meshHelper.js b/src/js/app/helpers/meshHelper.js index cdb2b3c..9baeb77 100644 --- a/src/js/app/helpers/meshHelper.js +++ b/src/js/app/helpers/meshHelper.js @@ -1,24 +1,41 @@ import * as THREE from 'three'; +import { VertexNormalsHelper } from './vertexNormalsHelper'; // Simple mesh helper that shows edges, wireframes, and face and vertex normals export default class MeshHelper { constructor(scene, mesh) { - const wireframe = new THREE.WireframeGeometry(mesh.geometry); - const wireLine = new THREE.LineSegments(wireframe); - wireLine.material.depthTest = false; - wireLine.material.opacity = 0.25; - wireLine.material.transparent = true; - mesh.add(wireLine); + this.mesh = mesh; + this.scene = scene; - const edges = new THREE.EdgesGeometry(mesh.geometry); - const edgesLine = new THREE.LineSegments(edges); - edgesLine.material.depthTest = false; - edgesLine.material.opacity = 0.25; - edgesLine.material.transparent = true; - mesh.add(edgesLine); + const wireframe = new THREE.WireframeGeometry(this.mesh.geometry); + this.wireLine = new THREE.LineSegments(wireframe); + this.wireLine.material.depthTest = false; + this.wireLine.material.opacity = 0.25; + this.wireLine.material.transparent = true; - scene.add(new THREE.BoxHelper(mesh)); - scene.add(new THREE.FaceNormalsHelper(mesh, 2)); - scene.add(new THREE.VertexNormalsHelper(mesh, 2)); + const edges = new THREE.EdgesGeometry(this.mesh.geometry); + this.edgesLine = new THREE.LineSegments(edges); + this.edgesLine.material.depthTest = false; + this.edgesLine.material.opacity = 0.25; + this.edgesLine.material.transparent = true; + + this.vertexHelper = new VertexNormalsHelper(this.mesh, 2); + this.boxHelper = new THREE.BoxHelper(this.mesh); + } + + enable() { + this.mesh.add(this.wireLine); + this.mesh.add(this.edgesLine); + + this.scene.add(this.vertexHelper); + this.scene.add(this.boxHelper); + } + + disable() { + this.mesh.remove(this.wireLine); + this.mesh.remove(this.edgesLine); + + this.scene.remove(this.vertexHelper); + this.scene.remove(this.boxHelper); } } diff --git a/src/js/app/helpers/vertexNormalsHelper.js b/src/js/app/helpers/vertexNormalsHelper.js new file mode 100644 index 0000000..c31c8a3 --- /dev/null +++ b/src/js/app/helpers/vertexNormalsHelper.js @@ -0,0 +1,124 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author WestLangley / http://github.com/WestLangley + */ + +import { + BufferGeometry, + Float32BufferAttribute, + LineSegments, + LineBasicMaterial, + Matrix3, + Vector3, +} from 'three'; + +const _v1 = new Vector3(); +const _v2 = new Vector3(); +const _normalMatrix = new Matrix3(); +const _keys = ['a', 'b', 'c']; + +function VertexNormalsHelper(object, size, hex) { + this.object = object; + this.size = size !== undefined ? size : 0.1; + + const color = hex !== undefined ? hex : 0xff0000; + + // + + let nNormals = 0; + + const objGeometry = this.object.geometry; + + if (objGeometry && objGeometry.isGeometry) { + nNormals = objGeometry.faces.length * 3; + } else if (objGeometry && objGeometry.isBufferGeometry) { + nNormals = objGeometry.attributes.normal.count; + } + + // + + const geometry = new BufferGeometry(); + const positions = new Float32BufferAttribute(nNormals * 2 * 3, 3); + + geometry.setAttribute('position', positions); + + LineSegments.call(this, geometry, new LineBasicMaterial({ color: color, toneMapped: false })); + + this.type = 'VertexNormalsHelper'; + + // + + this.matrixAutoUpdate = false; + + this.update(); +} + +VertexNormalsHelper.prototype = Object.create(LineSegments.prototype); +VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; + +VertexNormalsHelper.prototype.update = function () { + let idx; + this.object.updateMatrixWorld(true); + + _normalMatrix.getNormalMatrix(this.object.matrixWorld); + + const matrixWorld = this.object.matrixWorld; + const position = this.geometry.attributes.position; + + // + + const objGeometry = this.object.geometry; + + if (objGeometry && objGeometry.isGeometry) { + const vertices = objGeometry.vertices; + + const faces = objGeometry.faces; + + idx = 0; + + for (let i = 0, l = faces.length; i < l; i++) { + const face = faces[i]; + + for (let j = 0, jl = face.vertexNormals.length; j < jl; j++) { + const vertex = vertices[face[_keys[j]]]; + const normal = face.vertexNormals[j]; + + _v1.copy(vertex).applyMatrix4(matrixWorld); + _v2.copy(normal).applyMatrix3(_normalMatrix).normalize().multiplyScalar(this.size).add(_v1); + + position.setXYZ(idx, _v1.x, _v1.y, _v1.z); + + idx = idx + 1; + + position.setXYZ(idx, _v2.x, _v2.y, _v2.z); + + idx = idx + 1; + } + } + } else if (objGeometry && objGeometry.isBufferGeometry) { + const objPos = objGeometry.attributes.position; + const objNorm = objGeometry.attributes.normal; + + idx = 0; + + // for simplicity, ignore index and drawcalls, and render every normal + + for (var j = 0, jl = objPos.count; j < jl; j++) { + _v1.set(objPos.getX(j), objPos.getY(j), objPos.getZ(j)).applyMatrix4(matrixWorld); + _v2.set(objNorm.getX(j), objNorm.getY(j), objNorm.getZ(j)); + _v2.applyMatrix3(_normalMatrix).normalize().multiplyScalar(this.size).add(_v1); + + position.setXYZ(idx, _v1.x, _v1.y, _v1.z); + + idx = idx + 1; + + position.setXYZ(idx, _v2.x, _v2.y, _v2.z); + + idx = idx + 1; + } + } + + position.needsUpdate = true; +}; + +export { VertexNormalsHelper };