/** @module */
/**
* @file
*
* Summary.
*
* <p>MeshEdgesGeometry is a simple class to extract edges from a Three.js {@link THREE.Object3D object}
* - a mesh or a group with children.</p>
*
* The hierarchy and substructures of the input object are flattened out.
* Their positions, scales and rotations are baked into world coordinates.
*
* MeshEdgesGeometry is like {@link https://threejs.org/docs/#api/en/geometries/EdgesGeometry THREE.EdgesGeometry},
* except that it does not work on {@link THREE.BufferGeometry},
* but on {@link THREE.Object3D}.
*
* @author {@link https://github.com/boytchev Pavel Boytchev}
* @see <a href="/cwdc/13-webgl/examples/three/content/MeshEdgesGeometry.js">source</a>
* @see {@link https://github.com/boytchev/MeshEdgesGeometry github}
* @see <img src="../LittlestTokyo.png" HEIGHT="320">
* <img src="../LittlestTokyo.jpg" HEIGHT="320">
*/
import { BufferGeometry, EdgesGeometry } from "three";
import { mergeAttributes } from "three/addons/utils/BufferGeometryUtils.js?module";
/**
* This is the base class for most objects in three.js and provides
* a set of properties and methods for manipulating objects in 3D space.
* @memberof THREE
* @class Object3D
* @see {@link https://threejs.org/docs/#api/en/core/Object3D Object3D}
*/
/**
* This class stores data for an attribute (such as vertex positions,
* face indices, normals, colors, UVs, and any custom attributes )
* associated with a BufferGeometry, which allows for more efficient passing of data to the GPU.
* See that page for details and a usage example.
* When working with vector-like data, the .fromBufferAttribute( attribute, index )
* helper methods on Vector2, Vector3, Vector4, and Color classes may be helpful.
* @memberof THREE
* @class BufferAttribute
* @see {@link https://threejs.org/docs/#api/en/core/BufferAttribute BufferAttribute}
*/
/**
* Class for extracting edges from gltf files.
* @class
* @extends THREE.BufferGeometry
*/
class MeshEdgesGeometry extends BufferGeometry {
/**
* @constructor
* @param {THREE.Scene} object Any geometry object.
* @param {Number} thresholdAngle An edge is only rendered if the angle (in degrees) between<br>
* the face normals of the adjoining faces exceeds this value. <br> default = 1 degree.
*/
constructor(object, thresholdAngle = 1) {
super();
object.updateWorldMatrix(true, true);
const position = this.extractEdges(object, thresholdAngle);
this.setAttribute("position", position);
}
/**
* Extract edges - each edge is an individual segment.
* @param {THREE.Scene} object Any geometry object.
* @param {Number} thresholdAngle An edge is only rendered if the angle (in degrees) between<br>
* the face normals of the adjoining faces exceeds this value. <br> default = 1 degree.
* @return {THREE.BufferAttribute} position buffer.
* @see {@link https://threejs.org/docs/#examples/en/utils/BufferGeometryUtils.mergeAttributes mergeAttributes}
*/
extractEdges(object, thresholdAngle) {
const attributes = [];
object.traverse((child) => {
if (child.geometry) {
const geo = new EdgesGeometry(child.geometry, thresholdAngle);
const pos = geo.getAttribute("position");
attributes.push(pos.applyMatrix4(child.matrixWorld));
}
});
if (attributes.length == 0) {
throw "MeshEdgesGeometry: No edges found";
}
return mergeAttributes(attributes);
}
}
export { MeshEdgesGeometry };