mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-30 09:24:57 +01:00
624 lines
11 KiB
JavaScript
624 lines
11 KiB
JavaScript
|
/**
|
||
|
* @author mrdoob / http://mrdoob.com/
|
||
|
*/
|
||
|
|
||
|
var Viewport = function ( editor ) {
|
||
|
|
||
|
var signals = editor.signals;
|
||
|
|
||
|
var container = new UI.Panel();
|
||
|
container.setId( 'viewport' );
|
||
|
container.setPosition( 'absolute' );
|
||
|
|
||
|
container.add( new Viewport.Info( editor ) );
|
||
|
|
||
|
var scene = editor.scene;
|
||
|
var sceneHelpers = editor.sceneHelpers;
|
||
|
|
||
|
var objects = [];
|
||
|
|
||
|
// helpers
|
||
|
|
||
|
var grid = new THREE.GridHelper( 500, 25 );
|
||
|
sceneHelpers.add( grid );
|
||
|
|
||
|
//
|
||
|
|
||
|
var camera = editor.camera;
|
||
|
camera.position.fromArray( editor.config.getKey( 'camera/position' ) );
|
||
|
camera.lookAt( new THREE.Vector3().fromArray( editor.config.getKey( 'camera/target' ) ) );
|
||
|
|
||
|
//
|
||
|
|
||
|
var selectionBox = new THREE.BoxHelper();
|
||
|
selectionBox.material.depthTest = false;
|
||
|
selectionBox.material.transparent = true;
|
||
|
selectionBox.visible = false;
|
||
|
sceneHelpers.add( selectionBox );
|
||
|
|
||
|
var transformControls = new THREE.TransformControls( camera, container.dom );
|
||
|
transformControls.addEventListener( 'change', function () {
|
||
|
|
||
|
var object = transformControls.object;
|
||
|
|
||
|
if ( object !== undefined ) {
|
||
|
|
||
|
if ( editor.helpers[ object.id ] !== undefined ) {
|
||
|
|
||
|
editor.helpers[ object.id ].update();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
transformControls.addEventListener( 'mouseDown', function () {
|
||
|
|
||
|
controls.enabled = false;
|
||
|
|
||
|
} );
|
||
|
transformControls.addEventListener( 'mouseUp', function () {
|
||
|
|
||
|
signals.objectChanged.dispatch( transformControls.object );
|
||
|
controls.enabled = true;
|
||
|
|
||
|
} );
|
||
|
|
||
|
sceneHelpers.add( transformControls );
|
||
|
|
||
|
// fog
|
||
|
|
||
|
var oldFogType = "None";
|
||
|
var oldFogColor = 0xaaaaaa;
|
||
|
var oldFogNear = 1;
|
||
|
var oldFogFar = 5000;
|
||
|
var oldFogDensity = 0.00025;
|
||
|
|
||
|
// object picking
|
||
|
|
||
|
var raycaster = new THREE.Raycaster();
|
||
|
var mouse = new THREE.Vector2();
|
||
|
|
||
|
// events
|
||
|
|
||
|
var getIntersects = function ( point, object ) {
|
||
|
|
||
|
mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
|
||
|
|
||
|
raycaster.setFromCamera( mouse, camera );
|
||
|
|
||
|
if ( object instanceof Array ) {
|
||
|
|
||
|
return raycaster.intersectObjects( object );
|
||
|
|
||
|
}
|
||
|
|
||
|
return raycaster.intersectObject( object );
|
||
|
|
||
|
};
|
||
|
|
||
|
var onDownPosition = new THREE.Vector2();
|
||
|
var onUpPosition = new THREE.Vector2();
|
||
|
var onDoubleClickPosition = new THREE.Vector2();
|
||
|
|
||
|
var getMousePosition = function ( dom, x, y ) {
|
||
|
|
||
|
var rect = dom.getBoundingClientRect();
|
||
|
return [ ( x - rect.left ) / rect.width, ( y - rect.top ) / rect.height ];
|
||
|
|
||
|
};
|
||
|
|
||
|
var handleClick = function () {
|
||
|
|
||
|
if ( onDownPosition.distanceTo( onUpPosition ) == 0 ) {
|
||
|
|
||
|
var intersects = getIntersects( onUpPosition, objects );
|
||
|
|
||
|
if ( intersects.length > 0 ) {
|
||
|
|
||
|
var object = intersects[ 0 ].object;
|
||
|
|
||
|
if ( object.userData.object !== undefined ) {
|
||
|
|
||
|
// helper
|
||
|
|
||
|
editor.select( object.userData.object );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
editor.select( object );
|
||
|
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
editor.select( null );
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
var onMouseDown = function ( event ) {
|
||
|
|
||
|
event.preventDefault();
|
||
|
|
||
|
var array = getMousePosition( container.dom, event.clientX, event.clientY );
|
||
|
onDownPosition.fromArray( array );
|
||
|
|
||
|
document.addEventListener( 'mouseup', onMouseUp, false );
|
||
|
|
||
|
};
|
||
|
|
||
|
var onMouseUp = function ( event ) {
|
||
|
|
||
|
var array = getMousePosition( container.dom, event.clientX, event.clientY );
|
||
|
onUpPosition.fromArray( array );
|
||
|
|
||
|
handleClick();
|
||
|
|
||
|
document.removeEventListener( 'mouseup', onMouseUp, false );
|
||
|
|
||
|
};
|
||
|
|
||
|
var onTouchStart = function ( event ) {
|
||
|
|
||
|
var touch = event.changedTouches[ 0 ];
|
||
|
|
||
|
var array = getMousePosition( container.dom, touch.clientX, touch.clientY );
|
||
|
onDownPosition.fromArray( array );
|
||
|
|
||
|
document.addEventListener( 'touchend', onTouchEnd, false );
|
||
|
|
||
|
};
|
||
|
|
||
|
var onTouchEnd = function ( event ) {
|
||
|
|
||
|
var touch = event.changedTouches[ 0 ];
|
||
|
|
||
|
var array = getMousePosition( container.dom, touch.clientX, touch.clientY );
|
||
|
onUpPosition.fromArray( array );
|
||
|
|
||
|
handleClick();
|
||
|
|
||
|
document.removeEventListener( 'touchend', onTouchEnd, false );
|
||
|
|
||
|
};
|
||
|
|
||
|
var onDoubleClick = function ( event ) {
|
||
|
|
||
|
var array = getMousePosition( container.dom, event.clientX, event.clientY );
|
||
|
onDoubleClickPosition.fromArray( array );
|
||
|
|
||
|
var intersects = getIntersects( onDoubleClickPosition, objects );
|
||
|
|
||
|
if ( intersects.length > 0 ) {
|
||
|
|
||
|
var intersect = intersects[ 0 ];
|
||
|
|
||
|
signals.objectFocused.dispatch( intersect.object );
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
container.dom.addEventListener( 'mousedown', onMouseDown, false );
|
||
|
container.dom.addEventListener( 'touchstart', onTouchStart, false );
|
||
|
container.dom.addEventListener( 'dblclick', onDoubleClick, false );
|
||
|
|
||
|
// controls need to be added *after* main logic,
|
||
|
// otherwise controls.enabled doesn't work.
|
||
|
|
||
|
var controls = new THREE.EditorControls( camera, container.dom );
|
||
|
controls.center.fromArray( editor.config.getKey( 'camera/target' ) );
|
||
|
controls.addEventListener( 'change', function () {
|
||
|
|
||
|
transformControls.update();
|
||
|
signals.cameraChanged.dispatch( camera );
|
||
|
|
||
|
} );
|
||
|
|
||
|
// signals
|
||
|
|
||
|
signals.editorCleared.add( function () {
|
||
|
|
||
|
controls.center.set( 0, 0, 0 );
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.themeChanged.add( function ( value ) {
|
||
|
|
||
|
switch ( value ) {
|
||
|
|
||
|
case 'css/light.css':
|
||
|
grid.setColors( 0x444444, 0x888888 );
|
||
|
clearColor = 0xaaaaaa;
|
||
|
break;
|
||
|
case 'css/dark.css':
|
||
|
grid.setColors( 0xbbbbbb, 0x888888 );
|
||
|
clearColor = 0x333333;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
renderer.setClearColor( clearColor );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.transformModeChanged.add( function ( mode ) {
|
||
|
|
||
|
transformControls.setMode( mode );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.snapChanged.add( function ( dist ) {
|
||
|
|
||
|
transformControls.setSnap( dist );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.spaceChanged.add( function ( space ) {
|
||
|
|
||
|
transformControls.setSpace( space );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.rendererChanged.add( function ( type, antialias ) {
|
||
|
|
||
|
container.dom.removeChild( renderer.domElement );
|
||
|
|
||
|
renderer = createRenderer( type, antialias );
|
||
|
renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
|
||
|
|
||
|
container.dom.appendChild( renderer.domElement );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.sceneGraphChanged.add( function () {
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
var saveTimeout;
|
||
|
|
||
|
signals.cameraChanged.add( function () {
|
||
|
|
||
|
if ( saveTimeout !== undefined ) {
|
||
|
|
||
|
clearTimeout( saveTimeout );
|
||
|
|
||
|
}
|
||
|
|
||
|
saveTimeout = setTimeout( function () {
|
||
|
|
||
|
editor.config.setKey(
|
||
|
'camera/position', camera.position.toArray(),
|
||
|
'camera/target', controls.center.toArray()
|
||
|
);
|
||
|
|
||
|
}, 1000 );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.objectSelected.add( function ( object ) {
|
||
|
|
||
|
selectionBox.visible = false;
|
||
|
transformControls.detach();
|
||
|
|
||
|
if ( object !== null ) {
|
||
|
|
||
|
if ( object.geometry !== undefined &&
|
||
|
object instanceof THREE.Sprite === false ) {
|
||
|
|
||
|
selectionBox.update( object );
|
||
|
selectionBox.visible = true;
|
||
|
|
||
|
}
|
||
|
|
||
|
transformControls.attach( object );
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.objectFocused.add( function ( object ) {
|
||
|
|
||
|
controls.focus( object );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.geometryChanged.add( function ( geometry ) {
|
||
|
|
||
|
selectionBox.update( editor.selected );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.objectAdded.add( function ( object ) {
|
||
|
|
||
|
var materialsNeedUpdate = false;
|
||
|
|
||
|
object.traverse( function ( child ) {
|
||
|
|
||
|
if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
|
||
|
|
||
|
objects.push( child );
|
||
|
|
||
|
} );
|
||
|
|
||
|
if ( materialsNeedUpdate === true ) updateMaterials();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.objectChanged.add( function ( object ) {
|
||
|
|
||
|
transformControls.update();
|
||
|
|
||
|
if ( object instanceof THREE.PerspectiveCamera ) {
|
||
|
|
||
|
object.updateProjectionMatrix();
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( editor.helpers[ object.id ] !== undefined ) {
|
||
|
|
||
|
editor.helpers[ object.id ].update();
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.objectRemoved.add( function ( object ) {
|
||
|
|
||
|
var materialsNeedUpdate = false;
|
||
|
|
||
|
object.traverse( function ( child ) {
|
||
|
|
||
|
if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
|
||
|
|
||
|
objects.splice( objects.indexOf( child ), 1 );
|
||
|
|
||
|
} );
|
||
|
|
||
|
if ( materialsNeedUpdate === true ) updateMaterials();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.helperAdded.add( function ( object ) {
|
||
|
|
||
|
objects.push( object.getObjectByName( 'picker' ) );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.helperRemoved.add( function ( object ) {
|
||
|
|
||
|
objects.splice( objects.indexOf( object.getObjectByName( 'picker' ) ), 1 );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.materialChanged.add( function ( material ) {
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.fogTypeChanged.add( function ( fogType ) {
|
||
|
|
||
|
if ( fogType !== oldFogType ) {
|
||
|
|
||
|
if ( fogType === "None" ) {
|
||
|
|
||
|
scene.fog = null;
|
||
|
|
||
|
} else if ( fogType === "Fog" ) {
|
||
|
|
||
|
scene.fog = new THREE.Fog( oldFogColor, oldFogNear, oldFogFar );
|
||
|
|
||
|
} else if ( fogType === "FogExp2" ) {
|
||
|
|
||
|
scene.fog = new THREE.FogExp2( oldFogColor, oldFogDensity );
|
||
|
|
||
|
}
|
||
|
|
||
|
updateMaterials();
|
||
|
|
||
|
oldFogType = fogType;
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.fogColorChanged.add( function ( fogColor ) {
|
||
|
|
||
|
oldFogColor = fogColor;
|
||
|
|
||
|
updateFog( scene );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.fogParametersChanged.add( function ( near, far, density ) {
|
||
|
|
||
|
oldFogNear = near;
|
||
|
oldFogFar = far;
|
||
|
oldFogDensity = density;
|
||
|
|
||
|
updateFog( scene );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.windowResize.add( function () {
|
||
|
|
||
|
camera.aspect = container.dom.offsetWidth / container.dom.offsetHeight;
|
||
|
camera.updateProjectionMatrix();
|
||
|
|
||
|
renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
|
||
|
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.showGridChanged.add( function ( showGrid ) {
|
||
|
|
||
|
grid.visible = showGrid;
|
||
|
render();
|
||
|
|
||
|
} );
|
||
|
|
||
|
var animations = [];
|
||
|
|
||
|
signals.playAnimation.add( function ( animation ) {
|
||
|
|
||
|
animations.push( animation );
|
||
|
|
||
|
} );
|
||
|
|
||
|
signals.stopAnimation.add( function ( animation ) {
|
||
|
|
||
|
var index = animations.indexOf( animation );
|
||
|
|
||
|
if ( index !== -1 ) {
|
||
|
|
||
|
animations.splice( index, 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
} );
|
||
|
|
||
|
//
|
||
|
|
||
|
var createRenderer = function ( type, antialias ) {
|
||
|
|
||
|
if ( type === 'WebGLRenderer' && System.support.webgl === false ) {
|
||
|
|
||
|
type = 'CanvasRenderer';
|
||
|
|
||
|
}
|
||
|
|
||
|
var renderer = new THREE[ type ]( { antialias: antialias } );
|
||
|
renderer.setClearColor( clearColor );
|
||
|
renderer.setPixelRatio( window.devicePixelRatio );
|
||
|
renderer.autoClear = false;
|
||
|
renderer.autoUpdateScene = false;
|
||
|
|
||
|
return renderer;
|
||
|
|
||
|
};
|
||
|
|
||
|
var clearColor;
|
||
|
var renderer = createRenderer( editor.config.getKey( 'project/renderer' ), editor.config.getKey( 'project/renderer/antialias' ) );
|
||
|
container.dom.appendChild( renderer.domElement );
|
||
|
|
||
|
animate();
|
||
|
|
||
|
//
|
||
|
|
||
|
function updateMaterials() {
|
||
|
|
||
|
editor.scene.traverse( function ( node ) {
|
||
|
|
||
|
if ( node.material ) {
|
||
|
|
||
|
node.material.needsUpdate = true;
|
||
|
|
||
|
if ( node.material instanceof THREE.MeshFaceMaterial ) {
|
||
|
|
||
|
for ( var i = 0; i < node.material.materials.length; i ++ ) {
|
||
|
|
||
|
node.material.materials[ i ].needsUpdate = true;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
} );
|
||
|
|
||
|
}
|
||
|
|
||
|
function updateFog( root ) {
|
||
|
|
||
|
if ( root.fog ) {
|
||
|
|
||
|
root.fog.color.setHex( oldFogColor );
|
||
|
|
||
|
if ( root.fog.near !== undefined ) root.fog.near = oldFogNear;
|
||
|
if ( root.fog.far !== undefined ) root.fog.far = oldFogFar;
|
||
|
if ( root.fog.density !== undefined ) root.fog.density = oldFogDensity;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function animate() {
|
||
|
|
||
|
requestAnimationFrame( animate );
|
||
|
|
||
|
// animations
|
||
|
|
||
|
if ( THREE.AnimationHandler.animations.length > 0 ) {
|
||
|
|
||
|
THREE.AnimationHandler.update( 0.016 );
|
||
|
|
||
|
for ( var i = 0, l = sceneHelpers.children.length; i < l; i ++ ) {
|
||
|
|
||
|
var helper = sceneHelpers.children[ i ];
|
||
|
|
||
|
if ( helper instanceof THREE.SkeletonHelper ) {
|
||
|
|
||
|
helper.update();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function render() {
|
||
|
|
||
|
sceneHelpers.updateMatrixWorld();
|
||
|
scene.updateMatrixWorld();
|
||
|
|
||
|
renderer.clear();
|
||
|
renderer.render( scene, camera );
|
||
|
|
||
|
if ( renderer instanceof THREE.RaytracingRenderer === false ) {
|
||
|
|
||
|
renderer.render( sceneHelpers, camera );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return container;
|
||
|
|
||
|
}
|