2018-08-28 15:09:20 +00:00
// Global Vars
var scene = true ;
var camera , renderer ;
var projector , mouseVector , containerWidth , containerHeight ;
var raycaster = new THREE . Raycaster ( ) ;
var gridsystem = new THREE . Group ( ) ;
var container , stats ;
var camera , controls , control , scene , renderer , gridsystem , helper ;
var clock = new THREE . Clock ( ) ;
var marker ;
var sizexmax ;
var sizeymax ;
var lineincrement = 50
var camvideo ;
var objectsInScene = [ ] ; //array that holds all objects we added to the scene.
var clearSceneFlag = false ;
2018-08-28 15:29:27 +00:00
var isMac = navigator . platform . toUpperCase ( ) . indexOf ( 'MAC' ) >= 0 ;
2018-08-28 15:42:31 +00:00
var canvas = ! ! window . CanvasRenderingContext2D ;
2018-08-28 15:29:27 +00:00
2018-08-28 15:09:20 +00:00
// pause Animation when we loose webgl context focus
var pauseAnimation = false ;
var size = new THREE . Vector3 ( ) ;
var sky ;
var workspace = new THREE . Group ( ) ;
workspace . name = "Workspace"
var ground ;
containerWidth = window . innerWidth ;
containerHeight = window . innerHeight ;
2019-09-03 18:36:09 +00:00
var animationLoopTimeout ;
2018-08-28 15:09:20 +00:00
function drawWorkspace ( xmin , xmax , ymin , ymax ) {
if ( ! xmin ) xmin = 0 ;
if ( ! ymin ) ymin = 0 ;
2019-03-25 19:10:26 +00:00
if ( ! xmax ) xmax = 207
if ( ! ymax ) ymax = 207
2018-08-28 15:09:20 +00:00
var sceneLights = new THREE . Group ( ) ;
var light = new THREE . DirectionalLight ( 0xffffff , 0.8 ) ;
light . position . set ( 0 , 2 , 25 ) . normalize ( ) ;
light . name = "Light1;"
sceneLights . add ( light ) ;
var light2 = new THREE . DirectionalLight ( 0xffffff ) ;
light2 . name = "Light2"
light2 . position . set ( - 500 , - 500 , 1 ) . normalize ( ) ;
sceneLights . add ( light2 ) ;
dirLight = new THREE . DirectionalLight ( 0xffffff , 1 ) ;
dirLight . color . setHSL ( 0.1 , 1 , 0.95 ) ;
dirLight . position . set ( - 1 , 1.75 , 1 ) ;
dirLight . position . multiplyScalar ( 30 ) ;
dirLight . castShadow = true ;
dirLight . shadow . mapSize . width = 2048 ;
dirLight . shadow . mapSize . height = 2048 ;
var d = 50 ;
dirLight . shadow . camera . left = - d ;
dirLight . shadow . camera . right = d ;
dirLight . shadow . camera . top = d ;
dirLight . shadow . camera . bottom = - d ;
dirLight . shadow . camera . far = 3500 ;
dirLight . shadow . bias = - 0.0001 ;
dirLight . name = "dirLight;"
sceneLights . add ( dirLight ) ;
hemiLight = new THREE . HemisphereLight ( 0xffffff , 0xffffff , 0.6 ) ;
hemiLight . color . setHSL ( 0.6 , 1 , 0.6 ) ;
hemiLight . groundColor . setHSL ( 0.095 , 1 , 0.75 ) ;
hemiLight . position . set ( 0 , 50 , 0 ) ;
hemiLight . visible = false ;
hemiLight . name = "hemiLight"
sceneLights . add ( hemiLight ) ;
// if (helper) {
// workspace.remove(helper);
// }
sceneLights . name = "Scene Lights"
workspace . add ( sceneLights ) ;
scene . fog = new THREE . Fog ( 0xffffff , 1 , 20000 ) ;
// SKYDOME
2019-10-18 18:55:41 +00:00
if ( ! disable3Dskybox ) {
var uniforms = {
topColor : {
value : new THREE . Color ( 0x0077ff )
} ,
bottomColor : {
value : new THREE . Color ( 0xffffff )
} ,
offset : {
value : - 63
} ,
exponent : {
value : 0.71
}
} ;
uniforms . topColor . value . copy ( hemiLight . color ) ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
scene . fog . color . copy ( uniforms . bottomColor . value ) ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
var vertexShader = document . getElementById ( 'vertexShader' ) . textContent ;
var fragmentShader = document . getElementById ( 'fragmentShader' ) . textContent ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
var skyGeo = new THREE . SphereGeometry ( 9900 , 64 , 15 ) ;
var skyMat = new THREE . ShaderMaterial ( {
vertexShader : vertexShader ,
fragmentShader : fragmentShader ,
uniforms : uniforms ,
side : THREE . DoubleSide
} ) ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
sky = new THREE . Mesh ( skyGeo , skyMat ) ;
sky . name = "Skydome"
workspace . add ( sky ) ;
}
if ( ! disable3Drealtimepos ) {
cone = new THREE . Mesh ( new THREE . CylinderGeometry ( 0 , 5 , 40 , 15 , 1 , false ) , new THREE . MeshPhongMaterial ( {
color : 0x0000ff ,
specular : 0x0000ff ,
shininess : 00
} ) ) ;
cone . overdraw = true ;
cone . rotation . x = - 90 * Math . PI / 180 ;
cone . position . x = 20 ;
cone . position . y = 0 ;
cone . position . z = 0 ;
cone . material . opacity = 0.6 ;
cone . material . transparent = true ;
cone . castShadow = false ;
cone . visible = false ;
cone . name = "Simulation Marker"
workspace . add ( cone )
}
2018-08-28 15:09:20 +00:00
gridsystem . name = "Grid System"
workspace . add ( gridsystem )
2019-09-05 14:58:56 +00:00
redrawGrid ( xmin , xmax , ymin , ymax , false ) ;
2018-08-28 15:09:20 +00:00
scene . add ( workspace )
}
2018-09-18 14:09:11 +00:00
function redrawGrid ( xmin , xmax , ymin , ymax , inches ) {
2019-09-13 18:39:59 +00:00
// console.log(xmin, xmax, ymin, ymax, inches)
2018-09-18 14:09:11 +00:00
if ( inches ) {
xmin = Math . floor ( xmin * 25.4 ) ;
xmax = Math . ceil ( xmax * 25.4 ) ;
ymin = Math . floor ( ymin * 25.4 ) ;
ymax = Math . ceil ( ymax * 25.4 ) ;
}
2019-09-13 18:39:59 +00:00
// console.log(xmin, xmax, ymin, ymax, inches)
2018-08-28 15:09:20 +00:00
sizexmax = xmax ;
sizeymax = ymax ;
if ( ! xmax ) {
xmax = 200 ;
} ;
if ( ! ymax ) {
ymax = 200 ;
} ;
var grid = new THREE . Group ( ) ;
var axesgrp = new THREE . Object3D ( ) ;
axesgrp . name = "Axes Markers"
2018-09-18 14:09:11 +00:00
if ( inches ) {
var unitsval = "in"
2019-09-05 14:58:56 +00:00
var offset = 5 * 2.54
2018-09-18 14:09:11 +00:00
} else {
var unitsval = "mm"
var offset = 5
var size = 5
}
2018-08-28 15:09:20 +00:00
// add axes labels
var xlbl = this . makeSprite ( this . scene , "webgl" , {
2018-09-18 14:09:11 +00:00
x : parseInt ( xmax ) + offset ,
2018-08-28 15:09:20 +00:00
y : 0 ,
z : 0 ,
text : "X" ,
2018-09-18 14:09:11 +00:00
color : "#ff0000" ,
size : size
2018-08-28 15:09:20 +00:00
} ) ;
var ylbl = this . makeSprite ( this . scene , "webgl" , {
x : 0 ,
2018-09-18 14:09:11 +00:00
y : parseInt ( ymax ) + offset ,
2018-08-28 15:09:20 +00:00
z : 0 ,
text : "Y" ,
2018-09-18 14:09:11 +00:00
color : "#006600" ,
size : size
2018-08-28 15:09:20 +00:00
} ) ;
2018-09-18 14:09:11 +00:00
2018-08-28 15:09:20 +00:00
axesgrp . add ( xlbl ) ;
axesgrp . add ( ylbl ) ;
2018-09-18 14:09:11 +00:00
2018-08-28 15:09:20 +00:00
var materialX = new THREE . LineBasicMaterial ( {
color : 0xcc0000
} ) ;
var materialY = new THREE . LineBasicMaterial ( {
color : 0x00cc00
} ) ;
var geometryX = new THREE . Geometry ( ) ;
geometryX . vertices . push (
new THREE . Vector3 ( - 0.1 , 0 , 0 ) ,
new THREE . Vector3 ( - 0.1 , ( ymax ) , 0 )
) ;
var geometryY = new THREE . Geometry ( ) ;
geometryY . vertices . push (
new THREE . Vector3 ( 0 , - 0.1 , 0 ) ,
new THREE . Vector3 ( ( xmax ) , - 0.1 , 0 )
) ;
var line1 = new THREE . Line ( geometryX , materialY ) ;
var line2 = new THREE . Line ( geometryY , materialX ) ;
axesgrp . add ( line1 ) ;
axesgrp . add ( line2 ) ;
2018-09-18 14:09:11 +00:00
// if (inches) {
// axesgrp.scale.multiplyScalar(2.5);
// }
2018-08-28 15:09:20 +00:00
grid . add ( axesgrp ) ;
2018-09-18 14:09:11 +00:00
var step10 = 10 ;
var step100 = 100 ;
if ( inches ) {
2019-09-05 14:58:56 +00:00
step10 = 2.54 ;
step100 = 25.4 ;
2018-09-18 14:09:11 +00:00
}
2019-09-05 14:58:56 +00:00
helper = new THREE . GridHelper ( xmin , xmax , ymin , ymax , step10 , 0x888888 ) ;
2018-08-28 15:09:20 +00:00
helper . position . y = 0 ;
helper . position . x = 0 ;
helper . position . z = 0 ;
helper . material . opacity = 0.15 ;
helper . material . transparent = true ;
helper . receiveShadow = false ;
helper . name = "GridHelper10mm"
grid . add ( helper ) ;
2019-09-05 14:58:56 +00:00
helper = new THREE . GridHelper ( xmin , xmax , ymin , ymax , step100 , 0x666666 ) ;
2018-08-28 15:09:20 +00:00
helper . position . y = 0 ;
helper . position . x = 0 ;
helper . position . z = 0 ;
helper . material . opacity = 0.15 ;
helper . material . transparent = true ;
helper . receiveShadow = false ;
helper . name = "GridHelper50mm"
grid . add ( helper ) ;
grid . name = "Grid"
2018-09-06 17:50:01 +00:00
gridsystem . children . length = 0
2019-09-05 14:58:56 +00:00
if ( inches ) {
var ruler = drawRulerInches ( xmin , xmax , ymin , ymax , inches )
} else {
var ruler = drawRuler ( xmin , xmax , ymin , ymax , inches )
}
2018-08-28 15:09:20 +00:00
gridsystem . add ( grid ) ;
2018-09-06 17:50:01 +00:00
gridsystem . add ( ruler ) ;
2018-08-28 15:09:20 +00:00
}
function setBullseyePosition ( x , y , z ) {
//console.log('Set Position: ', x, y, z)
if ( x ) {
bullseye . position . x = parseInt ( x , 10 ) ;
} ;
if ( y ) {
bullseye . position . y = parseInt ( y , 10 ) ;
} ;
if ( z ) {
bullseye . position . z = ( parseInt ( z , 10 ) + 0.1 ) ;
} ;
}
function init3D ( ) {
2019-10-18 18:55:41 +00:00
if ( webgl ) {
2020-04-17 21:07:39 +00:00
// console.log('WebGL Support found! success: this application will work optimally on this device!');
2019-10-18 18:55:41 +00:00
printLog ( "<span class='fg-red'>[ 3D Viewer ] </span><span class='fg-green'>WebGL Support found! success: this application will work optimally on this device!</span>" )
renderer = new THREE . WebGLRenderer ( {
autoClearColor : true ,
antialias : false ,
preserveDrawingBuffer : true
} ) ;
// ThreeJS Render/Control/Camera
scene = new THREE . Scene ( ) ;
camera = new THREE . PerspectiveCamera ( 45 , window . innerWidth / window . innerHeight , 1 , 20000 ) ;
camera . position . z = 295 ;
$ ( '#renderArea' ) . append ( renderer . domElement ) ;
renderer . setClearColor ( 0xffffff , 1 ) ; // Background color of viewer = transparent
// renderer.setSize(window.innerWidth - 10, window.innerHeight - 10);
renderer . clear ( ) ;
sceneWidth = document . getElementById ( "renderArea" ) . offsetWidth ,
sceneHeight = document . getElementById ( "renderArea" ) . offsetHeight ;
camera . aspect = sceneWidth / sceneHeight ;
renderer . setSize ( sceneWidth , sceneHeight )
camera . updateProjectionMatrix ( ) ;
2019-10-16 13:57:56 +00:00
2019-10-18 18:55:41 +00:00
if ( ! disable3Dcontrols ) {
2019-10-16 13:57:56 +00:00
controls = new THREE . OrbitControls ( camera , renderer . domElement ) ;
controls . target . set ( 0 , 0 , 0 ) ; // view direction perpendicular to XY-plane
if ( ! isMac ) {
controls . mouseButtons = {
ORBIT : THREE . MOUSE . MIDDLE ,
ZOOM : false ,
PAN : THREE . MOUSE . RIGHT
} ;
}
controls . enableRotate = true ;
controls . enableZoom = true ; // optional
controls . maxDistance = 8000 ; // limit max zoom out
controls . enableKeys = false ; // Disable Keyboard on canvas
2019-10-18 18:55:41 +00:00
}
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
drawWorkspace ( ) ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
// Picking stuff
projector = new THREE . Projector ( ) ;
mouseVector = new THREE . Vector3 ( ) ;
raycaster . linePrecision = 1
setTimeout ( function ( ) {
resetView ( )
animate ( ) ;
} , 200 )
2018-08-28 15:09:20 +00:00
2018-08-28 15:42:31 +00:00
} else {
2019-10-18 18:55:41 +00:00
console . log ( 'No WebGL Support found on this computer! Disabled 3D Viewer - Sorry!' ) ;
printLog ( 'No WebGL Support found on this computer! Disabled 3D Viewer - Sorry!' ) ;
2018-08-28 15:16:17 +00:00
$ ( '#gcodeviewertab' ) . hide ( )
2019-01-24 18:25:01 +00:00
$ ( '#consoletab' ) . click ( )
2018-08-28 15:16:17 +00:00
return false ;
2019-10-18 18:55:41 +00:00
} ;
2018-08-28 15:09:20 +00:00
}
function animate ( ) {
if ( ! pauseAnimation ) {
camera . updateMatrixWorld ( ) ;
2020-04-20 20:58:03 +00:00
simAnimate ( )
2018-08-28 15:09:20 +00:00
if ( clearSceneFlag ) {
while ( scene . children . length > 1 ) {
scene . remove ( scene . children [ 1 ] )
}
2018-09-06 16:10:40 +00:00
if ( object ) {
scene . add ( object )
2018-08-28 15:09:20 +00:00
}
clearSceneFlag = false ;
} // end clearSceneFlag
// Limited FPS https://stackoverflow.com/questions/11285065/limiting-framerate-in-three-js-to-increase-performance-requestanimationframe
2019-09-03 18:36:09 +00:00
animationLoopTimeout = setTimeout ( function ( ) {
2018-08-28 15:09:20 +00:00
requestAnimationFrame ( animate ) ;
2019-10-16 13:57:56 +00:00
} , 60 ) ;
2018-08-28 15:09:20 +00:00
renderer . render ( scene , camera ) ;
}
}
2019-10-18 18:55:41 +00:00
function viewExtents ( objecttosee ) {
if ( ! disable3Dcontrols ) {
// console.log("viewExtents. object:", objecttosee);
// console.log("controls:", controls);
//wakeAnimate();
// lets override the bounding box with a newly
// generated one
// get its bounding box
if ( objecttosee ) {
// console.log(objecttosee)
var helper = new THREE . BoxHelper ( objecttosee ) ;
helper . update ( ) ;
var box3 = new THREE . Box3 ( ) ;
box3 . setFromObject ( helper ) ;
var minx = box3 . min . x ;
var miny = box3 . min . y ;
var maxx = box3 . max . x ;
var maxy = box3 . max . y ;
var minz = box3 . min . z ;
var maxz = box3 . max . z ;
2018-08-28 15:09:20 +00:00
2019-10-18 18:55:41 +00:00
controls . reset ( ) ;
var lenx = maxx - minx ;
var leny = maxy - miny ;
var lenz = maxz - minz ;
var centerx = minx + ( lenx / 2 ) ;
var centery = miny + ( leny / 2 ) ;
var centerz = minz + ( lenz / 2 ) ;
// console.log("lenx:", lenx, "leny:", leny, "lenz:", lenz);
var maxlen = Math . max ( lenx , leny , lenz ) ;
var dist = 2 * maxlen ;
// center camera on gcode objects center pos, but twice the maxlen
controls . object . position . x = centerx ;
controls . object . position . y = centery ;
controls . object . position . z = centerz + dist ;
controls . target . x = centerx ;
controls . target . y = centery ;
controls . target . z = centerz ;
// console.log("maxlen:", maxlen, "dist:", dist);
var fov = 2.2 * Math . atan ( maxlen / ( 2 * dist ) ) * ( 180 / Math . PI ) ;
// console.log("new fov:", fov, " old fov:", controls.object.fov);
if ( isNaN ( fov ) ) {
// console.log("giving up on viewing extents because fov could not be calculated");
return ;
} else {
// console.log("fov: ", fov);
controls . object . fov = fov ;
var L = dist ;
var camera2 = controls . object ;
var vector = controls . target . clone ( ) ;
var l = ( new THREE . Vector3 ( ) ) . subVectors ( camera2 . position , vector ) . length ( ) ;
var up = camera . up . clone ( ) ;
var quaternion = new THREE . Quaternion ( ) ;
// Zoom correction
camera2 . translateZ ( L - l ) ;
// console.log("up:", up);
up . y = 1 ;
up . x = 0 ;
up . z = 0 ;
quaternion . setFromAxisAngle ( up , 0 ) ;
camera2 . position . applyQuaternion ( quaternion ) ;
up . y = 0 ;
up . x = 1 ;
up . z = 0 ;
quaternion . setFromAxisAngle ( up , 0 ) ;
camera2 . position . applyQuaternion ( quaternion ) ;
up . y = 0 ;
up . x = 0 ;
up . z = 1 ;
quaternion . setFromAxisAngle ( up , 0 ) ;
camera2 . lookAt ( vector ) ;
controls . object . updateProjectionMatrix ( ) ;
}
2018-08-28 15:09:20 +00:00
}
}
} ;
function makeSprite ( scene , rendererType , vals ) {
var canvas = document . createElement ( 'canvas' ) ,
context = canvas . getContext ( '2d' ) ,
metrics = null ,
textHeight = 100 ,
textWidth = 0 ,
actualFontSize = 10 ;
var txt = vals . text ;
if ( vals . size ) actualFontSize = vals . size ;
context . font = "normal " + textHeight + "px Impact" ;
metrics = context . measureText ( txt ) ;
var textWidth = metrics . width ;
canvas . width = textWidth ;
canvas . height = textHeight ;
context . font = "normal " + textHeight + "px Impact" ;
context . textAlign = "center" ;
context . textBaseline = "middle" ;
//context.fillStyle = "#ff0000";
context . fillStyle = vals . color ;
context . fillText ( txt , textWidth / 2 , textHeight / 2 ) ;
var texture = new THREE . Texture ( canvas ) ;
texture . needsUpdate = true ;
texture . minFilter = THREE . LinearFilter ;
var material = new THREE . SpriteMaterial ( {
map : texture ,
// useScreenCoordinates: false,
transparent : true ,
opacity : 0.6
} ) ;
material . transparent = true ;
//var textObject = new THREE.Sprite(material);
var textObject = new THREE . Object3D ( ) ;
textObject . position . x = vals . x ;
textObject . position . y = vals . y ;
textObject . position . z = vals . z ;
var sprite = new THREE . Sprite ( material ) ;
textObject . textHeight = actualFontSize ;
textObject . textWidth = ( textWidth / textHeight ) * textObject . textHeight ;
if ( rendererType == "2d" ) {
sprite . scale . set ( textObject . textWidth / textWidth , textObject . textHeight / textHeight , 1 ) ;
} else {
sprite . scale . set ( textWidth / textHeight * actualFontSize , actualFontSize , 1 ) ;
}
textObject . add ( sprite ) ;
//scene.add(textObject);
return textObject ;
}
// Global Function to keep three fullscreen
function fixRenderSize ( ) {
if ( renderer ) {
setTimeout ( function ( ) {
sceneWidth = document . getElementById ( "renderArea" ) . offsetWidth ;
sceneHeight = document . getElementById ( "renderArea" ) . offsetHeight ;
renderer . setSize ( sceneWidth , sceneHeight ) ;
//renderer.setSize(window.innerWidth, window.innerHeight);
camera . aspect = sceneWidth / sceneHeight ;
camera . updateProjectionMatrix ( ) ;
2019-10-18 18:55:41 +00:00
if ( ! disable3Dcontrols ) {
controls . reset ( ) ;
}
2018-08-28 15:09:20 +00:00
setTimeout ( function ( ) {
resetView ( ) ;
2018-09-06 16:10:40 +00:00
} , 10 ) ;
} , 10 )
2018-08-28 15:09:20 +00:00
}
}
$ ( window ) . on ( 'resize' , function ( ) {
console . log ( "Window Resize" )
fixRenderSize ( ) ;
} ) ;
function resetView ( object ) {
2018-09-06 17:50:01 +00:00
// console.log(resetView.caller);
2018-08-28 15:09:20 +00:00
if ( ! object ) {
if ( objectsInScene . length > 0 ) {
var insceneGrp = new THREE . Group ( )
for ( i = 0 ; i < objectsInScene . length ; i ++ ) {
var object = objectsInScene [ i ] . clone ( ) ;
insceneGrp . add ( object )
}
// scene.add(insceneGrp)
viewExtents ( insceneGrp ) ;
// scene.remove(insceneGrp)
} else {
viewExtents ( helper ) ;
}
} else {
2019-05-01 18:44:44 +00:00
if ( object . userData . lines . length > 1 ) {
viewExtents ( object ) ;
}
2018-08-28 15:09:20 +00:00
}
}