362 lines
12 KiB
JavaScript
362 lines
12 KiB
JavaScript
import * as THREE from 'three'
|
|
import SelectionHelper from './SelectionHelper'
|
|
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js'
|
|
import { Box3 } from 'three'
|
|
|
|
export default class SectionBox {
|
|
|
|
constructor( viewer, bbox ) {
|
|
this.viewer = viewer
|
|
|
|
this.viewer.renderer.localClippingEnabled = true
|
|
|
|
this.orbiting = false
|
|
this.dragging = false
|
|
this.display = new THREE.Group()
|
|
this.viewer.scene.add( this.display )
|
|
this.viewer.controls.addEventListener( 'wake', () => { this.orbiting = true } )
|
|
this.viewer.controls.addEventListener( 'controlend', () => { this.orbiting = false } )
|
|
|
|
// box
|
|
this.boxGeometry = this._generateSimpleCube( 5, 5, 5 )
|
|
// this.material = new THREE.MeshBasicMaterial()
|
|
this.material = new THREE.MeshStandardMaterial( { color: 0x00ffff, opacity:0, wireframe: true, side: THREE.DoubleSide } )
|
|
this.cube = new THREE.Mesh( this.boxGeometry, this.material )
|
|
this.cube.visible = false
|
|
|
|
this.display.add( this.cube )
|
|
|
|
this.boxHelper = new THREE.BoxHelper( this.cube, 0x0A66FF )
|
|
this.display.add( this.boxHelper )
|
|
|
|
|
|
let sphere = new THREE.SphereGeometry( 0.01, 10, 10 )
|
|
this.sphere = new THREE.Mesh( sphere, new THREE.MeshStandardMaterial( { color:0x00ffff } ) )
|
|
this.display.add( this.sphere )
|
|
|
|
// plane
|
|
this.plane = new THREE.PlaneGeometry( 1, 1 )
|
|
this.hoverPlane = new THREE.Mesh( this.plane, new THREE.MeshStandardMaterial( { transparent: true, side: THREE.DoubleSide, opacity: 0, color: 0x0A66FF, metalness: 0.1, roughness: 0.75 } ) )
|
|
this.hoverPlane.visible = false
|
|
this.display.add( this.hoverPlane )
|
|
|
|
window.cube = this.cube
|
|
|
|
// controls
|
|
this.controls = new TransformControls( this.viewer.camera, this.viewer.renderer.domElement )
|
|
this.controls.setSize( 0.75 )
|
|
this.display.add( this.controls )
|
|
|
|
|
|
this.selectionHelper = new SelectionHelper( this.viewer, { subset: this.cube, hover: true } )
|
|
|
|
// this.selectionHelper.on( 'hovered', args => { } )
|
|
|
|
this.dragging = false
|
|
|
|
let sidesSimple = {
|
|
'256': { verts: [ 1, 2, 5, 6 ], axis:'x' },
|
|
'152': { verts: [ 1, 2, 5, 6 ], axis:'x' },
|
|
'407': { verts: [ 0, 3, 4, 7 ], axis:'x' },
|
|
'703': { verts: [ 0, 3, 4, 7 ], axis:'x' },
|
|
'327': { verts: [ 2, 3, 6, 7 ], axis:'y' },
|
|
'726': { verts: [ 2, 3, 6, 7 ], axis:'y' },
|
|
'450': { verts: [ 0, 1, 4, 5 ], axis:'y' },
|
|
'051': { verts: [ 0, 1, 4, 5 ], axis:'y' },
|
|
'312': { verts: [ 0, 1, 3, 2 ], axis:'z' },
|
|
'013': { verts: [ 0, 1, 3, 2 ], axis:'z' },
|
|
'546': { verts: [ 4, 5, 7, 6 ], axis:'z' },
|
|
'647': { verts: [ 4, 5, 7, 6 ], axis:'z' }
|
|
}
|
|
|
|
this.sidesSimple = sidesSimple
|
|
|
|
this._generateOrUpdatePlanes()
|
|
|
|
this.controls.addEventListener( 'dragging-changed', ( event ) => {
|
|
let val = !!event.value
|
|
if( val ) {
|
|
this.dragging = val
|
|
this.viewer.interactions.preventSelection = val
|
|
this.viewer.controls.enabled = !val
|
|
} else {
|
|
setTimeout( ()=> {
|
|
this.dragging = val
|
|
this.viewer.interactions.preventSelection = val
|
|
this.viewer.controls.enabled = !val
|
|
}, 100 )
|
|
|
|
}
|
|
} )
|
|
|
|
this.currentRange = null
|
|
this.prevPosition = null
|
|
|
|
this.controls.addEventListener( 'change', this._draggingChangeHandler.bind( this ) )
|
|
this.selectionHelper.on( 'object-clicked', this._clickHandler.bind( this ) )
|
|
|
|
this._attachControlsToBox()
|
|
}
|
|
|
|
_draggingChangeHandler( ) {
|
|
this.boxHelper.update()
|
|
this._generateOrUpdatePlanes()
|
|
|
|
// Dragging a side / plane
|
|
if( this.dragging && this.currentRange ) {
|
|
if( this.prevPosition === null ) this.prevPosition = this.hoverPlane.position.clone()
|
|
this.prevPosition.sub( this.hoverPlane.position )
|
|
this.prevPosition.negate()
|
|
let boxArr = this.boxGeometry.attributes.position.array
|
|
for( let i = 0; i < this.currentRange.length; i++ ) {
|
|
let index = this.currentRange[i]
|
|
boxArr[3 * index] += this.prevPosition.x
|
|
boxArr[3 * index + 1] += this.prevPosition.y
|
|
boxArr[3 * index + 2] += this.prevPosition.z
|
|
}
|
|
|
|
this.prevPosition = this.hoverPlane.position.clone()
|
|
this.boxGeometry.attributes.position.needsUpdate = true
|
|
this.boxGeometry.computeVertexNormals()
|
|
this.boxGeometry.computeBoundingBox()
|
|
this.boxGeometry.computeBoundingSphere()
|
|
}
|
|
|
|
// Dragging the whole section box
|
|
if( this.dragging && !this.currentRange ) {
|
|
if( this.prevPosition === null ) this.prevPosition = this.sphere.position.clone()
|
|
this.prevPosition.sub( this.sphere.position )
|
|
this.prevPosition.negate()
|
|
|
|
for( let i = 0; i < this.boxGeometry.attributes.position.array.length; i += 3 ) {
|
|
this.boxGeometry.attributes.position.array[i] += this.prevPosition.x
|
|
this.boxGeometry.attributes.position.array[i + 1] += this.prevPosition.y
|
|
this.boxGeometry.attributes.position.array[i + 2] += this.prevPosition.z
|
|
}
|
|
this.boxGeometry.attributes.position.needsUpdate = true
|
|
this.boxGeometry.computeVertexNormals()
|
|
this.boxGeometry.computeBoundingBox()
|
|
this.boxGeometry.computeBoundingSphere()
|
|
|
|
this.prevPosition = this.sphere.position.clone()
|
|
}
|
|
this.viewer.needsRender = true
|
|
}
|
|
|
|
_clickHandler( args ) {
|
|
if( this.orbiting || this.dragging ) return
|
|
if( args.length === 0 && !this.dragging ) {
|
|
this._attachControlsToBox()
|
|
return
|
|
}
|
|
|
|
this.hoverPlane.visible = true
|
|
let side = this.sidesSimple[`${args[0].face.a}${args[0].face.b}${args[0].face.c}`]
|
|
this.controls.showX = side.axis === 'x'
|
|
this.controls.showY = side.axis === 'y'
|
|
this.controls.showZ = side.axis === 'z'
|
|
|
|
this.currentRange = side.verts
|
|
|
|
let boxArr = this.boxGeometry.attributes.position
|
|
let index = 0
|
|
let planeArr = this.plane.attributes.position.array
|
|
let centre = new THREE.Vector3()
|
|
|
|
let tempArr = []
|
|
for( let i = 0; i < planeArr.length; i++ ) {
|
|
if( i % 3 === 0 ) {
|
|
tempArr.push( boxArr.getX( this.currentRange[index] ) )
|
|
}
|
|
else if( i % 3 === 1 ) {
|
|
tempArr.push( boxArr.getY( this.currentRange[index] ) )
|
|
}
|
|
else if( i % 3 === 2 ) {
|
|
tempArr.push( boxArr.getZ( this.currentRange[index] ) )
|
|
centre.add( new THREE.Vector3( tempArr[i - 2], tempArr[i - 1], tempArr[i] ) )
|
|
index++
|
|
}
|
|
}
|
|
|
|
centre.multiplyScalar( 0.25 )
|
|
this.hoverPlane.position.copy( centre.applyMatrix4( this.cube.matrixWorld ) )
|
|
this.prevPosition = this.hoverPlane.position.clone()
|
|
index = 0
|
|
for( let i = 0; i < planeArr.length; i++ ) {
|
|
if( i % 3 === 0 ) {
|
|
planeArr[i] = boxArr.getX( this.currentRange[index] ) - centre.x
|
|
}
|
|
else if( i % 3 === 1 ) {
|
|
planeArr[i] = boxArr.getY( this.currentRange[index] ) - centre.y
|
|
}
|
|
else if( i % 3 === 2 ) {
|
|
planeArr[i] = boxArr.getZ( this.currentRange[index] ) - centre.z
|
|
index++
|
|
}
|
|
}
|
|
|
|
this.plane.applyMatrix4( this.cube.matrixWorld )
|
|
this.plane.attributes.position.needsUpdate = true
|
|
this.plane.computeBoundingSphere()
|
|
this.plane.computeBoundingBox()
|
|
this.controls.detach()
|
|
this.controls.attach( this.hoverPlane )
|
|
this.controls.updateMatrixWorld()
|
|
}
|
|
|
|
_generateSimpleCube( width = 0.5, depth = 0.5, height = 0.5 ) {
|
|
const vertices = [
|
|
[ -1 * width, -1 * depth, -1 * height ],
|
|
[ 1 * width, -1 * depth, -1 * height ],
|
|
[ 1 * width, 1 * depth, -1 * height ],
|
|
[ -1 * width, 1 * depth, -1 * height ],
|
|
[ -1 * width, -1 * depth, 1 * height ],
|
|
[ 1 * width, -1 * depth, 1 * height ],
|
|
[ 1 * width, 1 * depth, 1 * height ],
|
|
[ -1 * width, 1 * depth, 1 * height ]
|
|
]
|
|
|
|
const indexes = [
|
|
0, 1, 3, 3, 1, 2,
|
|
1, 5, 2, 2, 5, 6,
|
|
5, 4, 6, 6, 4, 7,
|
|
4, 0, 7, 7, 0, 3,
|
|
3, 2, 7, 7, 2, 6,
|
|
4, 5, 0, 0, 5, 1
|
|
]
|
|
|
|
let positions = []
|
|
for( let vert of vertices ) {
|
|
positions.push( ...vert )
|
|
}
|
|
|
|
let g = new THREE.BufferGeometry()
|
|
g.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) )
|
|
g.setIndex( indexes )
|
|
g.computeVertexNormals()
|
|
return g
|
|
}
|
|
|
|
_generateOrUpdatePlanes() {
|
|
this.planes = this.planes || [ new THREE.Plane(), new THREE.Plane(), new THREE.Plane(), new THREE.Plane(), new THREE.Plane(), new THREE.Plane() ]
|
|
|
|
let index = 0
|
|
let boxArr = this.boxGeometry.attributes.position
|
|
const indexes = [
|
|
0, 1, 3, 3, 1, 2,
|
|
1, 5, 2, 2, 5, 6,
|
|
5, 4, 6, 6, 4, 7,
|
|
4, 0, 7, 7, 0, 3,
|
|
3, 2, 7, 7, 2, 6,
|
|
4, 5, 0, 0, 5, 1
|
|
]
|
|
|
|
for( let i = 0; i < indexes.length; i += 6 ) {
|
|
let a = new THREE.Vector3( boxArr.getX( indexes[i] ), boxArr.getY( indexes[i] ), boxArr.getZ( indexes[i] ) )
|
|
let b = new THREE.Vector3( boxArr.getX( indexes[i + 1] ), boxArr.getY( indexes[i + 1] ), boxArr.getZ( indexes[i + 1] ) )
|
|
let c = new THREE.Vector3( boxArr.getX( indexes[i + 2] ), boxArr.getY( indexes[i + 2] ), boxArr.getZ( indexes[i + 2] ) )
|
|
let plane = this.planes[index]
|
|
plane.setFromCoplanarPoints( a, b, c )
|
|
index++
|
|
}
|
|
}
|
|
|
|
_attachControlsToBox() {
|
|
this.controls.detach()
|
|
|
|
let centre = new THREE.Vector3()
|
|
let boxArr = this.boxGeometry.attributes.position.array
|
|
for( let i = 0; i < boxArr.length; i += 3 ) {
|
|
centre.add( new THREE.Vector3( boxArr[i], boxArr[i + 1], boxArr[i + 2] ) )
|
|
}
|
|
centre.multiplyScalar( 1 / 8 )
|
|
this.sphere.position.copy( centre )
|
|
|
|
this.cube.geometry.computeBoundingSphere()
|
|
this.cube.geometry.computeBoundingBox()
|
|
this.controls.attach( this.sphere )
|
|
this.currentRange = null
|
|
this.prevPosition = null
|
|
this.hoverPlane.visible = false
|
|
this.controls.showX = true
|
|
this.controls.showY = true
|
|
this.controls.showZ = true
|
|
}
|
|
|
|
setPlanesFromBox( box ) {
|
|
|
|
}
|
|
|
|
setBox( ) {
|
|
let box = null
|
|
console.log(this.viewer.interactions.selectedObjects.children.length )
|
|
console.log(this.viewer.sceneManager.sceneObjects.allObjects.children.length )
|
|
if( this.viewer.interactions.selectedObjects.children.length !== 0 ) {
|
|
box = new THREE.Box3( ).setFromObject(this.viewer.interactions.selectedObjects)
|
|
} else if( this.viewer.sceneManager.sceneObjects.allObjects.children.length !== 0 ){
|
|
box = new THREE.Box3( ).setFromObject(this.viewer.sceneManager.sceneObjects.allObjects)
|
|
} else {
|
|
box = new Box3( new THREE.Vector3(-1, -1, -1), new THREE.Vector3(1, 1, 1))
|
|
}
|
|
if(box.min.x === Infinity) {
|
|
box = new Box3( new THREE.Vector3(-1, -1, -1), new THREE.Vector3(1, 1, 1))
|
|
}
|
|
const dist = box.min.distanceTo(box.max)
|
|
|
|
const x1 = box.min.x - (box.max.x-box.min.x) * 0.05 // - dist * 0.05
|
|
const y1 = box.min.y - (box.max.y-box.min.y) * 0.05 // - dist * 0.05
|
|
const z1 = box.min.z - (box.max.z-box.min.z) * 0.05 // - dist * 0.05
|
|
const x2 = box.max.x + (box.max.x-box.min.x) * 0.05 // + dist * 0.05
|
|
const y2 = box.max.y + (box.max.y-box.min.y) * 0.05 // + dist * 0.05
|
|
const z2 = box.max.z + (box.max.z-box.min.z) * 0.05 // + dist * 0.05
|
|
|
|
const newVertices = [
|
|
x1, y1, z1,
|
|
x2, y1, z1,
|
|
x2, y2, z1,
|
|
x1, y2, z1,
|
|
x1, y1, z2,
|
|
x2, y1, z2,
|
|
x2, y2, z2,
|
|
x1, y2, z2,
|
|
]
|
|
|
|
let boxVerts = this.boxGeometry.attributes.position.array
|
|
for(let i = 0; i < newVertices.length; i++) {
|
|
boxVerts[i] = newVertices[i]
|
|
}
|
|
|
|
this.boxGeometry.attributes.position.needsUpdate = true
|
|
this.boxGeometry.computeVertexNormals()
|
|
this.boxGeometry.computeBoundingBox()
|
|
this.boxGeometry.computeBoundingSphere()
|
|
this._generateOrUpdatePlanes()
|
|
this._attachControlsToBox()
|
|
this.boxHelper.update()
|
|
this.viewer.needsRender = true
|
|
}
|
|
|
|
toggle() {
|
|
this.setBox()
|
|
this.display.visible = !this.display.visible
|
|
this.viewer.renderer.localClippingEnabled = this.display.visible
|
|
this.viewer.needsRender = true
|
|
}
|
|
|
|
off() {
|
|
this.display.visible = false
|
|
this.viewer.renderer.localClippingEnabled = false
|
|
this.viewer.needsRender = true
|
|
}
|
|
|
|
on() {
|
|
this.display.visible = true
|
|
this.viewer.renderer.localClippingEnabled = true
|
|
this.viewer.needsRender = true
|
|
}
|
|
|
|
dispose() {
|
|
|
|
}
|
|
}
|