UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

279 lines (268 loc) 8.88 kB
import { Geom2d_Curve, TopoDS_Edge, TopoDS_Wire, TopoDS_Vertex, TopoDS_Shape, gp_Pnt2d, CadGeometryType, CadTypeMap, cadGeometryTypeFromShape, cadDowncast, CADTesselationParams, CadBox3Handle, _createCadBox3Handle, CadGeometryTypeShape, } from './CadCommon'; import {ObjectContent, CoreObjectType, ObjectGeometryMap, objectContentCopyProperties} from '../../ObjectContent'; import {cadPnt2dClone, cadPnt2dToObject3D} from './toObject3D/CadPnt2d'; import {cadVertexClone, cadVertexToObject3D} from './toObject3D/CadVertex'; import { cadGeom2dCurveClone, cadGeom2dCurveToBufferGeometry, cadGeom2dCurveToObject3D, CURVE_2D_TESSELATION_PARAMS, } from './toObject3D/CadGeom2dCurve'; import {cadEdgeClone, cadEdgeObjectToObject3D} from './toObject3D/CadEdge'; import {cadWireClone, cadWireToObject3D} from './toObject3D/CadWire'; import {CoreCadType} from './CadCoreType'; import {CadLoaderSync} from './CadLoaderSync'; import {cadShapeClone} from './toObject3D/CadShapeCommon'; import {TypeAssert} from '../../../../engine/poly/Assert'; import {cadShapeToObject3D} from './toObject3D/CadShape'; import {Object3D, Material, Matrix4, Box3, Vector3, Quaternion, Euler} from 'three'; import {cadGeometryTransform} from './operations/CadTransform'; import {BaseSopNodeType} from '../../../../engine/nodes/sop/_Base'; import {cadCompoundToObject3D} from './toObject3D/CadCompound'; const t = new Vector3(); const q = new Quaternion(); const s = new Vector3(); const euler = new Euler(); const r = new Vector3(); const pivot = new Vector3(); const DEFAULT_BND_BOX: CadBox3Handle = _createCadBox3Handle(); const BBOX_EMPTY = new Box3(); // const DEG2RAD = Math.PI / 180; const RAD2DEG = 180 / Math.PI; export class CadObject<T extends CadGeometryType> implements ObjectContent<CoreObjectType.CAD> { public visible = true; get geometry() { return this._geometry as ObjectGeometryMap[CoreObjectType.CAD]; } get type() { return this._type; } userData = {}; name = ''; castShadow = true; receiveShadow = true; renderOrder = 0; frustumCulled = true; matrixAutoUpdate = false; material: Material | undefined; children: ObjectContent<CoreObjectType.CAD>[] = []; parent: ObjectContent<CoreObjectType.CAD> | null = null; constructor(private _geometry: CadTypeMap[T], private _type: T) { this._validate(); } setGeometry<TE extends CadGeometryType>(geometry: CadTypeMap[TE], type: TE) { this._geometry = geometry as CadTypeMap[T]; this._type = type as any as T; this._validate(); } private _validate() { if (CoreCadType.isGeometryShape(this._geometry)) { const oc = CadLoaderSync.oc(); if (oc) { this._geometry = cadDowncast(oc, this._geometry) as CadTypeMap[T]; const type = cadGeometryTypeFromShape(oc, this._geometry as any) as T; if (type) { this._type = type; } else { console.error('no type for geometry', this._geometry); } } } else { if (this.type == null) { console.error('type is required for geometry', this._geometry); } } } // static fromGeometry<T extends CadGeometryType>(geometry: CadTypeMap[T], type: T) { // return new CadObject(geometry, type); // } // type() { // return this._type!; // } cadGeometry() { return this.geometry! as CadTypeMap[T]; } dispose() {} applyMatrix4(matrix: Matrix4) { matrix.decompose(t, q, s); euler.setFromQuaternion(q); r.set(euler.x, euler.y, euler.z).multiplyScalar(RAD2DEG); const newGeometry = cadGeometryTransform(this.type, this.cadGeometry(), t, r, s.x, pivot); if (newGeometry) { const oc = CadLoaderSync.oc(); if (CoreCadType.isGeometryShape(newGeometry)) { const newType = cadGeometryTypeFromShape(oc, newGeometry); if (newType) { this.setGeometry(newGeometry, newType); } } else { // no need to re-add as it is transformed in place } } } add(...object: ObjectContent<CoreObjectType>[]) {} remove(...object: ObjectContent<CoreObjectType>[]) {} dispatchEvent(event: {type: string}) {} traverse(callback: (object: CadObject<T>) => any) { callback(this); } clone(): CadObject<T> { const geometry = cloneCadGeometry(this.type, this.cadGeometry()); const clone = new CadObject(geometry, this.type); objectContentCopyProperties(this, clone); return clone; } toObject3D( tesselationParams: CADTesselationParams, displayNode: BaseSopNodeType ): Object3D | Object3D[] | undefined { return CadObject.toObject3D(this, this.type, tesselationParams, displayNode); } static toObject3D<T extends CadGeometryType>( cadObject: CadObject<T>, type: T, tesselationParams: CADTesselationParams, displayNode: BaseSopNodeType ): Object3D | Object3D[] | undefined { switch (type) { case CadGeometryType.POINT_2D: { return cadPnt2dToObject3D(cadObject as CadObject<CadGeometryType.POINT_2D>); } case CadGeometryType.CURVE_2D: { return cadGeom2dCurveToObject3D(cadObject as CadObject<CadGeometryType.CURVE_2D>, tesselationParams); } // case CadObjectType.CURVE_3D: { // return cadGeomCurveToObject3D(oc, object as Geom_Curve, tesselationParams); // } case CadGeometryType.VERTEX: { return cadVertexToObject3D(cadObject as CadObject<CadGeometryType.VERTEX>); } case CadGeometryType.EDGE: { return cadEdgeObjectToObject3D(cadObject as CadObject<CadGeometryType.EDGE>, tesselationParams); } case CadGeometryType.WIRE: { return cadWireToObject3D(cadObject as CadObject<CadGeometryType.WIRE>, tesselationParams); } case CadGeometryType.FACE: case CadGeometryType.SHELL: case CadGeometryType.SOLID: case CadGeometryType.COMPSOLID: { return cadShapeToObject3D(cadObject as CadObject<CadGeometryTypeShape>, tesselationParams, displayNode); } case CadGeometryType.COMPOUND: { return cadCompoundToObject3D( cadObject as CadObject<CadGeometryType.COMPOUND>, tesselationParams, displayNode ); } } TypeAssert.unreachable(type); } boundingBox(target: Box3): void { const oc = CadLoaderSync.oc(); const Bnd_Box = CadLoaderSync.Bnd_Box; Bnd_Box.SetVoid(); const useTriangulation = true; if (CoreCadType.isShape(this)) { oc.BRepBndLib.Add(this.cadGeometry() as TopoDS_Shape, Bnd_Box, useTriangulation); Bnd_Box.Get( DEFAULT_BND_BOX.min.x as any, DEFAULT_BND_BOX.min.y as any, DEFAULT_BND_BOX.min.z as any, DEFAULT_BND_BOX.max.x as any, DEFAULT_BND_BOX.max.y as any, DEFAULT_BND_BOX.max.z as any ); target.min.x = DEFAULT_BND_BOX.min.x.current; target.min.y = DEFAULT_BND_BOX.min.y.current; target.min.z = DEFAULT_BND_BOX.min.z.current; target.max.x = DEFAULT_BND_BOX.max.x.current; target.max.y = DEFAULT_BND_BOX.max.y.current; target.max.z = DEFAULT_BND_BOX.max.z.current; return; } else { switch (this.type) { case CadGeometryType.POINT_2D: { const point = this.cadGeometry() as gp_Pnt2d; target.min.x = point.X(); target.min.y = point.Y(); target.min.z = 0; target.max.x = point.X(); target.max.y = point.Y(); target.max.z = 0; return; } case CadGeometryType.CURVE_2D: { const geometry = cadGeom2dCurveToBufferGeometry( this as CadObject<CadGeometryType.CURVE_2D>, CURVE_2D_TESSELATION_PARAMS ); geometry.computeBoundingBox(); if (geometry.boundingBox) { target.copy(geometry.boundingBox); } else { target.copy(BBOX_EMPTY); } return; } default: { console.warn('cad BoundingBox not implemented for type', this.type); target.copy(BBOX_EMPTY); } } } // switch (type) { // } } } function cloneCadGeometry<T extends CadGeometryType>(type: CadGeometryType, srcGeometry: CadTypeMap[T]): CadTypeMap[T] { switch (type) { case CadGeometryType.POINT_2D: { return cadPnt2dClone(srcGeometry as gp_Pnt2d) as CadTypeMap[T]; } case CadGeometryType.CURVE_2D: { return cadGeom2dCurveClone(srcGeometry as Geom2d_Curve) as CadTypeMap[T]; } // case CadObjectType.CURVE_3D: { // return cadGeomCurveClone(srcObject as Geom_Curve) as CadTypeMap[T]; // } case CadGeometryType.VERTEX: { return cadVertexClone(srcGeometry as TopoDS_Vertex) as CadTypeMap[T]; } case CadGeometryType.EDGE: { return cadEdgeClone(srcGeometry as TopoDS_Edge) as CadTypeMap[T]; } case CadGeometryType.WIRE: { return cadWireClone(srcGeometry as TopoDS_Wire) as CadTypeMap[T]; } case CadGeometryType.FACE: case CadGeometryType.SHELL: case CadGeometryType.SOLID: case CadGeometryType.COMPSOLID: case CadGeometryType.COMPOUND: { return cadShapeClone(srcGeometry as TopoDS_Shape) as CadTypeMap[T]; } } TypeAssert.unreachable(type); } // const ORIGIN = new Vector3(0, 0, 0); // export function cadObjectPosition<T extends CadGeometryType>(cadObject: CadObject<T>) { // console.warn('cadObjectPosition not implemented'); // return ORIGIN; // }