import * as THREE1 from "../Libs/node_modules/three/build/three.module.js"; const MAINCOLOR = 0xDDDDDD ; const ACCENTCOLOR = 0xF7F7F7 ; const OUTLINECOLOR = 0xCCCCCC ; export default class ViewCubeControls extends THREE1.EventDispatcher { constructor( camera, cubeSize, edgeSize, domElement, orbitControls) { super() ; this.cubeSize = cubeSize ; this.edgeSize = edgeSize ; this.domElement = domElement ; this._cube = new ViewCube({ size: this.cubeSize, edge: this.edgeSize, outline: true, bgColor: MAINCOLOR, hoverColor: ACCENTCOLOR, outlineColor: OUTLINECOLOR }) ; this._blockRot = false ; this._TopBottom = false ; this._camera = camera ; this._orbitControls = orbitControls ; this._dir = null ; this._lastSelFace = null ; this._currSelFace = null ; this._color = null ; this._name = null ; this._name_click = null ; this._interp = null ; this._animation = null ; this._faceList = [] ; this._red = 0xd9534f ; this._green = 0x5cb85c ; this._blue = 0x0275d8 ; this._vers = null ; this._rot = null ; this._last_event_target_x = null ; this._last_event_target_y = null ; this._handleMouseMove = this._handleMouseMove.bind( this) ; this._handleMouseClick = this._handleMouseClick.bind( this) ; this._listen() ; } _listen() { this.domElement.addEventListener( 'mousemove', this._handleMouseMove) ; this.domElement.addEventListener( 'click', this._handleMouseClick) ; } _handleMouseClick( event) { const x = ( event.offsetX / event.target.clientWidth) * 2 - 1 ; const y = -( event.offsetY / event.target.clientHeight) * 2 + 1 ; this._checkSideTouch( x, y) ; } _checkSideTouch( x, y) { const raycaster = new THREE1.Raycaster() ; raycaster.setFromCamera( { x, y }, this._camera) ; const intersects = raycaster.intersectObjects( this._cube.children, true) ; if ( intersects.length) { for ( let { object } of intersects) { if ( object.name) { this._name_click = object.name ; this._name = object.name ; this._rotateTheCube( object.name) ; break ; } } } } _rotateTheCube( side) { switch ( side) { case FACES.FRONT: this._setCubeAngles( 0, 0, 0) ; break ; case FACES.RIGHT: this._setCubeAngles( 0, -90, 0) ; break ; case FACES.BACK: this._setCubeAngles( 0, -180, 0) ; break ; case FACES.LEFT: this._setCubeAngles( 0, -270, 0) ; break ; case FACES.TOP: this._setCubeAngles( 90, 0, 0) ; break ; case FACES.BOTTOM: this._setCubeAngles( -90, 0, 0) ; break ; case FACES.TOP_FRONT_EDGE: this._setCubeAngles( 45, 0, 0) ; break ; case FACES.TOP_RIGHT_EDGE: this._setCubeAngles( 45, -90, 0) ; break ; case FACES.TOP_BACK_EDGE: this._setCubeAngles( 45, -180, 0) ; break ; case FACES.TOP_LEFT_EDGE: this._setCubeAngles( 45, -270, 0) ; break ; case FACES.BOTTOM_FRONT_EDGE: this._setCubeAngles( -45, 0, 0) ; break ; case FACES.BOTTOM_RIGHT_EDGE: this._setCubeAngles( -45, -90, 0) ; break ; case FACES.BOTTOM_BACK_EDGE: this._setCubeAngles( -45, -180, 0) ; break ; case FACES.BOTTOM_LEFT_EDGE: this._setCubeAngles( -45, -270, 0) ; break ; case FACES.FRONT_RIGHT_EDGE: this._setCubeAngles( 0, -45, 0) ; break ; case FACES.BACK_RIGHT_EDGE: this._setCubeAngles( 0, -135, 0) ; break ; case FACES.BACK_LEFT_EDGE: this._setCubeAngles( 0, -225, 0) ; break ; case FACES.FRONT_LEFT_EDGE: this._setCubeAngles( 0, -315, 0) ; break ; case FACES.TOP_FRONT_RIGHT_CORNER: this._setCubeAngles( 45, -45, 0) ; break ; case FACES.TOP_BACK_RIGHT_CORNER: this._setCubeAngles(45, -135, 0); break; case FACES.TOP_BACK_LEFT_CORNER: this._setCubeAngles( 45, -225, 0) ; break ; case FACES.TOP_FRONT_LEFT_CORNER: this._setCubeAngles( 45, -315, 0) ; break ; case FACES.BOTTOM_FRONT_RIGHT_CORNER: this._setCubeAngles(-45, -45, 0); break ; case FACES.BOTTOM_BACK_RIGHT_CORNER: this._setCubeAngles( -45, -135, 0) ; break ; case FACES.BOTTOM_BACK_LEFT_CORNER: this._setCubeAngles( -45, -225, 0) ; break ; case FACES.BOTTOM_FRONT_LEFT_CORNER: this._setCubeAngles( -45, -315, 0) ; break ; default: break ; } } _setCubeAngles( x, y, z) { const base = this._cube.rotation ; this._blockRot = true ; this._animation = { base: { x: base.x, y: base.y, z: base.z }, delta: { x: calculateAngleDelta( base.x, x * toRad, 'x'), y: calculateAngleDelta( base.y, y * toRad, 'y'), z: calculateAngleDelta( base.z, z * toRad, 'z') }, duration: 500, time: Date.now() } ; } _handleMouseMove( event) { const x = ( event.offsetX / event.target.clientWidth) * 2 - 1 ; const y = -( event.offsetY / event.target.clientHeight) * 2 + 1 ; this._last_event_target_x = x ; this._last_event_target_y = y ; this._checkSideOver( x, y) ; } _checkSideOver(x, y) { const raycaster = new THREE1.Raycaster() ; raycaster.setFromCamera( { x, y }, this._camera) ; const intersects = raycaster.intersectObjects( this._cube.children, true) ; // check hover if ( intersects.length) { for ( let { object } of intersects) { if ( object.name) { object.parent.children.forEach( function( child) { if ( child.name === object.name) { child.material.color.setHex( ACCENTCOLOR) ; } }) ; this.decolorCube( object.name) ; break ; } } if ( intersects[0].object.name != null) { this._name = intersects[0].object.name ; } } else if ( ! this.name) { this._name = null ; this.decolorCube( null) ; } } decolorCube( name) { // main faces for ( let i = 0 ; i < this._cube.children[0].children.length ; ++ i) { if ( this._cube.children[0].children[i].name != name) this._cube.children[0].children[i].material.color.set( this._cube.children[0].children[i].material.oldColor) ; } // edges and corners for ( let i = 1 ; i < this._cube.children.length ; ++ i) { const child = this._cube.children[i] ; for ( let j = 0 ; j < child.children.length ; ++ j) { const granChild = child.children[j] ; for ( let k = 0 ; k < granChild.children.length ; ++ k) { const myMesh = granChild.children[k] ; if ( myMesh.name !== name) myMesh.material.color.set( myMesh.material.oldColor) ; } } } } update( orbitControls) { this._animate() ; this._orbitControls = orbitControls ; } _animate() { this._orbitControls.object.updateMatrix() ; var invRotMat = new THREE1.Matrix4() ; invRotMat.extractRotation( this._orbitControls.object.matrix) ; invRotMat.invert() ; const RotY_mat = new THREE1.Matrix4() ; RotY_mat.makeRotationY( Math.PI / 2) ; invRotMat.multiply( RotY_mat) ; var euler = new THREE1.Euler().setFromRotationMatrix( invRotMat) ; this._cube.rotation.set( euler.x, euler.y , euler.z) ; if ( this._animation) { // for top and bottom faces if ( this._name_click == 1 || this._name_click == 6) { //this._TopBottomRotation( this._name_click, this._orbitControls) ; } this.dispatchEvent({ type: 'angle-change', quaternion: this._cube.quaternion.clone(), }) ; this._animation = null ; } else { this._interp = null ; } if ( this._last_event_target_x != null && this._last_event_target_y != null) this._checkSideOver( this._last_event_target_x, this._last_event_target_y) ; } _TopBottomRotation( type, orbit){ const duration = 150 ; const start = performance.now() ; const maxAlpha = 1 ; var theta_i = orbit.object.rotation.z ; var theta_tn = 0 ; var theta_to = 0 ; var theta_t = theta_i ; var theta_tt = theta_i ; var somma = 0 ; function loop() { const now = performance.now() ; const delta = now - start ; const alpha = Math.min( delta / duration, maxAlpha); if ( type == 1){ if ( theta_i >= -Math.PI / 2 && theta_i <= Math.PI / 2){ theta_tt = theta_t ; if ( theta_i >= 0){ theta_t = theta_i - alpha * ( Math.PI / 2 + theta_i) ; var jump = theta_t - theta_tt ; somma += jump ; orbit.rotateLeft( - jump) ; } if ( theta_i < 0) { theta_t = theta_i - alpha * ( Math.PI / 2 + theta_i); var jump = theta_t - theta_tt ; orbit.rotateLeft( - jump) ; } } else { theta_tt = theta_t ; if ( theta_i >= 0){ theta_t = theta_i + alpha * ( Math.PI/2 + Math.PI - theta_i) ; var jump = theta_t - theta_tt ; orbit.rotateLeft( - jump) ; } if ( theta_i < 0){ theta_t = theta_i + alpha * (- theta_i - Math.PI / 2) ; var jump = theta_t - theta_tt ; orbit.rotateLeft( - jump) ; } } } if ( type == 6){ if( theta_i >= -Math.PI/2 && theta_i <= Math.PI / 2){ theta_tt = theta_t ; if ( theta_i >= 0){ theta_t = theta_i + alpha * ( Math.PI / 2 - theta_i) ; var jump = theta_t - theta_tt ; orbit.rotateLeft( jump) ; } if( theta_i < 0){ theta_t = theta_i + alpha * ( Math.PI / 2 - theta_i) ; var jump = theta_t - theta_tt ; orbit.rotateLeft( jump) ; } } else { theta_tt = theta_t ; if ( theta_i >= 0){ theta_t = theta_i - alpha * ( theta_i - Math.PI / 2) ; var jump = theta_t - theta_tt ; orbit.rotateLeft(jump); } if (theta_i < 0){ theta_t = theta_i + alpha * ( Math.PI + Math.PI / 2 + theta_i); var jump = theta_t - theta_tt ; orbit.rotateLeft( - jump) ; } } } orbit.update() ; if ( alpha !== maxAlpha){ return requestAnimationFrame( loop) ; } } loop() ; } _animateCubeRotation({ base, delta }, alpha) { const ease = ( Math.sin((( alpha * 2) - 1) * Math.PI * 0.5) + 1) * 0.5 ; let angleX = -TWOPI + base.x + delta.x * ease ; let angleY = -TWOPI + base.y + delta.y * ease ; let angleZ = -TWOPI + base.z + delta.z * ease ; this._cube.rotation.set( angleX % TWOPI, angleY % TWOPI, angleZ % TWOPI) ; } _colorCube() { // defining standard color ( tone mapping Toy ) var blue = this._blue ; var red = this._red ; var green = this._green ; // main faces this._cube.children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[0].children[1].material.color = new THREE1.Color( green) ; this._cube.children[0].children[2].material.color = new THREE1.Color( red) ; this._cube.children[0].children[3].material.color = new THREE1.Color( green) ; this._cube.children[0].children[4].material.color = new THREE1.Color( blue) ; this._cube.children[0].children[5].material.color = new THREE1.Color( blue) ; // other faces this._cube.children[1].children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[1].children[0].children[1].material.color = new THREE1.Color( green) ; this._cube.children[1].children[0].children[2].material.color = new THREE1.Color( blue) ; this._cube.children[1].children[1].children[0].material.color = new THREE1.Color( green) ; this._cube.children[1].children[1].children[1].material.color = new THREE1.Color( red) ; this._cube.children[1].children[1].children[2].material.color = new THREE1.Color( blue) ; this._cube.children[1].children[2].children[0].material.color = new THREE1.Color( red) ; this._cube.children[1].children[2].children[1].material.color = new THREE1.Color( green); this._cube.children[1].children[2].children[2].material.color = new THREE1.Color( blue) ; this._cube.children[1].children[3].children[0].material.color = new THREE1.Color( green) ; this._cube.children[1].children[3].children[1].material.color = new THREE1.Color( red) ; this._cube.children[1].children[3].children[2].material.color = new THREE1.Color (blue) ; this._cube.children[2].children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[2].children[0].children[1].material.color = new THREE1.Color( green); this._cube.children[2].children[0].children[2].material.color = new THREE1.Color( blue) ; this._cube.children[2].children[1].children[0].material.color = new THREE1.Color( green); this._cube.children[2].children[1].children[1].material.color = new THREE1.Color( red) ; this._cube.children[2].children[1].children[2].material.color = new THREE1.Color( blue); this._cube.children[2].children[2].children[0].material.color = new THREE1.Color( red) ; this._cube.children[2].children[2].children[1].material.color = new THREE1.Color( green) ; this._cube.children[2].children[2].children[2].material.color = new THREE1.Color( blue) ; this._cube.children[2].children[3].children[0].material.color = new THREE1.Color( green) ; this._cube.children[2].children[3].children[1].material.color = new THREE1.Color( red) ; this._cube.children[2].children[3].children[2].material.color = new THREE1.Color( blue); this._cube.children[3].children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[3].children[0].children[1].material.color = new THREE1.Color( blue); this._cube.children[3].children[1].children[0].material.color = new THREE1.Color( green) ; this._cube.children[3].children[1].children[1].material.color = new THREE1.Color( blue); this._cube.children[3].children[2].children[0].material.color = new THREE1.Color( red) ; this._cube.children[3].children[2].children[1].material.color = new THREE1.Color( blue); this._cube.children[3].children[3].children[0].material.color = new THREE1.Color( green) ; this._cube.children[3].children[3].children[1].material.color = new THREE1.Color( blue) ; this._cube.children[4].children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[4].children[0].children[1].material.color = new THREE1.Color( blue) ; this._cube.children[4].children[1].children[0].material.color = new THREE1.Color( green) ; this._cube.children[4].children[1].children[1].material.color = new THREE1.Color( blue) ; this._cube.children[4].children[2].children[0].material.color = new THREE1.Color( red) ; this._cube.children[4].children[2].children[1].material.color = new THREE1.Color( blue); this._cube.children[4].children[3].children[0].material.color = new THREE1.Color( green) ; this._cube.children[4].children[3].children[1].material.color = new THREE1.Color( blue) ; this._cube.children[5].children[0].children[0].material.color = new THREE1.Color( red) ; this._cube.children[5].children[0].children[1].material.color = new THREE1.Color( green) ; this._cube.children[5].children[1].children[0].material.color = new THREE1.Color( green) ; this._cube.children[5].children[1].children[1].material.color = new THREE1.Color( red) ; this._cube.children[5].children[2].children[0].material.color = new THREE1.Color( red) ; this._cube.children[5].children[2].children[1].material.color = new THREE1.Color( green) ; this._cube.children[5].children[3].children[0].material.color = new THREE1.Color( green) ; this._cube.children[5].children[3].children[1].material.color = new THREE1.Color( red) ; // setting second Color for raytracaing effect this._cube.children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[0].children[1].material.oldColor = new THREE1.Color( green); this._cube.children[0].children[2].material.oldColor = new THREE1.Color( red) ; this._cube.children[0].children[3].material.oldColor = new THREE1.Color( green); this._cube.children[0].children[4].material.oldColor = new THREE1.Color( blue) ; this._cube.children[0].children[5].material.oldColor = new THREE1.Color( blue) ; this._cube.children[1].children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[1].children[0].children[1].material.oldColor = new THREE1.Color( green) ; this._cube.children[1].children[0].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[1].children[1].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[1].children[1].children[1].material.oldColor = new THREE1.Color( red) ; this._cube.children[1].children[1].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[1].children[2].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[1].children[2].children[1].material.oldColor = new THREE1.Color( green); this._cube.children[1].children[2].children[2].material.oldColor = new THREE1.Color( blue); this._cube.children[1].children[3].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[1].children[3].children[1].material.oldColor = new THREE1.Color( red) ; this._cube.children[1].children[3].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[2].children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[2].children[0].children[1].material.oldColor = new THREE1.Color( green) ; this._cube.children[2].children[0].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[2].children[1].children[0].material.oldColor = new THREE1.Color( green); this._cube.children[2].children[1].children[1].material.oldColor = new THREE1.Color( red) ; this._cube.children[2].children[1].children[2].material.oldColor = new THREE1.Color( blue); this._cube.children[2].children[2].children[0].material.oldColor = new THREE1.Color( red); this._cube.children[2].children[2].children[1].material.oldColor = new THREE1.Color( green); this._cube.children[2].children[2].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[2].children[3].children[0].material.oldColor = new THREE1.Color( green); this._cube.children[2].children[3].children[1].material.oldColor = new THREE1.Color( red) ; this._cube.children[2].children[3].children[2].material.oldColor = new THREE1.Color( blue) ; this._cube.children[3].children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[3].children[0].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[3].children[1].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[3].children[1].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[3].children[2].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[3].children[2].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[3].children[3].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[3].children[3].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[4].children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[4].children[0].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[4].children[1].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[4].children[1].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[4].children[2].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[4].children[2].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[4].children[3].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[4].children[3].children[1].material.oldColor = new THREE1.Color( blue) ; this._cube.children[5].children[0].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[5].children[0].children[1].material.oldColor = new THREE1.Color(green) ; this._cube.children[5].children[1].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[5].children[1].children[1].material.oldColor = new THREE1.Color( red) ; this._cube.children[5].children[2].children[0].material.oldColor = new THREE1.Color( red) ; this._cube.children[5].children[2].children[1].material.oldColor = new THREE1.Color( green) ; this._cube.children[5].children[3].children[0].material.oldColor = new THREE1.Color( green) ; this._cube.children[5].children[3].children[1].material.oldColor = new THREE1.Color( red) ; // adding faces to list this._face_list = [] ; this._face_list.push( this._cube.children[0].children[0]) ; this._face_list.push( this._cube.children[0].children[1]) ; this._face_list.push( this._cube.children[0].children[2]) ; this._face_list.push( this._cube.children[0].children[3]) ; this._face_list.push( this._cube.children[0].children[4]) ; this._face_list.push( this._cube.children[0].children[5]) ; this._face_list.push( this._cube.children[1].children[0].children[0]) ; this._face_list.push( this._cube.children[1].children[0].children[1]) ; this._face_list.push( this._cube.children[1].children[0].children[2]) ; this._face_list.push( this._cube.children[1].children[1].children[0]) ; this._face_list.push( this._cube.children[1].children[1].children[1]) ; this._face_list.push( this._cube.children[1].children[1].children[2]) ; this._face_list.push( this._cube.children[1].children[2].children[0]) ; this._face_list.push( this._cube.children[1].children[2].children[1]) ; this._face_list.push( this._cube.children[1].children[2].children[2]) ; this._face_list.push( this._cube.children[1].children[3].children[0]) ; this._face_list.push( this._cube.children[1].children[3].children[1]) ; this._face_list.push( this._cube.children[1].children[3].children[2]) ; this._face_list.push( this._cube.children[2].children[0].children[0]) ; this._face_list.push( this._cube.children[2].children[0].children[1]) ; this._face_list.push( this._cube.children[2].children[0].children[2]) ; this._face_list.push( this._cube.children[2].children[1].children[0]) ; this._face_list.push( this._cube.children[2].children[1].children[1]) ; this._face_list.push( this._cube.children[2].children[1].children[2]) ; this._face_list.push( this._cube.children[2].children[2].children[0]) ; this._face_list.push( this._cube.children[2].children[2].children[1]) ; this._face_list.push( this._cube.children[2].children[2].children[2]) ; this._face_list.push( this._cube.children[2].children[3].children[0]) ; this._face_list.push( this._cube.children[2].children[3].children[1]) ; this._face_list.push( this._cube.children[2].children[3].children[2]) ; this._face_list.push( this._cube.children[3].children[0].children[0]) ; this._face_list.push( this._cube.children[3].children[0].children[1]) ; this._face_list.push( this._cube.children[3].children[1].children[0]) ; this._face_list.push( this._cube.children[3].children[1].children[1]) ; this._face_list.push( this._cube.children[3].children[2].children[0]) ; this._face_list.push( this._cube.children[3].children[2].children[1]) ; this._face_list.push( this._cube.children[3].children[3].children[0]) ; this._face_list.push( this._cube.children[3].children[3].children[1]) ; this._face_list.push( this._cube.children[4].children[0].children[0]) ; this._face_list.push( this._cube.children[4].children[0].children[1]) ; this._face_list.push( this._cube.children[4].children[1].children[0]) ; this._face_list.push( this._cube.children[4].children[1].children[1]) ; this._face_list.push( this._cube.children[4].children[2].children[0]) ; this._face_list.push( this._cube.children[4].children[2].children[1]) ; this._face_list.push( this._cube.children[4].children[3].children[0]) ; this._face_list.push( this._cube.children[4].children[3].children[1]) ; this._face_list.push( this._cube.children[5].children[0].children[0]) ; this._face_list.push( this._cube.children[5].children[0].children[1]) ; this._face_list.push( this._cube.children[5].children[1].children[0]) ; this._face_list.push( this._cube.children[5].children[1].children[1]) ; this._face_list.push( this._cube.children[5].children[2].children[0]) ; this._face_list.push( this._cube.children[5].children[2].children[1]) ; this._face_list.push( this._cube.children[5].children[3].children[0]) ; this._face_list.push( this._cube.children[5].children[3].children[1]) ; } _setVersorAndRotation() { switch ( this._name) { case 2: // RIGHT this._vers = new THREE1.Vector3( 1, 0, 0) ; this._rot = new THREE1.Vector3( 0 * toRad, 90 * toRad, 0 * toRad) ; break ; case 4: // LEFT this._vers = new THREE1.Vector3( -1, 0, 0) ; this._rot = new THREE1.Vector3( 0 * toRad, -90 * toRad, 0 * toRad) ; break ; case 3: // FRONT this._vers = new THREE1.Vector3( 0, 0, -1) ; this._rot = new THREE1.Vector3( 0 * toRad, 0 * toRad, 180 * toRad) ; break ; case 5: // BACK this._vers = new THREE1.Vector3( 0, 0, 1) ; this._rot = new THREE1.Vector3( 0 * toRad, 0 * toRad, 0 * toRad) ; break ; case 1: // TOP this._vers = new THREE1.Vector3( 0, 1, 0) ; this._rot = new THREE1.Vector3( 90 * toRad, 0 * toRad, 0 * toRad) ; break ; case 6: // BOTTOM this._vers = new THREE1.Vector3( 0, -1, 0) ; this._rot = new THREE1.Vector3( -90 * toRad, 0 * toRad, 0 * toRad) ; break ; case 11: // RIGHT-FRONT this._vers = new THREE1.Vector3( 1 / Math.sqrt( 2), 0, - 1 / Math.sqrt( 2)) ; this._rot = new THREE1.Vector3( 0 * toRad, 45 * toRad, 0 * toRad) ; break ; case 7: // RIGHT-TOP this._vers = new THREE1.Vector3( 1 / Math.sqrt( 2), 1 / Math.sqrt( 2), 0.) ; this._rot = new THREE1.Vector3( 45 * toRad, 90 * toRad, 0 * toRad) ; break ; case 14: // BACK-RIGHT this._vers = new THREE1.Vector3( 1 / Math.sqrt( 2), 0, 1 / Math.sqrt( 2)) ; this._rot = new THREE1.Vector3( 0 * toRad, -315 * toRad, 0 * toRad) ; break ; case 15: // BOTTOM-RIGHT this._vers = new THREE1.Vector3( 1 / Math.sqrt( 2), -1 / Math.sqrt( 2), 0.) ; this._rot = new THREE1.Vector3( 135 * toRad, - 135 * toRad, 0 * toRad) ; break ; case 12: // FRONT-LEFT this._vers = new THREE1.Vector3( -1 / Math.sqrt( 2), 0, -1 / Math.sqrt( 2)) ; this._rot = new THREE1.Vector3( 0 * toRad, 135 * toRad, 0 * toRad) ; break ; case 9: // LEFT-TOP this._vers = new THREE1.Vector3( -1 / Math.sqrt( 2), 1 / Math.sqrt( 2), 0) ; this._rot = new THREE1.Vector3( 45 * toRad, -90 * toRad, 0 * toRad) ; break ; case 13: // LEFT-BACK this._vers = new THREE1.Vector3( -1 / Math.sqrt(2), 0, 1 / Math.sqrt(2)) ; this._rot = new THREE1.Vector3(0 * toRad, -45 * toRad, 0 * toRad) ; break ; case 17: // BOTTOM-LEFT this._vers = new THREE1.Vector3( -1 / Math.sqrt( 2), -1 / Math.sqrt( 2), 0) ; this._rot = new THREE1.Vector3( -45 * toRad, 90 * toRad, 0 * toRad) ; break ; case 8: // FRONT-TOP this._vers = new THREE1.Vector3( 0., 1 / Math.sqrt( 2), -1 / Math.sqrt( 2)) ; this._rot = new THREE1.Vector3( 45 * toRad, 180 * toRad, 0 * toRad) ; break ; case 16: // BOTTOM-FRONT this._vers = new THREE1.Vector3( 0., -1 / Math.sqrt( 2), -1 / Math.sqrt(2)) ; this._rot = new THREE1.Vector3( 135 * toRad, 0 * toRad, 0 * toRad) ; break ; case 10: // TOP-BACK this._vers = new THREE1.Vector3( 0, 1 / Math.sqrt( 2), 1 / Math.sqrt( 2)) ; this._rot = new THREE1.Vector3( 45 * toRad, 0 * toRad, 0 * toRad) ; break ; case 18: // BOTTOM-BACK this._vers = new THREE1.Vector3( 0., -1 / Math.sqrt(2), 1 / Math.sqrt(2), 0) ; this._rot = new THREE1.Vector3( 135 * toRad, 180 * toRad, 0 * toRad) ; break ; case 21: // LEFT-BACK-TOP this._vers = new THREE1.Vector3( -1 / Math.sqrt( 3), 1 / Math.sqrt( 3), 1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 45 * toRad, -45 * toRad, 0 * toRad) ; break ; case 20: // FRONT-LEFT-TOP this._vers = new THREE1.Vector3( -1 / Math.sqrt( 3), 1 / Math.sqrt( 3), -1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 45 * toRad, -135 * toRad, 0 * toRad) ; break ; case 19: // RIGHT-FRONT-TOP this._vers = new THREE1.Vector3( 1 / Math.sqrt( 3), 1 / Math.sqrt( 3), -1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 45 * toRad, 135 * toRad, 0 * toRad) ; break ; case 22: // BACK-RIGHT-TOP this._vers = new THREE1.Vector3( 1 / Math.sqrt( 3), 1 / Math.sqrt( 3), 1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 45 * toRad, 45 * toRad, 0 * toRad) ; break ; case 26: // BOTTOM-BACK-RIGHT this._vers = new THREE1.Vector3( 1 / Math.sqrt( 3), -1 / Math.sqrt( 3), 1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 135 * toRad, 45 * toRad, 0 * toRad); break ; case 23: // BOTTOM-RIGHT-FRONT this._vers = new THREE1.Vector3( 1 / Math.sqrt( 3), -1 / Math.sqrt( 3), -1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 135 * toRad, 135 * toRad, 0 * toRad); break ; case 25: // BOTTOM-LEFT-BACK this._vers = new THREE1.Vector3( -1 / Math.sqrt( 3), -1 / Math.sqrt( 3), 1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 135 * toRad, -45 * toRad, 0 * toRad); break ; case 24: // BOTTOM-FRONT-LEFT this._vers = new THREE1.Vector3( -1 / Math.sqrt( 3), -1 / Math.sqrt( 3), -1 / Math.sqrt( 3)) ; this._rot = new THREE1.Vector3( 135 * toRad, - 135 * toRad, 0 * toRad) ; break ; } } setQuaternion( quaternion) { this._cube.setRotationFromQuaternion( quaternion) ; } getObject() { return this._cube ; } } class ViewCube extends THREE1.Object3D { constructor({ size = 60, edge = 5, outline = true, bgColor = 0xCCCCCC, hoverColor = 0xFFFFFF, outlineColor = 0x999999 }) { super() ; this._cubeSize = size ; this._edgeSize = edge ; this._outline = outline ; this._bgColor = bgColor ; this._hoverColor = hoverColor ; this._outlineColor = outlineColor ; this._build() ; } _build() { const faceSize = this._cubeSize - this._edgeSize * 2 ; const faceOffset = this._cubeSize / 2 ; const borderSize = this._edgeSize ; /* faces: front, right, back, left, top, bottom */ const cubeFaces = this._createCubeFaces( faceSize, faceOffset); for ( let [i, props] of BOX_FACES.entries()) { cubeFaces.children[i].name = props.name ; cubeFaces.children[i].material.color.setHex( this._bgColor) ; cubeFaces.children[i].material.map = props.map ; } this.add( cubeFaces) ; /* corners: top, bottom */ const corners = [] ; for ( let [i, props] of CORNER_FACES.entries()) { const corner = this._createCornerFaces( borderSize, faceOffset, props.name, { color: this._bgColor}) ; corner.rotateOnAxis( new THREE1.Vector3( 0, 1, 0), ( i % 4) * 90 * toRad) ; corners.push( corner) ; } const topCorners = new THREE1.Group() ; const bottomCorners = new THREE1.Group() ; this.add( topCorners.add( ...corners.slice(0, 4))) ; this.add( bottomCorners.add( ...corners.slice(4)).rotateOnAxis( new THREE1.Vector3( 1, 0, 0), 180 * toRad)) ; /* edges: top + bottom */ const edges = [] ; for ( let [i, props] of EDGE_FACES.entries()) { const edge = this._createHorzEdgeFaces( faceSize, borderSize, faceOffset, props.name, { color: this._bgColor}) ; edge.rotateOnAxis( new THREE1.Vector3(0, 1, 0), (i % 4) * 90 * toRad) ; edges.push( edge) ; } const topEdges = new THREE1.Group() ; const bottomEdges = new THREE1.Group() ; this.add( topEdges.add( ...edges.slice(0, 4))) ; this.add( bottomEdges.add( ...edges.slice(4)).rotateOnAxis( new THREE1.Vector3(1, 0, 0), 180 * toRad)) ; /* edges on the side */ const sideEdges = new THREE1.Group() ; for ( let [i, props] of EDGE_FACES_SIDE.entries()) { const edge = this._createVertEdgeFaces( borderSize, faceSize, faceOffset, props.name, { color: this._bgColor}) ; edge.rotateOnAxis( new THREE1.Vector3( 0, 1, 0), i * 90 * toRad) ; sideEdges.add( edge) ; } this.add( sideEdges) ; if ( this._outline) { this.add( this._createCubeOutline( this._cubeSize)) ; } } _createFace( size, position, { axis = [0, 1, 0], angle = 0, name = "", matProps = {} } = {}) { if ( ! Array.isArray( size)) size = [size, size] ; const material = new THREE1.MeshBasicMaterial( matProps) ; const geometry = new THREE1.PlaneGeometry( size[0], size[1]) ; const face = new THREE1.Mesh( geometry, material) ; face.name = name ; face.rotateOnAxis( new THREE1.Vector3( ...axis), angle * toRad) ; face.position.set( ...position); return face ; } _createCubeFaces( faceSize, offset) { const faces = new THREE1.Object3D() ; faces.add( this._createFace( faceSize, [0, 0, offset], { axis: [0, 1, 0], angle: 0 })); faces.add( this._createFace( faceSize, [offset, 0, 0], { axis: [0, 1, 0], angle: 90 })); faces.add( this._createFace( faceSize, [0, 0, -offset], { axis: [0, 1, 0], angle: 180 })); faces.add( this._createFace( faceSize, [-offset, 0, 0], { axis: [0, 1, 0], angle: 270 })); faces.add(( this._createFace( faceSize, [0, offset, 0], { axis: [1, 0, 0], angle: -90 })).rotateOnAxis( new THREE1.Vector3(0,0,1), -Math.PI / 2)) ; faces.add( this._createFace( faceSize, [0, -offset, 0], { axis: [1, 0, 0], angle: 90 }).rotateOnAxis( new THREE1.Vector3(0,0,1), Math.PI / 2)) ; return faces; } _createCornerFaces( faceSize, offset, name = "", matProps = {}) { const corner = new THREE1.Object3D() ; const borderOffset = offset - faceSize / 2 ; corner.add(this._createFace( faceSize, [borderOffset, borderOffset, offset], { axis: [0, 1, 0], angle: 0, matProps, name })) ; corner.add( this._createFace( faceSize, [offset, borderOffset, borderOffset], { axis: [0, 1, 0], angle: 90, matProps, name })) ; corner.add( this._createFace( faceSize, [borderOffset, offset, borderOffset], { axis: [1, 0, 0], angle: -90, matProps, name })) ; return corner ; } _createHorzEdgeFaces( w, h, offset, name = "", matProps = {}) { const edge = new THREE1.Object3D() ; const borderOffset = offset - h / 2 ; edge.add( this._createFace( [w, h], [0, borderOffset, offset], { axis: [0, 1, 0], angle: 0, name, matProps })) ; edge.add( this._createFace( [w, h], [0, offset, borderOffset], { axis: [1, 0, 0], angle: -90, name, matProps })) ; return edge ; } _createVertEdgeFaces( w, h, offset, name = "", matProps = {}) { const edge = new THREE1.Object3D() ; const borderOffset = offset - w / 2 ; edge.add( this._createFace([w, h], [borderOffset, 0, offset], { axis: [0, 1, 0], angle: 0, name, matProps })) ; edge.add( this._createFace([w, h], [offset, 0, borderOffset], { axis: [0, 1, 0], angle: 90, name, matProps })) ; return edge; } _createCubeOutline( size) { const geometry = new THREE1.BoxGeometry( size, size, size) ; const geo = new THREE1.EdgesGeometry( geometry); const mat = new THREE1.LineBasicMaterial({ color: this._outlineColor, linewidth: 1 }) ; const wireframe = new THREE1.LineSegments( geo, mat) ; return wireframe ; } } var toRad = Math.PI / 180 ; var TWOPI = 2 * Math.PI ; function calculateAngleDelta( from, to, axis) { const direct = to - from ; const altA = direct - TWOPI ; const altB = direct + TWOPI ; if ( Math.abs( direct) > Math.abs( altA)) return altA ; else if ( Math.abs( direct) > Math.abs( altB)) return altB ; // direction always between [-PI, +PI] return direct ; } function createTextSprite( text, props) { const fontface = props.font || 'Helvetica' ; const fontsize = props.fontSize || 30 ; const width = props.width || 200 ; const height = props.height || 200 ; const bgColor = props.color ? props.bgColor.join(', ') : "255, 255, 255, 1.0" ; const fgColor = props.color ? props.color.join(', ') : "0, 0, 0, 1.0" ; const canvas = document.createElement( 'canvas') ; canvas.width = width ; canvas.height = height ; const context = canvas.getContext( '2d') ; context.font = `bold ${fontsize}px ${fontface}` ; context.fillStyle = `rgba(${bgColor})` ; context.fillRect( 0, 0, width, height) ; // get size data (height depends only on font size) const metrics = context.measureText( text) ; const textWidth = metrics.width ; // text color context.fillStyle = `rgba(${fgColor})`; context.fillText( text, width / 2 - textWidth / 2, height / 2 + fontsize / 2 - 2) ; // canvas contents will be used for a texture const texture = new THREE1.Texture( canvas) texture.minFilter = THREE1.LinearFilter ; texture.needsUpdate = true ; return texture ; } var FACES = { TOP: 1, FRONT: 2, RIGHT: 3, BACK: 4, LEFT: 5, BOTTOM: 6, TOP_FRONT_EDGE: 7, TOP_RIGHT_EDGE: 8, TOP_BACK_EDGE: 9, TOP_LEFT_EDGE: 10, FRONT_RIGHT_EDGE: 11, BACK_RIGHT_EDGE: 12, BACK_LEFT_EDGE: 13, FRONT_LEFT_EDGE: 14, BOTTOM_FRONT_EDGE: 15, BOTTOM_RIGHT_EDGE: 16, BOTTOM_BACK_EDGE: 17, BOTTOM_LEFT_EDGE: 18, TOP_FRONT_RIGHT_CORNER: 19, TOP_BACK_RIGHT_CORNER: 20, TOP_BACK_LEFT_CORNER: 21, TOP_FRONT_LEFT_CORNER: 22, BOTTOM_FRONT_RIGHT_CORNER: 23, BOTTOM_BACK_RIGHT_CORNER: 24, BOTTOM_BACK_LEFT_CORNER: 25, BOTTOM_FRONT_LEFT_CORNER: 26 }; var BOX_FACES = [ { name: FACES.FRONT, map: createTextSprite( "RIGHT", { fontSize: 60, font: "Arial Narrow, sans-serif" }) }, { name: FACES.RIGHT, map: createTextSprite( "BACK", { fontSize: 60, font: "Arial Narrow, sans-serif" }) }, { name: FACES.BACK, map: createTextSprite( "LEFT", { fontSize: 60, font: "Arial Narrow, sans-serif" }) }, { name: FACES.LEFT, map: createTextSprite( "FRONT", { fontSize: 60, font: "Arial Narrow, sans-serif" }) }, { name: FACES.TOP, map: createTextSprite( "TOP", { fontSize: 60, font: "Arial Narrow, sans-serif" }) }, { name: FACES.BOTTOM, map: createTextSprite( "BOTTOM", { fontSize: 40, font: "Arial Narrow, sans-serif" }) } ] ; var CORNER_FACES = [ { name: FACES.TOP_FRONT_RIGHT_CORNER }, { name: FACES.TOP_BACK_RIGHT_CORNER }, { name: FACES.TOP_BACK_LEFT_CORNER }, { name: FACES.TOP_FRONT_LEFT_CORNER }, { name: FACES.BOTTOM_BACK_RIGHT_CORNER }, { name: FACES.BOTTOM_FRONT_RIGHT_CORNER }, { name: FACES.BOTTOM_FRONT_LEFT_CORNER }, { name: FACES.BOTTOM_BACK_LEFT_CORNER } ] ; var EDGE_FACES = [ { name: FACES.TOP_FRONT_EDGE }, { name: FACES.TOP_RIGHT_EDGE }, { name: FACES.TOP_BACK_EDGE }, { name: FACES.TOP_LEFT_EDGE }, // flip back and front bottom edges { name: FACES.BOTTOM_BACK_EDGE }, { name: FACES.BOTTOM_RIGHT_EDGE }, { name: FACES.BOTTOM_FRONT_EDGE }, { name: FACES.BOTTOM_LEFT_EDGE }, ] ; var EDGE_FACES_SIDE = [ { name: FACES.FRONT_RIGHT_EDGE }, { name: FACES.BACK_RIGHT_EDGE }, { name: FACES.BACK_LEFT_EDGE }, { name: FACES.FRONT_LEFT_EDGE } ] ; // merge them all to ease the traversing var CUBE_FACES = [...BOX_FACES, ...CORNER_FACES, ...EDGE_FACES, ...EDGE_FACES_SIDE] ;