2020-06-03 22:39:30 -04:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-06-03 22:39:30 -04:00
|
|
|
"use strict";
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
(function() {
|
2021-12-29 10:57:10 -05:00
|
|
|
// dep: ext.tween
|
2021-12-29 10:37:17 -05:00
|
|
|
gapp.register('moto.space', [
|
2021-12-29 16:49:15 -05:00
|
|
|
'add.three', // dep: add.three
|
2021-12-29 10:37:17 -05:00
|
|
|
'add.array', // dep: add.array
|
|
|
|
|
'moto.orbit' // dep: moto.orbit
|
|
|
|
|
]);
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2021-12-26 22:49:41 -05:00
|
|
|
let MOTO = self.moto = self.moto || {},
|
2020-06-03 22:39:30 -04:00
|
|
|
WIN = window,
|
2017-04-18 17:09:33 -04:00
|
|
|
DOC = document,
|
|
|
|
|
SCENE = new THREE.Scene(),
|
|
|
|
|
WORLD = new THREE.Group(),
|
|
|
|
|
PI = Math.PI,
|
|
|
|
|
PI2 = PI / 2,
|
|
|
|
|
PI4 = PI / 4,
|
2021-01-22 10:41:04 -05:00
|
|
|
panX = 0,
|
2017-04-18 17:09:33 -04:00
|
|
|
panY = 0,
|
2021-01-22 10:41:04 -05:00
|
|
|
panZ = 0,
|
2021-01-22 15:33:18 -05:00
|
|
|
home = 0,
|
2021-11-26 21:32:19 -05:00
|
|
|
up = PI4,
|
2017-04-18 17:09:33 -04:00
|
|
|
gridZOff = 0,
|
2021-02-10 20:11:03 -05:00
|
|
|
tweenTime = 500,
|
|
|
|
|
tweenDelay = 20,
|
2017-04-18 17:09:33 -04:00
|
|
|
platformZOff = 0,
|
|
|
|
|
perspective = 35,
|
2020-03-19 18:34:03 -04:00
|
|
|
refreshTimeout = null,
|
2017-04-18 17:09:33 -04:00
|
|
|
refreshRequested = false,
|
|
|
|
|
selectRecurse = false,
|
|
|
|
|
defaultKeys = true,
|
|
|
|
|
lightIntensity = 0.3,
|
|
|
|
|
initialized = false,
|
|
|
|
|
alignedTracking = false,
|
|
|
|
|
skyColor = 0xbbbbbb,
|
|
|
|
|
skyGridColor = 0xcccccc,
|
2020-07-08 15:36:46 -04:00
|
|
|
skyMaterial = undefined,
|
|
|
|
|
skyGridMaterial = undefined,
|
2020-11-13 23:09:53 -05:00
|
|
|
showSkyGrid = false,
|
2017-04-18 17:09:33 -04:00
|
|
|
showPlatform = true,
|
|
|
|
|
hidePlatformBelow = true,
|
2021-01-08 21:56:46 -05:00
|
|
|
origin = {x:0, y:0, z: 0},
|
2017-04-18 17:09:33 -04:00
|
|
|
trackcam = addLight(0, 0, 0, lightIntensity/3),
|
|
|
|
|
trackDelta = {x:0, y:0, z:0},
|
|
|
|
|
mouse = {x: 0, y: 0},
|
2020-03-19 18:34:03 -04:00
|
|
|
mouseStart = null,
|
2017-04-18 17:09:33 -04:00
|
|
|
mouseDragPoint = null,
|
|
|
|
|
mouseDragStart = null,
|
|
|
|
|
mouseDownSelect,
|
|
|
|
|
mouseUpSelect,
|
2020-12-06 21:25:31 -05:00
|
|
|
mouseUp,
|
|
|
|
|
mouseDown,
|
2017-04-18 17:09:33 -04:00
|
|
|
mouseHover,
|
|
|
|
|
mouseDrag,
|
2021-01-08 21:56:46 -05:00
|
|
|
grid = {
|
2021-01-09 23:57:46 -05:00
|
|
|
origin: origin,
|
2021-01-08 21:56:46 -05:00
|
|
|
unitMinor: 0,
|
|
|
|
|
unitMajor: 0,
|
|
|
|
|
colorMinor: 0,
|
|
|
|
|
colorMajor: 0,
|
|
|
|
|
zoff: 0,
|
|
|
|
|
view: undefined
|
|
|
|
|
},
|
|
|
|
|
ruler = {
|
|
|
|
|
x1: 0,
|
|
|
|
|
x2: 0,
|
|
|
|
|
y1: 0,
|
|
|
|
|
y2: 0,
|
|
|
|
|
xlabel: 'X',
|
|
|
|
|
ylabel: 'Y',
|
|
|
|
|
xon: undefined,
|
|
|
|
|
yon: undefined,
|
|
|
|
|
factor: undefined,
|
|
|
|
|
view: undefined
|
|
|
|
|
},
|
|
|
|
|
timers = {},
|
2020-11-10 11:17:51 -05:00
|
|
|
fontColor = '#333333',
|
|
|
|
|
fontScale = 1.4, // computed relative to grid size
|
2020-11-10 15:05:08 -05:00
|
|
|
rulerColor,
|
|
|
|
|
axisColor,
|
|
|
|
|
axesOn = true,
|
2020-11-10 15:38:09 -05:00
|
|
|
volumeOn = true,
|
2017-04-18 17:09:33 -04:00
|
|
|
viewControl,
|
|
|
|
|
trackPlane,
|
|
|
|
|
platform,
|
|
|
|
|
platformHover,
|
|
|
|
|
platformClick,
|
|
|
|
|
platformClickAt,
|
|
|
|
|
platformOnMove,
|
|
|
|
|
platformMoveTimer,
|
2020-11-10 15:38:09 -05:00
|
|
|
volume,
|
2017-04-18 17:09:33 -04:00
|
|
|
light1,
|
|
|
|
|
light2,
|
|
|
|
|
light3,
|
|
|
|
|
light4,
|
|
|
|
|
light5,
|
|
|
|
|
camera,
|
|
|
|
|
renderer,
|
2020-02-29 20:13:49 -05:00
|
|
|
container,
|
2021-03-04 13:22:53 -05:00
|
|
|
raycaster,
|
2020-12-25 14:26:46 -05:00
|
|
|
freezeTo,
|
|
|
|
|
freeze,
|
2020-02-29 20:13:49 -05:00
|
|
|
isRound = false,
|
|
|
|
|
platformMaterial = new THREE.MeshPhongMaterial({
|
2020-11-14 11:12:12 -05:00
|
|
|
color: 0xeeeeee,
|
|
|
|
|
specular: 0xeeeeee,
|
|
|
|
|
shininess: 0,
|
2020-02-29 20:13:49 -05:00
|
|
|
transparent: true,
|
|
|
|
|
opacity: 0.6,
|
2020-11-14 11:12:12 -05:00
|
|
|
side: THREE.DoubleSide
|
2020-04-24 16:07:19 -04:00
|
|
|
}),
|
|
|
|
|
hiddenKey,
|
|
|
|
|
vizChange,
|
2020-06-14 18:42:15 -04:00
|
|
|
docVisible = true,
|
2020-11-11 18:07:53 -05:00
|
|
|
lastAction = Date.now(),
|
|
|
|
|
fps = 0;
|
2020-04-24 16:07:19 -04:00
|
|
|
|
|
|
|
|
if (typeof DOC.hidden !== "undefined") {
|
|
|
|
|
hiddenKey = "hidden";
|
|
|
|
|
vizChange = "visibilitychange";
|
|
|
|
|
} else if (typeof DOC.msHidden !== "undefined") {
|
|
|
|
|
hiddenKey = "msHidden";
|
|
|
|
|
vizChange = "msvisibilitychange";
|
|
|
|
|
} else if (typeof DOC.webkitHidden !== "undefined") {
|
|
|
|
|
hiddenKey = "webkitHidden";
|
|
|
|
|
vizChange = "webkitvisibilitychange";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DOC.addEventListener(vizChange, () => {
|
|
|
|
|
docVisible = DOC[hiddenKey] ? false : true;
|
|
|
|
|
}, false);
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-06-14 18:42:15 -04:00
|
|
|
function updateLastAction() {
|
|
|
|
|
lastAction = Date.now();
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
function delayed(key, time, fn) {
|
|
|
|
|
clearTimeout(timers[key]);
|
|
|
|
|
timers[key] = setTimeout(fn, time);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* TWEENing Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
|
|
|
|
function tweenit() {
|
|
|
|
|
TWEEN.update();
|
2021-02-10 20:11:03 -05:00
|
|
|
setTimeout(tweenit, tweenDelay);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tweenit();
|
|
|
|
|
|
|
|
|
|
function tweenCamPan(x,y,z) {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2020-02-29 20:13:49 -05:00
|
|
|
let pos = viewControl.getPosition();
|
2017-04-18 17:09:33 -04:00
|
|
|
pos.panX = x;
|
|
|
|
|
pos.panY = y;
|
|
|
|
|
pos.panZ = z;
|
|
|
|
|
tweenCam(pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function tweenCam(pos) {
|
2020-02-29 20:13:49 -05:00
|
|
|
let tf = function () {
|
2017-04-18 17:09:33 -04:00
|
|
|
viewControl.setPosition(this);
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
refresh();
|
|
|
|
|
};
|
2021-01-15 12:32:07 -05:00
|
|
|
let from = Object.clone(viewControl.getPosition());
|
|
|
|
|
let to = Object.clone(pos);
|
|
|
|
|
let dist = Math.abs(from.left - to.left);
|
|
|
|
|
if (dist > Math.PI) {
|
|
|
|
|
if (from.left < to.left) {
|
|
|
|
|
from.left += Math.PI * 2;
|
|
|
|
|
} else {
|
|
|
|
|
from.left -= Math.PI * 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
new TWEEN.Tween(from).
|
2021-02-10 20:11:03 -05:00
|
|
|
to(to, tweenTime).
|
2017-04-18 17:09:33 -04:00
|
|
|
onUpdate(tf).
|
2021-01-15 12:32:07 -05:00
|
|
|
onComplete(() => {
|
|
|
|
|
viewControl.setPosition(pos);
|
|
|
|
|
updateLastAction();
|
|
|
|
|
refresh();
|
2021-02-10 20:11:03 -05:00
|
|
|
if (pos.then) pos.then();
|
2021-01-15 12:32:07 -05:00
|
|
|
}).
|
2017-04-18 17:09:33 -04:00
|
|
|
start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ******************************************************************
|
|
|
|
|
* Utility Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
|
|
|
|
function width() { return WIN.innerWidth }
|
|
|
|
|
|
|
|
|
|
function height() { return WIN.innerHeight }
|
|
|
|
|
|
|
|
|
|
function aspect() { return width() / height() }
|
|
|
|
|
|
|
|
|
|
function addEventListener(el, key, fn) {
|
|
|
|
|
el.addEventListener(key, fn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addEventHandlers(el, pairs) {
|
2020-02-29 20:13:49 -05:00
|
|
|
for (let i=0; i<pairs.length; i += 2) {
|
2017-04-18 17:09:33 -04:00
|
|
|
addEventListener(el, pairs[i], pairs[i+1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-07 22:14:53 -04:00
|
|
|
function onEnterKey(el, fn, onblur) {
|
2017-04-18 17:09:33 -04:00
|
|
|
if (Array.isArray(el)) {
|
2021-04-07 22:14:53 -04:00
|
|
|
for (let i=0; i<el.length; i += 2) onEnterKey(el[i], el[i+1], fn);
|
2017-04-18 17:09:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
addEventListener(el, 'keyup', function(event) {
|
|
|
|
|
if (event.keyCode === 13) fn(event);
|
|
|
|
|
});
|
2021-04-07 22:14:53 -04:00
|
|
|
if (onblur) {
|
|
|
|
|
addEventListener(el, 'blur', function(event) {
|
|
|
|
|
fn(event);
|
|
|
|
|
});
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addLight(x,y,z,i) {
|
2020-02-29 20:13:49 -05:00
|
|
|
let l = new THREE.PointLight(0xffffff, i, 0);
|
2017-04-18 17:09:33 -04:00
|
|
|
l.position.set(x,y,z);
|
|
|
|
|
SCENE.add(l);
|
|
|
|
|
return l;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updatePlatformPosition() {
|
2020-02-29 20:13:49 -05:00
|
|
|
if (isRound) {
|
|
|
|
|
platform.position.y = -platform.scale.y/2 - platformZOff;
|
|
|
|
|
} else {
|
|
|
|
|
platform.position.y = -platform.scale.z/2 - platformZOff;
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
requestRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:38:09 -05:00
|
|
|
function setPlatformSize(width, depth, height, maxz) {
|
2020-02-29 20:13:49 -05:00
|
|
|
if (isRound) {
|
|
|
|
|
platform.scale.set(width || 300, height || 5, depth || 175);
|
|
|
|
|
} else {
|
|
|
|
|
platform.scale.set(width || 300, depth || 175, height || 5);
|
|
|
|
|
}
|
2017-10-10 15:38:47 -04:00
|
|
|
viewControl.maxDistance = Math.max(width,depth) * 4;
|
2017-04-18 17:09:33 -04:00
|
|
|
updatePlatformPosition();
|
2020-02-29 20:13:49 -05:00
|
|
|
let y = Math.max(width, height) * 1;
|
2017-04-18 17:09:33 -04:00
|
|
|
light1.position.set( width, y, depth);
|
|
|
|
|
light2.position.set(-width, y, -depth);
|
|
|
|
|
light4.position.set( width, light4.position.y, -depth);
|
|
|
|
|
light5.position.set(-width, light5.position.y, depth);
|
2020-11-10 15:38:09 -05:00
|
|
|
if (volume) {
|
|
|
|
|
SCENE.remove(volume);
|
|
|
|
|
volume = null;
|
|
|
|
|
}
|
|
|
|
|
if (maxz) {
|
|
|
|
|
const points = [
|
|
|
|
|
// pillars
|
|
|
|
|
{x: -width/2, z: -depth/2, y: 0},
|
|
|
|
|
{x: -width/2, z: -depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: depth/2, y: 0},
|
|
|
|
|
{x: width/2, z: depth/2, y: maxz},
|
|
|
|
|
{x: -width/2, z: depth/2, y: 0},
|
|
|
|
|
{x: -width/2, z: depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: -depth/2, y: 0},
|
|
|
|
|
{x: width/2, z: -depth/2, y: maxz},
|
|
|
|
|
// top
|
|
|
|
|
{x: -width/2, z: -depth/2, y: maxz},
|
|
|
|
|
{x: -width/2, z: depth/2, y: maxz},
|
|
|
|
|
{x: -width/2, z: -depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: -depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: -depth/2, y: maxz},
|
|
|
|
|
{x: width/2, z: depth/2, y: maxz},
|
|
|
|
|
{x: -width/2, z: depth/2, y: maxz},
|
|
|
|
|
];
|
|
|
|
|
SCENE.add(volume = makeLinesFromPoints(points, 0x888888, 0.25));
|
2021-12-27 09:00:27 -05:00
|
|
|
showVolume(volumeOn);
|
2020-11-10 15:38:09 -05:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:38:09 -05:00
|
|
|
function setPlatformSizeUpdateGrid(width, depth, height, maxz) {
|
2020-12-25 14:26:46 -05:00
|
|
|
freeze = { width, depth, height, maxz };
|
2020-11-10 15:38:09 -05:00
|
|
|
setPlatformSize(width, depth, height, maxz);
|
2021-01-08 21:56:46 -05:00
|
|
|
setGrid(grid.unitMajor, grid.unitMinor);
|
2020-12-25 14:26:46 -05:00
|
|
|
clearTimeout(freezeTo);
|
|
|
|
|
freezeTo = setTimeout(() => { freeze = undefined }, 10);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setPlatformColor(color) {
|
2020-04-22 00:24:06 -04:00
|
|
|
let was = platform.material.color.getHex();
|
2017-04-18 17:09:33 -04:00
|
|
|
platform.material.color.set(color);
|
|
|
|
|
requestRefresh();
|
2020-04-22 00:24:06 -04:00
|
|
|
return was;
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-10 11:17:51 -05:00
|
|
|
function setFont(options) {
|
|
|
|
|
if (options.color) fontColor = options.color;
|
|
|
|
|
if (options.scale) fontScale = options.scale;
|
2020-11-10 15:05:08 -05:00
|
|
|
if (options.axisColor) axisColor = options.axisColor;
|
|
|
|
|
if (options.rulerColor) rulerColor = options.rulerColor;
|
2021-01-08 21:56:46 -05:00
|
|
|
updateRulers();
|
2020-11-10 15:05:08 -05:00
|
|
|
}
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
function showAxes(bool) {
|
2020-11-10 15:05:08 -05:00
|
|
|
axesOn = bool;
|
2021-01-08 21:56:46 -05:00
|
|
|
updateRulers();
|
2020-11-10 11:17:51 -05:00
|
|
|
}
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
function showVolume(bool) {
|
2020-11-10 15:38:09 -05:00
|
|
|
volumeOn = bool;
|
|
|
|
|
if (volume) volume.visible = bool;
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
function canvasInMesh(w, h, textAlign, textBaseline, color, size) {
|
|
|
|
|
let canvas = document.createElement('canvas'),
|
|
|
|
|
canvasTexture = new THREE.CanvasTexture(canvas),
|
|
|
|
|
plane = new THREE.PlaneGeometry(w, h),
|
|
|
|
|
context = canvas.getContext('2d'),
|
|
|
|
|
scale = 8;
|
|
|
|
|
|
|
|
|
|
canvas.width = w * scale;
|
|
|
|
|
canvas.height = h * scale;
|
|
|
|
|
|
|
|
|
|
context.scale(scale, scale);
|
|
|
|
|
context.fillStyle = color || fontColor;
|
|
|
|
|
context.font = `${size}px sans-serif`;
|
|
|
|
|
context.textAlign = textAlign;
|
|
|
|
|
context.textBaseline = textBaseline;
|
|
|
|
|
canvasTexture.minFilter = THREE.LinearFilter;
|
|
|
|
|
|
|
|
|
|
// set 'transparent' to false to debug mesh bounds
|
|
|
|
|
let material = new THREE.MeshBasicMaterial({transparent: true, map: canvasTexture});
|
|
|
|
|
let mesh = new THREE.Mesh(plane, material);
|
|
|
|
|
|
|
|
|
|
return { context, mesh };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
function setRulers(
|
|
|
|
|
xon = ruler.xon,
|
|
|
|
|
yon = ruler.yon,
|
2021-12-27 10:14:21 -05:00
|
|
|
factor = ruler.factor || 1,
|
|
|
|
|
xl = ruler.xlabel || 'X',
|
|
|
|
|
yl = ruler.ylabel || 'Y')
|
2021-12-27 09:36:55 -05:00
|
|
|
{
|
2021-01-08 21:56:46 -05:00
|
|
|
if (xon !== ruler.xon || yon !== ruler.yon || factor !== ruler.factor || xl !== ruler.xlabel || yl !== ruler.ylabel) {
|
|
|
|
|
ruler.factor = factor;
|
|
|
|
|
ruler.xon = xon;
|
|
|
|
|
ruler.yon = yon;
|
|
|
|
|
ruler.xlabel = xl;
|
|
|
|
|
ruler.ylabel = yl;
|
|
|
|
|
updateRulers();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-10 11:17:51 -05:00
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
function updateRulers() {
|
|
|
|
|
let { xon, yon, factor, xlabel, ylabel } = ruler;
|
2020-10-29 14:01:44 +02:00
|
|
|
let x = platform.scale.x,
|
|
|
|
|
y = isRound ? platform.scale.z : platform.scale.y,
|
|
|
|
|
z = isRound ? platform.scale.y : platform.scale.z,
|
|
|
|
|
w = x / 2,
|
|
|
|
|
h = y / 2,
|
|
|
|
|
d = z / 2,
|
2021-12-27 09:00:27 -05:00
|
|
|
zp = -d - platformZOff + (gridZOff || (z/2-0.1)),
|
2021-01-08 21:56:46 -05:00
|
|
|
labelSize = grid.unitMinor * fontScale,
|
|
|
|
|
oldView = ruler.view,
|
|
|
|
|
view = ruler.view = new THREE.Group();
|
|
|
|
|
|
|
|
|
|
if (xon && axesOn) {
|
|
|
|
|
let xPadding = labelSize * 4,
|
|
|
|
|
canvas = canvasInMesh(x + xPadding, labelSize * 3, 'center', 'top', rulerColor, labelSize),
|
|
|
|
|
context = canvas.context,
|
|
|
|
|
mesh = canvas.mesh;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i >= ruler.x1; i -= grid.unitMajor) {
|
|
|
|
|
context.fillText((i * factor).round(1).toString(), ruler.xo + i + xPadding / 2, 0);
|
|
|
|
|
}
|
|
|
|
|
for (let i = 0; i <= ruler.x2; i += grid.unitMajor) {
|
|
|
|
|
context.fillText((i * factor).round(1).toString(), ruler.xo + i + xPadding / 2, 0);
|
|
|
|
|
}
|
2020-10-29 14:01:44 +02:00
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
context.font = (labelSize * 0.75) + 'px sans-serif';
|
|
|
|
|
context.fillText(xlabel, (x + xPadding) / 2, labelSize * 1.5);
|
|
|
|
|
mesh.position.set(0, - h - labelSize * 2, zp);
|
|
|
|
|
view.add(mesh);
|
2020-10-29 14:01:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
if (yon && axesOn) {
|
|
|
|
|
let yPadding = labelSize,
|
|
|
|
|
canvas = canvasInMesh(labelSize * 4, y + yPadding, 'end', 'middle', rulerColor, labelSize),
|
|
|
|
|
context = canvas.context,
|
|
|
|
|
mesh = canvas.mesh;
|
2020-10-29 14:01:44 +02:00
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
for (let i = 0; i >= ruler.y1; i -= grid.unitMajor) {
|
|
|
|
|
context.fillText((i * factor).round(1), labelSize * 4, y - (ruler.yo + i) + yPadding / 2);
|
2020-10-29 14:01:44 +02:00
|
|
|
}
|
2021-01-08 21:56:46 -05:00
|
|
|
for (let i = 0; i <= ruler.y2; i += grid.unitMajor) {
|
|
|
|
|
context.fillText((i * factor).round(1), labelSize * 4, y - (ruler.yo + i) + yPadding / 2);
|
2020-11-10 15:05:08 -05:00
|
|
|
}
|
2020-10-29 14:01:44 +02:00
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
context.font = (labelSize * 0.75) + 'px sans-serif';
|
|
|
|
|
context.fillText(ylabel, labelSize * 1.25, (y + yPadding) / 2);
|
|
|
|
|
mesh.position.set(-w - labelSize * 2 - 5, 0, zp);
|
|
|
|
|
view.add(mesh);
|
|
|
|
|
}
|
2020-10-29 14:01:44 +02:00
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
Space.scene.remove(oldView);
|
|
|
|
|
Space.scene.add(view);
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
2020-11-10 15:05:08 -05:00
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
function setGrid(
|
|
|
|
|
unitMajor = grid.unitMajor,
|
|
|
|
|
unitMinor = grid.unitMinor,
|
|
|
|
|
colorMajor = grid.colorMajor,
|
|
|
|
|
colorMinor = grid.colorMinor)
|
|
|
|
|
{
|
2021-01-08 21:56:46 -05:00
|
|
|
if (!unitMajor) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (unitMajor !== grid.unitMajor || unitMinor !== grid.unitMinor) {
|
|
|
|
|
grid.unitMajor = unitMajor;
|
|
|
|
|
grid.unitMinor = unitMinor;
|
|
|
|
|
grid.colorMajor = colorMajor || grid.colorMajor;
|
|
|
|
|
grid.colorMinor = colorMinor || grid.colorMinor;
|
|
|
|
|
updateGrid();
|
2020-10-29 14:01:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-10 19:10:55 -05:00
|
|
|
function modMatch(val, mod) {
|
|
|
|
|
let mv = Math.abs(val) % mod;
|
|
|
|
|
return (mv < 1) || ((mod - mv) < 1);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 21:56:46 -05:00
|
|
|
function updateGrid() {
|
|
|
|
|
let { view, unitMinor, unitMajor, colorMajor, colorMinor } = grid;
|
|
|
|
|
let oldView = view;
|
|
|
|
|
view = grid.view = new THREE.Group();
|
|
|
|
|
|
|
|
|
|
let majors = [],
|
|
|
|
|
minors = [],
|
|
|
|
|
x = platform.scale.x,
|
2020-02-29 20:13:49 -05:00
|
|
|
y = isRound ? platform.scale.z : platform.scale.y,
|
|
|
|
|
z = isRound ? platform.scale.y : platform.scale.z,
|
2021-12-27 09:00:27 -05:00
|
|
|
zp = -(z / 2) - platformZOff + (gridZOff || (z/2-0.1)),
|
2021-01-08 21:56:46 -05:00
|
|
|
xh = x / 2,
|
|
|
|
|
yh = y / 2,
|
|
|
|
|
x1 = -xh - origin.x,
|
|
|
|
|
x2 = xh - origin.x,
|
|
|
|
|
y1 = -yh + origin.y,
|
|
|
|
|
y2 = yh + origin.y,
|
|
|
|
|
xo = x1 + xh,
|
|
|
|
|
yo = y1 + yh;
|
|
|
|
|
|
|
|
|
|
ruler.x1 = x1;
|
|
|
|
|
ruler.x2 = x2;
|
|
|
|
|
ruler.y1 = y1;
|
|
|
|
|
ruler.y2 = y2;
|
|
|
|
|
ruler.xo = xh - xo;
|
|
|
|
|
ruler.yo = yh - yo;
|
|
|
|
|
|
|
|
|
|
for (let x=0; x>x1; x -= unitMinor) {
|
|
|
|
|
let oh = isRound ? Math.sqrt(1-(x/xh)*(x/xh)) * yh : yh;
|
2021-01-10 19:10:55 -05:00
|
|
|
let arr = modMatch(x, unitMajor) ? majors : minors;
|
2021-01-08 21:56:46 -05:00
|
|
|
arr.append({x:x-xo, y:-oh, z:zp}).append({x:x-xo, y:oh, z:zp});
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2021-01-08 21:56:46 -05:00
|
|
|
for (let x=0; x<x2; x += unitMinor) {
|
|
|
|
|
let oh = isRound ? Math.sqrt(1-(x/xh)*(x/xh)) * yh : yh;
|
2021-01-10 19:10:55 -05:00
|
|
|
let arr = modMatch(x, unitMajor) ? majors : minors;
|
2021-01-08 21:56:46 -05:00
|
|
|
arr.append({x:x-xo, y:-oh, z:zp}).append({x:x-xo, y:oh, z:zp});
|
|
|
|
|
}
|
|
|
|
|
for (let y=0; y>y1; y -= unitMinor) {
|
|
|
|
|
let ow = isRound ? Math.sqrt(1-(y/yh)*(y/yh)) * xh : xh;
|
2021-01-10 19:10:55 -05:00
|
|
|
let arr = modMatch(y, unitMajor) ? majors : minors;
|
2021-01-08 21:56:46 -05:00
|
|
|
arr.append({x:-ow, y:y-yo, z:zp}).append({x:ow, y:y-yo, z:zp});
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2021-01-08 21:56:46 -05:00
|
|
|
for (let y=0; y<y2; y += unitMinor) {
|
|
|
|
|
let ow = isRound ? Math.sqrt(1-(y/yh)*(y/yh)) * xh : xh;
|
2021-01-10 19:10:55 -05:00
|
|
|
let arr = modMatch(y, unitMajor) ? majors : minors;
|
2021-01-08 21:56:46 -05:00
|
|
|
arr.append({x:-ow, y:y-yo, z:zp}).append({x:ow, y:y-yo, z:zp});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
view.add(makeLinesFromPoints(majors, colorMajor || 0x999999, 1));
|
|
|
|
|
view.add(makeLinesFromPoints(minors, colorMinor || 0xcccccc, 1));
|
|
|
|
|
|
|
|
|
|
Space.scene.remove(oldView);
|
|
|
|
|
Space.scene.add(grid.view);
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateDraws() {
|
|
|
|
|
updateGrid();
|
|
|
|
|
updateRulers();
|
|
|
|
|
requestRefresh();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2021-01-09 23:57:46 -05:00
|
|
|
function setOrigin(x, y, z, show) {
|
2021-01-08 21:56:46 -05:00
|
|
|
if (grid.origin) {
|
2021-01-09 23:57:46 -05:00
|
|
|
let or = origin;
|
|
|
|
|
let unchanged = x === or.x && y === or.y && z === or.z && show === or.show;
|
|
|
|
|
if (!unchanged) {
|
|
|
|
|
Space.scene.remove(grid.origin.group);
|
|
|
|
|
}
|
|
|
|
|
if (unchanged) {
|
2021-01-08 21:56:46 -05:00
|
|
|
updateDraws();
|
2020-03-01 19:47:34 -05:00
|
|
|
return;
|
|
|
|
|
}
|
2020-03-01 19:00:36 -05:00
|
|
|
}
|
2021-01-09 23:57:46 -05:00
|
|
|
origin = {x, y, z, show};
|
|
|
|
|
if (!show) {
|
2020-03-01 19:00:36 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let cmat = new THREE.MeshPhongMaterial({
|
|
|
|
|
color: 0xcceeff,
|
|
|
|
|
specular: 0xcceeff,
|
|
|
|
|
shininess: 5,
|
|
|
|
|
transparent: true,
|
|
|
|
|
opacity: 0.5,
|
2020-11-13 23:09:53 -05:00
|
|
|
// side: THREE.DoubleSide
|
2020-03-01 19:00:36 -05:00
|
|
|
});
|
|
|
|
|
let rmat = new THREE.MeshPhongMaterial({
|
|
|
|
|
color: 0x88aadd,
|
|
|
|
|
transparent: true,
|
|
|
|
|
opacity: 0.5,
|
2020-11-13 23:09:53 -05:00
|
|
|
// side: THREE.DoubleSide
|
2020-03-01 19:00:36 -05:00
|
|
|
});
|
|
|
|
|
let PIP = Math.PI/2;
|
|
|
|
|
let pi1, pi2, pi3, pi4;
|
2020-03-01 19:47:34 -05:00
|
|
|
let group = new THREE.Group();
|
2021-01-08 21:56:46 -05:00
|
|
|
grid.origin = {x, y, z, group};
|
2020-03-01 19:47:34 -05:00
|
|
|
group.add(pi1 = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.CircleGeometry(4.6, 50, PIP*0, PIP*1),
|
|
|
|
|
cmat
|
|
|
|
|
));
|
|
|
|
|
pi1.position.x = 0.25;
|
|
|
|
|
pi1.position.y = 0.25;
|
2020-03-01 19:47:34 -05:00
|
|
|
group.add(pi2 = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.CircleGeometry(4.6, 50, PIP*1, PIP*1),
|
|
|
|
|
cmat
|
|
|
|
|
));
|
|
|
|
|
pi2.position.x = -0.25;
|
|
|
|
|
pi2.position.y = 0.25;
|
2020-03-01 19:47:34 -05:00
|
|
|
group.add(pi3 = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.CircleGeometry(4.6, 50, PIP*2, PIP*1),
|
|
|
|
|
cmat
|
|
|
|
|
));
|
|
|
|
|
pi3.position.x = -0.25;
|
|
|
|
|
pi3.position.y = -0.25;
|
2020-03-01 19:47:34 -05:00
|
|
|
group.add(pi4 = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.CircleGeometry(4.6, 50, PIP*3, PIP*1),
|
|
|
|
|
cmat
|
|
|
|
|
));
|
|
|
|
|
pi4.position.x = 0.25;
|
|
|
|
|
pi4.position.y = -0.25;
|
2020-11-14 11:12:12 -05:00
|
|
|
let aa, bb, cc;
|
|
|
|
|
group.add(aa = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.RingGeometry(5, 5.5, 50),
|
|
|
|
|
rmat
|
|
|
|
|
));
|
2020-11-14 11:12:12 -05:00
|
|
|
group.add(bb = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.PlaneGeometry(0.5, 10),
|
|
|
|
|
rmat
|
|
|
|
|
));
|
2020-11-14 11:12:12 -05:00
|
|
|
group.add(cc = new THREE.Mesh(
|
2020-03-01 19:00:36 -05:00
|
|
|
new THREE.PlaneGeometry(10, 0.5),
|
|
|
|
|
rmat
|
|
|
|
|
));
|
2020-03-01 19:47:34 -05:00
|
|
|
group.rotation.x = -PI2;
|
|
|
|
|
group.position.x = x;
|
|
|
|
|
group.position.y = z;
|
|
|
|
|
group.position.z = y;
|
2020-11-14 11:12:12 -05:00
|
|
|
[bb,cc].forEach(m => {
|
|
|
|
|
m.renderOrder = 3;
|
|
|
|
|
});
|
2020-03-01 19:47:34 -05:00
|
|
|
Space.scene.add(group);
|
2021-01-08 21:56:46 -05:00
|
|
|
updateDraws();
|
2020-03-01 19:00:36 -05:00
|
|
|
}
|
|
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
function setRound(bool) {
|
|
|
|
|
let current = platform;
|
|
|
|
|
isRound = bool;
|
|
|
|
|
if (bool) {
|
|
|
|
|
platform = new THREE.Mesh(
|
|
|
|
|
new THREE.CylinderGeometry(.5, .5, 1, 60),
|
|
|
|
|
platformMaterial
|
|
|
|
|
);
|
|
|
|
|
platform.rotation.x = 0;
|
|
|
|
|
} else {
|
|
|
|
|
platform = new THREE.Mesh(
|
|
|
|
|
new THREE.BoxGeometry(1, 1, 1),
|
|
|
|
|
platformMaterial
|
|
|
|
|
);
|
|
|
|
|
platform.rotation.x = -PI2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
platform.position.y = current.position.y;
|
|
|
|
|
platform.visible = current.visible;
|
|
|
|
|
|
|
|
|
|
SCENE.remove(current);
|
|
|
|
|
SCENE.add(platform);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function refresh() {
|
|
|
|
|
refreshRequested = false;
|
2021-01-08 21:56:46 -05:00
|
|
|
clearTimeout(refreshTimeout);
|
2020-06-29 23:36:18 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
viewControl.update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** deferred refresh that collapses multiple requests */
|
|
|
|
|
function requestRefresh(timeout) {
|
|
|
|
|
if (refreshRequested === false) {
|
|
|
|
|
refreshRequested = true;
|
2020-03-19 18:34:03 -04:00
|
|
|
clearTimeout(refreshTimeout);
|
|
|
|
|
refreshTimeout = setTimeout(refresh, timeout || 10);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onResize() {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
camera.aspect = aspect();
|
|
|
|
|
camera.updateProjectionMatrix();
|
|
|
|
|
renderer.setSize(width(), height());
|
|
|
|
|
container.style.width = width();
|
|
|
|
|
container.style.height = height();
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function alignTracking(point, rot, out) {
|
|
|
|
|
if (point && rot) {
|
|
|
|
|
alignedTracking = true;
|
|
|
|
|
trackPlane.position.set(point.x, point.y, point.z);
|
|
|
|
|
trackPlane.rotation.set(rot.x, rot.y, rot.z);
|
|
|
|
|
trackDelta = out;
|
|
|
|
|
} else {
|
|
|
|
|
alignedTracking = false;
|
|
|
|
|
trackPlane.position.set(0, 0, 0);
|
|
|
|
|
trackPlane.rotation.set(PI2, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cca(c) {
|
|
|
|
|
return c.charCodeAt(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function inputHasFocus() {
|
|
|
|
|
return DOC.activeElement && (DOC.activeElement != DOC.body);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function keyHandler(evt) {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
if (!defaultKeys || inputHasFocus()) return false;
|
|
|
|
|
if (evt.metaKey) return false;
|
2020-02-29 20:13:49 -05:00
|
|
|
let handled = true;
|
2017-04-18 17:09:33 -04:00
|
|
|
switch (evt.charCode) {
|
|
|
|
|
case cca('z'):
|
|
|
|
|
Space.view.reset();
|
|
|
|
|
break;
|
|
|
|
|
case cca('h'):
|
|
|
|
|
Space.view.home();
|
|
|
|
|
break;
|
|
|
|
|
case cca('t'):
|
|
|
|
|
Space.view.top();
|
|
|
|
|
break;
|
2021-01-15 11:50:59 -05:00
|
|
|
case cca('f'):
|
|
|
|
|
Space.view.front();
|
|
|
|
|
cycleInd = 0;
|
|
|
|
|
break;
|
2021-01-16 16:56:37 -05:00
|
|
|
case cca('b'):
|
|
|
|
|
Space.view.back();
|
|
|
|
|
cycleInd = 2;
|
|
|
|
|
break;
|
2021-01-15 11:50:59 -05:00
|
|
|
case cca('>'):
|
|
|
|
|
cycleInd = (++cycleInd % cycle.length);
|
|
|
|
|
cycle[cycleInd]();
|
|
|
|
|
break;
|
|
|
|
|
case cca('<'):
|
|
|
|
|
cycleInd--;
|
|
|
|
|
if (cycleInd < 0) {
|
|
|
|
|
cycleInd += cycle.length;
|
|
|
|
|
}
|
|
|
|
|
cycle[cycleInd]();
|
|
|
|
|
break;
|
2017-04-18 17:09:33 -04:00
|
|
|
default:
|
|
|
|
|
handled = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (handled) evt.preventDefault();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ******************************************************************
|
|
|
|
|
* ThreeJS Helper Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
2020-11-10 15:38:09 -05:00
|
|
|
function makeLinesFromPoints(points, color, opacity) {
|
|
|
|
|
if (points.length % 2 != 0) {
|
|
|
|
|
throw "invalid line : "+points.length;
|
|
|
|
|
}
|
2021-03-01 22:41:29 -05:00
|
|
|
const geo = new THREE.BufferGeometry();
|
|
|
|
|
const vrt = new Float32Array(points.length * 3);
|
|
|
|
|
let vi = 0;
|
|
|
|
|
for (let p of points) {
|
|
|
|
|
vrt[vi++] = p.x;
|
|
|
|
|
vrt[vi++] = p.y;
|
|
|
|
|
vrt[vi++] = p.z;
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2021-03-01 22:41:29 -05:00
|
|
|
geo.setAttribute('position', new THREE.BufferAttribute(vrt, 3));
|
2020-11-10 15:38:09 -05:00
|
|
|
return new THREE.LineSegments(geo, new THREE.LineBasicMaterial({
|
2017-04-18 17:09:33 -04:00
|
|
|
color: color,
|
2020-11-10 15:38:09 -05:00
|
|
|
opacity: opacity || 1,
|
|
|
|
|
transparent: opacity != 1
|
2017-04-18 17:09:33 -04:00
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function intersect(objects, recurse) {
|
2021-03-04 13:22:53 -05:00
|
|
|
return raycaster.intersectObjects(objects, recurse);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ******************************************************************
|
|
|
|
|
* Mouse Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
|
|
|
|
function onMouseDown(event) {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
if (event.target === renderer.domElement) {
|
|
|
|
|
DOC.activeElement.blur();
|
|
|
|
|
event.preventDefault();
|
2020-02-29 20:13:49 -05:00
|
|
|
let selection = null,
|
2020-04-15 09:51:21 -04:00
|
|
|
trackTo = alignedTracking ? trackPlane : platform,
|
|
|
|
|
isVis = trackTo.visible;
|
2017-04-18 17:09:33 -04:00
|
|
|
if (mouseDownSelect) selection = mouseDownSelect();
|
|
|
|
|
if (selection && selection.length > 0) {
|
|
|
|
|
trackTo.visible = true;
|
2020-02-29 20:13:49 -05:00
|
|
|
let int = intersect(selection.slice().append(trackTo), false);
|
2020-04-15 09:51:21 -04:00
|
|
|
trackTo.visible = isVis;
|
2017-04-18 17:09:33 -04:00
|
|
|
if (int.length > 0) {
|
2020-02-29 20:13:49 -05:00
|
|
|
let trackInt, selectInt;
|
|
|
|
|
for (let i=0; i<int.length; i++) {
|
2017-04-18 17:09:33 -04:00
|
|
|
if (!trackInt && int[i].object === trackTo) {
|
|
|
|
|
trackInt = int[i];
|
|
|
|
|
} else if (!selectInt && selection.contains(int[i].object)) {
|
|
|
|
|
selectInt = int[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (trackInt && selectInt) {
|
|
|
|
|
mouseDragPoint = trackInt.point.clone();
|
|
|
|
|
mouseDragStart = mouseDragPoint;
|
|
|
|
|
viewControl.enabled = false;
|
2020-03-30 14:10:36 -04:00
|
|
|
}
|
|
|
|
|
if (selectInt) {
|
2017-04-18 17:09:33 -04:00
|
|
|
mouseDownSelect(selectInt, event);
|
|
|
|
|
}
|
2020-12-06 21:25:31 -05:00
|
|
|
if (mouseDown) mouseDown(event, int);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2020-12-06 21:25:31 -05:00
|
|
|
} else if (mouseDown) {
|
|
|
|
|
let int = intersect(selection.slice().append(platform), false);
|
|
|
|
|
if (int && int.length) mouseDown(event, int);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
if (platformClick) {
|
2020-02-29 20:13:49 -05:00
|
|
|
let vis = platform.visible;
|
2017-04-18 17:09:33 -04:00
|
|
|
platform.visible = true;
|
2020-03-09 14:14:09 -04:00
|
|
|
let int = intersect([platform], false);
|
2017-04-18 17:09:33 -04:00
|
|
|
platform.visible = vis;
|
|
|
|
|
platformClickAt = int && int.length > 0 ? int[0].point : null;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
viewControl.enabled = false;
|
|
|
|
|
}
|
2020-03-19 18:34:03 -04:00
|
|
|
mouseStart = {
|
|
|
|
|
x: (event.clientX / width()) * 2 - 1,
|
|
|
|
|
y: -(event.clientY / height()) * 2 + 1};
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onMouseUp(event) {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2017-04-18 17:09:33 -04:00
|
|
|
if (!viewControl.enabled) {
|
|
|
|
|
viewControl.enabled = true;
|
|
|
|
|
viewControl.onMouseUp(event);
|
|
|
|
|
}
|
2020-03-19 18:34:03 -04:00
|
|
|
let mouseEnd = {
|
|
|
|
|
x: (event.clientX / width()) * 2 - 1,
|
|
|
|
|
y: -(event.clientY / height()) * 2 + 1};
|
|
|
|
|
// only fire on mouse move between mouseStart (down) and up
|
2020-07-03 22:07:45 -04:00
|
|
|
if (mouseStart && mouseEnd.x - mouseStart.x + mouseEnd.y - mouseStart.y === 0) {
|
2017-04-18 17:09:33 -04:00
|
|
|
event.preventDefault();
|
2020-03-19 18:34:03 -04:00
|
|
|
let refresh = false,
|
|
|
|
|
selection = null;
|
2021-10-19 21:58:06 -04:00
|
|
|
if (mouseUpSelect) {
|
|
|
|
|
selection = mouseUpSelect();
|
|
|
|
|
}
|
2020-03-19 18:34:03 -04:00
|
|
|
if (selection && selection.length > 0) {
|
|
|
|
|
let int = intersect(selection, selectRecurse);
|
2020-12-06 21:25:31 -05:00
|
|
|
if (mouseUp) {
|
|
|
|
|
if (int.length) {
|
|
|
|
|
mouseUp(event, int);
|
|
|
|
|
} else {
|
|
|
|
|
mouseUp(event, intersect([platform], selectRecurse));
|
|
|
|
|
}
|
|
|
|
|
if (event.button === 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-19 18:34:03 -04:00
|
|
|
if (int.length > 0) {
|
|
|
|
|
mouseUpSelect(int[0], event);
|
|
|
|
|
refresh = true;
|
|
|
|
|
} else {
|
|
|
|
|
mouseUpSelect(null, event);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-19 18:34:03 -04:00
|
|
|
if (!refresh && platformClickAt) {
|
|
|
|
|
platformClick(platformClickAt);
|
|
|
|
|
}
|
2021-10-19 21:58:06 -04:00
|
|
|
if (refresh) {
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
2020-07-03 22:07:45 -04:00
|
|
|
mouseStart = null;
|
2017-04-18 17:09:33 -04:00
|
|
|
} else if (mouseDrag && mouseDragStart) {
|
|
|
|
|
mouseDrag(null,null,true);
|
|
|
|
|
}
|
|
|
|
|
mouseDragPoint = null;
|
|
|
|
|
mouseDragStart = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onMouseMove(event) {
|
2020-06-14 18:42:15 -04:00
|
|
|
updateLastAction();
|
2020-02-29 20:13:49 -05:00
|
|
|
let int, vis;
|
2020-11-22 12:12:23 -05:00
|
|
|
|
2021-03-04 13:22:53 -05:00
|
|
|
const mv = new THREE.Vector2();
|
|
|
|
|
mv.x = ( event.clientX / window.innerWidth ) * 2 - 1;
|
|
|
|
|
mv.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
|
|
|
|
|
raycaster.setFromCamera( mv, camera );
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
if (viewControl.enabled) {
|
|
|
|
|
event.preventDefault();
|
2020-02-29 20:13:49 -05:00
|
|
|
let selection = mouseHover ? mouseHover() : null;
|
2017-04-18 17:09:33 -04:00
|
|
|
if (selection && selection.length > 0) {
|
|
|
|
|
int = intersect(selection, selectRecurse);
|
2020-12-01 00:35:25 -05:00
|
|
|
if (int.length > 0) mouseHover(int[0], event, int);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
if ((!int || int.length == 0) && platformHover) {
|
|
|
|
|
vis = platform.visible;
|
|
|
|
|
platform.visible = true;
|
|
|
|
|
int = intersect([platform], false);
|
|
|
|
|
platform.visible = vis;
|
|
|
|
|
if (int && int.length > 0) platformHover(int[0].point);
|
|
|
|
|
}
|
|
|
|
|
} else if (mouseDragPoint && mouseDrag && mouseDrag()) {
|
|
|
|
|
event.preventDefault();
|
2020-02-29 20:13:49 -05:00
|
|
|
let trackTo = alignedTracking ? trackPlane : platform;
|
2020-04-15 09:51:21 -04:00
|
|
|
let vis = trackTo.visible;
|
2017-04-18 17:09:33 -04:00
|
|
|
trackTo.visible = true;
|
|
|
|
|
int = intersect([trackTo], false);
|
2020-04-15 09:51:21 -04:00
|
|
|
trackTo.visible = vis;
|
2017-04-18 17:09:33 -04:00
|
|
|
if (int.length > 0 && int[0].object === trackTo) {
|
2020-02-29 20:13:49 -05:00
|
|
|
let delta = mouseDragPoint.clone().sub(int[0].point);
|
|
|
|
|
let offset = mouseDragStart.clone().sub(int[0].point);
|
2017-04-18 17:09:33 -04:00
|
|
|
mouseDragPoint = int[0].point;
|
|
|
|
|
mouseDrag({x: -delta.x, y: delta.z}, offset.multiplyVectors(offset, trackDelta));
|
|
|
|
|
requestRefresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mouse = {
|
|
|
|
|
x: (event.clientX / width()) * 2 - 1,
|
|
|
|
|
y: -(event.clientY / height()) * 2 + 1};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ******************************************************************
|
|
|
|
|
* Space Object
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
2021-12-28 13:02:01 -05:00
|
|
|
function setSky(opt = {}) {
|
|
|
|
|
let { grid, color, gridColor } = opt;
|
|
|
|
|
if (grid) Space.sky.showGrid(grid);
|
|
|
|
|
if (color) Space.sky.setColor(color);
|
|
|
|
|
if (gridColor) Space.sky.setGridColor(gridColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setPlatform(opt = {}) {
|
|
|
|
|
let { color, round, size, grid, opacity, volume, zOffset } = opt;
|
|
|
|
|
if (color) {
|
|
|
|
|
Space.platform.setColor(color);
|
|
|
|
|
}
|
|
|
|
|
if (round !== undefined) {
|
|
|
|
|
Space.platform.setRound(round);
|
|
|
|
|
}
|
|
|
|
|
if (size) {
|
|
|
|
|
let { width = 300, depth = 300, height = 2.5, maxz = 300 } = size;
|
|
|
|
|
Space.platform.setSize(width, depth, height, maxz);
|
|
|
|
|
}
|
|
|
|
|
if (grid) {
|
|
|
|
|
let { major = 25, minor = 5, majorColor = 0x999999, minorColor = 0xcccccc } = grid;
|
|
|
|
|
Space.platform.setGrid(major, minor, majorColor, minorColor);
|
|
|
|
|
}
|
|
|
|
|
if (opacity !== undefined) {
|
|
|
|
|
Space.platform.opacity(opacity);
|
|
|
|
|
}
|
|
|
|
|
if (volume !== undefined) {
|
|
|
|
|
Space.platform.showVolume(volume);
|
|
|
|
|
}
|
|
|
|
|
if (zOffset !== undefined) {
|
|
|
|
|
Space.platform.setZOff(zOffset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 15:29:47 -04:00
|
|
|
let Space = MOTO.Space = {
|
2021-12-27 09:36:55 -05:00
|
|
|
refresh: refresh,
|
2017-04-18 17:09:33 -04:00
|
|
|
update: requestRefresh,
|
2021-12-27 09:36:55 -05:00
|
|
|
|
|
|
|
|
alignTracking: alignTracking,
|
2021-03-04 13:22:53 -05:00
|
|
|
raycast: intersect,
|
2021-12-27 09:36:55 -05:00
|
|
|
|
|
|
|
|
event: {
|
|
|
|
|
addHandlers: addEventHandlers,
|
|
|
|
|
onEnterKey: onEnterKey,
|
|
|
|
|
onResize: onResize
|
|
|
|
|
},
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
sky: {
|
2021-12-28 13:02:01 -05:00
|
|
|
set: setSky,
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
showGrid: (b) => {
|
|
|
|
|
showSkyGrid = b;
|
|
|
|
|
},
|
2020-07-08 15:36:46 -04:00
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
setColor: (c) => {
|
|
|
|
|
skyColor = c;
|
|
|
|
|
if (skyMaterial) skyMaterial.color = new THREE.Color(c);
|
|
|
|
|
},
|
2020-07-08 15:36:46 -04:00
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
setGridColor: (c) => {
|
|
|
|
|
skyGridColor = c;
|
|
|
|
|
if (skyGridMaterial) skyGridMaterial.color = new THREE.Color(c);
|
|
|
|
|
}
|
2020-07-08 15:36:46 -04:00
|
|
|
},
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
scene: {
|
|
|
|
|
add: function (o) {
|
|
|
|
|
o.rotation.x = WORLD.rotation.x;
|
|
|
|
|
return SCENE.add(o);
|
|
|
|
|
},
|
2021-12-27 09:00:27 -05:00
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
remove: function (o) {
|
|
|
|
|
return SCENE.remove(o);
|
2020-04-15 15:20:02 -04:00
|
|
|
},
|
2021-12-27 09:00:27 -05:00
|
|
|
|
2020-06-19 19:23:09 -04:00
|
|
|
active: updateLastAction
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
world: WORLD,
|
2020-11-22 12:12:23 -05:00
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
platform: {
|
2021-12-28 13:02:01 -05:00
|
|
|
set: setPlatform,
|
2021-12-27 09:00:27 -05:00
|
|
|
update: updateDraws,
|
|
|
|
|
setSize: setPlatformSizeUpdateGrid,
|
|
|
|
|
setColor: setPlatformColor,
|
|
|
|
|
setOrigin: setOrigin,
|
|
|
|
|
setRulers: setRulers,
|
|
|
|
|
setGrid: setGrid,
|
|
|
|
|
setFont: setFont,
|
2021-12-27 09:36:55 -05:00
|
|
|
setRound: setRound,
|
2021-12-27 09:00:27 -05:00
|
|
|
showAxes: showAxes,
|
|
|
|
|
showVolume: showVolume,
|
2021-12-27 09:36:55 -05:00
|
|
|
showGrid: (b) => { grid.view.visible = b },
|
2021-12-27 09:00:27 -05:00
|
|
|
setMaxZ: (z) => { panY = z / 2 },
|
|
|
|
|
setCenter: (x,y,z) => { panX = x; panY = z, panZ = y },
|
|
|
|
|
setHidden: (b) => { showPlatform = !b; platform.visible = !b },
|
|
|
|
|
setHiding: (b) => { hidePlatformBelow = b },
|
|
|
|
|
setZOff: (z) => { platformZOff = z; updatePlatformPosition() },
|
|
|
|
|
setGridZOff:(z) => { gridZOff = z; updatePlatformPosition() },
|
2021-12-27 09:36:55 -05:00
|
|
|
isHidden: () => { return !showPlatform },
|
|
|
|
|
isVisible: () => { return platform.visible },
|
2021-12-27 09:00:27 -05:00
|
|
|
opacity: (o) => { platform.material.opacity = o },
|
|
|
|
|
onMove: (f) => { platformOnMove = f },
|
|
|
|
|
onHover: (f) => { platformHover = f },
|
|
|
|
|
onClick: (f) => { platformClick = f},
|
2021-12-27 09:36:55 -05:00
|
|
|
size: () => { return platform.scale }
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
view: {
|
2021-12-27 09:36:55 -05:00
|
|
|
top: (then) => { tweenCam({left: home, up: 0, panX, panY, panZ, then}) },
|
|
|
|
|
back: (then) => { tweenCam({left: PI, up: PI2, panX, panY, panZ, then}) },
|
|
|
|
|
home: (then) => { tweenCam({left: home, up, panX, panY, panZ, then}) },
|
|
|
|
|
front: (then) => { tweenCam({left: 0, up: PI2, panX, panY, panZ, then}) },
|
|
|
|
|
right: (then) => { tweenCam({left: PI2, up: PI2, panX, panY, panZ, then}) },
|
|
|
|
|
left: (then) => { tweenCam({left: -PI2, up: PI2, panX, panY, panZ, then}) },
|
|
|
|
|
reset: () => { viewControl.reset(); requestRefresh() },
|
|
|
|
|
load: (cam) => { viewControl.setPosition(cam) },
|
|
|
|
|
save: () => { return viewControl.getPosition(true) },
|
|
|
|
|
panTo: (x,y,z) => { tweenCamPan(x,y,z) },
|
2021-12-27 09:00:27 -05:00
|
|
|
setZoom: (r,v) => { viewControl.setZoom(r,v) },
|
|
|
|
|
setCtrl: (name) => {
|
2020-11-17 20:26:13 -05:00
|
|
|
if (name === 'onshape') {
|
|
|
|
|
viewControl.setMouse(viewControl.mouseOnshape);
|
|
|
|
|
} else {
|
|
|
|
|
viewControl.setMouse(viewControl.mouseDefault);
|
|
|
|
|
}
|
|
|
|
|
},
|
2021-12-27 09:00:27 -05:00
|
|
|
getFPS: () => { return fps },
|
|
|
|
|
getFocus: () => { return viewControl.getTarget() },
|
2021-12-27 09:36:55 -05:00
|
|
|
setFocus: (v) => { viewControl.setTarget(v); refresh() },
|
2021-12-27 09:00:27 -05:00
|
|
|
setHome: (r,u) => {
|
2021-01-22 15:33:18 -05:00
|
|
|
home = r || 0;
|
2021-11-26 21:32:19 -05:00
|
|
|
up = u || PI4;
|
2021-02-10 20:11:03 -05:00
|
|
|
},
|
2021-12-27 09:00:27 -05:00
|
|
|
spin: (then, count) => {
|
2021-02-10 20:11:03 -05:00
|
|
|
Space.view.front(() => {
|
2021-12-27 09:36:55 -05:00
|
|
|
Space.view.right(() => {
|
|
|
|
|
Space.view.back(() => {
|
|
|
|
|
Space.view.left(() => {
|
|
|
|
|
if (--count > 0) {
|
|
|
|
|
Space.view.spin(then, count);
|
|
|
|
|
} else {
|
|
|
|
|
Space.view.front(then);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-02-10 20:11:03 -05:00
|
|
|
});
|
2021-01-22 15:33:18 -05:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
mouse: {
|
2021-12-27 09:00:27 -05:00
|
|
|
up: (f) => { mouseUp = f },
|
|
|
|
|
down: (f) => { mouseDown = f },
|
|
|
|
|
downSelect: (f) => { mouseDownSelect = f },
|
|
|
|
|
upSelect: (f) => { mouseUpSelect = f },
|
|
|
|
|
onDrag: (f) => { mouseDrag = f },
|
|
|
|
|
onHover: (f) => { mouseHover = f }
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
tween: {
|
|
|
|
|
setTime: (t) => { tweenTime = t || 500 },
|
|
|
|
|
setDelay: (d) => { tweenDelay = d || 20 }
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:36:55 -05:00
|
|
|
useDefaultKeys: (b) => { defaultKeys = b },
|
|
|
|
|
selectRecurse: (b) => { selectRecurse = b },
|
|
|
|
|
objects: () => { return WORLD.children },
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
screenshot: (format, options) => {
|
2021-07-09 20:31:37 -04:00
|
|
|
return renderer.domElement.toDataURL(format || "image/png", options);
|
|
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
screenshot2: (param = {}) => {
|
2021-07-09 20:31:37 -04:00
|
|
|
let oco = renderer.domElement;
|
|
|
|
|
let oWidth = oco.offsetWidth;
|
|
|
|
|
let oHeight = oco.offsetHeight;
|
|
|
|
|
let oRatio = oHeight / oWidth;
|
|
|
|
|
let width = param.width || 240;
|
|
|
|
|
let ncv = document.createElement('canvas');
|
|
|
|
|
ncv.width = width;
|
|
|
|
|
ncv.height = width * oRatio;
|
|
|
|
|
let nco = ncv.getContext('2d');
|
|
|
|
|
nco.drawImage(oco, 0, 0, ncv.width, ncv.height);
|
|
|
|
|
return {
|
|
|
|
|
url: ncv.toDataURL(param.format || "image/png", param.options),
|
|
|
|
|
width: ncv.width,
|
|
|
|
|
height: ncv.height
|
|
|
|
|
};
|
2017-10-30 14:21:23 -04:00
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
internals: () => {
|
2020-11-22 13:15:27 -05:00
|
|
|
return { renderer, camera, platform };
|
2020-11-10 10:24:26 -05:00
|
|
|
},
|
|
|
|
|
|
2021-12-27 09:00:27 -05:00
|
|
|
init: (domelement, slider, ortho) => {
|
2017-04-18 17:09:33 -04:00
|
|
|
container = domelement;
|
|
|
|
|
|
|
|
|
|
WORLD.rotation.x = -PI2;
|
|
|
|
|
SCENE.add(WORLD);
|
|
|
|
|
|
|
|
|
|
domelement.style.width = width();
|
|
|
|
|
domelement.style.height = height();
|
|
|
|
|
|
2017-10-30 14:21:23 -04:00
|
|
|
renderer = new THREE.WebGLRenderer({
|
|
|
|
|
antialias: true,
|
2021-09-18 12:50:05 -04:00
|
|
|
preserveDrawingBuffer: true,
|
|
|
|
|
logarithmicDepthBuffer: true
|
2017-10-30 14:21:23 -04:00
|
|
|
});
|
2021-03-04 13:22:53 -05:00
|
|
|
camera = ortho ?
|
|
|
|
|
new THREE.OrthographicCamera(-100 * aspect(), 100 * aspect(), 100, -100, 0.1, 100000) :
|
2021-12-02 18:26:22 -05:00
|
|
|
new THREE.PerspectiveCamera(perspective, aspect(), 0.1, 100000);
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
camera.position.set(0, 200, 340);
|
|
|
|
|
renderer.setSize(width(), height());
|
|
|
|
|
domelement.appendChild(renderer.domElement);
|
|
|
|
|
|
2021-03-04 13:22:53 -05:00
|
|
|
raycaster = new THREE.Raycaster();
|
|
|
|
|
|
2021-12-28 16:38:05 -05:00
|
|
|
viewControl = new MOTO.Orbit(camera, domelement, (position, moved) => {
|
2020-03-17 15:29:47 -04:00
|
|
|
if (platform) {
|
|
|
|
|
platform.visible = hidePlatformBelow ?
|
|
|
|
|
initialized && position.y >= 0 && showPlatform : showPlatform;
|
|
|
|
|
}
|
|
|
|
|
if (trackcam) {
|
|
|
|
|
trackcam.position.copy(camera.position);
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
if (moved && platformOnMove) {
|
2020-03-17 15:29:47 -04:00
|
|
|
clearTimeout(platformMoveTimer);
|
2017-04-18 17:09:33 -04:00
|
|
|
platformMoveTimer = setTimeout(platformOnMove, 500);
|
|
|
|
|
}
|
2020-07-08 19:47:12 -04:00
|
|
|
updateLastAction();
|
2020-06-14 19:13:46 -04:00
|
|
|
}, (val) => {
|
|
|
|
|
updateLastAction();
|
2020-06-30 10:31:52 -04:00
|
|
|
if (slider) slider(val);
|
2020-06-14 19:13:46 -04:00
|
|
|
});
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
viewControl.noKeys = true;
|
|
|
|
|
viewControl.maxDistance = 1000;
|
|
|
|
|
|
|
|
|
|
SCENE.add(new THREE.AmbientLight(0x707070));
|
|
|
|
|
|
|
|
|
|
light1 = addLight( 200, 250, 200, lightIntensity * 1.15);
|
|
|
|
|
light2 = addLight(-200, 250, -200, lightIntensity * 0.95);
|
|
|
|
|
light3 = addLight( 0, -200, 0, lightIntensity * 0.5);
|
|
|
|
|
light4 = addLight( 200, 5, -200, lightIntensity * 0.35);
|
|
|
|
|
light5 = addLight(-200, 5, 200, lightIntensity * 0.4);
|
|
|
|
|
|
|
|
|
|
platform = new THREE.Mesh(
|
|
|
|
|
new THREE.BoxGeometry(1, 1, 1),
|
2020-02-29 20:13:49 -05:00
|
|
|
platformMaterial
|
2017-04-18 17:09:33 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
platform.position.y = platformZOff;
|
|
|
|
|
platform.rotation.x = -PI2;
|
|
|
|
|
platform.visible = showPlatform;
|
|
|
|
|
|
|
|
|
|
trackPlane = new THREE.Mesh(
|
2020-04-15 09:51:21 -04:00
|
|
|
new THREE.PlaneBufferGeometry(100000, 100000, 1, 1),
|
2020-11-13 23:09:53 -05:00
|
|
|
new THREE.MeshBasicMaterial( { color: 0x777777, opacity: 0, transparent: true } )
|
2017-04-18 17:09:33 -04:00
|
|
|
);
|
2020-04-23 22:44:22 -04:00
|
|
|
trackPlane.visible = false;
|
2017-04-18 17:09:33 -04:00
|
|
|
trackPlane.rotation.x = PI2;
|
|
|
|
|
|
2020-02-29 20:13:49 -05:00
|
|
|
let sky = new THREE.Mesh(
|
2017-04-18 17:09:33 -04:00
|
|
|
new THREE.BoxGeometry(50000, 50000, 50000, 1, 1, 1),
|
2020-07-08 15:36:46 -04:00
|
|
|
skyMaterial =
|
2017-04-18 17:09:33 -04:00
|
|
|
new THREE.MeshBasicMaterial({ color: skyColor, side: THREE.DoubleSide })
|
|
|
|
|
),
|
|
|
|
|
skygrid = new THREE.Mesh(
|
|
|
|
|
new THREE.BoxGeometry(5000, 5000, 5000, 10, 10, 10),
|
2020-07-08 15:36:46 -04:00
|
|
|
skyGridMaterial =
|
2017-04-18 17:09:33 -04:00
|
|
|
new THREE.MeshBasicMaterial({ color: skyGridColor, side: THREE.DoubleSide })
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SCENE.add(platform);
|
|
|
|
|
SCENE.add(trackPlane);
|
|
|
|
|
SCENE.add(sky);
|
|
|
|
|
|
|
|
|
|
if (showSkyGrid) {
|
|
|
|
|
skygrid.material.wireframe = true;
|
|
|
|
|
SCENE.add(skygrid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addEventHandlers(WIN, [
|
|
|
|
|
'resize', onResize,
|
|
|
|
|
'mousemove', onMouseMove,
|
|
|
|
|
'mousedown', onMouseDown,
|
|
|
|
|
'mouseup', onMouseUp,
|
2020-06-14 18:42:15 -04:00
|
|
|
'keypress', keyHandler,
|
|
|
|
|
'touchstart', updateLastAction,
|
|
|
|
|
'touchmove', updateLastAction,
|
|
|
|
|
'touchend', updateLastAction
|
2017-04-18 17:09:33 -04:00
|
|
|
]);
|
|
|
|
|
|
2020-11-11 18:07:53 -05:00
|
|
|
let animates = 0;
|
|
|
|
|
let rateStart = Date.now();
|
2020-06-14 18:42:15 -04:00
|
|
|
|
2020-04-15 09:51:21 -04:00
|
|
|
function animate() {
|
2020-11-11 18:07:53 -05:00
|
|
|
animates++;
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
if (now - rateStart > 1000) {
|
|
|
|
|
const delta = now - rateStart;
|
|
|
|
|
fps = 1000 * animates / delta;
|
|
|
|
|
animates = 0;
|
|
|
|
|
rateStart = now;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-15 09:51:21 -04:00
|
|
|
requestAnimationFrame(animate);
|
2020-06-14 19:13:46 -04:00
|
|
|
if (docVisible && !freeze && Date.now() - lastAction < 1500) {
|
2020-06-14 18:42:15 -04:00
|
|
|
renderer.render(SCENE, camera);
|
2021-12-28 15:52:28 -05:00
|
|
|
} else {
|
|
|
|
|
fps = 0;
|
2020-06-14 18:42:15 -04:00
|
|
|
}
|
2020-04-15 09:51:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
animate();
|
|
|
|
|
|
2020-11-10 10:24:26 -05:00
|
|
|
const ctx = renderer.getContext();
|
|
|
|
|
const ext = ctx.getExtension('WEBGL_debug_renderer_info');
|
|
|
|
|
const nav = navigator;
|
|
|
|
|
Space.info = {
|
|
|
|
|
ver: ctx.getParameter(ctx.VERSION),
|
|
|
|
|
ven: ctx.getParameter(ctx.VENDOR),
|
|
|
|
|
glr: ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL),
|
|
|
|
|
// glv: ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL),
|
|
|
|
|
pla: nav.platform
|
|
|
|
|
},
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
initialized = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
2021-01-15 11:50:59 -05:00
|
|
|
let cycle = [
|
|
|
|
|
Space.view.front,
|
|
|
|
|
Space.view.right,
|
|
|
|
|
Space.view.back,
|
|
|
|
|
Space.view.left,
|
|
|
|
|
];
|
|
|
|
|
let cycleInd = 0;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
})();
|