@inweb/viewer-three 25.9.8 → 25.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -18
- package/dist/viewer-three.js +9963 -6031
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -2
- package/dist/viewer-three.module.js +2648 -353
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/IDisposable.d.ts +6 -0
- package/lib/Viewer/Viewer.d.ts +119 -14
- package/lib/Viewer/commands/ApplyModelTransform.d.ts +1 -0
- package/lib/Viewer/commands/ClearMarkup.d.ts +1 -0
- package/lib/Viewer/commands/ClearSelected.d.ts +1 -0
- package/lib/Viewer/commands/ClearSlices.d.ts +1 -0
- package/lib/Viewer/commands/CreatePreview.d.ts +1 -0
- package/lib/Viewer/commands/Explode.d.ts +1 -0
- package/lib/Viewer/commands/GetDefaultViewPositions.d.ts +1 -0
- package/lib/Viewer/commands/GetModels.d.ts +1 -0
- package/lib/Viewer/commands/GetSelected.d.ts +1 -0
- package/lib/Viewer/commands/HideSelected.d.ts +1 -0
- package/lib/Viewer/commands/IsolateSelected.d.ts +1 -0
- package/lib/Viewer/commands/RegenerateAll.d.ts +1 -0
- package/lib/Viewer/commands/ResetView.d.ts +1 -0
- package/lib/Viewer/commands/SelectModel.d.ts +1 -0
- package/lib/Viewer/commands/SetActiveDragger.d.ts +1 -0
- package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +13 -0
- package/lib/Viewer/commands/SetMarkupColor.d.ts +1 -0
- package/lib/Viewer/commands/SetSelected.d.ts +1 -0
- package/lib/Viewer/commands/ShowAll.d.ts +1 -0
- package/lib/Viewer/commands/ZoomToExtents.d.ts +1 -0
- package/lib/Viewer/commands/ZoomToObjects.d.ts +1 -0
- package/lib/Viewer/commands/ZoomToSelected.d.ts +1 -0
- package/lib/Viewer/commands/index.d.ts +22 -0
- package/lib/Viewer/components/AxesHelperComponent.d.ts +10 -0
- package/lib/Viewer/components/BackgroundComponent.d.ts +4 -4
- package/lib/Viewer/components/{DefaultCameraPositionComponent.d.ts → DefaultPositionComponent.d.ts} +3 -2
- package/lib/Viewer/components/ExtentsComponent.d.ts +8 -0
- package/lib/Viewer/components/ExtentsHelperComponent.d.ts +9 -0
- package/lib/Viewer/components/LightComponent.d.ts +5 -5
- package/lib/Viewer/components/RenderLoopComponent.d.ts +3 -3
- package/lib/Viewer/components/ResizeCanvasComponent.d.ts +2 -2
- package/lib/Viewer/components/SelectionComponent.d.ts +19 -0
- package/lib/Viewer/components/ViewPositionComponent.d.ts +31 -0
- package/lib/Viewer/components/WCSHelperComponent.d.ts +9 -0
- package/lib/Viewer/controls/WalkControls.d.ts +26 -0
- package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +17 -0
- package/lib/Viewer/draggers/CuttingPlaneXAxis.d.ts +5 -0
- package/lib/Viewer/draggers/CuttingPlaneYAxis.d.ts +5 -0
- package/lib/Viewer/draggers/CuttingPlaneZAxis.d.ts +5 -0
- package/lib/Viewer/draggers/OrbitDragger.d.ts +10 -6
- package/lib/Viewer/draggers/WalkDragger.d.ts +7 -33
- package/lib/Viewer/helpers/PlaneHelper.d.ts +11 -0
- package/lib/Viewer/helpers/WCSHelper.d.ts +10 -0
- package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +3 -3
- package/lib/index.d.ts +1 -0
- package/package.json +6 -5
- package/src/Viewer/IDisposable.ts +29 -0
- package/src/Viewer/Viewer.ts +240 -49
- package/src/Viewer/commands/ApplyModelTransform.ts +33 -0
- package/src/Viewer/commands/ClearMarkup.ts +29 -0
- package/src/Viewer/commands/ClearSelected.ts +38 -0
- package/src/Viewer/commands/ClearSlices.ts +32 -0
- package/src/Viewer/commands/CreatePreview.ts +32 -0
- package/src/Viewer/commands/Explode.ts +83 -0
- package/src/Viewer/commands/GetDefaultViewPositions.ts +31 -0
- package/src/Viewer/commands/GetModels.ts +32 -0
- package/src/Viewer/commands/GetSelected.ts +31 -0
- package/src/Viewer/commands/HideSelected.ts +40 -0
- package/src/Viewer/commands/IsolateSelected.ts +50 -0
- package/src/Viewer/commands/RegenerateAll.ts +32 -0
- package/src/Viewer/commands/ResetView.ts +41 -0
- package/src/Viewer/commands/SelectModel.ts +32 -0
- package/src/Viewer/commands/SetActiveDragger.ts +29 -0
- package/src/Viewer/commands/SetDefaultViewPosition.ts +83 -0
- package/src/Viewer/commands/SetMarkupColor.ts +30 -0
- package/src/Viewer/commands/SetSelected.ts +44 -0
- package/src/Viewer/commands/ShowAll.ts +34 -0
- package/src/Viewer/commands/ZoomToExtents.ts +47 -0
- package/src/Viewer/commands/ZoomToObjects.ts +55 -0
- package/src/Viewer/commands/ZoomToSelected.ts +51 -0
- package/src/Viewer/commands/index.ts +45 -0
- package/src/Viewer/components/AxesHelperComponent.ts +70 -0
- package/src/Viewer/components/BackgroundComponent.ts +9 -7
- package/src/Viewer/components/{DefaultCameraPositionComponent.ts → DefaultPositionComponent.ts} +11 -22
- package/src/Viewer/components/ExtentsComponent.ts +54 -0
- package/src/Viewer/components/ExtentsHelperComponent.ts +58 -0
- package/src/Viewer/components/LightComponent.ts +14 -10
- package/src/Viewer/components/RenderLoopComponent.ts +6 -6
- package/src/Viewer/components/ResizeCanvasComponent.ts +2 -2
- package/src/Viewer/components/SelectionComponent.ts +132 -0
- package/src/Viewer/components/ViewPositionComponent.ts +165 -0
- package/src/Viewer/components/WCSHelperComponent.ts +46 -0
- package/src/Viewer/controls/OrbitControls.js +1007 -0
- package/src/Viewer/controls/WalkControls.ts +222 -0
- package/src/Viewer/draggers/CuttingPlaneDragger.ts +110 -0
- package/src/Viewer/draggers/CuttingPlaneXAxis.ts +33 -0
- package/src/Viewer/draggers/CuttingPlaneYAxis.ts +33 -0
- package/src/Viewer/draggers/CuttingPlaneZAxis.ts +33 -0
- package/src/Viewer/draggers/OrbitDragger.ts +70 -23
- package/src/Viewer/draggers/PanDragger.ts +4 -3
- package/src/Viewer/draggers/WalkDragger.ts +27 -216
- package/src/Viewer/draggers/ZoomDragger.ts +4 -3
- package/src/Viewer/helpers/PlaneHelper.ts +99 -0
- package/src/Viewer/helpers/WCSHelper.ts +119 -0
- package/src/Viewer/loaders/GLTFLoadingManager.ts +6 -6
- package/src/index.ts +2 -0
- package/lib/Viewer/IComponent.d.ts +0 -3
- package/lib/Viewer/components/ObjectSelectionComponent.d.ts +0 -16
- package/lib/Viewer/draggers/ClippingPlaneDragger.d.ts +0 -17
- package/src/Viewer/IComponent.ts +0 -3
- package/src/Viewer/components/ObjectSelectionComponent.ts +0 -105
- package/src/Viewer/draggers/ClippingPlaneDragger.ts +0 -120
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Vector2, Raycaster, MeshBasicMaterial, Box3, Vector3, Sphere, LoadingManager, LoaderUtils, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Clock, Object3D, Euler, Matrix4, LineBasicMaterial, CylinderGeometry, BoxGeometry, BufferGeometry, Float32BufferAttribute, Mesh, OctahedronGeometry, Line, SphereGeometry, TorusGeometry, PlaneGeometry, DoubleSide, Plane, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Vector4, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
|
|
2
2
|
|
|
3
3
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
4
|
|
|
5
|
-
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
6
|
-
|
|
7
5
|
import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment.js";
|
|
8
6
|
|
|
9
7
|
class Commands {
|
|
@@ -105,7 +103,8 @@ function defaultOptions() {
|
|
|
105
103
|
reverseZoomWheel: false,
|
|
106
104
|
enableZoomWheel: true,
|
|
107
105
|
enableGestures: true,
|
|
108
|
-
geometryType: "vsfx"
|
|
106
|
+
geometryType: "vsfx",
|
|
107
|
+
rulerUnit: "Default"
|
|
109
108
|
};
|
|
110
109
|
}
|
|
111
110
|
|
|
@@ -365,6 +364,13 @@ class Options {
|
|
|
365
364
|
this._data.geometryType = value;
|
|
366
365
|
this.change();
|
|
367
366
|
}
|
|
367
|
+
get rulerUnit() {
|
|
368
|
+
return this._data.rulerUnit;
|
|
369
|
+
}
|
|
370
|
+
set rulerUnit(value) {
|
|
371
|
+
this._data.rulerUnit = value;
|
|
372
|
+
this.change();
|
|
373
|
+
}
|
|
368
374
|
}
|
|
369
375
|
|
|
370
376
|
const CanvasEvents = [ "click", "contextmenu", "dblclick", "mousedown", "mouseleave", "mousemove", "mouseup", "pointercancel", "pointerdown", "pointerleave", "pointermove", "pointerup", "touchcancel", "touchend", "touchmove", "touchstart", "wheel" ];
|
|
@@ -380,6 +386,480 @@ class Dragger {
|
|
|
380
386
|
updatePreview() {}
|
|
381
387
|
}
|
|
382
388
|
|
|
389
|
+
function applyModelTransform(viewer, model) {
|
|
390
|
+
console.warn("applyModelTransform not implemented");
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
commands("ThreeJS").registerCommand("applyModelTransform", applyModelTransform);
|
|
394
|
+
|
|
395
|
+
commands("ThreeJS").registerCommand("clearMarkup", (viewer => console.warn("clearMarkup not implemented")));
|
|
396
|
+
|
|
397
|
+
commands("ThreeJS").registerCommandAlias("clearMarkup", "clearOverlay");
|
|
398
|
+
|
|
399
|
+
class SelectionComponent {
|
|
400
|
+
constructor(viewer) {
|
|
401
|
+
this.onPointerDown = event => {
|
|
402
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
403
|
+
this.getMousePosition(event, this.downPosition);
|
|
404
|
+
};
|
|
405
|
+
this.onPointerUp = event => {
|
|
406
|
+
if (!event.isPrimary) return;
|
|
407
|
+
const upPosition = this.getMousePosition(event, new Vector2);
|
|
408
|
+
if (this.downPosition.distanceTo(upPosition) !== 0) return;
|
|
409
|
+
const intersects = this.getPointerIntersects(upPosition);
|
|
410
|
+
this.clearSelection();
|
|
411
|
+
if (intersects.length > 0) this.select(intersects[0].object);
|
|
412
|
+
this.viewer.update();
|
|
413
|
+
this.viewer.emitEvent({
|
|
414
|
+
type: "select",
|
|
415
|
+
data: undefined,
|
|
416
|
+
handles: this.viewer.getSelected()
|
|
417
|
+
});
|
|
418
|
+
};
|
|
419
|
+
this.onDoubleClick = event => {
|
|
420
|
+
if (event.button !== 0) return;
|
|
421
|
+
this.viewer.executeCommand("zoomToSelected");
|
|
422
|
+
};
|
|
423
|
+
this.optionsChange = () => {
|
|
424
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
|
|
425
|
+
this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
426
|
+
this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
427
|
+
this.viewer.update();
|
|
428
|
+
};
|
|
429
|
+
this.viewer = viewer;
|
|
430
|
+
this.raycaster = new Raycaster;
|
|
431
|
+
this.downPosition = new Vector2;
|
|
432
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
|
|
433
|
+
this.facesMaterial = new MeshBasicMaterial;
|
|
434
|
+
this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
435
|
+
this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
436
|
+
this.facesMaterial.transparent = true;
|
|
437
|
+
this.viewer.addEventListener("pointerdown", this.onPointerDown);
|
|
438
|
+
this.viewer.addEventListener("pointerup", this.onPointerUp);
|
|
439
|
+
this.viewer.addEventListener("dblclick", this.onDoubleClick);
|
|
440
|
+
this.viewer.addEventListener("optionschange", this.optionsChange);
|
|
441
|
+
}
|
|
442
|
+
dispose() {
|
|
443
|
+
this.facesMaterial.dispose();
|
|
444
|
+
this.viewer.removeEventListener("pointerdown", this.onPointerDown);
|
|
445
|
+
this.viewer.removeEventListener("pointerup", this.onPointerUp);
|
|
446
|
+
this.viewer.removeEventListener("dblclick", this.onDoubleClick);
|
|
447
|
+
this.viewer.removeEventListener("optionschange", this.optionsChange);
|
|
448
|
+
}
|
|
449
|
+
getMousePosition(event, position) {
|
|
450
|
+
const rect = this.viewer.canvas.getBoundingClientRect();
|
|
451
|
+
position.setX((event.clientX - rect.left) / rect.width);
|
|
452
|
+
position.setY((event.clientY - rect.top) / rect.height);
|
|
453
|
+
return position;
|
|
454
|
+
}
|
|
455
|
+
getPointerIntersects(position) {
|
|
456
|
+
const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
|
|
457
|
+
this.raycaster.setFromCamera(mouse, this.viewer.camera);
|
|
458
|
+
const objects = [];
|
|
459
|
+
this.viewer.scene.traverseVisible((child => objects.push(child)));
|
|
460
|
+
return this.raycaster.intersectObjects(objects, false);
|
|
461
|
+
}
|
|
462
|
+
select(object) {
|
|
463
|
+
if (object.isSelected) return;
|
|
464
|
+
object.isSelected = true;
|
|
465
|
+
object.originalMaterial = object.material;
|
|
466
|
+
object.material = this.facesMaterial;
|
|
467
|
+
this.viewer.selected.push(object);
|
|
468
|
+
}
|
|
469
|
+
clearSelection() {
|
|
470
|
+
this.viewer.selected.forEach((object => {
|
|
471
|
+
object.isSelected = false;
|
|
472
|
+
object.material = object.originalMaterial;
|
|
473
|
+
}));
|
|
474
|
+
this.viewer.selected.length = 0;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function clearSelected(viewer) {
|
|
479
|
+
const selection = new SelectionComponent(viewer);
|
|
480
|
+
selection.clearSelection();
|
|
481
|
+
selection.dispose();
|
|
482
|
+
viewer.update();
|
|
483
|
+
viewer.emitEvent({
|
|
484
|
+
type: "select",
|
|
485
|
+
data: undefined,
|
|
486
|
+
handles: []
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
commands("ThreeJS").registerCommand("clearSelected", clearSelected);
|
|
491
|
+
|
|
492
|
+
commands("ThreeJS").registerCommandAlias("clearSelected", "unselect");
|
|
493
|
+
|
|
494
|
+
function clearSlices(viewer) {
|
|
495
|
+
viewer.renderer.clippingPlanes = [];
|
|
496
|
+
viewer.update();
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
commands("ThreeJS").registerCommand("clearSlices", clearSlices);
|
|
500
|
+
|
|
501
|
+
function createPreview(viewer, type = "image/jpeg", encoderOptions = .25) {
|
|
502
|
+
viewer.update(true);
|
|
503
|
+
return viewer.canvas.toDataURL(type, encoderOptions);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
commands("ThreeJS").registerCommand("createPreview", createPreview);
|
|
507
|
+
|
|
508
|
+
function calcObjectDepth(object, depth) {
|
|
509
|
+
let res = depth;
|
|
510
|
+
object.children.forEach((x => {
|
|
511
|
+
const objectDepth = calcObjectDepth(x, depth + 1);
|
|
512
|
+
if (res < objectDepth) res = objectDepth;
|
|
513
|
+
}));
|
|
514
|
+
object.originalPosition = object.position.clone();
|
|
515
|
+
return res;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function explodeScene(scene, scale = 0) {
|
|
519
|
+
scale /= 100;
|
|
520
|
+
if (!scene.maxDepth) scene.maxDepth = calcObjectDepth(scene, 1);
|
|
521
|
+
const maxDepth = scene.maxDepth;
|
|
522
|
+
let explodeDepth = scale * (maxDepth - 1) + 1;
|
|
523
|
+
if (maxDepth === 1) explodeDepth = 1;
|
|
524
|
+
function explodeObject(object, depth, parentCenter, parentOffset) {
|
|
525
|
+
const objectBox = (new Box3).setFromObject(object);
|
|
526
|
+
const objectCenter = objectBox.getCenter(new Vector3);
|
|
527
|
+
const objectOffset = parentOffset.clone();
|
|
528
|
+
if (depth > 0 && depth <= explodeDepth) {
|
|
529
|
+
const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
|
|
530
|
+
objectOffset.add(offset);
|
|
531
|
+
}
|
|
532
|
+
object.children.forEach((object => explodeObject(object, depth + 1, objectCenter, objectOffset)));
|
|
533
|
+
const originalPosition = object.originalPosition;
|
|
534
|
+
object.position.copy(originalPosition);
|
|
535
|
+
if (scale > 0) {
|
|
536
|
+
const direction = objectCenter.sub(parentCenter).normalize();
|
|
537
|
+
object.position.add(direction.add(objectOffset));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const sceneExtents = (new Box3).setFromObject(scene);
|
|
541
|
+
const sceneCenter = sceneExtents.getCenter(new Vector3);
|
|
542
|
+
explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function explode(viewer, index = 0) {
|
|
546
|
+
viewer.models.forEach((gltf => explodeScene(gltf.scene, index)));
|
|
547
|
+
viewer.update();
|
|
548
|
+
viewer.emitEvent({
|
|
549
|
+
type: "explode",
|
|
550
|
+
data: index
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
commands("ThreeJS").registerCommand("explode", explode);
|
|
555
|
+
|
|
556
|
+
commands("ThreeJS").registerCommand("collect", (viewer => explode(viewer, 0)));
|
|
557
|
+
|
|
558
|
+
const defaultViewPositions = {
|
|
559
|
+
top: new Vector3(0, 0, 1),
|
|
560
|
+
bottom: new Vector3(0, 0, -1),
|
|
561
|
+
left: new Vector3(-1, 0, 0),
|
|
562
|
+
right: new Vector3(1, 0, 0),
|
|
563
|
+
front: new Vector3(0, 1, 0),
|
|
564
|
+
back: new Vector3(0, -1, 0),
|
|
565
|
+
sw: new Vector3(-.5, -.5, 1).normalize(),
|
|
566
|
+
se: new Vector3(.5, -.5, 1).normalize(),
|
|
567
|
+
ne: new Vector3(.5, .5, 1).normalize(),
|
|
568
|
+
nw: new Vector3(-.5, .5, 1).normalize()
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
function setDefaultViewPosition(viewer, position) {
|
|
572
|
+
const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
|
|
573
|
+
const camera = viewer.camera;
|
|
574
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
575
|
+
const sphere = viewer.extents.getBoundingSphere(new Sphere);
|
|
576
|
+
const offset = (new Vector3).copy(direction).multiplyScalar(sphere.radius);
|
|
577
|
+
camera.position.copy(center);
|
|
578
|
+
camera.position.add(offset);
|
|
579
|
+
camera.rotation.set(0, 0, 0);
|
|
580
|
+
camera.lookAt(center);
|
|
581
|
+
camera.updateProjectionMatrix();
|
|
582
|
+
viewer.update();
|
|
583
|
+
viewer.emit({
|
|
584
|
+
type: "viewposition",
|
|
585
|
+
data: position
|
|
586
|
+
});
|
|
587
|
+
viewer.executeCommand("zoomToExtents");
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
commands("ThreeJS").registerCommand("setDefaultViewPosition", setDefaultViewPosition);
|
|
591
|
+
|
|
592
|
+
commands("ThreeJS").registerCommand("top", (viewer => setDefaultViewPosition(viewer, "top")));
|
|
593
|
+
|
|
594
|
+
commands("ThreeJS").registerCommand("bottom", (viewer => setDefaultViewPosition(viewer, "bottom")));
|
|
595
|
+
|
|
596
|
+
commands("ThreeJS").registerCommand("left", (viewer => setDefaultViewPosition(viewer, "left")));
|
|
597
|
+
|
|
598
|
+
commands("ThreeJS").registerCommand("right", (viewer => setDefaultViewPosition(viewer, "right")));
|
|
599
|
+
|
|
600
|
+
commands("ThreeJS").registerCommand("front", (viewer => setDefaultViewPosition(viewer, "front")));
|
|
601
|
+
|
|
602
|
+
commands("ThreeJS").registerCommand("back", (viewer => setDefaultViewPosition(viewer, "back")));
|
|
603
|
+
|
|
604
|
+
commands("ThreeJS").registerCommand("sw", (viewer => setDefaultViewPosition(viewer, "sw")));
|
|
605
|
+
|
|
606
|
+
commands("ThreeJS").registerCommand("se", (viewer => setDefaultViewPosition(viewer, "se")));
|
|
607
|
+
|
|
608
|
+
commands("ThreeJS").registerCommand("ne", (viewer => setDefaultViewPosition(viewer, "ne")));
|
|
609
|
+
|
|
610
|
+
commands("ThreeJS").registerCommand("nw", (viewer => setDefaultViewPosition(viewer, "nw")));
|
|
611
|
+
|
|
612
|
+
commands("ThreeJS").registerCommandAlias("top", "k3DViewTop");
|
|
613
|
+
|
|
614
|
+
commands("ThreeJS").registerCommandAlias("bottom", "k3DViewBottom");
|
|
615
|
+
|
|
616
|
+
commands("ThreeJS").registerCommandAlias("left", "k3DViewLeft");
|
|
617
|
+
|
|
618
|
+
commands("ThreeJS").registerCommandAlias("right", "k3DViewRight");
|
|
619
|
+
|
|
620
|
+
commands("ThreeJS").registerCommandAlias("front", "k3DViewFront");
|
|
621
|
+
|
|
622
|
+
commands("ThreeJS").registerCommandAlias("back", "k3DViewBack");
|
|
623
|
+
|
|
624
|
+
commands("ThreeJS").registerCommandAlias("se", "k3DViewSE");
|
|
625
|
+
|
|
626
|
+
commands("ThreeJS").registerCommandAlias("sw", "k3DViewSW");
|
|
627
|
+
|
|
628
|
+
commands("ThreeJS").registerCommandAlias("ne", "k3DViewNE");
|
|
629
|
+
|
|
630
|
+
commands("ThreeJS").registerCommandAlias("nw", "k3DViewNW");
|
|
631
|
+
|
|
632
|
+
function getDefaultViewPositions() {
|
|
633
|
+
return Object.keys(defaultViewPositions);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
commands("ThreeJS").registerCommand("getDefaultViewPositions", getDefaultViewPositions);
|
|
637
|
+
|
|
638
|
+
function getModels(viewer) {
|
|
639
|
+
const handles = viewer.models.map((model => model.userData.handle || "")).filter((handle => handle));
|
|
640
|
+
return handles;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
commands("ThreeJS").registerCommand("getModels", getModels);
|
|
644
|
+
|
|
645
|
+
function getSelected(viewer) {
|
|
646
|
+
return viewer.selected.map((object => {
|
|
647
|
+
var _a;
|
|
648
|
+
return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle;
|
|
649
|
+
})).filter((handle => handle));
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
commands("ThreeJS").registerCommand("getSelected", getSelected);
|
|
653
|
+
|
|
654
|
+
function hideSelected(viewer) {
|
|
655
|
+
viewer.selected.forEach((object => object.visible = false));
|
|
656
|
+
const selection = new SelectionComponent(viewer);
|
|
657
|
+
selection.clearSelection();
|
|
658
|
+
selection.dispose();
|
|
659
|
+
viewer.update();
|
|
660
|
+
viewer.emitEvent({
|
|
661
|
+
type: "hide"
|
|
662
|
+
});
|
|
663
|
+
viewer.emitEvent({
|
|
664
|
+
type: "select",
|
|
665
|
+
data: undefined,
|
|
666
|
+
handles: []
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
commands("ThreeJS").registerCommand("hideSelected", hideSelected);
|
|
671
|
+
|
|
672
|
+
function isolateSelected(viewer) {
|
|
673
|
+
const selectedSet = new Set(viewer.selected);
|
|
674
|
+
function isolateObject(object, depth) {
|
|
675
|
+
let canBeIsolated = true;
|
|
676
|
+
object.children.forEach((object => {
|
|
677
|
+
if (selectedSet.has(object)) canBeIsolated = false; else isolateObject(object, depth + 1);
|
|
678
|
+
}));
|
|
679
|
+
if (canBeIsolated && depth > 0) object.visible = false;
|
|
680
|
+
return canBeIsolated;
|
|
681
|
+
}
|
|
682
|
+
isolateObject(viewer.scene, 0);
|
|
683
|
+
viewer.update();
|
|
684
|
+
viewer.emitEvent({
|
|
685
|
+
type: "isolate"
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
commands("ThreeJS").registerCommand("isolateSelected", isolateSelected);
|
|
690
|
+
|
|
691
|
+
function regenerateAll(viewer) {
|
|
692
|
+
console.warn("regenerateAll not implemented");
|
|
693
|
+
viewer.emit({
|
|
694
|
+
type: "regenerateall"
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
commands("ThreeJS").registerCommand("regenerateAll", regenerateAll);
|
|
699
|
+
|
|
700
|
+
function resetView(viewer) {
|
|
701
|
+
viewer.executeCommand("setActiveDragger", "");
|
|
702
|
+
viewer.executeCommand("clearSlices");
|
|
703
|
+
viewer.executeCommand("clearOverlay");
|
|
704
|
+
viewer.executeCommand("setMarkupColor");
|
|
705
|
+
viewer.executeCommand("clearSelected");
|
|
706
|
+
viewer.executeCommand("showAll");
|
|
707
|
+
viewer.executeCommand("explode", 0);
|
|
708
|
+
viewer.executeCommand("zoomToExtents", true);
|
|
709
|
+
viewer.executeCommand("k3DViewSW");
|
|
710
|
+
viewer.emit({
|
|
711
|
+
type: "resetview"
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
commands("ThreeJS").registerCommand("resetView", resetView);
|
|
716
|
+
|
|
717
|
+
function selectModel(viewer, handle) {
|
|
718
|
+
console.warn("selectModel not implemented");
|
|
719
|
+
viewer.emit({
|
|
720
|
+
type: "select",
|
|
721
|
+
data: []
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
commands("ThreeJS").registerCommand("selectModel", selectModel);
|
|
726
|
+
|
|
727
|
+
commands("ThreeJS").registerCommand("setActiveDragger", ((viewer, dragger = "") => {
|
|
728
|
+
viewer.setActiveDragger(dragger);
|
|
729
|
+
}));
|
|
730
|
+
|
|
731
|
+
commands("ThreeJS").registerCommand("setMarkupColor", ((viewer, r = 255, g = 0, b = 0) => {
|
|
732
|
+
console.warn("setMarkupColor not implemented");
|
|
733
|
+
}));
|
|
734
|
+
|
|
735
|
+
function setSelected(viewer, handles = []) {
|
|
736
|
+
const handleSet = new Set(handles);
|
|
737
|
+
const objects = [];
|
|
738
|
+
viewer.scene.traverseVisible((child => {
|
|
739
|
+
var _a;
|
|
740
|
+
if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
|
|
741
|
+
}));
|
|
742
|
+
const selection = new SelectionComponent(viewer);
|
|
743
|
+
selection.clearSelection();
|
|
744
|
+
objects.forEach((object => selection.select(object)));
|
|
745
|
+
selection.dispose();
|
|
746
|
+
viewer.update();
|
|
747
|
+
viewer.emitEvent({
|
|
748
|
+
type: "select",
|
|
749
|
+
data: undefined,
|
|
750
|
+
handles: handles
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
commands("ThreeJS").registerCommand("setSelected", setSelected);
|
|
755
|
+
|
|
756
|
+
function showAll(viewer) {
|
|
757
|
+
viewer.scene.traverse((object => object.visible = true));
|
|
758
|
+
viewer.update();
|
|
759
|
+
viewer.emitEvent({
|
|
760
|
+
type: "showall"
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
commands("ThreeJS").registerCommand("showAll", showAll);
|
|
765
|
+
|
|
766
|
+
function zoomToExtents(viewer) {
|
|
767
|
+
if (viewer.extents.isEmpty()) return;
|
|
768
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
769
|
+
const distance = viewer.extents.getBoundingSphere(new Sphere).radius;
|
|
770
|
+
const delta = new Vector3(0, 0, 1);
|
|
771
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
772
|
+
delta.multiplyScalar(distance * 3);
|
|
773
|
+
viewer.camera.position.copy(center).add(delta);
|
|
774
|
+
viewer.target.copy(center);
|
|
775
|
+
viewer.update();
|
|
776
|
+
viewer.emitEvent({
|
|
777
|
+
type: "zoom"
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
commands("ThreeJS").registerCommand("zoomToExtents", zoomToExtents);
|
|
782
|
+
|
|
783
|
+
commands("ThreeJS").registerCommandAlias("zoomToExtents", "zoomExtents");
|
|
784
|
+
|
|
785
|
+
function zoomToObjects(viewer, handles = []) {
|
|
786
|
+
const handleSet = new Set(handles);
|
|
787
|
+
const objects = [];
|
|
788
|
+
viewer.scene.traverseVisible((child => {
|
|
789
|
+
var _a;
|
|
790
|
+
if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
|
|
791
|
+
}));
|
|
792
|
+
const extents = objects.reduce(((result, object) => {
|
|
793
|
+
const objectExtents = (new Box3).setFromObject(object);
|
|
794
|
+
return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
|
|
795
|
+
}), new Box3);
|
|
796
|
+
const center = extents.getCenter(new Vector3);
|
|
797
|
+
const distance = extents.getBoundingSphere(new Sphere).radius;
|
|
798
|
+
const delta = new Vector3(0, 0, 1);
|
|
799
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
800
|
+
delta.multiplyScalar(distance * 3);
|
|
801
|
+
viewer.camera.position.copy(center).add(delta);
|
|
802
|
+
viewer.target.copy(center);
|
|
803
|
+
viewer.update();
|
|
804
|
+
viewer.emitEvent({
|
|
805
|
+
type: "zoom"
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
commands("ThreeJS").registerCommand("zoomToObjects", zoomToObjects);
|
|
810
|
+
|
|
811
|
+
function zoomToSelected(viewer) {
|
|
812
|
+
const extents = viewer.selected.reduce(((result, object) => {
|
|
813
|
+
const objectExtents = (new Box3).setFromObject(object);
|
|
814
|
+
return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
|
|
815
|
+
}), new Box3);
|
|
816
|
+
if (extents.isEmpty()) extents.copy(viewer.extents);
|
|
817
|
+
const center = extents.getCenter(new Vector3);
|
|
818
|
+
const distance = extents.getBoundingSphere(new Sphere).radius;
|
|
819
|
+
const delta = new Vector3(0, 0, 1);
|
|
820
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
821
|
+
delta.multiplyScalar(distance * 3);
|
|
822
|
+
viewer.camera.position.copy(center).add(delta);
|
|
823
|
+
viewer.target.copy(center);
|
|
824
|
+
viewer.update();
|
|
825
|
+
viewer.emitEvent({
|
|
826
|
+
type: "zoom"
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
commands("ThreeJS").registerCommand("zoomToSelected", zoomToSelected);
|
|
831
|
+
|
|
832
|
+
class GLTFLoadingManager extends LoadingManager {
|
|
833
|
+
constructor(file, externalData = new Map, params = {}) {
|
|
834
|
+
super();
|
|
835
|
+
this.path = "";
|
|
836
|
+
this.resourcePath = "";
|
|
837
|
+
this.fileURL = "";
|
|
838
|
+
this.dataURLs = new Map;
|
|
839
|
+
this.path = params.path || "";
|
|
840
|
+
if (typeof file === "string") {
|
|
841
|
+
this.fileURL = file;
|
|
842
|
+
this.resourcePath = LoaderUtils.extractUrlBase(file);
|
|
843
|
+
} else {
|
|
844
|
+
externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
|
|
845
|
+
externalData.set(this.fileURL, file);
|
|
846
|
+
}
|
|
847
|
+
externalData.forEach(((value, key) => {
|
|
848
|
+
let dataURL;
|
|
849
|
+
if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
|
|
850
|
+
this.dataURLs.set(key, dataURL);
|
|
851
|
+
}));
|
|
852
|
+
this.setURLModifier((url => {
|
|
853
|
+
const key = decodeURI(url).replace(this.path, "").replace(this.resourcePath, "").replace(/^(\.?\/)/, "");
|
|
854
|
+
const dataURL = this.dataURLs.get(key);
|
|
855
|
+
return dataURL !== null && dataURL !== void 0 ? dataURL : url;
|
|
856
|
+
}));
|
|
857
|
+
}
|
|
858
|
+
dispose() {
|
|
859
|
+
this.dataURLs.forEach(URL.revokeObjectURL);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
383
863
|
class EventEmitter2 {
|
|
384
864
|
constructor() {
|
|
385
865
|
this._listeners = {};
|
|
@@ -419,367 +899,2031 @@ class EventEmitter2 {
|
|
|
419
899
|
}
|
|
420
900
|
}
|
|
421
901
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
this.path = "";
|
|
426
|
-
this.resourcePath = "";
|
|
427
|
-
this.fileURL = "";
|
|
428
|
-
this.dataURLs = new Map;
|
|
429
|
-
this.path = params.path || "";
|
|
430
|
-
if (typeof file === "string") {
|
|
431
|
-
this.fileURL = file;
|
|
432
|
-
this.resourcePath = THREE.LoaderUtils.extractUrlBase(file);
|
|
433
|
-
} else {
|
|
434
|
-
externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
|
|
435
|
-
externalData.set(this.fileURL, file);
|
|
436
|
-
}
|
|
437
|
-
externalData.forEach(((value, key) => {
|
|
438
|
-
let dataURL;
|
|
439
|
-
if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
|
|
440
|
-
this.dataURLs.set(key, dataURL);
|
|
441
|
-
}));
|
|
442
|
-
this.setURLModifier((url => {
|
|
443
|
-
const key = decodeURI(url).replace(this.path, "").replace(this.resourcePath, "").replace(/^(\.?\/)/, "");
|
|
444
|
-
const dataURL = this.dataURLs.get(key);
|
|
445
|
-
return dataURL !== null && dataURL !== void 0 ? dataURL : url;
|
|
446
|
-
}));
|
|
447
|
-
}
|
|
448
|
-
dispose() {
|
|
449
|
-
this.dataURLs.forEach(URL.revokeObjectURL);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
902
|
+
const _changeEvent$2 = {
|
|
903
|
+
type: "change"
|
|
904
|
+
};
|
|
452
905
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
906
|
+
const _startEvent = {
|
|
907
|
+
type: "start"
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
const _endEvent = {
|
|
911
|
+
type: "end"
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
const STATE = {
|
|
915
|
+
NONE: -1,
|
|
916
|
+
ROTATE: 0,
|
|
917
|
+
DOLLY: 1,
|
|
918
|
+
PAN: 2,
|
|
919
|
+
TOUCH_ROTATE: 3,
|
|
920
|
+
TOUCH_PAN: 4,
|
|
921
|
+
TOUCH_DOLLY_PAN: 5,
|
|
922
|
+
TOUCH_DOLLY_ROTATE: 6
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
class OrbitControls extends EventDispatcher {
|
|
926
|
+
constructor(object, domElement) {
|
|
927
|
+
super();
|
|
928
|
+
this.object = object;
|
|
929
|
+
this.domElement = domElement;
|
|
930
|
+
this.domElement.style.touchAction = "none";
|
|
931
|
+
this.enabled = true;
|
|
932
|
+
this.target = new Vector3;
|
|
933
|
+
this.minDistance = 0;
|
|
934
|
+
this.maxDistance = Infinity;
|
|
935
|
+
this.minZoom = 0;
|
|
936
|
+
this.maxZoom = Infinity;
|
|
937
|
+
this.minPolarAngle = 0;
|
|
938
|
+
this.maxPolarAngle = Math.PI;
|
|
939
|
+
this.minAzimuthAngle = -Infinity;
|
|
940
|
+
this.maxAzimuthAngle = Infinity;
|
|
941
|
+
this.enableDamping = false;
|
|
942
|
+
this.dampingFactor = .05;
|
|
943
|
+
this.enableZoom = true;
|
|
944
|
+
this.zoomSpeed = 1;
|
|
945
|
+
this.enableRotate = true;
|
|
946
|
+
this.rotateSpeed = 1;
|
|
947
|
+
this.enablePan = true;
|
|
948
|
+
this.panSpeed = 1;
|
|
949
|
+
this.screenSpacePanning = true;
|
|
950
|
+
this.keyPanSpeed = 7;
|
|
951
|
+
this.autoRotate = false;
|
|
952
|
+
this.autoRotateSpeed = 2;
|
|
953
|
+
this.keys = {
|
|
954
|
+
LEFT: "ArrowLeft",
|
|
955
|
+
UP: "ArrowUp",
|
|
956
|
+
RIGHT: "ArrowRight",
|
|
957
|
+
BOTTOM: "ArrowDown"
|
|
465
958
|
};
|
|
466
959
|
this.mouseButtons = {
|
|
467
|
-
LEFT:
|
|
468
|
-
MIDDLE:
|
|
469
|
-
RIGHT:
|
|
960
|
+
LEFT: MOUSE.ROTATE,
|
|
961
|
+
MIDDLE: MOUSE.DOLLY,
|
|
962
|
+
RIGHT: MOUSE.PAN
|
|
470
963
|
};
|
|
471
964
|
this.touches = {
|
|
472
|
-
ONE:
|
|
473
|
-
TWO:
|
|
965
|
+
ONE: TOUCH.ROTATE,
|
|
966
|
+
TWO: TOUCH.DOLLY_PAN
|
|
474
967
|
};
|
|
475
|
-
this.
|
|
476
|
-
this.
|
|
477
|
-
this.
|
|
478
|
-
this.
|
|
479
|
-
this.
|
|
480
|
-
|
|
481
|
-
dispose() {
|
|
482
|
-
this.removeEventListener("change", this.updateViewer);
|
|
483
|
-
this.viewer.removeEventListener("geometryend", this.geometryEnd);
|
|
484
|
-
super.dispose();
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
class PanDragger extends OrbitDragger {
|
|
489
|
-
constructor(viewer) {
|
|
490
|
-
super(viewer);
|
|
491
|
-
this.mouseButtons = {
|
|
492
|
-
LEFT: THREE.MOUSE.PAN,
|
|
493
|
-
MIDDLE: THREE.MOUSE.PAN,
|
|
494
|
-
RIGHT: THREE.MOUSE.PAN
|
|
968
|
+
this.target0 = this.target.clone();
|
|
969
|
+
this.position0 = this.object.position.clone();
|
|
970
|
+
this.zoom0 = this.object.zoom;
|
|
971
|
+
this._domElementKeyEvents = null;
|
|
972
|
+
this.getPolarAngle = function() {
|
|
973
|
+
return spherical.phi;
|
|
495
974
|
};
|
|
496
|
-
this.
|
|
497
|
-
|
|
498
|
-
TWO: THREE.TOUCH.DOLLY_ROTATE
|
|
975
|
+
this.getAzimuthalAngle = function() {
|
|
976
|
+
return spherical.theta;
|
|
499
977
|
};
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
class ZoomDragger extends OrbitDragger {
|
|
504
|
-
constructor(viewer) {
|
|
505
|
-
super(viewer);
|
|
506
|
-
this.mouseButtons = {
|
|
507
|
-
LEFT: THREE.MOUSE.DOLLY,
|
|
508
|
-
MIDDLE: THREE.MOUSE.PAN,
|
|
509
|
-
RIGHT: THREE.MOUSE.PAN
|
|
978
|
+
this.getDistance = function() {
|
|
979
|
+
return this.object.position.distanceTo(this.target);
|
|
510
980
|
};
|
|
511
|
-
this.
|
|
512
|
-
|
|
513
|
-
|
|
981
|
+
this.listenToKeyEvents = function(domElement) {
|
|
982
|
+
domElement.addEventListener("keydown", onKeyDown);
|
|
983
|
+
this._domElementKeyEvents = domElement;
|
|
514
984
|
};
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
985
|
+
this.stopListenToKeyEvents = function() {
|
|
986
|
+
this._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
|
|
987
|
+
this._domElementKeyEvents = null;
|
|
988
|
+
};
|
|
989
|
+
this.saveState = function() {
|
|
990
|
+
scope.target0.copy(scope.target);
|
|
991
|
+
scope.position0.copy(scope.object.position);
|
|
992
|
+
scope.zoom0 = scope.object.zoom;
|
|
993
|
+
};
|
|
994
|
+
this.reset = function() {
|
|
995
|
+
scope.target.copy(scope.target0);
|
|
996
|
+
scope.object.position.copy(scope.position0);
|
|
997
|
+
scope.object.zoom = scope.zoom0;
|
|
998
|
+
scope.object.updateProjectionMatrix();
|
|
999
|
+
scope.dispatchEvent(_changeEvent$2);
|
|
1000
|
+
scope.update();
|
|
1001
|
+
scope.state = STATE.NONE;
|
|
1002
|
+
};
|
|
1003
|
+
this.update = function() {
|
|
1004
|
+
const offset = new Vector3;
|
|
1005
|
+
const quat = (new Quaternion).setFromUnitVectors(object.up, new Vector3(0, 1, 0));
|
|
1006
|
+
const quatInverse = quat.clone().invert();
|
|
1007
|
+
const lastPosition = new Vector3;
|
|
1008
|
+
const lastQuaternion = new Quaternion;
|
|
1009
|
+
const lastTargetPosition = new Vector3;
|
|
1010
|
+
const twoPI = 2 * Math.PI;
|
|
1011
|
+
return function update() {
|
|
1012
|
+
const position = scope.object.position;
|
|
1013
|
+
offset.copy(position).sub(scope.target);
|
|
1014
|
+
offset.applyQuaternion(quat);
|
|
1015
|
+
spherical.setFromVector3(offset);
|
|
1016
|
+
if (scope.autoRotate && scope.state === STATE.NONE) {
|
|
1017
|
+
rotateLeft(getAutoRotationAngle());
|
|
527
1018
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (event.shiftKey) {
|
|
532
|
-
this.speed.z = -this.walkSpeed * this.boostSpeed;
|
|
1019
|
+
if (scope.enableDamping) {
|
|
1020
|
+
spherical.theta += sphericalDelta.theta * scope.dampingFactor;
|
|
1021
|
+
spherical.phi += sphericalDelta.phi * scope.dampingFactor;
|
|
533
1022
|
} else {
|
|
534
|
-
|
|
1023
|
+
spherical.theta += sphericalDelta.theta;
|
|
1024
|
+
spherical.phi += sphericalDelta.phi;
|
|
535
1025
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
1026
|
+
let min = scope.minAzimuthAngle;
|
|
1027
|
+
let max = scope.maxAzimuthAngle;
|
|
1028
|
+
if (isFinite(min) && isFinite(max)) {
|
|
1029
|
+
if (min < -Math.PI) min += twoPI; else if (min > Math.PI) min -= twoPI;
|
|
1030
|
+
if (max < -Math.PI) max += twoPI; else if (max > Math.PI) max -= twoPI;
|
|
1031
|
+
if (min <= max) {
|
|
1032
|
+
spherical.theta = Math.max(min, Math.min(max, spherical.theta));
|
|
1033
|
+
} else {
|
|
1034
|
+
spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
|
|
1038
|
+
spherical.makeSafe();
|
|
1039
|
+
spherical.radius *= scope.scale;
|
|
1040
|
+
spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
|
|
1041
|
+
if (scope.enableDamping === true) {
|
|
1042
|
+
scope.target.addScaledVector(scope.panOffset, scope.dampingFactor);
|
|
541
1043
|
} else {
|
|
542
|
-
|
|
1044
|
+
scope.target.add(scope.panOffset);
|
|
543
1045
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
1046
|
+
offset.setFromSpherical(spherical);
|
|
1047
|
+
offset.applyQuaternion(quatInverse);
|
|
1048
|
+
position.copy(scope.target).add(offset);
|
|
1049
|
+
scope.object.lookAt(scope.target);
|
|
1050
|
+
if (scope.enableDamping === true) {
|
|
1051
|
+
sphericalDelta.theta *= 1 - scope.dampingFactor;
|
|
1052
|
+
sphericalDelta.phi *= 1 - scope.dampingFactor;
|
|
1053
|
+
scope.panOffset.multiplyScalar(1 - scope.dampingFactor);
|
|
549
1054
|
} else {
|
|
550
|
-
|
|
1055
|
+
sphericalDelta.set(0, 0, 0);
|
|
1056
|
+
scope.panOffset.set(0, 0, 0);
|
|
551
1057
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
this.onMouseDown = event => {
|
|
575
|
-
const {clientX: clientX, clientY: clientY} = event;
|
|
576
|
-
this.mouseStart.set(clientX, clientY);
|
|
577
|
-
this.mouseDelta.set(0, 0);
|
|
578
|
-
this.quaternion.copy(this.viewer.camera.quaternion);
|
|
579
|
-
this.viewer.addEventListener("mousemove", this.onMouseMove);
|
|
580
|
-
};
|
|
581
|
-
this.onMouseMove = event => {
|
|
582
|
-
const {clientX: clientX, clientY: clientY} = event;
|
|
583
|
-
this.mouseDelta.set(this.mouseStart.x - clientX, this.mouseStart.y - clientY);
|
|
584
|
-
this.rotateCamera(this.mouseDelta);
|
|
585
|
-
};
|
|
586
|
-
this.onMouseUp = event => {
|
|
587
|
-
this.speed.set(0, 0, 0);
|
|
588
|
-
this.mouseStart.set(0, 0);
|
|
589
|
-
this.mouseDelta.set(0, 0);
|
|
590
|
-
this.quaternion.copy(this.viewer.camera.quaternion);
|
|
591
|
-
this.viewer.removeEventListener("mousemove", this.onMouseMove);
|
|
592
|
-
};
|
|
593
|
-
this.onMouseWheel = event => {
|
|
594
|
-
event.preventDefault();
|
|
595
|
-
if (-event.deltaY < 0) {
|
|
596
|
-
this.walkSpeed = Math.max(.001, this.walkSpeed - 1);
|
|
597
|
-
} else if (-event.deltaY > 0) {
|
|
598
|
-
this.walkSpeed++;
|
|
1058
|
+
scope.scale = 1;
|
|
1059
|
+
if (scope.zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS || lastTargetPosition.distanceToSquared(scope.target) > 0) {
|
|
1060
|
+
scope.dispatchEvent(_changeEvent$2);
|
|
1061
|
+
lastPosition.copy(scope.object.position);
|
|
1062
|
+
lastQuaternion.copy(scope.object.quaternion);
|
|
1063
|
+
lastTargetPosition.copy(scope.target);
|
|
1064
|
+
scope.zoomChanged = false;
|
|
1065
|
+
return true;
|
|
1066
|
+
}
|
|
1067
|
+
return false;
|
|
1068
|
+
};
|
|
1069
|
+
}();
|
|
1070
|
+
this.dispose = function() {
|
|
1071
|
+
scope.domElement.removeEventListener("contextmenu", onContextMenu);
|
|
1072
|
+
scope.domElement.removeEventListener("pointerdown", onPointerDown);
|
|
1073
|
+
scope.domElement.removeEventListener("pointercancel", onPointerUp);
|
|
1074
|
+
scope.domElement.removeEventListener("wheel", onMouseWheel);
|
|
1075
|
+
scope.domElement.removeEventListener("pointermove", onPointerMove);
|
|
1076
|
+
scope.domElement.removeEventListener("pointerup", onPointerUp);
|
|
1077
|
+
if (scope._domElementKeyEvents !== null) {
|
|
1078
|
+
scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
|
|
1079
|
+
scope._domElementKeyEvents = null;
|
|
599
1080
|
}
|
|
600
1081
|
};
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
1082
|
+
const scope = this;
|
|
1083
|
+
scope.state = STATE.NONE;
|
|
1084
|
+
const EPS = 1e-6;
|
|
1085
|
+
const spherical = new Spherical;
|
|
1086
|
+
const sphericalDelta = new Spherical;
|
|
1087
|
+
scope.scale = 1;
|
|
1088
|
+
scope.panOffset = new Vector3;
|
|
1089
|
+
scope.zoomChanged = false;
|
|
1090
|
+
scope.rotateStart = new Vector2;
|
|
1091
|
+
scope.rotateEnd = new Vector2;
|
|
1092
|
+
scope.rotateDelta = new Vector2;
|
|
1093
|
+
scope.panStart = new Vector2;
|
|
1094
|
+
scope.panEnd = new Vector2;
|
|
1095
|
+
scope.panDelta = new Vector2;
|
|
1096
|
+
scope.dollyStart = new Vector2;
|
|
1097
|
+
scope.dollyEnd = new Vector2;
|
|
1098
|
+
scope.dollyDelta = new Vector2;
|
|
1099
|
+
scope.dollyScale = 0;
|
|
1100
|
+
scope.pointers = [];
|
|
1101
|
+
scope.pointerPositions = {};
|
|
1102
|
+
function getAutoRotationAngle() {
|
|
1103
|
+
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
|
|
1104
|
+
}
|
|
1105
|
+
function getZoomScale() {
|
|
1106
|
+
return Math.pow(.95, scope.zoomSpeed);
|
|
1107
|
+
}
|
|
1108
|
+
function rotateLeft(angle) {
|
|
1109
|
+
sphericalDelta.theta -= angle;
|
|
1110
|
+
}
|
|
1111
|
+
function rotateUp(angle) {
|
|
1112
|
+
sphericalDelta.phi -= angle;
|
|
1113
|
+
}
|
|
1114
|
+
const panLeft = function() {
|
|
1115
|
+
const v = new Vector3;
|
|
1116
|
+
return function panLeft(distance, objectMatrix) {
|
|
1117
|
+
v.setFromMatrixColumn(objectMatrix, 0);
|
|
1118
|
+
v.multiplyScalar(-distance);
|
|
1119
|
+
scope.panOffset.add(v);
|
|
1120
|
+
};
|
|
1121
|
+
}();
|
|
1122
|
+
const panUp = function() {
|
|
1123
|
+
const v = new Vector3;
|
|
1124
|
+
return function panUp(distance, objectMatrix) {
|
|
1125
|
+
if (scope.screenSpacePanning === true) {
|
|
1126
|
+
v.setFromMatrixColumn(objectMatrix, 1);
|
|
1127
|
+
} else {
|
|
1128
|
+
v.setFromMatrixColumn(objectMatrix, 0);
|
|
1129
|
+
v.crossVectors(scope.object.up, v);
|
|
1130
|
+
}
|
|
1131
|
+
v.multiplyScalar(distance);
|
|
1132
|
+
scope.panOffset.add(v);
|
|
1133
|
+
};
|
|
1134
|
+
}();
|
|
1135
|
+
const pan = function() {
|
|
1136
|
+
const offset = new Vector3;
|
|
1137
|
+
return function pan(deltaX, deltaY) {
|
|
1138
|
+
const element = scope.domElement;
|
|
1139
|
+
if (scope.object.isPerspectiveCamera) {
|
|
1140
|
+
const position = scope.object.position;
|
|
1141
|
+
offset.copy(position).sub(scope.target);
|
|
1142
|
+
let targetDistance = offset.length();
|
|
1143
|
+
targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
|
|
1144
|
+
panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
|
|
1145
|
+
panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
|
|
1146
|
+
} else if (scope.object.isOrthographicCamera) {
|
|
1147
|
+
panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
|
|
1148
|
+
panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
|
|
1149
|
+
} else {
|
|
1150
|
+
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
|
|
1151
|
+
scope.enablePan = false;
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}();
|
|
1155
|
+
function dollyOut(dollyScale) {
|
|
1156
|
+
if (scope.object.isPerspectiveCamera) {
|
|
1157
|
+
scope.scale /= dollyScale;
|
|
1158
|
+
} else if (scope.object.isOrthographicCamera) {
|
|
1159
|
+
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
|
|
1160
|
+
scope.object.updateProjectionMatrix();
|
|
1161
|
+
scope.zoomChanged = true;
|
|
609
1162
|
} else {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
this.mouseDelta.set(0, 0);
|
|
613
|
-
this.quaternion.copy(this.viewer.camera.quaternion);
|
|
1163
|
+
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
|
|
1164
|
+
scope.enableZoom = false;
|
|
614
1165
|
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
if (
|
|
618
|
-
|
|
1166
|
+
}
|
|
1167
|
+
function dollyIn(dollyScale) {
|
|
1168
|
+
if (scope.object.isPerspectiveCamera) {
|
|
1169
|
+
scope.scale *= dollyScale;
|
|
1170
|
+
} else if (scope.object.isOrthographicCamera) {
|
|
1171
|
+
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
|
|
1172
|
+
scope.object.updateProjectionMatrix();
|
|
1173
|
+
scope.zoomChanged = true;
|
|
1174
|
+
} else {
|
|
1175
|
+
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
|
|
1176
|
+
scope.enableZoom = false;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
function handleMouseDownRotate(event) {
|
|
1180
|
+
scope.rotateStart.set(event.clientX, event.clientY);
|
|
1181
|
+
}
|
|
1182
|
+
function handleMouseDownDolly(event) {
|
|
1183
|
+
scope.dollyStart.set(event.clientX, event.clientY);
|
|
1184
|
+
}
|
|
1185
|
+
function handleMouseDownPan(event) {
|
|
1186
|
+
scope.panStart.set(event.clientX, event.clientY);
|
|
1187
|
+
}
|
|
1188
|
+
function handleMouseMoveRotate(event) {
|
|
1189
|
+
scope.rotateEnd.set(event.clientX, event.clientY);
|
|
1190
|
+
scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
|
|
1191
|
+
const element = scope.domElement;
|
|
1192
|
+
rotateLeft(2 * Math.PI * scope.rotateDelta.x / element.clientHeight);
|
|
1193
|
+
rotateUp(2 * Math.PI * scope.rotateDelta.y / element.clientHeight);
|
|
1194
|
+
scope.rotateStart.copy(scope.rotateEnd);
|
|
1195
|
+
scope.update();
|
|
1196
|
+
}
|
|
1197
|
+
function handleMouseMoveDolly(event) {
|
|
1198
|
+
scope.dollyEnd.set(event.clientX, event.clientY);
|
|
1199
|
+
scope.dollyDelta.subVectors(scope.dollyEnd, scope.dollyStart);
|
|
1200
|
+
if (scope.dollyDelta.y < 0) {
|
|
1201
|
+
scope.dollyScale = 1 / getZoomScale();
|
|
1202
|
+
dollyOut(getZoomScale());
|
|
1203
|
+
} else if (scope.dollyDelta.y > 0) {
|
|
1204
|
+
scope.dollyScale = getZoomScale();
|
|
1205
|
+
dollyIn(getZoomScale());
|
|
1206
|
+
}
|
|
1207
|
+
scope.dollyStart.copy(scope.dollyEnd);
|
|
1208
|
+
scope.update();
|
|
1209
|
+
}
|
|
1210
|
+
function handleMouseMovePan(event) {
|
|
1211
|
+
scope.panEnd.set(event.clientX, event.clientY);
|
|
1212
|
+
scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
|
|
1213
|
+
pan(scope.panDelta.x, scope.panDelta.y);
|
|
1214
|
+
scope.panStart.copy(scope.panEnd);
|
|
1215
|
+
scope.update();
|
|
1216
|
+
}
|
|
1217
|
+
function handleMouseWheel(event) {
|
|
1218
|
+
scope.dollyEnd.set(scope.domElement.clientWidth / 2, scope.domElement.clientHeight / 2);
|
|
1219
|
+
scope.dollyDelta.set(event.deltaX, event.deltaY);
|
|
1220
|
+
if (event.deltaY < 0) {
|
|
1221
|
+
scope.dollyScale = 1 / getZoomScale();
|
|
1222
|
+
dollyIn(getZoomScale());
|
|
1223
|
+
} else if (event.deltaY > 0) {
|
|
1224
|
+
scope.dollyScale = getZoomScale();
|
|
1225
|
+
dollyOut(getZoomScale());
|
|
1226
|
+
}
|
|
1227
|
+
scope.dollyStart.copy(scope.dollyEnd);
|
|
1228
|
+
scope.update();
|
|
1229
|
+
if (event.deltaY !== 0) {
|
|
1230
|
+
scope.state = STATE.DOLLY;
|
|
1231
|
+
scope.dispatchEvent(_changeEvent$2);
|
|
1232
|
+
scope.state = STATE.NONE;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
function handleKeyDown(event) {
|
|
1236
|
+
let needsUpdate = false;
|
|
1237
|
+
switch (event.code) {
|
|
1238
|
+
case scope.keys.UP:
|
|
1239
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1240
|
+
rotateUp(2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
|
|
1241
|
+
} else {
|
|
1242
|
+
pan(0, scope.keyPanSpeed);
|
|
1243
|
+
}
|
|
1244
|
+
needsUpdate = true;
|
|
1245
|
+
break;
|
|
1246
|
+
|
|
1247
|
+
case scope.keys.BOTTOM:
|
|
1248
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1249
|
+
rotateUp(-2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
|
|
1250
|
+
} else {
|
|
1251
|
+
pan(0, -scope.keyPanSpeed);
|
|
1252
|
+
}
|
|
1253
|
+
needsUpdate = true;
|
|
1254
|
+
break;
|
|
1255
|
+
|
|
1256
|
+
case scope.keys.LEFT:
|
|
1257
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1258
|
+
rotateLeft(2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
|
|
1259
|
+
} else {
|
|
1260
|
+
pan(scope.keyPanSpeed, 0);
|
|
1261
|
+
}
|
|
1262
|
+
needsUpdate = true;
|
|
1263
|
+
break;
|
|
1264
|
+
|
|
1265
|
+
case scope.keys.RIGHT:
|
|
1266
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1267
|
+
rotateLeft(-2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
|
|
1268
|
+
} else {
|
|
1269
|
+
pan(-scope.keyPanSpeed, 0);
|
|
1270
|
+
}
|
|
1271
|
+
needsUpdate = true;
|
|
1272
|
+
break;
|
|
1273
|
+
}
|
|
1274
|
+
if (needsUpdate) {
|
|
1275
|
+
event.preventDefault();
|
|
1276
|
+
scope.update();
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
function handleTouchStartRotate() {
|
|
1280
|
+
if (scope.pointers.length === 1) {
|
|
1281
|
+
scope.rotateStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
|
|
1282
|
+
} else {
|
|
1283
|
+
const x = .5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
|
|
1284
|
+
const y = .5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
|
|
1285
|
+
scope.rotateStart.set(x, y);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
function handleTouchStartPan() {
|
|
1289
|
+
if (scope.pointers.length === 1) {
|
|
1290
|
+
scope.panStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
|
|
1291
|
+
} else {
|
|
1292
|
+
const x = .5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
|
|
1293
|
+
const y = .5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
|
|
1294
|
+
scope.panStart.set(x, y);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function handleTouchStartDolly() {
|
|
1298
|
+
const dx = scope.pointers[0].pageX - scope.pointers[1].pageX;
|
|
1299
|
+
const dy = scope.pointers[0].pageY - scope.pointers[1].pageY;
|
|
1300
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
1301
|
+
scope.dollyStart.set(0, distance);
|
|
1302
|
+
}
|
|
1303
|
+
function handleTouchStartDollyPan() {
|
|
1304
|
+
if (scope.enableZoom) handleTouchStartDolly();
|
|
1305
|
+
if (scope.enablePan) handleTouchStartPan();
|
|
1306
|
+
}
|
|
1307
|
+
function handleTouchStartDollyRotate() {
|
|
1308
|
+
if (scope.enableZoom) handleTouchStartDolly();
|
|
1309
|
+
if (scope.enableRotate) handleTouchStartRotate();
|
|
1310
|
+
}
|
|
1311
|
+
function handleTouchMoveRotate(event) {
|
|
1312
|
+
if (scope.pointers.length == 1) {
|
|
1313
|
+
scope.rotateEnd.set(event.pageX, event.pageY);
|
|
1314
|
+
} else {
|
|
1315
|
+
const position = getSecondPointerPosition(event);
|
|
1316
|
+
const x = .5 * (event.pageX + position.x);
|
|
1317
|
+
const y = .5 * (event.pageY + position.y);
|
|
1318
|
+
scope.rotateEnd.set(x, y);
|
|
1319
|
+
}
|
|
1320
|
+
scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
|
|
1321
|
+
const element = scope.domElement;
|
|
1322
|
+
rotateLeft(2 * Math.PI * scope.rotateDelta.x / element.clientHeight);
|
|
1323
|
+
rotateUp(2 * Math.PI * scope.rotateDelta.y / element.clientHeight);
|
|
1324
|
+
scope.rotateStart.copy(scope.rotateEnd);
|
|
1325
|
+
}
|
|
1326
|
+
function handleTouchMovePan(event) {
|
|
1327
|
+
if (scope.pointers.length === 1) {
|
|
1328
|
+
scope.panEnd.set(event.pageX, event.pageY);
|
|
1329
|
+
} else {
|
|
1330
|
+
const position = getSecondPointerPosition(event);
|
|
1331
|
+
const x = .5 * (event.pageX + position.x);
|
|
1332
|
+
const y = .5 * (event.pageY + position.y);
|
|
1333
|
+
scope.panEnd.set(x, y);
|
|
1334
|
+
}
|
|
1335
|
+
scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
|
|
1336
|
+
pan(scope.panDelta.x, scope.panDelta.y);
|
|
1337
|
+
scope.panStart.copy(scope.panEnd);
|
|
1338
|
+
}
|
|
1339
|
+
function handleTouchMoveDolly(event) {
|
|
1340
|
+
const position = getSecondPointerPosition(event);
|
|
1341
|
+
const dx = event.pageX - position.x;
|
|
1342
|
+
const dy = event.pageY - position.y;
|
|
1343
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
1344
|
+
scope.dollyEnd.set(0, distance);
|
|
1345
|
+
scope.dollyDelta.set(0, Math.pow(scope.dollyEnd.y / scope.dollyStart.y, scope.zoomSpeed));
|
|
1346
|
+
dollyOut(scope.dollyDelta.y);
|
|
1347
|
+
scope.dollyStart.copy(scope.dollyEnd);
|
|
1348
|
+
}
|
|
1349
|
+
function handleTouchMoveDollyPan(event) {
|
|
1350
|
+
if (scope.enableZoom) handleTouchMoveDolly(event);
|
|
1351
|
+
if (scope.enablePan) handleTouchMovePan(event);
|
|
1352
|
+
}
|
|
1353
|
+
function handleTouchMoveDollyRotate(event) {
|
|
1354
|
+
if (scope.enableZoom) handleTouchMoveDolly(event);
|
|
1355
|
+
if (scope.enableRotate) handleTouchMoveRotate(event);
|
|
1356
|
+
}
|
|
1357
|
+
function onPointerDown(event) {
|
|
1358
|
+
if (scope.enabled === false) return;
|
|
1359
|
+
if (scope.pointers.length === 0) {
|
|
1360
|
+
scope.domElement.setPointerCapture(event.pointerId);
|
|
1361
|
+
scope.domElement.addEventListener("pointermove", onPointerMove);
|
|
1362
|
+
scope.domElement.addEventListener("pointerup", onPointerUp);
|
|
1363
|
+
}
|
|
1364
|
+
addPointer(event);
|
|
1365
|
+
if (event.pointerType === "touch") {
|
|
1366
|
+
onTouchStart(event);
|
|
1367
|
+
} else {
|
|
1368
|
+
onMouseDown(event);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
function onPointerMove(event) {
|
|
1372
|
+
if (scope.enabled === false) return;
|
|
1373
|
+
if (event.pointerType === "touch") {
|
|
1374
|
+
onTouchMove(event);
|
|
1375
|
+
} else {
|
|
1376
|
+
onMouseMove(event);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
function onPointerUp(event) {
|
|
1380
|
+
removePointer(event);
|
|
1381
|
+
if (scope.pointers.length === 0) {
|
|
1382
|
+
scope.domElement.releasePointerCapture(event.pointerId);
|
|
1383
|
+
scope.domElement.removeEventListener("pointermove", onPointerMove);
|
|
1384
|
+
scope.domElement.removeEventListener("pointerup", onPointerUp);
|
|
1385
|
+
}
|
|
1386
|
+
scope.dispatchEvent(_endEvent);
|
|
1387
|
+
scope.state = STATE.NONE;
|
|
1388
|
+
}
|
|
1389
|
+
function onMouseDown(event) {
|
|
1390
|
+
let mouseAction;
|
|
1391
|
+
switch (event.button) {
|
|
1392
|
+
case 0:
|
|
1393
|
+
mouseAction = scope.mouseButtons.LEFT;
|
|
1394
|
+
break;
|
|
1395
|
+
|
|
1396
|
+
case 1:
|
|
1397
|
+
mouseAction = scope.mouseButtons.MIDDLE;
|
|
1398
|
+
break;
|
|
1399
|
+
|
|
1400
|
+
case 2:
|
|
1401
|
+
mouseAction = scope.mouseButtons.RIGHT;
|
|
1402
|
+
break;
|
|
1403
|
+
|
|
1404
|
+
default:
|
|
1405
|
+
mouseAction = -1;
|
|
1406
|
+
}
|
|
1407
|
+
switch (mouseAction) {
|
|
1408
|
+
case MOUSE.DOLLY:
|
|
1409
|
+
if (scope.enableZoom === false) return;
|
|
1410
|
+
handleMouseDownDolly(event);
|
|
1411
|
+
scope.state = STATE.DOLLY;
|
|
1412
|
+
break;
|
|
1413
|
+
|
|
1414
|
+
case MOUSE.ROTATE:
|
|
1415
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1416
|
+
if (scope.enablePan === false) return;
|
|
1417
|
+
handleMouseDownPan(event);
|
|
1418
|
+
scope.state = STATE.PAN;
|
|
1419
|
+
} else {
|
|
1420
|
+
if (scope.enableRotate === false) return;
|
|
1421
|
+
handleMouseDownRotate(event);
|
|
1422
|
+
scope.state = STATE.ROTATE;
|
|
1423
|
+
}
|
|
1424
|
+
break;
|
|
1425
|
+
|
|
1426
|
+
case MOUSE.PAN:
|
|
1427
|
+
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1428
|
+
if (scope.enableRotate === false) return;
|
|
1429
|
+
handleMouseDownRotate(event);
|
|
1430
|
+
scope.state = STATE.ROTATE;
|
|
1431
|
+
} else {
|
|
1432
|
+
if (scope.enablePan === false) return;
|
|
1433
|
+
handleMouseDownPan(event);
|
|
1434
|
+
scope.state = STATE.PAN;
|
|
1435
|
+
}
|
|
1436
|
+
break;
|
|
1437
|
+
|
|
1438
|
+
default:
|
|
1439
|
+
scope.state = STATE.NONE;
|
|
1440
|
+
}
|
|
1441
|
+
if (scope.state !== STATE.NONE) {
|
|
1442
|
+
scope.dispatchEvent(_startEvent);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
function onMouseMove(event) {
|
|
1446
|
+
switch (scope.state) {
|
|
1447
|
+
case STATE.ROTATE:
|
|
1448
|
+
if (scope.enableRotate === false) return;
|
|
1449
|
+
handleMouseMoveRotate(event);
|
|
1450
|
+
break;
|
|
1451
|
+
|
|
1452
|
+
case STATE.DOLLY:
|
|
1453
|
+
if (scope.enableZoom === false) return;
|
|
1454
|
+
handleMouseMoveDolly(event);
|
|
1455
|
+
break;
|
|
1456
|
+
|
|
1457
|
+
case STATE.PAN:
|
|
1458
|
+
if (scope.enablePan === false) return;
|
|
1459
|
+
handleMouseMovePan(event);
|
|
1460
|
+
break;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
function onMouseWheel(event) {
|
|
1464
|
+
if (scope.enabled === false || scope.enableZoom === false || scope.state !== STATE.NONE) return;
|
|
1465
|
+
event.preventDefault();
|
|
1466
|
+
scope.dispatchEvent(_startEvent);
|
|
1467
|
+
handleMouseWheel(event);
|
|
1468
|
+
scope.dispatchEvent(_endEvent);
|
|
1469
|
+
}
|
|
1470
|
+
function onKeyDown(event) {
|
|
1471
|
+
if (scope.enabled === false || scope.enablePan === false) return;
|
|
1472
|
+
handleKeyDown(event);
|
|
1473
|
+
}
|
|
1474
|
+
function onTouchStart(event) {
|
|
1475
|
+
trackPointer(event);
|
|
1476
|
+
switch (scope.pointers.length) {
|
|
1477
|
+
case 1:
|
|
1478
|
+
switch (scope.touches.ONE) {
|
|
1479
|
+
case TOUCH.ROTATE:
|
|
1480
|
+
if (scope.enableRotate === false) return;
|
|
1481
|
+
handleTouchStartRotate();
|
|
1482
|
+
scope.state = STATE.TOUCH_ROTATE;
|
|
1483
|
+
break;
|
|
1484
|
+
|
|
1485
|
+
case TOUCH.PAN:
|
|
1486
|
+
if (scope.enablePan === false) return;
|
|
1487
|
+
handleTouchStartPan();
|
|
1488
|
+
scope.state = STATE.TOUCH_PAN;
|
|
1489
|
+
break;
|
|
1490
|
+
|
|
1491
|
+
default:
|
|
1492
|
+
scope.state = STATE.NONE;
|
|
1493
|
+
}
|
|
1494
|
+
break;
|
|
1495
|
+
|
|
1496
|
+
case 2:
|
|
1497
|
+
switch (scope.touches.TWO) {
|
|
1498
|
+
case TOUCH.DOLLY_PAN:
|
|
1499
|
+
if (scope.enableZoom === false && scope.enablePan === false) return;
|
|
1500
|
+
handleTouchStartDollyPan();
|
|
1501
|
+
scope.state = STATE.TOUCH_DOLLY_PAN;
|
|
1502
|
+
break;
|
|
1503
|
+
|
|
1504
|
+
case TOUCH.DOLLY_ROTATE:
|
|
1505
|
+
if (scope.enableZoom === false && scope.enableRotate === false) return;
|
|
1506
|
+
handleTouchStartDollyRotate();
|
|
1507
|
+
scope.state = STATE.TOUCH_DOLLY_ROTATE;
|
|
1508
|
+
break;
|
|
1509
|
+
|
|
1510
|
+
default:
|
|
1511
|
+
scope.state = STATE.NONE;
|
|
1512
|
+
}
|
|
1513
|
+
break;
|
|
1514
|
+
|
|
1515
|
+
default:
|
|
1516
|
+
scope.state = STATE.NONE;
|
|
1517
|
+
}
|
|
1518
|
+
if (scope.state !== STATE.NONE) {
|
|
1519
|
+
scope.dispatchEvent(_startEvent);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
function onTouchMove(event) {
|
|
1523
|
+
trackPointer(event);
|
|
1524
|
+
switch (scope.state) {
|
|
1525
|
+
case STATE.TOUCH_ROTATE:
|
|
1526
|
+
if (scope.enableRotate === false) return;
|
|
1527
|
+
handleTouchMoveRotate(event);
|
|
1528
|
+
scope.update();
|
|
1529
|
+
break;
|
|
1530
|
+
|
|
1531
|
+
case STATE.TOUCH_PAN:
|
|
1532
|
+
if (scope.enablePan === false) return;
|
|
1533
|
+
handleTouchMovePan(event);
|
|
1534
|
+
scope.update();
|
|
1535
|
+
break;
|
|
1536
|
+
|
|
1537
|
+
case STATE.TOUCH_DOLLY_PAN:
|
|
1538
|
+
if (scope.enableZoom === false && scope.enablePan === false) return;
|
|
1539
|
+
handleTouchMoveDollyPan(event);
|
|
1540
|
+
scope.update();
|
|
1541
|
+
break;
|
|
1542
|
+
|
|
1543
|
+
case STATE.TOUCH_DOLLY_ROTATE:
|
|
1544
|
+
if (scope.enableZoom === false && scope.enableRotate === false) return;
|
|
1545
|
+
handleTouchMoveDollyRotate(event);
|
|
1546
|
+
scope.update();
|
|
1547
|
+
break;
|
|
1548
|
+
|
|
1549
|
+
default:
|
|
1550
|
+
scope.state = STATE.NONE;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
function onContextMenu(event) {
|
|
1554
|
+
if (scope.enabled === false) return;
|
|
1555
|
+
event.preventDefault();
|
|
1556
|
+
}
|
|
1557
|
+
function addPointer(event) {
|
|
1558
|
+
scope.pointers.push(event);
|
|
1559
|
+
}
|
|
1560
|
+
function removePointer(event) {
|
|
1561
|
+
delete scope.pointerPositions[event.pointerId];
|
|
1562
|
+
for (let i = 0; i < scope.pointers.length; i++) {
|
|
1563
|
+
if (scope.pointers[i].pointerId == event.pointerId) {
|
|
1564
|
+
scope.pointers.splice(i, 1);
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
function trackPointer(event) {
|
|
1570
|
+
let position = scope.pointerPositions[event.pointerId];
|
|
1571
|
+
if (position === undefined) {
|
|
1572
|
+
position = new Vector2;
|
|
1573
|
+
scope.pointerPositions[event.pointerId] = position;
|
|
619
1574
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
1575
|
+
position.set(event.pageX, event.pageY);
|
|
1576
|
+
}
|
|
1577
|
+
function getSecondPointerPosition(event) {
|
|
1578
|
+
const pointer = event.pointerId === scope.pointers[0].pointerId ? scope.pointers[1] : scope.pointers[0];
|
|
1579
|
+
return scope.pointerPositions[pointer.pointerId];
|
|
1580
|
+
}
|
|
1581
|
+
scope.domElement.addEventListener("contextmenu", onContextMenu);
|
|
1582
|
+
scope.domElement.addEventListener("pointerdown", onPointerDown);
|
|
1583
|
+
scope.domElement.addEventListener("pointercancel", onPointerUp);
|
|
1584
|
+
scope.domElement.addEventListener("wheel", onMouseWheel, {
|
|
1585
|
+
passive: false
|
|
1586
|
+
});
|
|
1587
|
+
this.update();
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
class OrbitDragger {
|
|
1592
|
+
constructor(viewer) {
|
|
1593
|
+
this.updateControls = () => {
|
|
1594
|
+
this.orbit.maxDistance = this.viewer.camera.far;
|
|
1595
|
+
this.orbit.minDistance = this.viewer.camera.near;
|
|
1596
|
+
this.orbit.target.copy(this.viewer.target);
|
|
1597
|
+
this.orbit.update();
|
|
624
1598
|
};
|
|
625
|
-
this.
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
1599
|
+
this.controlsStart = () => {
|
|
1600
|
+
this.changed = false;
|
|
1601
|
+
};
|
|
1602
|
+
this.controlsChange = () => {
|
|
1603
|
+
this.viewer.target.copy(this.orbit.target);
|
|
1604
|
+
this.viewer.update();
|
|
1605
|
+
switch (this.orbit.state) {
|
|
1606
|
+
case STATE.PAN:
|
|
1607
|
+
case STATE.TOUCH_PAN:
|
|
1608
|
+
this.viewer.emitEvent({
|
|
1609
|
+
type: "pan",
|
|
1610
|
+
x: this.orbit.panEnd.x,
|
|
1611
|
+
y: this.orbit.panEnd.y,
|
|
1612
|
+
dX: this.orbit.panDelta.x,
|
|
1613
|
+
dY: this.orbit.panDelta.y
|
|
1614
|
+
});
|
|
1615
|
+
break;
|
|
1616
|
+
|
|
1617
|
+
case STATE.DOLLY:
|
|
1618
|
+
this.viewer.emitEvent({
|
|
1619
|
+
type: "zoomat",
|
|
1620
|
+
data: this.orbit.dollyScale,
|
|
1621
|
+
x: this.orbit.dollyEnd.x,
|
|
1622
|
+
y: this.orbit.dollyEnd.y
|
|
1623
|
+
});
|
|
1624
|
+
break;
|
|
630
1625
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
1626
|
+
this.changed = true;
|
|
1627
|
+
};
|
|
1628
|
+
this.stopContextMenu = event => {
|
|
1629
|
+
if (this.changed) {
|
|
1630
|
+
event.preventDefault();
|
|
1631
|
+
event.stopPropagation();
|
|
634
1632
|
}
|
|
635
1633
|
};
|
|
636
|
-
this.
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
1634
|
+
this.orbit = new OrbitControls(viewer.camera, viewer.canvas);
|
|
1635
|
+
this.orbit.mouseButtons = {
|
|
1636
|
+
LEFT: MOUSE.ROTATE,
|
|
1637
|
+
MIDDLE: MOUSE.PAN,
|
|
1638
|
+
RIGHT: MOUSE.PAN
|
|
1639
|
+
};
|
|
1640
|
+
this.orbit.touches = {
|
|
1641
|
+
ONE: TOUCH.ROTATE,
|
|
1642
|
+
TWO: TOUCH.DOLLY_PAN
|
|
640
1643
|
};
|
|
1644
|
+
this.orbit.screenSpacePanning = true;
|
|
1645
|
+
this.orbit.rotateSpeed = .33;
|
|
1646
|
+
this.orbit.addEventListener("start", this.controlsStart);
|
|
1647
|
+
this.orbit.addEventListener("change", this.controlsChange);
|
|
1648
|
+
this.changed = false;
|
|
641
1649
|
this.viewer = viewer;
|
|
642
|
-
this.
|
|
643
|
-
this.
|
|
644
|
-
this.
|
|
645
|
-
this.
|
|
646
|
-
this.
|
|
647
|
-
this.mouseDelta = new THREE.Vector2;
|
|
648
|
-
this.xAxis = new THREE.Vector3;
|
|
649
|
-
this.yAxis = new THREE.Vector3;
|
|
650
|
-
this.zAxis = new THREE.Vector3;
|
|
651
|
-
this.yRotationAxis = new THREE.Vector3(1, 0, 0);
|
|
652
|
-
this.walkSpeed = 1;
|
|
653
|
-
this.boostSpeed = 5;
|
|
654
|
-
this.speed = new THREE.Vector3;
|
|
655
|
-
this._maxDistance = 1;
|
|
656
|
-
this.touchStartDistance = 0;
|
|
657
|
-
this.viewer.addEventListener("render", this.onRender);
|
|
658
|
-
this.viewer.addEventListener("contextmenu", this.onContextMenu);
|
|
659
|
-
this.viewer.addEventListener("mousedown", this.onMouseDown);
|
|
660
|
-
this.viewer.addEventListener("mouseup", this.onMouseUp);
|
|
661
|
-
this.viewer.addEventListener("touchstart", this.onTouchStart);
|
|
662
|
-
this.viewer.addEventListener("touchmove", this.onTouchMove);
|
|
663
|
-
this.viewer.addEventListener("touchend", this.onTouchEnd);
|
|
664
|
-
this.viewer.addEventListener("wheel", this.onMouseWheel);
|
|
665
|
-
document.addEventListener("keydown", this.onKeyDown);
|
|
666
|
-
document.addEventListener("keyup", this.onKeyUp);
|
|
1650
|
+
this.viewer.on("geometryend", this.updateControls);
|
|
1651
|
+
this.viewer.on("viewposition", this.updateControls);
|
|
1652
|
+
this.viewer.on("zoom", this.updateControls);
|
|
1653
|
+
this.viewer.on("contextmenu", this.stopContextMenu);
|
|
1654
|
+
this.updateControls();
|
|
667
1655
|
}
|
|
668
1656
|
dispose() {
|
|
669
|
-
this.viewer.
|
|
670
|
-
this.viewer.
|
|
671
|
-
this.viewer.
|
|
672
|
-
this.viewer.
|
|
673
|
-
this.
|
|
674
|
-
this.
|
|
675
|
-
this.viewer.removeEventListener("touchmove", this.onTouchMove);
|
|
676
|
-
this.viewer.removeEventListener("touchend", this.onTouchEnd);
|
|
677
|
-
this.viewer.removeEventListener("wheel", this.onMouseWheel);
|
|
678
|
-
document.removeEventListener("keydown", this.onKeyDown);
|
|
679
|
-
document.removeEventListener("keyup", this.onKeyUp);
|
|
680
|
-
}
|
|
681
|
-
getTouchsDistance(touches) {
|
|
682
|
-
const [start, end] = touches;
|
|
683
|
-
const dx = start.clientX - end.clientX;
|
|
684
|
-
const dy = start.clientY - end.clientY;
|
|
685
|
-
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
686
|
-
return distance;
|
|
687
|
-
}
|
|
688
|
-
update() {}
|
|
689
|
-
rotateCamera(delta) {
|
|
690
|
-
const rotateX = Math.PI * delta.x / this.viewer.canvas.clientWidth;
|
|
691
|
-
const rotateY = Math.PI * delta.y / this.viewer.canvas.clientHeight;
|
|
692
|
-
const quaternion = this.quaternion.clone();
|
|
693
|
-
this.xRotation.setFromAxisAngle(this.viewer.camera.up, rotateX);
|
|
694
|
-
this.yRotation.setFromAxisAngle(this.yRotationAxis, rotateY);
|
|
695
|
-
quaternion.premultiply(this.xRotation).multiply(this.yRotation).normalize();
|
|
696
|
-
this.viewer.camera.setRotationFromQuaternion(quaternion);
|
|
1657
|
+
this.viewer.off("geometryend", this.updateControls);
|
|
1658
|
+
this.viewer.off("viewposition", this.updateControls);
|
|
1659
|
+
this.viewer.off("zoom", this.updateControls);
|
|
1660
|
+
this.viewer.off("contextmenu", this.stopContextMenu);
|
|
1661
|
+
this.orbit.removeEventListener("change", this.controlsChange);
|
|
1662
|
+
this.orbit.dispose();
|
|
697
1663
|
}
|
|
698
1664
|
}
|
|
699
1665
|
|
|
700
|
-
class
|
|
1666
|
+
class PanDragger extends OrbitDragger {
|
|
701
1667
|
constructor(viewer) {
|
|
1668
|
+
super(viewer);
|
|
1669
|
+
this.orbit.mouseButtons = {
|
|
1670
|
+
LEFT: MOUSE.PAN,
|
|
1671
|
+
MIDDLE: MOUSE.PAN,
|
|
1672
|
+
RIGHT: MOUSE.PAN
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
class ZoomDragger extends OrbitDragger {
|
|
1678
|
+
constructor(viewer) {
|
|
1679
|
+
super(viewer);
|
|
1680
|
+
this.orbit.mouseButtons = {
|
|
1681
|
+
LEFT: MOUSE.DOLLY,
|
|
1682
|
+
MIDDLE: MOUSE.PAN,
|
|
1683
|
+
RIGHT: MOUSE.PAN
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
const _changeEvent$1 = {
|
|
1689
|
+
type: "change"
|
|
1690
|
+
};
|
|
1691
|
+
|
|
1692
|
+
class WalkControls extends EventDispatcher {
|
|
1693
|
+
constructor(camera, canvas) {
|
|
1694
|
+
super();
|
|
1695
|
+
this.movementSpeed = .2;
|
|
1696
|
+
this.lookSpeed = 5;
|
|
1697
|
+
this.multiplier = 5;
|
|
1698
|
+
this.moveWheel = 0;
|
|
1699
|
+
this.mouseDragOn = false;
|
|
702
1700
|
this.onPointerDown = event => {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
this.
|
|
706
|
-
this.
|
|
707
|
-
this.
|
|
708
|
-
|
|
1701
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
1702
|
+
this.canvas.setPointerCapture(event.pointerId);
|
|
1703
|
+
this.downPosition.set(event.clientX, event.clientY);
|
|
1704
|
+
this.quaternion.copy(this.camera.quaternion);
|
|
1705
|
+
this.mouseDragOn = true;
|
|
1706
|
+
};
|
|
1707
|
+
this.onPointerMove = event => {
|
|
1708
|
+
if (!event.isPrimary || !this.mouseDragOn) return;
|
|
1709
|
+
const movePosition = new Vector2(event.clientX, event.clientY);
|
|
1710
|
+
if (this.downPosition.distanceTo(movePosition) === 0) return;
|
|
1711
|
+
this.rotateDelta.copy(this.downPosition).sub(movePosition);
|
|
1712
|
+
this.rotateCamera(this.rotateDelta);
|
|
1713
|
+
this.dispatchEvent(_changeEvent$1);
|
|
709
1714
|
};
|
|
710
1715
|
this.onPointerUp = event => {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1716
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
1717
|
+
this.canvas.releasePointerCapture(event.pointerId);
|
|
1718
|
+
this.mouseDragOn = false;
|
|
1719
|
+
};
|
|
1720
|
+
this.onPointerCancel = event => {
|
|
1721
|
+
this.canvas.dispatchEvent(new PointerEvent("pointerup", event));
|
|
1722
|
+
};
|
|
1723
|
+
this.onWheel = event => {
|
|
1724
|
+
this.moveWheel = event.deltaY;
|
|
1725
|
+
this.update();
|
|
1726
|
+
};
|
|
1727
|
+
this.onKeyDown = event => {
|
|
1728
|
+
switch (event.code) {
|
|
1729
|
+
case "NumpadSubtract":
|
|
1730
|
+
case "Minus":
|
|
1731
|
+
if (this.multiplier > 1) {
|
|
1732
|
+
this.multiplier = this.multiplier - 1;
|
|
1733
|
+
this.dispatchEvent({
|
|
1734
|
+
type: "walkspeedchange",
|
|
1735
|
+
data: this.multiplier
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
break;
|
|
1739
|
+
|
|
1740
|
+
case "NumpadAdd":
|
|
1741
|
+
case "Equal":
|
|
1742
|
+
if (this.multiplier < 10) {
|
|
1743
|
+
this.multiplier = this.multiplier + 1;
|
|
1744
|
+
this.dispatchEvent({
|
|
1745
|
+
type: "walkspeedchange",
|
|
1746
|
+
data: this.multiplier
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1749
|
+
break;
|
|
1750
|
+
|
|
1751
|
+
case "ArrowLeft":
|
|
1752
|
+
case "ArrowRight":
|
|
1753
|
+
case "ArrowUp":
|
|
1754
|
+
case "ArrowDown":
|
|
1755
|
+
case "KeyW":
|
|
1756
|
+
case "KeyS":
|
|
1757
|
+
case "KeyA":
|
|
1758
|
+
case "KeyD":
|
|
1759
|
+
case "KeyQ":
|
|
1760
|
+
case "KeyE":
|
|
1761
|
+
this.moveKeys.add(event.code);
|
|
1762
|
+
this.update();
|
|
1763
|
+
break;
|
|
720
1764
|
}
|
|
721
1765
|
};
|
|
722
|
-
this.
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
1766
|
+
this.onKeyUp = event => {
|
|
1767
|
+
switch (event.code) {
|
|
1768
|
+
case "ArrowLeft":
|
|
1769
|
+
case "ArrowRight":
|
|
1770
|
+
case "ArrowUp":
|
|
1771
|
+
case "ArrowDown":
|
|
1772
|
+
case "KeyW":
|
|
1773
|
+
case "KeyS":
|
|
1774
|
+
case "KeyA":
|
|
1775
|
+
case "KeyD":
|
|
1776
|
+
case "KeyQ":
|
|
1777
|
+
case "KeyE":
|
|
1778
|
+
this.moveKeys.delete(event.code);
|
|
1779
|
+
this.update();
|
|
1780
|
+
break;
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
this.camera = camera;
|
|
1784
|
+
this.canvas = canvas;
|
|
1785
|
+
this.moveKeys = new Set;
|
|
1786
|
+
this.moveClock = new Clock;
|
|
1787
|
+
this.quaternion = camera.quaternion.clone();
|
|
1788
|
+
this.downPosition = new Vector2(0, 0);
|
|
1789
|
+
this.rotateDelta = new Vector2(0, 0);
|
|
1790
|
+
this.canvas.addEventListener("pointerdown", this.onPointerDown);
|
|
1791
|
+
this.canvas.addEventListener("pointermove", this.onPointerMove);
|
|
1792
|
+
this.canvas.addEventListener("pointerup", this.onPointerUp);
|
|
1793
|
+
this.canvas.addEventListener("pointercancel", this.onPointerCancel);
|
|
1794
|
+
this.canvas.addEventListener("wheel", this.onWheel);
|
|
1795
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
1796
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
1797
|
+
}
|
|
1798
|
+
dispose() {
|
|
1799
|
+
this.canvas.removeEventListener("pointerdown", this.onPointerDown);
|
|
1800
|
+
this.canvas.removeEventListener("pointermove", this.onPointerMove);
|
|
1801
|
+
this.canvas.removeEventListener("pointerup", this.onPointerUp);
|
|
1802
|
+
this.canvas.removeEventListener("pointercancel", this.onPointerCancel);
|
|
1803
|
+
this.canvas.removeEventListener("wheel", this.onWheel);
|
|
1804
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
1805
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
1806
|
+
}
|
|
1807
|
+
update() {
|
|
1808
|
+
if (this.moveKeys.size > 0) {
|
|
1809
|
+
const timeDelta = this.moveClock.getDelta();
|
|
1810
|
+
const moveDelta = timeDelta * this.movementSpeed * this.multiplier;
|
|
1811
|
+
if (this.moveKeys.has("KeyW")) this.camera.translateZ(-moveDelta);
|
|
1812
|
+
if (this.moveKeys.has("KeyS")) this.camera.translateZ(moveDelta);
|
|
1813
|
+
if (this.moveKeys.has("KeyA")) this.camera.translateX(-moveDelta);
|
|
1814
|
+
if (this.moveKeys.has("KeyD")) this.camera.translateX(moveDelta);
|
|
1815
|
+
if (this.moveKeys.has("KeyQ")) this.camera.translateY(moveDelta);
|
|
1816
|
+
if (this.moveKeys.has("KeyE")) this.camera.translateY(-moveDelta);
|
|
1817
|
+
const lookDelta = this.lookSpeed + (this.multiplier - 1);
|
|
1818
|
+
if (this.moveKeys.has("ArrowUp")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, -lookDelta / 2)));
|
|
1819
|
+
if (this.moveKeys.has("ArrowDown")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, lookDelta / 2)));
|
|
1820
|
+
if (this.moveKeys.has("ArrowLeft")) this.rotateCamera(this.rotateDelta.add(new Vector2(lookDelta, 0)));
|
|
1821
|
+
if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
|
|
1822
|
+
this.moveWheel = 0;
|
|
1823
|
+
this.dispatchEvent(_changeEvent$1);
|
|
1824
|
+
}
|
|
1825
|
+
if (this.moveWheel !== 0) {
|
|
1826
|
+
const moveDelta = this.moveWheel * 1e-4 * this.movementSpeed * this.multiplier;
|
|
1827
|
+
this.camera.translateZ(-moveDelta);
|
|
1828
|
+
this.moveWheel += -1 * Math.sign(this.moveWheel);
|
|
1829
|
+
this.dispatchEvent(_changeEvent$1);
|
|
1830
|
+
}
|
|
1831
|
+
if (this.moveKeys.size === 0 && this.moveWheel === 0) {
|
|
1832
|
+
this.moveClock.stop();
|
|
1833
|
+
this.moveClock.autoStart = true;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
rotateCamera(delta) {
|
|
1837
|
+
const rotateX = Math.PI * delta.x / this.canvas.clientWidth;
|
|
1838
|
+
const rotateY = Math.PI * delta.y / this.canvas.clientHeight;
|
|
1839
|
+
const xRotation = new Quaternion;
|
|
1840
|
+
xRotation.setFromAxisAngle(this.camera.up, rotateX);
|
|
1841
|
+
const yRotation = new Quaternion;
|
|
1842
|
+
yRotation.setFromAxisAngle(new Vector3(1, 0, 0), rotateY);
|
|
1843
|
+
const quaternion = this.quaternion.clone();
|
|
1844
|
+
quaternion.premultiply(xRotation).multiply(yRotation).normalize();
|
|
1845
|
+
this.camera.setRotationFromQuaternion(quaternion);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
class WalkDragger {
|
|
1850
|
+
constructor(viewer) {
|
|
1851
|
+
this.updateControls = () => {
|
|
1852
|
+
const size = this.viewer.extents.getSize(new Vector3);
|
|
1853
|
+
this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
|
|
1854
|
+
};
|
|
1855
|
+
this.controlsChange = () => {
|
|
1856
|
+
this.viewer.update();
|
|
1857
|
+
};
|
|
1858
|
+
this.walkspeedChange = event => {
|
|
1859
|
+
this.viewer.emitEvent(event);
|
|
730
1860
|
};
|
|
1861
|
+
this.viewerRender = () => {
|
|
1862
|
+
this.controls.update();
|
|
1863
|
+
};
|
|
1864
|
+
this.viewerZoom = () => {
|
|
1865
|
+
this.controls.rotateDelta.set(0, 0);
|
|
1866
|
+
};
|
|
1867
|
+
this.controls = new WalkControls(viewer.camera, viewer.canvas);
|
|
1868
|
+
this.controls.addEventListener("change", this.controlsChange);
|
|
1869
|
+
this.controls.addEventListener("walkspeedchange", this.walkspeedChange);
|
|
731
1870
|
this.viewer = viewer;
|
|
732
|
-
this.viewer.
|
|
733
|
-
this.viewer.
|
|
734
|
-
this.
|
|
735
|
-
this.start = new THREE.Vector3;
|
|
736
|
-
this.end = new THREE.Vector3;
|
|
737
|
-
this.delta = new THREE.Vector3;
|
|
738
|
-
if (!this.viewer.renderer.clippingPlanes) this.viewer.renderer.clippingPlanes = [];
|
|
739
|
-
this.viewer.renderer.clippingPlanes.push(this.plane);
|
|
740
|
-
this.planeHelper = new THREE.PlaneHelper(this.plane, 150, 16776960);
|
|
741
|
-
this.viewer.scene.add(this.planeHelper);
|
|
1871
|
+
this.viewer.on("render", this.viewerRender);
|
|
1872
|
+
this.viewer.on("zoom", this.viewerZoom);
|
|
1873
|
+
this.updateControls();
|
|
742
1874
|
}
|
|
743
1875
|
dispose() {
|
|
744
|
-
this.viewer.
|
|
745
|
-
this.viewer.
|
|
746
|
-
this.
|
|
747
|
-
this.
|
|
1876
|
+
this.viewer.off("render", this.viewerRender);
|
|
1877
|
+
this.viewer.off("zoom", this.viewerZoom);
|
|
1878
|
+
this.controls.removeEventListener("walkspeedchange", this.walkspeedChange);
|
|
1879
|
+
this.controls.removeEventListener("change", this.controlsChange);
|
|
1880
|
+
this.controls.dispose();
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
const _raycaster = new Raycaster;
|
|
1885
|
+
|
|
1886
|
+
const _tempVector = new Vector3;
|
|
1887
|
+
|
|
1888
|
+
const _tempVector2 = new Vector3;
|
|
1889
|
+
|
|
1890
|
+
const _tempQuaternion = new Quaternion;
|
|
1891
|
+
|
|
1892
|
+
const _unit = {
|
|
1893
|
+
X: new Vector3(1, 0, 0),
|
|
1894
|
+
Y: new Vector3(0, 1, 0),
|
|
1895
|
+
Z: new Vector3(0, 0, 1)
|
|
1896
|
+
};
|
|
1897
|
+
|
|
1898
|
+
const _changeEvent = {
|
|
1899
|
+
type: "change"
|
|
1900
|
+
};
|
|
1901
|
+
|
|
1902
|
+
const _mouseDownEvent = {
|
|
1903
|
+
type: "mouseDown"
|
|
1904
|
+
};
|
|
1905
|
+
|
|
1906
|
+
const _mouseUpEvent = {
|
|
1907
|
+
type: "mouseUp",
|
|
1908
|
+
mode: null
|
|
1909
|
+
};
|
|
1910
|
+
|
|
1911
|
+
const _objectChangeEvent = {
|
|
1912
|
+
type: "objectChange"
|
|
1913
|
+
};
|
|
1914
|
+
|
|
1915
|
+
class TransformControls extends Object3D {
|
|
1916
|
+
constructor(camera, domElement) {
|
|
1917
|
+
super();
|
|
1918
|
+
if (domElement === undefined) {
|
|
1919
|
+
console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.');
|
|
1920
|
+
domElement = document;
|
|
1921
|
+
}
|
|
1922
|
+
this.isTransformControls = true;
|
|
1923
|
+
this.visible = false;
|
|
1924
|
+
this.domElement = domElement;
|
|
1925
|
+
this.domElement.style.touchAction = "none";
|
|
1926
|
+
const _gizmo = new TransformControlsGizmo;
|
|
1927
|
+
this._gizmo = _gizmo;
|
|
1928
|
+
this.add(_gizmo);
|
|
1929
|
+
const _plane = new TransformControlsPlane;
|
|
1930
|
+
this._plane = _plane;
|
|
1931
|
+
this.add(_plane);
|
|
1932
|
+
const scope = this;
|
|
1933
|
+
function defineProperty(propName, defaultValue) {
|
|
1934
|
+
let propValue = defaultValue;
|
|
1935
|
+
Object.defineProperty(scope, propName, {
|
|
1936
|
+
get: function() {
|
|
1937
|
+
return propValue !== undefined ? propValue : defaultValue;
|
|
1938
|
+
},
|
|
1939
|
+
set: function(value) {
|
|
1940
|
+
if (propValue !== value) {
|
|
1941
|
+
propValue = value;
|
|
1942
|
+
_plane[propName] = value;
|
|
1943
|
+
_gizmo[propName] = value;
|
|
1944
|
+
scope.dispatchEvent({
|
|
1945
|
+
type: propName + "-changed",
|
|
1946
|
+
value: value
|
|
1947
|
+
});
|
|
1948
|
+
scope.dispatchEvent(_changeEvent);
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
});
|
|
1952
|
+
scope[propName] = defaultValue;
|
|
1953
|
+
_plane[propName] = defaultValue;
|
|
1954
|
+
_gizmo[propName] = defaultValue;
|
|
1955
|
+
}
|
|
1956
|
+
defineProperty("camera", camera);
|
|
1957
|
+
defineProperty("object", undefined);
|
|
1958
|
+
defineProperty("enabled", true);
|
|
1959
|
+
defineProperty("axis", null);
|
|
1960
|
+
defineProperty("mode", "translate");
|
|
1961
|
+
defineProperty("translationSnap", null);
|
|
1962
|
+
defineProperty("rotationSnap", null);
|
|
1963
|
+
defineProperty("scaleSnap", null);
|
|
1964
|
+
defineProperty("space", "world");
|
|
1965
|
+
defineProperty("size", 1);
|
|
1966
|
+
defineProperty("dragging", false);
|
|
1967
|
+
defineProperty("showX", true);
|
|
1968
|
+
defineProperty("showY", true);
|
|
1969
|
+
defineProperty("showZ", true);
|
|
1970
|
+
const worldPosition = new Vector3;
|
|
1971
|
+
const worldPositionStart = new Vector3;
|
|
1972
|
+
const worldQuaternion = new Quaternion;
|
|
1973
|
+
const worldQuaternionStart = new Quaternion;
|
|
1974
|
+
const cameraPosition = new Vector3;
|
|
1975
|
+
const cameraQuaternion = new Quaternion;
|
|
1976
|
+
const pointStart = new Vector3;
|
|
1977
|
+
const pointEnd = new Vector3;
|
|
1978
|
+
const rotationAxis = new Vector3;
|
|
1979
|
+
const rotationAngle = 0;
|
|
1980
|
+
const eye = new Vector3;
|
|
1981
|
+
defineProperty("worldPosition", worldPosition);
|
|
1982
|
+
defineProperty("worldPositionStart", worldPositionStart);
|
|
1983
|
+
defineProperty("worldQuaternion", worldQuaternion);
|
|
1984
|
+
defineProperty("worldQuaternionStart", worldQuaternionStart);
|
|
1985
|
+
defineProperty("cameraPosition", cameraPosition);
|
|
1986
|
+
defineProperty("cameraQuaternion", cameraQuaternion);
|
|
1987
|
+
defineProperty("pointStart", pointStart);
|
|
1988
|
+
defineProperty("pointEnd", pointEnd);
|
|
1989
|
+
defineProperty("rotationAxis", rotationAxis);
|
|
1990
|
+
defineProperty("rotationAngle", rotationAngle);
|
|
1991
|
+
defineProperty("eye", eye);
|
|
1992
|
+
this._offset = new Vector3;
|
|
1993
|
+
this._startNorm = new Vector3;
|
|
1994
|
+
this._endNorm = new Vector3;
|
|
1995
|
+
this._cameraScale = new Vector3;
|
|
1996
|
+
this._parentPosition = new Vector3;
|
|
1997
|
+
this._parentQuaternion = new Quaternion;
|
|
1998
|
+
this._parentQuaternionInv = new Quaternion;
|
|
1999
|
+
this._parentScale = new Vector3;
|
|
2000
|
+
this._worldScaleStart = new Vector3;
|
|
2001
|
+
this._worldQuaternionInv = new Quaternion;
|
|
2002
|
+
this._worldScale = new Vector3;
|
|
2003
|
+
this._positionStart = new Vector3;
|
|
2004
|
+
this._quaternionStart = new Quaternion;
|
|
2005
|
+
this._scaleStart = new Vector3;
|
|
2006
|
+
this._getPointer = getPointer.bind(this);
|
|
2007
|
+
this._onPointerDown = onPointerDown.bind(this);
|
|
2008
|
+
this._onPointerHover = onPointerHover.bind(this);
|
|
2009
|
+
this._onPointerMove = onPointerMove.bind(this);
|
|
2010
|
+
this._onPointerUp = onPointerUp.bind(this);
|
|
2011
|
+
this.domElement.addEventListener("pointerdown", this._onPointerDown);
|
|
2012
|
+
this.domElement.addEventListener("pointermove", this._onPointerHover);
|
|
2013
|
+
this.domElement.addEventListener("pointerup", this._onPointerUp);
|
|
2014
|
+
}
|
|
2015
|
+
updateMatrixWorld() {
|
|
2016
|
+
if (this.object !== undefined) {
|
|
2017
|
+
this.object.updateMatrixWorld();
|
|
2018
|
+
if (this.object.parent === null) {
|
|
2019
|
+
console.error("TransformControls: The attached 3D object must be a part of the scene graph.");
|
|
2020
|
+
} else {
|
|
2021
|
+
this.object.parent.matrixWorld.decompose(this._parentPosition, this._parentQuaternion, this._parentScale);
|
|
2022
|
+
}
|
|
2023
|
+
this.object.matrixWorld.decompose(this.worldPosition, this.worldQuaternion, this._worldScale);
|
|
2024
|
+
this._parentQuaternionInv.copy(this._parentQuaternion).invert();
|
|
2025
|
+
this._worldQuaternionInv.copy(this.worldQuaternion).invert();
|
|
2026
|
+
}
|
|
2027
|
+
this.camera.updateMatrixWorld();
|
|
2028
|
+
this.camera.matrixWorld.decompose(this.cameraPosition, this.cameraQuaternion, this._cameraScale);
|
|
2029
|
+
if (this.camera.isOrthographicCamera) {
|
|
2030
|
+
this.camera.getWorldDirection(this.eye).negate();
|
|
2031
|
+
} else {
|
|
2032
|
+
this.eye.copy(this.cameraPosition).sub(this.worldPosition).normalize();
|
|
2033
|
+
}
|
|
2034
|
+
super.updateMatrixWorld(this);
|
|
2035
|
+
}
|
|
2036
|
+
pointerHover(pointer) {
|
|
2037
|
+
if (this.object === undefined || this.dragging === true) return;
|
|
2038
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
2039
|
+
const intersect = intersectObjectWithRay(this._gizmo.picker[this.mode], _raycaster);
|
|
2040
|
+
if (intersect) {
|
|
2041
|
+
this.axis = intersect.object.name;
|
|
2042
|
+
} else {
|
|
2043
|
+
this.axis = null;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
pointerDown(pointer) {
|
|
2047
|
+
if (this.object === undefined || this.dragging === true || pointer.button !== 0) return;
|
|
2048
|
+
if (this.axis !== null) {
|
|
2049
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
2050
|
+
const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
|
|
2051
|
+
if (planeIntersect) {
|
|
2052
|
+
this.object.updateMatrixWorld();
|
|
2053
|
+
this.object.parent.updateMatrixWorld();
|
|
2054
|
+
this._positionStart.copy(this.object.position);
|
|
2055
|
+
this._quaternionStart.copy(this.object.quaternion);
|
|
2056
|
+
this._scaleStart.copy(this.object.scale);
|
|
2057
|
+
this.object.matrixWorld.decompose(this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart);
|
|
2058
|
+
this.pointStart.copy(planeIntersect.point).sub(this.worldPositionStart);
|
|
2059
|
+
}
|
|
2060
|
+
this.dragging = true;
|
|
2061
|
+
_mouseDownEvent.mode = this.mode;
|
|
2062
|
+
this.dispatchEvent(_mouseDownEvent);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
pointerMove(pointer) {
|
|
2066
|
+
const axis = this.axis;
|
|
2067
|
+
const mode = this.mode;
|
|
2068
|
+
const object = this.object;
|
|
2069
|
+
let space = this.space;
|
|
2070
|
+
if (mode === "scale") {
|
|
2071
|
+
space = "local";
|
|
2072
|
+
} else if (axis === "E" || axis === "XYZE" || axis === "XYZ") {
|
|
2073
|
+
space = "world";
|
|
2074
|
+
}
|
|
2075
|
+
if (object === undefined || axis === null || this.dragging === false || pointer.button !== -1) return;
|
|
2076
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
2077
|
+
const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
|
|
2078
|
+
if (!planeIntersect) return;
|
|
2079
|
+
this.pointEnd.copy(planeIntersect.point).sub(this.worldPositionStart);
|
|
2080
|
+
if (mode === "translate") {
|
|
2081
|
+
this._offset.copy(this.pointEnd).sub(this.pointStart);
|
|
2082
|
+
if (space === "local" && axis !== "XYZ") {
|
|
2083
|
+
this._offset.applyQuaternion(this._worldQuaternionInv);
|
|
2084
|
+
}
|
|
2085
|
+
if (axis.indexOf("X") === -1) this._offset.x = 0;
|
|
2086
|
+
if (axis.indexOf("Y") === -1) this._offset.y = 0;
|
|
2087
|
+
if (axis.indexOf("Z") === -1) this._offset.z = 0;
|
|
2088
|
+
if (space === "local" && axis !== "XYZ") {
|
|
2089
|
+
this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale);
|
|
2090
|
+
} else {
|
|
2091
|
+
this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale);
|
|
2092
|
+
}
|
|
2093
|
+
object.position.copy(this._offset).add(this._positionStart);
|
|
2094
|
+
if (this.translationSnap) {
|
|
2095
|
+
if (space === "local") {
|
|
2096
|
+
object.position.applyQuaternion(_tempQuaternion.copy(this._quaternionStart).invert());
|
|
2097
|
+
if (axis.search("X") !== -1) {
|
|
2098
|
+
object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
|
|
2099
|
+
}
|
|
2100
|
+
if (axis.search("Y") !== -1) {
|
|
2101
|
+
object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
|
|
2102
|
+
}
|
|
2103
|
+
if (axis.search("Z") !== -1) {
|
|
2104
|
+
object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
|
|
2105
|
+
}
|
|
2106
|
+
object.position.applyQuaternion(this._quaternionStart);
|
|
2107
|
+
}
|
|
2108
|
+
if (space === "world") {
|
|
2109
|
+
if (object.parent) {
|
|
2110
|
+
object.position.add(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
|
|
2111
|
+
}
|
|
2112
|
+
if (axis.search("X") !== -1) {
|
|
2113
|
+
object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
|
|
2114
|
+
}
|
|
2115
|
+
if (axis.search("Y") !== -1) {
|
|
2116
|
+
object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
|
|
2117
|
+
}
|
|
2118
|
+
if (axis.search("Z") !== -1) {
|
|
2119
|
+
object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
|
|
2120
|
+
}
|
|
2121
|
+
if (object.parent) {
|
|
2122
|
+
object.position.sub(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
} else if (mode === "scale") {
|
|
2127
|
+
if (axis.search("XYZ") !== -1) {
|
|
2128
|
+
let d = this.pointEnd.length() / this.pointStart.length();
|
|
2129
|
+
if (this.pointEnd.dot(this.pointStart) < 0) d *= -1;
|
|
2130
|
+
_tempVector2.set(d, d, d);
|
|
2131
|
+
} else {
|
|
2132
|
+
_tempVector.copy(this.pointStart);
|
|
2133
|
+
_tempVector2.copy(this.pointEnd);
|
|
2134
|
+
_tempVector.applyQuaternion(this._worldQuaternionInv);
|
|
2135
|
+
_tempVector2.applyQuaternion(this._worldQuaternionInv);
|
|
2136
|
+
_tempVector2.divide(_tempVector);
|
|
2137
|
+
if (axis.search("X") === -1) {
|
|
2138
|
+
_tempVector2.x = 1;
|
|
2139
|
+
}
|
|
2140
|
+
if (axis.search("Y") === -1) {
|
|
2141
|
+
_tempVector2.y = 1;
|
|
2142
|
+
}
|
|
2143
|
+
if (axis.search("Z") === -1) {
|
|
2144
|
+
_tempVector2.z = 1;
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
object.scale.copy(this._scaleStart).multiply(_tempVector2);
|
|
2148
|
+
if (this.scaleSnap) {
|
|
2149
|
+
if (axis.search("X") !== -1) {
|
|
2150
|
+
object.scale.x = Math.round(object.scale.x / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
2151
|
+
}
|
|
2152
|
+
if (axis.search("Y") !== -1) {
|
|
2153
|
+
object.scale.y = Math.round(object.scale.y / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
2154
|
+
}
|
|
2155
|
+
if (axis.search("Z") !== -1) {
|
|
2156
|
+
object.scale.z = Math.round(object.scale.z / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
} else if (mode === "rotate") {
|
|
2160
|
+
this._offset.copy(this.pointEnd).sub(this.pointStart);
|
|
2161
|
+
const ROTATION_SPEED = 20 / this.worldPosition.distanceTo(_tempVector.setFromMatrixPosition(this.camera.matrixWorld));
|
|
2162
|
+
if (axis === "E") {
|
|
2163
|
+
this.rotationAxis.copy(this.eye);
|
|
2164
|
+
this.rotationAngle = this.pointEnd.angleTo(this.pointStart);
|
|
2165
|
+
this._startNorm.copy(this.pointStart).normalize();
|
|
2166
|
+
this._endNorm.copy(this.pointEnd).normalize();
|
|
2167
|
+
this.rotationAngle *= this._endNorm.cross(this._startNorm).dot(this.eye) < 0 ? 1 : -1;
|
|
2168
|
+
} else if (axis === "XYZE") {
|
|
2169
|
+
this.rotationAxis.copy(this._offset).cross(this.eye).normalize();
|
|
2170
|
+
this.rotationAngle = this._offset.dot(_tempVector.copy(this.rotationAxis).cross(this.eye)) * ROTATION_SPEED;
|
|
2171
|
+
} else if (axis === "X" || axis === "Y" || axis === "Z") {
|
|
2172
|
+
this.rotationAxis.copy(_unit[axis]);
|
|
2173
|
+
_tempVector.copy(_unit[axis]);
|
|
2174
|
+
if (space === "local") {
|
|
2175
|
+
_tempVector.applyQuaternion(this.worldQuaternion);
|
|
2176
|
+
}
|
|
2177
|
+
this.rotationAngle = this._offset.dot(_tempVector.cross(this.eye).normalize()) * ROTATION_SPEED;
|
|
2178
|
+
}
|
|
2179
|
+
if (this.rotationSnap) this.rotationAngle = Math.round(this.rotationAngle / this.rotationSnap) * this.rotationSnap;
|
|
2180
|
+
if (space === "local" && axis !== "E" && axis !== "XYZE") {
|
|
2181
|
+
object.quaternion.copy(this._quaternionStart);
|
|
2182
|
+
object.quaternion.multiply(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle)).normalize();
|
|
2183
|
+
} else {
|
|
2184
|
+
this.rotationAxis.applyQuaternion(this._parentQuaternionInv);
|
|
2185
|
+
object.quaternion.copy(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle));
|
|
2186
|
+
object.quaternion.multiply(this._quaternionStart).normalize();
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
this.dispatchEvent(_changeEvent);
|
|
2190
|
+
this.dispatchEvent(_objectChangeEvent);
|
|
2191
|
+
}
|
|
2192
|
+
pointerUp(pointer) {
|
|
2193
|
+
if (pointer.button !== 0) return;
|
|
2194
|
+
if (this.dragging && this.axis !== null) {
|
|
2195
|
+
_mouseUpEvent.mode = this.mode;
|
|
2196
|
+
this.dispatchEvent(_mouseUpEvent);
|
|
2197
|
+
}
|
|
2198
|
+
this.dragging = false;
|
|
2199
|
+
this.axis = null;
|
|
2200
|
+
}
|
|
2201
|
+
dispose() {
|
|
2202
|
+
this.domElement.removeEventListener("pointerdown", this._onPointerDown);
|
|
2203
|
+
this.domElement.removeEventListener("pointermove", this._onPointerHover);
|
|
2204
|
+
this.domElement.removeEventListener("pointermove", this._onPointerMove);
|
|
2205
|
+
this.domElement.removeEventListener("pointerup", this._onPointerUp);
|
|
2206
|
+
this.traverse((function(child) {
|
|
2207
|
+
if (child.geometry) child.geometry.dispose();
|
|
2208
|
+
if (child.material) child.material.dispose();
|
|
2209
|
+
}));
|
|
2210
|
+
}
|
|
2211
|
+
attach(object) {
|
|
2212
|
+
this.object = object;
|
|
2213
|
+
this.visible = true;
|
|
2214
|
+
return this;
|
|
2215
|
+
}
|
|
2216
|
+
detach() {
|
|
2217
|
+
this.object = undefined;
|
|
2218
|
+
this.visible = false;
|
|
2219
|
+
this.axis = null;
|
|
2220
|
+
return this;
|
|
2221
|
+
}
|
|
2222
|
+
reset() {
|
|
2223
|
+
if (!this.enabled) return;
|
|
2224
|
+
if (this.dragging) {
|
|
2225
|
+
this.object.position.copy(this._positionStart);
|
|
2226
|
+
this.object.quaternion.copy(this._quaternionStart);
|
|
2227
|
+
this.object.scale.copy(this._scaleStart);
|
|
2228
|
+
this.dispatchEvent(_changeEvent);
|
|
2229
|
+
this.dispatchEvent(_objectChangeEvent);
|
|
2230
|
+
this.pointStart.copy(this.pointEnd);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
getRaycaster() {
|
|
2234
|
+
return _raycaster;
|
|
2235
|
+
}
|
|
2236
|
+
getMode() {
|
|
2237
|
+
return this.mode;
|
|
2238
|
+
}
|
|
2239
|
+
setMode(mode) {
|
|
2240
|
+
this.mode = mode;
|
|
2241
|
+
}
|
|
2242
|
+
setTranslationSnap(translationSnap) {
|
|
2243
|
+
this.translationSnap = translationSnap;
|
|
2244
|
+
}
|
|
2245
|
+
setRotationSnap(rotationSnap) {
|
|
2246
|
+
this.rotationSnap = rotationSnap;
|
|
2247
|
+
}
|
|
2248
|
+
setScaleSnap(scaleSnap) {
|
|
2249
|
+
this.scaleSnap = scaleSnap;
|
|
2250
|
+
}
|
|
2251
|
+
setSize(size) {
|
|
2252
|
+
this.size = size;
|
|
2253
|
+
}
|
|
2254
|
+
setSpace(space) {
|
|
2255
|
+
this.space = space;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
function getPointer(event) {
|
|
2260
|
+
if (this.domElement.ownerDocument.pointerLockElement) {
|
|
2261
|
+
return {
|
|
2262
|
+
x: 0,
|
|
2263
|
+
y: 0,
|
|
2264
|
+
button: event.button
|
|
2265
|
+
};
|
|
2266
|
+
} else {
|
|
2267
|
+
const rect = this.domElement.getBoundingClientRect();
|
|
2268
|
+
return {
|
|
2269
|
+
x: (event.clientX - rect.left) / rect.width * 2 - 1,
|
|
2270
|
+
y: -(event.clientY - rect.top) / rect.height * 2 + 1,
|
|
2271
|
+
button: event.button
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
function onPointerHover(event) {
|
|
2277
|
+
if (!this.enabled) return;
|
|
2278
|
+
switch (event.pointerType) {
|
|
2279
|
+
case "mouse":
|
|
2280
|
+
case "pen":
|
|
2281
|
+
this.pointerHover(this._getPointer(event));
|
|
2282
|
+
break;
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
function onPointerDown(event) {
|
|
2287
|
+
if (!this.enabled) return;
|
|
2288
|
+
if (!document.pointerLockElement) {
|
|
2289
|
+
this.domElement.setPointerCapture(event.pointerId);
|
|
2290
|
+
}
|
|
2291
|
+
this.domElement.addEventListener("pointermove", this._onPointerMove);
|
|
2292
|
+
this.pointerHover(this._getPointer(event));
|
|
2293
|
+
this.pointerDown(this._getPointer(event));
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
function onPointerMove(event) {
|
|
2297
|
+
if (!this.enabled) return;
|
|
2298
|
+
this.pointerMove(this._getPointer(event));
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
function onPointerUp(event) {
|
|
2302
|
+
if (!this.enabled) return;
|
|
2303
|
+
this.domElement.releasePointerCapture(event.pointerId);
|
|
2304
|
+
this.domElement.removeEventListener("pointermove", this._onPointerMove);
|
|
2305
|
+
this.pointerUp(this._getPointer(event));
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
function intersectObjectWithRay(object, raycaster, includeInvisible) {
|
|
2309
|
+
const allIntersections = raycaster.intersectObject(object, true);
|
|
2310
|
+
for (let i = 0; i < allIntersections.length; i++) {
|
|
2311
|
+
if (allIntersections[i].object.visible || includeInvisible) {
|
|
2312
|
+
return allIntersections[i];
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
return false;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
const _tempEuler = new Euler;
|
|
2319
|
+
|
|
2320
|
+
const _alignVector = new Vector3(0, 1, 0);
|
|
2321
|
+
|
|
2322
|
+
const _zeroVector = new Vector3(0, 0, 0);
|
|
2323
|
+
|
|
2324
|
+
const _lookAtMatrix = new Matrix4;
|
|
2325
|
+
|
|
2326
|
+
const _tempQuaternion2 = new Quaternion;
|
|
2327
|
+
|
|
2328
|
+
const _identityQuaternion = new Quaternion;
|
|
2329
|
+
|
|
2330
|
+
const _dirVector = new Vector3;
|
|
2331
|
+
|
|
2332
|
+
const _tempMatrix = new Matrix4;
|
|
2333
|
+
|
|
2334
|
+
const _unitX = new Vector3(1, 0, 0);
|
|
2335
|
+
|
|
2336
|
+
const _unitY = new Vector3(0, 1, 0);
|
|
2337
|
+
|
|
2338
|
+
const _unitZ = new Vector3(0, 0, 1);
|
|
2339
|
+
|
|
2340
|
+
const _v1 = new Vector3;
|
|
2341
|
+
|
|
2342
|
+
const _v2 = new Vector3;
|
|
2343
|
+
|
|
2344
|
+
const _v3 = new Vector3;
|
|
2345
|
+
|
|
2346
|
+
class TransformControlsGizmo extends Object3D {
|
|
2347
|
+
constructor() {
|
|
2348
|
+
super();
|
|
2349
|
+
this.isTransformControlsGizmo = true;
|
|
2350
|
+
this.type = "TransformControlsGizmo";
|
|
2351
|
+
const gizmoMaterial = new MeshBasicMaterial({
|
|
2352
|
+
depthTest: false,
|
|
2353
|
+
depthWrite: false,
|
|
2354
|
+
fog: false,
|
|
2355
|
+
toneMapped: false,
|
|
2356
|
+
transparent: true
|
|
2357
|
+
});
|
|
2358
|
+
const gizmoLineMaterial = new LineBasicMaterial({
|
|
2359
|
+
depthTest: false,
|
|
2360
|
+
depthWrite: false,
|
|
2361
|
+
fog: false,
|
|
2362
|
+
toneMapped: false,
|
|
2363
|
+
transparent: true
|
|
2364
|
+
});
|
|
2365
|
+
const matInvisible = gizmoMaterial.clone();
|
|
2366
|
+
matInvisible.opacity = .15;
|
|
2367
|
+
const matHelper = gizmoLineMaterial.clone();
|
|
2368
|
+
matHelper.opacity = .5;
|
|
2369
|
+
const matRed = gizmoMaterial.clone();
|
|
2370
|
+
matRed.color.setHex(16711680);
|
|
2371
|
+
const matGreen = gizmoMaterial.clone();
|
|
2372
|
+
matGreen.color.setHex(65280);
|
|
2373
|
+
const matBlue = gizmoMaterial.clone();
|
|
2374
|
+
matBlue.color.setHex(255);
|
|
2375
|
+
const matRedTransparent = gizmoMaterial.clone();
|
|
2376
|
+
matRedTransparent.color.setHex(16711680);
|
|
2377
|
+
matRedTransparent.opacity = .5;
|
|
2378
|
+
const matGreenTransparent = gizmoMaterial.clone();
|
|
2379
|
+
matGreenTransparent.color.setHex(65280);
|
|
2380
|
+
matGreenTransparent.opacity = .5;
|
|
2381
|
+
const matBlueTransparent = gizmoMaterial.clone();
|
|
2382
|
+
matBlueTransparent.color.setHex(255);
|
|
2383
|
+
matBlueTransparent.opacity = .5;
|
|
2384
|
+
const matWhiteTransparent = gizmoMaterial.clone();
|
|
2385
|
+
matWhiteTransparent.opacity = .25;
|
|
2386
|
+
const matYellowTransparent = gizmoMaterial.clone();
|
|
2387
|
+
matYellowTransparent.color.setHex(16776960);
|
|
2388
|
+
matYellowTransparent.opacity = .25;
|
|
2389
|
+
const matYellow = gizmoMaterial.clone();
|
|
2390
|
+
matYellow.color.setHex(16776960);
|
|
2391
|
+
const matGray = gizmoMaterial.clone();
|
|
2392
|
+
matGray.color.setHex(7895160);
|
|
2393
|
+
const arrowGeometry = new CylinderGeometry(0, .04, .1, 12);
|
|
2394
|
+
arrowGeometry.translate(0, .05, 0);
|
|
2395
|
+
const scaleHandleGeometry = new BoxGeometry(.08, .08, .08);
|
|
2396
|
+
scaleHandleGeometry.translate(0, .04, 0);
|
|
2397
|
+
const lineGeometry = new BufferGeometry;
|
|
2398
|
+
lineGeometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 0, 0 ], 3));
|
|
2399
|
+
const lineGeometry2 = new CylinderGeometry(.0075, .0075, .5, 3);
|
|
2400
|
+
lineGeometry2.translate(0, .25, 0);
|
|
2401
|
+
function CircleGeometry(radius, arc) {
|
|
2402
|
+
const geometry = new TorusGeometry(radius, .0075, 3, 64, arc * Math.PI * 2);
|
|
2403
|
+
geometry.rotateY(Math.PI / 2);
|
|
2404
|
+
geometry.rotateX(Math.PI / 2);
|
|
2405
|
+
return geometry;
|
|
2406
|
+
}
|
|
2407
|
+
function TranslateHelperGeometry() {
|
|
2408
|
+
const geometry = new BufferGeometry;
|
|
2409
|
+
geometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 1, 1 ], 3));
|
|
2410
|
+
return geometry;
|
|
2411
|
+
}
|
|
2412
|
+
const gizmoTranslate = {
|
|
2413
|
+
X: [ [ new Mesh(arrowGeometry, matRed), [ .5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(arrowGeometry, matRed), [ -.5, 0, 0 ], [ 0, 0, Math.PI / 2 ] ], [ new Mesh(lineGeometry2, matRed), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] ],
|
|
2414
|
+
Y: [ [ new Mesh(arrowGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(arrowGeometry, matGreen), [ 0, -.5, 0 ], [ Math.PI, 0, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ] ],
|
|
2415
|
+
Z: [ [ new Mesh(arrowGeometry, matBlue), [ 0, 0, .5 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(arrowGeometry, matBlue), [ 0, 0, -.5 ], [ -Math.PI / 2, 0, 0 ] ], [ new Mesh(lineGeometry2, matBlue), null, [ Math.PI / 2, 0, 0 ] ] ],
|
|
2416
|
+
XYZ: [ [ new Mesh(new OctahedronGeometry(.1, 0), matWhiteTransparent.clone()), [ 0, 0, 0 ] ] ],
|
|
2417
|
+
XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent.clone()), [ .15, .15, 0 ] ] ],
|
|
2418
|
+
YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent.clone()), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
2419
|
+
XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent.clone()), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
|
|
2420
|
+
};
|
|
2421
|
+
const pickerTranslate = {
|
|
2422
|
+
X: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ .3, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ -.3, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
|
|
2423
|
+
Y: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, .3, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, -.3, 0 ], [ 0, 0, Math.PI ] ] ],
|
|
2424
|
+
Z: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, .3 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, -.3 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
2425
|
+
XYZ: [ [ new Mesh(new OctahedronGeometry(.2, 0), matInvisible) ] ],
|
|
2426
|
+
XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
|
|
2427
|
+
YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
2428
|
+
XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
|
|
2429
|
+
};
|
|
2430
|
+
const helperTranslate = {
|
|
2431
|
+
START: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
|
|
2432
|
+
END: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
|
|
2433
|
+
DELTA: [ [ new Line(TranslateHelperGeometry(), matHelper), null, null, null, "helper" ] ],
|
|
2434
|
+
X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
|
|
2435
|
+
Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
|
|
2436
|
+
Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
|
|
2437
|
+
};
|
|
2438
|
+
const gizmoRotate = {
|
|
2439
|
+
XYZE: [ [ new Mesh(CircleGeometry(.5, 1), matGray), null, [ 0, Math.PI / 2, 0 ] ] ],
|
|
2440
|
+
X: [ [ new Mesh(CircleGeometry(.5, .5), matRed) ] ],
|
|
2441
|
+
Y: [ [ new Mesh(CircleGeometry(.5, .5), matGreen), null, [ 0, 0, -Math.PI / 2 ] ] ],
|
|
2442
|
+
Z: [ [ new Mesh(CircleGeometry(.5, .5), matBlue), null, [ 0, Math.PI / 2, 0 ] ] ],
|
|
2443
|
+
E: [ [ new Mesh(CircleGeometry(.75, 1), matYellowTransparent), null, [ 0, Math.PI / 2, 0 ] ] ]
|
|
2444
|
+
};
|
|
2445
|
+
const helperRotate = {
|
|
2446
|
+
AXIS: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ]
|
|
2447
|
+
};
|
|
2448
|
+
const pickerRotate = {
|
|
2449
|
+
XYZE: [ [ new Mesh(new SphereGeometry(.25, 10, 8), matInvisible) ] ],
|
|
2450
|
+
X: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ] ],
|
|
2451
|
+
Y: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ] ],
|
|
2452
|
+
Z: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] ],
|
|
2453
|
+
E: [ [ new Mesh(new TorusGeometry(.75, .1, 2, 24), matInvisible) ] ]
|
|
2454
|
+
};
|
|
2455
|
+
const gizmoScale = {
|
|
2456
|
+
X: [ [ new Mesh(scaleHandleGeometry, matRed), [ .5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(lineGeometry2, matRed), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(scaleHandleGeometry, matRed), [ -.5, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
|
|
2457
|
+
Y: [ [ new Mesh(scaleHandleGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ], [ new Mesh(scaleHandleGeometry, matGreen), [ 0, -.5, 0 ], [ 0, 0, Math.PI ] ] ],
|
|
2458
|
+
Z: [ [ new Mesh(scaleHandleGeometry, matBlue), [ 0, 0, .5 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(lineGeometry2, matBlue), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(scaleHandleGeometry, matBlue), [ 0, 0, -.5 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
2459
|
+
XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent), [ .15, .15, 0 ] ] ],
|
|
2460
|
+
YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
2461
|
+
XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
2462
|
+
XYZ: [ [ new Mesh(new BoxGeometry(.1, .1, .1), matWhiteTransparent.clone()) ] ]
|
|
2463
|
+
};
|
|
2464
|
+
const pickerScale = {
|
|
2465
|
+
X: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ .3, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ -.3, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
|
|
2466
|
+
Y: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, .3, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, -.3, 0 ], [ 0, 0, Math.PI ] ] ],
|
|
2467
|
+
Z: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, .3 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, -.3 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
2468
|
+
XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
|
|
2469
|
+
YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
2470
|
+
XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
2471
|
+
XYZ: [ [ new Mesh(new BoxGeometry(.2, .2, .2), matInvisible), [ 0, 0, 0 ] ] ]
|
|
2472
|
+
};
|
|
2473
|
+
const helperScale = {
|
|
2474
|
+
X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
|
|
2475
|
+
Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
|
|
2476
|
+
Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
|
|
2477
|
+
};
|
|
2478
|
+
function setupGizmo(gizmoMap) {
|
|
2479
|
+
const gizmo = new Object3D;
|
|
2480
|
+
for (const name in gizmoMap) {
|
|
2481
|
+
for (let i = gizmoMap[name].length; i--; ) {
|
|
2482
|
+
const object = gizmoMap[name][i][0].clone();
|
|
2483
|
+
const position = gizmoMap[name][i][1];
|
|
2484
|
+
const rotation = gizmoMap[name][i][2];
|
|
2485
|
+
const scale = gizmoMap[name][i][3];
|
|
2486
|
+
const tag = gizmoMap[name][i][4];
|
|
2487
|
+
object.name = name;
|
|
2488
|
+
object.tag = tag;
|
|
2489
|
+
if (position) {
|
|
2490
|
+
object.position.set(position[0], position[1], position[2]);
|
|
2491
|
+
}
|
|
2492
|
+
if (rotation) {
|
|
2493
|
+
object.rotation.set(rotation[0], rotation[1], rotation[2]);
|
|
2494
|
+
}
|
|
2495
|
+
if (scale) {
|
|
2496
|
+
object.scale.set(scale[0], scale[1], scale[2]);
|
|
2497
|
+
}
|
|
2498
|
+
object.updateMatrix();
|
|
2499
|
+
const tempGeometry = object.geometry.clone();
|
|
2500
|
+
tempGeometry.applyMatrix4(object.matrix);
|
|
2501
|
+
object.geometry = tempGeometry;
|
|
2502
|
+
object.renderOrder = Infinity;
|
|
2503
|
+
object.position.set(0, 0, 0);
|
|
2504
|
+
object.rotation.set(0, 0, 0);
|
|
2505
|
+
object.scale.set(1, 1, 1);
|
|
2506
|
+
gizmo.add(object);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
return gizmo;
|
|
2510
|
+
}
|
|
2511
|
+
this.gizmo = {};
|
|
2512
|
+
this.picker = {};
|
|
2513
|
+
this.helper = {};
|
|
2514
|
+
this.add(this.gizmo["translate"] = setupGizmo(gizmoTranslate));
|
|
2515
|
+
this.add(this.gizmo["rotate"] = setupGizmo(gizmoRotate));
|
|
2516
|
+
this.add(this.gizmo["scale"] = setupGizmo(gizmoScale));
|
|
2517
|
+
this.add(this.picker["translate"] = setupGizmo(pickerTranslate));
|
|
2518
|
+
this.add(this.picker["rotate"] = setupGizmo(pickerRotate));
|
|
2519
|
+
this.add(this.picker["scale"] = setupGizmo(pickerScale));
|
|
2520
|
+
this.add(this.helper["translate"] = setupGizmo(helperTranslate));
|
|
2521
|
+
this.add(this.helper["rotate"] = setupGizmo(helperRotate));
|
|
2522
|
+
this.add(this.helper["scale"] = setupGizmo(helperScale));
|
|
2523
|
+
this.picker["translate"].visible = false;
|
|
2524
|
+
this.picker["rotate"].visible = false;
|
|
2525
|
+
this.picker["scale"].visible = false;
|
|
2526
|
+
}
|
|
2527
|
+
updateMatrixWorld(force) {
|
|
2528
|
+
const space = this.mode === "scale" ? "local" : this.space;
|
|
2529
|
+
const quaternion = space === "local" ? this.worldQuaternion : _identityQuaternion;
|
|
2530
|
+
this.gizmo["translate"].visible = this.mode === "translate";
|
|
2531
|
+
this.gizmo["rotate"].visible = this.mode === "rotate";
|
|
2532
|
+
this.gizmo["scale"].visible = this.mode === "scale";
|
|
2533
|
+
this.helper["translate"].visible = this.mode === "translate";
|
|
2534
|
+
this.helper["rotate"].visible = this.mode === "rotate";
|
|
2535
|
+
this.helper["scale"].visible = this.mode === "scale";
|
|
2536
|
+
let handles = [];
|
|
2537
|
+
handles = handles.concat(this.picker[this.mode].children);
|
|
2538
|
+
handles = handles.concat(this.gizmo[this.mode].children);
|
|
2539
|
+
handles = handles.concat(this.helper[this.mode].children);
|
|
2540
|
+
for (let i = 0; i < handles.length; i++) {
|
|
2541
|
+
const handle = handles[i];
|
|
2542
|
+
handle.visible = true;
|
|
2543
|
+
handle.rotation.set(0, 0, 0);
|
|
2544
|
+
handle.position.copy(this.worldPosition);
|
|
2545
|
+
let factor;
|
|
2546
|
+
if (this.camera.isOrthographicCamera) {
|
|
2547
|
+
factor = (this.camera.top - this.camera.bottom) / this.camera.zoom;
|
|
2548
|
+
} else {
|
|
2549
|
+
factor = this.worldPosition.distanceTo(this.cameraPosition) * Math.min(1.9 * Math.tan(Math.PI * this.camera.fov / 360) / this.camera.zoom, 7);
|
|
2550
|
+
}
|
|
2551
|
+
handle.scale.set(1, 1, 1).multiplyScalar(factor * this.size / 4);
|
|
2552
|
+
if (handle.tag === "helper") {
|
|
2553
|
+
handle.visible = false;
|
|
2554
|
+
if (handle.name === "AXIS") {
|
|
2555
|
+
handle.visible = !!this.axis;
|
|
2556
|
+
if (this.axis === "X") {
|
|
2557
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0));
|
|
2558
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
2559
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
2560
|
+
handle.visible = false;
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
if (this.axis === "Y") {
|
|
2564
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, 0, Math.PI / 2));
|
|
2565
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
2566
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
2567
|
+
handle.visible = false;
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
if (this.axis === "Z") {
|
|
2571
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
|
|
2572
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
2573
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
2574
|
+
handle.visible = false;
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
if (this.axis === "XYZE") {
|
|
2578
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
|
|
2579
|
+
_alignVector.copy(this.rotationAxis);
|
|
2580
|
+
handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY));
|
|
2581
|
+
handle.quaternion.multiply(_tempQuaternion);
|
|
2582
|
+
handle.visible = this.dragging;
|
|
2583
|
+
}
|
|
2584
|
+
if (this.axis === "E") {
|
|
2585
|
+
handle.visible = false;
|
|
2586
|
+
}
|
|
2587
|
+
} else if (handle.name === "START") {
|
|
2588
|
+
handle.position.copy(this.worldPositionStart);
|
|
2589
|
+
handle.visible = this.dragging;
|
|
2590
|
+
} else if (handle.name === "END") {
|
|
2591
|
+
handle.position.copy(this.worldPosition);
|
|
2592
|
+
handle.visible = this.dragging;
|
|
2593
|
+
} else if (handle.name === "DELTA") {
|
|
2594
|
+
handle.position.copy(this.worldPositionStart);
|
|
2595
|
+
handle.quaternion.copy(this.worldQuaternionStart);
|
|
2596
|
+
_tempVector.set(1e-10, 1e-10, 1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1);
|
|
2597
|
+
_tempVector.applyQuaternion(this.worldQuaternionStart.clone().invert());
|
|
2598
|
+
handle.scale.copy(_tempVector);
|
|
2599
|
+
handle.visible = this.dragging;
|
|
2600
|
+
} else {
|
|
2601
|
+
handle.quaternion.copy(quaternion);
|
|
2602
|
+
if (this.dragging) {
|
|
2603
|
+
handle.position.copy(this.worldPositionStart);
|
|
2604
|
+
} else {
|
|
2605
|
+
handle.position.copy(this.worldPosition);
|
|
2606
|
+
}
|
|
2607
|
+
if (this.axis) {
|
|
2608
|
+
handle.visible = this.axis.search(handle.name) !== -1;
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
continue;
|
|
2612
|
+
}
|
|
2613
|
+
handle.quaternion.copy(quaternion);
|
|
2614
|
+
if (this.mode === "translate" || this.mode === "scale") {
|
|
2615
|
+
const AXIS_HIDE_THRESHOLD = .99;
|
|
2616
|
+
const PLANE_HIDE_THRESHOLD = .2;
|
|
2617
|
+
if (handle.name === "X") {
|
|
2618
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
2619
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2620
|
+
handle.visible = false;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
if (handle.name === "Y") {
|
|
2624
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
2625
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2626
|
+
handle.visible = false;
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
if (handle.name === "Z") {
|
|
2630
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
2631
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2632
|
+
handle.visible = false;
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
if (handle.name === "XY") {
|
|
2636
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
2637
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2638
|
+
handle.visible = false;
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
if (handle.name === "YZ") {
|
|
2642
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
2643
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2644
|
+
handle.visible = false;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
if (handle.name === "XZ") {
|
|
2648
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
2649
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
2650
|
+
handle.visible = false;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
} else if (this.mode === "rotate") {
|
|
2654
|
+
_tempQuaternion2.copy(quaternion);
|
|
2655
|
+
_alignVector.copy(this.eye).applyQuaternion(_tempQuaternion.copy(quaternion).invert());
|
|
2656
|
+
if (handle.name.search("E") !== -1) {
|
|
2657
|
+
handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY));
|
|
2658
|
+
}
|
|
2659
|
+
if (handle.name === "X") {
|
|
2660
|
+
_tempQuaternion.setFromAxisAngle(_unitX, Math.atan2(-_alignVector.y, _alignVector.z));
|
|
2661
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
2662
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
2663
|
+
}
|
|
2664
|
+
if (handle.name === "Y") {
|
|
2665
|
+
_tempQuaternion.setFromAxisAngle(_unitY, Math.atan2(_alignVector.x, _alignVector.z));
|
|
2666
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
2667
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
2668
|
+
}
|
|
2669
|
+
if (handle.name === "Z") {
|
|
2670
|
+
_tempQuaternion.setFromAxisAngle(_unitZ, Math.atan2(_alignVector.y, _alignVector.x));
|
|
2671
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
2672
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
handle.visible = handle.visible && (handle.name.indexOf("X") === -1 || this.showX);
|
|
2676
|
+
handle.visible = handle.visible && (handle.name.indexOf("Y") === -1 || this.showY);
|
|
2677
|
+
handle.visible = handle.visible && (handle.name.indexOf("Z") === -1 || this.showZ);
|
|
2678
|
+
handle.visible = handle.visible && (handle.name.indexOf("E") === -1 || this.showX && this.showY && this.showZ);
|
|
2679
|
+
handle.material._color = handle.material._color || handle.material.color.clone();
|
|
2680
|
+
handle.material._opacity = handle.material._opacity || handle.material.opacity;
|
|
2681
|
+
handle.material.color.copy(handle.material._color);
|
|
2682
|
+
handle.material.opacity = handle.material._opacity;
|
|
2683
|
+
if (this.enabled && this.axis) {
|
|
2684
|
+
if (handle.name === this.axis) {
|
|
2685
|
+
handle.material.color.setHex(16776960);
|
|
2686
|
+
handle.material.opacity = 1;
|
|
2687
|
+
} else if (this.axis.split("").some((function(a) {
|
|
2688
|
+
return handle.name === a;
|
|
2689
|
+
}))) {
|
|
2690
|
+
handle.material.color.setHex(16776960);
|
|
2691
|
+
handle.material.opacity = 1;
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
super.updateMatrixWorld(force);
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
class TransformControlsPlane extends Mesh {
|
|
2700
|
+
constructor() {
|
|
2701
|
+
super(new PlaneGeometry(1e5, 1e5, 2, 2), new MeshBasicMaterial({
|
|
2702
|
+
visible: false,
|
|
2703
|
+
wireframe: true,
|
|
2704
|
+
side: DoubleSide,
|
|
2705
|
+
transparent: true,
|
|
2706
|
+
opacity: .1,
|
|
2707
|
+
toneMapped: false
|
|
2708
|
+
}));
|
|
2709
|
+
this.isTransformControlsPlane = true;
|
|
2710
|
+
this.type = "TransformControlsPlane";
|
|
2711
|
+
}
|
|
2712
|
+
updateMatrixWorld(force) {
|
|
2713
|
+
let space = this.space;
|
|
2714
|
+
this.position.copy(this.worldPosition);
|
|
2715
|
+
if (this.mode === "scale") space = "local";
|
|
2716
|
+
_v1.copy(_unitX).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
2717
|
+
_v2.copy(_unitY).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
2718
|
+
_v3.copy(_unitZ).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
2719
|
+
_alignVector.copy(_v2);
|
|
2720
|
+
switch (this.mode) {
|
|
2721
|
+
case "translate":
|
|
2722
|
+
case "scale":
|
|
2723
|
+
switch (this.axis) {
|
|
2724
|
+
case "X":
|
|
2725
|
+
_alignVector.copy(this.eye).cross(_v1);
|
|
2726
|
+
_dirVector.copy(_v1).cross(_alignVector);
|
|
2727
|
+
break;
|
|
2728
|
+
|
|
2729
|
+
case "Y":
|
|
2730
|
+
_alignVector.copy(this.eye).cross(_v2);
|
|
2731
|
+
_dirVector.copy(_v2).cross(_alignVector);
|
|
2732
|
+
break;
|
|
2733
|
+
|
|
2734
|
+
case "Z":
|
|
2735
|
+
_alignVector.copy(this.eye).cross(_v3);
|
|
2736
|
+
_dirVector.copy(_v3).cross(_alignVector);
|
|
2737
|
+
break;
|
|
2738
|
+
|
|
2739
|
+
case "XY":
|
|
2740
|
+
_dirVector.copy(_v3);
|
|
2741
|
+
break;
|
|
2742
|
+
|
|
2743
|
+
case "YZ":
|
|
2744
|
+
_dirVector.copy(_v1);
|
|
2745
|
+
break;
|
|
2746
|
+
|
|
2747
|
+
case "XZ":
|
|
2748
|
+
_alignVector.copy(_v3);
|
|
2749
|
+
_dirVector.copy(_v2);
|
|
2750
|
+
break;
|
|
2751
|
+
|
|
2752
|
+
case "XYZ":
|
|
2753
|
+
case "E":
|
|
2754
|
+
_dirVector.set(0, 0, 0);
|
|
2755
|
+
break;
|
|
2756
|
+
}
|
|
2757
|
+
break;
|
|
2758
|
+
|
|
2759
|
+
case "rotate":
|
|
2760
|
+
default:
|
|
2761
|
+
_dirVector.set(0, 0, 0);
|
|
2762
|
+
}
|
|
2763
|
+
if (_dirVector.length() === 0) {
|
|
2764
|
+
this.quaternion.copy(this.cameraQuaternion);
|
|
2765
|
+
} else {
|
|
2766
|
+
_tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector);
|
|
2767
|
+
this.quaternion.setFromRotationMatrix(_tempMatrix);
|
|
2768
|
+
}
|
|
2769
|
+
super.updateMatrixWorld(force);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
class PlaneHelper extends Line {
|
|
2774
|
+
constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
|
|
2775
|
+
const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
|
|
2776
|
+
const geometry = new BufferGeometry;
|
|
2777
|
+
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
2778
|
+
geometry.computeBoundingSphere();
|
|
2779
|
+
super(geometry, new LineBasicMaterial({
|
|
2780
|
+
color: color,
|
|
2781
|
+
toneMapped: false
|
|
2782
|
+
}));
|
|
2783
|
+
this.type = "PlaneHelper";
|
|
2784
|
+
this.plane = plane;
|
|
2785
|
+
this.size = size;
|
|
2786
|
+
this.offset = offset;
|
|
2787
|
+
const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
|
|
2788
|
+
const geometry2 = new BufferGeometry;
|
|
2789
|
+
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
2790
|
+
geometry2.computeBoundingSphere();
|
|
2791
|
+
this.helper = new Mesh(geometry2, new MeshBasicMaterial({
|
|
2792
|
+
color: color,
|
|
2793
|
+
opacity: .2,
|
|
2794
|
+
transparent: true,
|
|
2795
|
+
depthWrite: false,
|
|
2796
|
+
toneMapped: false,
|
|
2797
|
+
side: DoubleSide
|
|
2798
|
+
}));
|
|
2799
|
+
this.add(this.helper);
|
|
2800
|
+
}
|
|
2801
|
+
dispose() {
|
|
2802
|
+
this.geometry.dispose();
|
|
2803
|
+
this.material.dispose();
|
|
2804
|
+
this.children[0].geometry.dispose();
|
|
2805
|
+
this.children[0].material.dispose();
|
|
2806
|
+
}
|
|
2807
|
+
updateMatrixWorld(force) {
|
|
2808
|
+
this.position.set(0, 0, 0);
|
|
2809
|
+
this.lookAt(this.plane.normal);
|
|
2810
|
+
this.position.copy(this.offset);
|
|
2811
|
+
this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
|
|
2812
|
+
this.scale.set(.5 * this.size, .5 * this.size, 1);
|
|
2813
|
+
super.updateMatrixWorld(force);
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
class CuttingPlaneDragger extends OrbitDragger {
|
|
2818
|
+
constructor(viewer, normal, color) {
|
|
2819
|
+
super(viewer);
|
|
2820
|
+
this.transformChange = () => {
|
|
2821
|
+
this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
|
|
2822
|
+
this.viewer.update();
|
|
2823
|
+
};
|
|
2824
|
+
this.transformDrag = event => {
|
|
2825
|
+
this.orbit.enabled = !event.value;
|
|
2826
|
+
};
|
|
2827
|
+
this.viewerExplode = () => {
|
|
2828
|
+
this.planeHelper.size = this.viewer.extents.getSize(new Vector3).length();
|
|
2829
|
+
this.viewer.update();
|
|
2830
|
+
};
|
|
2831
|
+
this.onDoubleClick = event => {
|
|
2832
|
+
event.stopPropagation();
|
|
2833
|
+
this.plane.negate();
|
|
2834
|
+
this.viewer.update();
|
|
2835
|
+
};
|
|
2836
|
+
const size = viewer.extents.getSize(new Vector3).length();
|
|
2837
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
2838
|
+
const constant = -center.dot(normal);
|
|
2839
|
+
this.plane = new Plane(normal, constant);
|
|
2840
|
+
if (!viewer.renderer.clippingPlanes) viewer.renderer.clippingPlanes = [];
|
|
2841
|
+
viewer.renderer.clippingPlanes.push(this.plane);
|
|
2842
|
+
this.planeHelper = new PlaneHelper(this.plane, size, color, center);
|
|
2843
|
+
this.viewer.helpers.add(this.planeHelper);
|
|
2844
|
+
this.planeCenter = new Object3D;
|
|
2845
|
+
this.planeCenter.position.copy(viewer.extents.getCenter(new Vector3));
|
|
2846
|
+
this.viewer.helpers.add(this.planeCenter);
|
|
2847
|
+
this.transform = new TransformControls(viewer.camera, viewer.canvas);
|
|
2848
|
+
this.transform.showX = !!normal.x;
|
|
2849
|
+
this.transform.showY = !!normal.y;
|
|
2850
|
+
this.transform.showZ = !!normal.z;
|
|
2851
|
+
this.transform.attach(this.planeCenter);
|
|
2852
|
+
this.transform.addEventListener("change", this.transformChange);
|
|
2853
|
+
this.transform.addEventListener("dragging-changed", this.transformDrag);
|
|
2854
|
+
this.viewer.helpers.add(this.transform);
|
|
2855
|
+
this.viewer.on("explode", this.viewerExplode);
|
|
2856
|
+
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
2857
|
+
this.viewer.update();
|
|
2858
|
+
}
|
|
2859
|
+
dispose() {
|
|
2860
|
+
this.viewer.off("explode", this.viewerExplode);
|
|
2861
|
+
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
2862
|
+
this.transform.removeEventListener("change", this.transformChange);
|
|
2863
|
+
this.transform.removeEventListener("dragging-changed", this.transformDrag);
|
|
2864
|
+
this.transform.removeFromParent();
|
|
2865
|
+
this.transform.dispose();
|
|
748
2866
|
this.planeHelper.removeFromParent();
|
|
2867
|
+
this.planeHelper.dispose();
|
|
2868
|
+
this.planeCenter.removeFromParent();
|
|
2869
|
+
super.dispose();
|
|
749
2870
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
2874
|
+
constructor(viewer) {
|
|
2875
|
+
super(viewer, new Vector3(1, 0, 0), 16711680);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
2880
|
+
constructor(viewer) {
|
|
2881
|
+
super(viewer, new Vector3(0, 1, 0), 65280);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
2886
|
+
constructor(viewer) {
|
|
2887
|
+
super(viewer, new Vector3(0, 0, 1), 255);
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
class ExtentsComponent {
|
|
2892
|
+
constructor(viewer) {
|
|
2893
|
+
this.syncExtents = () => {
|
|
2894
|
+
const extents = this.viewer.models.reduce(((result, gltf) => {
|
|
2895
|
+
const modelExtents = (new Box3).setFromObject(gltf.scene);
|
|
2896
|
+
return result.isEmpty() ? result.copy(modelExtents) : result.union(modelExtents);
|
|
2897
|
+
}), new Box3);
|
|
2898
|
+
this.viewer.extents.copy(extents);
|
|
2899
|
+
this.viewer.target.copy(extents.getCenter(new Vector3));
|
|
2900
|
+
};
|
|
2901
|
+
this.viewer = viewer;
|
|
2902
|
+
this.viewer.addEventListener("geometryend", this.syncExtents);
|
|
2903
|
+
this.viewer.addEventListener("clear", this.syncExtents);
|
|
2904
|
+
this.viewer.on("explode", this.syncExtents);
|
|
2905
|
+
}
|
|
2906
|
+
dispose() {
|
|
2907
|
+
this.viewer.removeEventListener("geometryend", this.syncExtents);
|
|
2908
|
+
this.viewer.removeEventListener("clear", this.syncExtents);
|
|
2909
|
+
this.viewer.off("explode", this.syncExtents);
|
|
768
2910
|
}
|
|
769
2911
|
}
|
|
770
2912
|
|
|
771
2913
|
class LightComponent {
|
|
772
2914
|
constructor(viewer) {
|
|
773
2915
|
this.viewer = viewer;
|
|
774
|
-
this.ambientLight = new
|
|
2916
|
+
this.ambientLight = new AmbientLight(16777215, 0);
|
|
775
2917
|
this.viewer.camera.add(this.ambientLight);
|
|
776
|
-
this.
|
|
777
|
-
this.
|
|
778
|
-
this.viewer.camera.add(this.
|
|
2918
|
+
this.directionalLight = new DirectionalLight(16777215, 1);
|
|
2919
|
+
this.directionalLight.position.set(.5, 0, .866);
|
|
2920
|
+
this.viewer.camera.add(this.directionalLight);
|
|
779
2921
|
}
|
|
780
2922
|
dispose() {
|
|
781
2923
|
this.ambientLight.removeFromParent();
|
|
782
|
-
this.
|
|
2924
|
+
this.ambientLight = undefined;
|
|
2925
|
+
this.directionalLight.removeFromParent();
|
|
2926
|
+
this.directionalLight = undefined;
|
|
783
2927
|
}
|
|
784
2928
|
}
|
|
785
2929
|
|
|
@@ -789,9 +2933,10 @@ class BackgroundComponent {
|
|
|
789
2933
|
this.backgroundColor.setHex(16777215);
|
|
790
2934
|
};
|
|
791
2935
|
this.viewer = viewer;
|
|
792
|
-
this.backgroundColor = new
|
|
2936
|
+
this.backgroundColor = new Color(16777215);
|
|
793
2937
|
const environment = new RoomEnvironment;
|
|
794
|
-
const pmremGenerator = new
|
|
2938
|
+
const pmremGenerator = new PMREMGenerator(this.viewer.renderer);
|
|
2939
|
+
this.viewer.renderer.setClearColor(this.backgroundColor);
|
|
795
2940
|
this.viewer.scene.background = this.backgroundColor;
|
|
796
2941
|
this.viewer.scene.environment = pmremGenerator.fromScene(environment).texture;
|
|
797
2942
|
this.viewer.addEventListener("optionschange", this.syncOptions);
|
|
@@ -804,26 +2949,16 @@ class BackgroundComponent {
|
|
|
804
2949
|
}
|
|
805
2950
|
}
|
|
806
2951
|
|
|
807
|
-
class
|
|
2952
|
+
class DefaultPositionComponent {
|
|
808
2953
|
constructor(viewer) {
|
|
809
2954
|
this.geometryEnd = event => {
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
const box = (new THREE.Box3).setFromObject(scene);
|
|
813
|
-
const size = box.getSize(new THREE.Vector3).length();
|
|
814
|
-
const center = box.getCenter(new THREE.Vector3);
|
|
815
|
-
scene.position.x += scene.position.x - center.x;
|
|
816
|
-
scene.position.y += scene.position.y - center.y;
|
|
817
|
-
scene.position.z += scene.position.z - center.z;
|
|
2955
|
+
const box = this.viewer.extents;
|
|
2956
|
+
const size = box.getSize(new Vector3).length();
|
|
818
2957
|
this.viewer.camera.near = size / 100;
|
|
819
2958
|
this.viewer.camera.far = size * 100;
|
|
820
|
-
this.viewer.camera.position.copy(center);
|
|
821
|
-
this.viewer.camera.position.x += size / 2;
|
|
822
|
-
this.viewer.camera.position.y += size / 5;
|
|
823
|
-
this.viewer.camera.position.z += size / 2;
|
|
824
2959
|
this.viewer.camera.updateMatrixWorld();
|
|
825
2960
|
this.viewer.camera.updateProjectionMatrix();
|
|
826
|
-
this.viewer.
|
|
2961
|
+
this.viewer.executeCommand("zoomToExtents");
|
|
827
2962
|
};
|
|
828
2963
|
this.viewer = viewer;
|
|
829
2964
|
this.viewer.addEventListener("geometryend", this.geometryEnd);
|
|
@@ -859,38 +2994,136 @@ class ResizeCanvasComponent {
|
|
|
859
2994
|
|
|
860
2995
|
class RenderLoopComponent {
|
|
861
2996
|
constructor(viewer) {
|
|
862
|
-
this.requestID = 0;
|
|
863
2997
|
this.animate = (time = 0) => {
|
|
864
|
-
this.
|
|
2998
|
+
this.requestId = requestAnimationFrame(this.animate);
|
|
865
2999
|
this.viewer.render(time);
|
|
866
3000
|
};
|
|
867
3001
|
this.viewer = viewer;
|
|
868
3002
|
this.animate();
|
|
869
3003
|
}
|
|
870
3004
|
dispose() {
|
|
871
|
-
cancelAnimationFrame(this.
|
|
3005
|
+
cancelAnimationFrame(this.requestId);
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
class WCSHelper extends Object3D {
|
|
3010
|
+
constructor(camera) {
|
|
3011
|
+
super();
|
|
3012
|
+
this.camera = camera;
|
|
3013
|
+
this.size = 160;
|
|
3014
|
+
this.orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
|
|
3015
|
+
this.orthoCamera.position.set(0, 0, 2);
|
|
3016
|
+
const matRed = new MeshBasicMaterial({
|
|
3017
|
+
toneMapped: false,
|
|
3018
|
+
color: "#aa0000"
|
|
3019
|
+
});
|
|
3020
|
+
const matGreen = new MeshBasicMaterial({
|
|
3021
|
+
toneMapped: false,
|
|
3022
|
+
color: "#00aa00"
|
|
3023
|
+
});
|
|
3024
|
+
const matBlue = new MeshBasicMaterial({
|
|
3025
|
+
toneMapped: false,
|
|
3026
|
+
color: "#0000aa"
|
|
3027
|
+
});
|
|
3028
|
+
const spriteRed = this.getSpriteMaterial(matRed.color, "X");
|
|
3029
|
+
const spriteGreen = this.getSpriteMaterial(matGreen.color, "Y");
|
|
3030
|
+
const spriteBlue = this.getSpriteMaterial(matBlue.color, "Z");
|
|
3031
|
+
const lineGeometry = new CylinderGeometry(.01, .01, 1, 3);
|
|
3032
|
+
lineGeometry.translate(0, .5, 0);
|
|
3033
|
+
const arrowGeometry = new CylinderGeometry(0, .1, .25, 12);
|
|
3034
|
+
arrowGeometry.translate(0, .625, 0);
|
|
3035
|
+
const axesMap = {
|
|
3036
|
+
X: [ [ new Mesh(arrowGeometry, matRed), [ .5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(lineGeometry, matRed), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Sprite(spriteRed), [ 1.55, 0, 0 ] ] ],
|
|
3037
|
+
Y: [ [ new Mesh(arrowGeometry, matGreen), [ 0, .5, 0 ], null ], [ new Mesh(lineGeometry, matGreen), null, null ], [ new Sprite(spriteGreen), [ 0, 1.55, 0 ] ] ],
|
|
3038
|
+
Z: [ [ new Mesh(arrowGeometry, matBlue), [ 0, 0, .5 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(lineGeometry, matBlue), null, [ Math.PI / 2, 0, 0 ] ], [ new Sprite(spriteBlue), [ 0, 0, 1.55 ] ] ]
|
|
3039
|
+
};
|
|
3040
|
+
Object.keys(axesMap).forEach((key => {
|
|
3041
|
+
axesMap[key].forEach((objects => {
|
|
3042
|
+
const object = objects[0];
|
|
3043
|
+
const position = objects[1];
|
|
3044
|
+
const rotation = objects[2];
|
|
3045
|
+
object.name = key;
|
|
3046
|
+
if (position) object.position.set(position[0], position[1], position[2]);
|
|
3047
|
+
if (rotation) object.rotation.set(rotation[0], rotation[1], rotation[2]);
|
|
3048
|
+
object.updateMatrixWorld();
|
|
3049
|
+
this.add(object);
|
|
3050
|
+
}));
|
|
3051
|
+
}));
|
|
3052
|
+
}
|
|
3053
|
+
dispose() {
|
|
3054
|
+
this.traverse((object => {
|
|
3055
|
+
if (object.geometry) object.geometry.dispose();
|
|
3056
|
+
if (object.material) object.material.dispose();
|
|
3057
|
+
}));
|
|
3058
|
+
}
|
|
3059
|
+
getSpriteMaterial(color, text) {
|
|
3060
|
+
const canvas = document.createElement("canvas");
|
|
3061
|
+
canvas.width = 64;
|
|
3062
|
+
canvas.height = 64;
|
|
3063
|
+
const context = canvas.getContext("2d");
|
|
3064
|
+
context.clearRect(0, 0, 64, 64);
|
|
3065
|
+
context.font = "24px Arial";
|
|
3066
|
+
context.textAlign = "center";
|
|
3067
|
+
context.fillStyle = color.getStyle();
|
|
3068
|
+
context.fillText(text, 32, 41);
|
|
3069
|
+
const texture = new CanvasTexture(canvas);
|
|
3070
|
+
texture.colorSpace = SRGBColorSpace;
|
|
3071
|
+
return new SpriteMaterial({
|
|
3072
|
+
map: texture,
|
|
3073
|
+
toneMapped: false
|
|
3074
|
+
});
|
|
3075
|
+
}
|
|
3076
|
+
render(renderer) {
|
|
3077
|
+
this.quaternion.copy(this.camera.quaternion).invert();
|
|
3078
|
+
this.updateMatrixWorld();
|
|
3079
|
+
const clippingPlanes = renderer.clippingPlanes;
|
|
3080
|
+
const viewport = renderer.getViewport(new Vector4);
|
|
3081
|
+
renderer.setViewport(this.position.x, this.position.y, this.size, this.size);
|
|
3082
|
+
renderer.clippingPlanes = [];
|
|
3083
|
+
renderer.clearDepth();
|
|
3084
|
+
renderer.render(this, this.orthoCamera);
|
|
3085
|
+
renderer.setViewport(viewport);
|
|
3086
|
+
renderer.clippingPlanes = clippingPlanes;
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3090
|
+
class WCSHelperComponent {
|
|
3091
|
+
constructor(viewer) {
|
|
3092
|
+
this.viewerRender = () => {
|
|
3093
|
+
if (!this.viewer.extents.isEmpty()) this.wcsHelper.render(this.viewer.renderer);
|
|
3094
|
+
};
|
|
3095
|
+
this.wcsHelper = new WCSHelper(viewer.camera);
|
|
3096
|
+
this.viewer = viewer;
|
|
3097
|
+
this.viewer.addEventListener("render", this.viewerRender);
|
|
3098
|
+
}
|
|
3099
|
+
dispose() {
|
|
3100
|
+
this.viewer.removeEventListener("render", this.viewerRender);
|
|
3101
|
+
this.wcsHelper.dispose();
|
|
872
3102
|
}
|
|
873
3103
|
}
|
|
874
3104
|
|
|
875
3105
|
class Viewer extends EventEmitter2 {
|
|
876
3106
|
constructor(client) {
|
|
877
3107
|
super();
|
|
878
|
-
this.renderNeeded = false;
|
|
879
3108
|
this._options = new Options(this);
|
|
880
3109
|
this.client = client;
|
|
881
|
-
this.canvasEvents = CANVAS_EVENTS
|
|
3110
|
+
this.canvasEvents = CANVAS_EVENTS;
|
|
882
3111
|
this.canvaseventlistener = event => this.emit(event);
|
|
3112
|
+
this.extents = new Box3;
|
|
3113
|
+
this.target = new Vector3;
|
|
883
3114
|
this.draggerFactory = {
|
|
884
3115
|
Pan: PanDragger,
|
|
885
3116
|
Zoom: ZoomDragger,
|
|
886
3117
|
Orbit: OrbitDragger,
|
|
887
3118
|
Walk: WalkDragger,
|
|
888
|
-
|
|
3119
|
+
CuttingPlaneXAxis: CuttingPlaneXAxisDragger,
|
|
3120
|
+
CuttingPlaneYAxis: CuttingPlaneYAxisDragger,
|
|
3121
|
+
CuttingPlaneZAxis: CuttingPlaneZAxisDragger
|
|
889
3122
|
};
|
|
890
3123
|
this._activeDragger = null;
|
|
891
3124
|
this.models = [];
|
|
892
3125
|
this.components = [];
|
|
893
|
-
this.
|
|
3126
|
+
this.selected = [];
|
|
894
3127
|
this.renderTime = 0;
|
|
895
3128
|
this.render = this.render.bind(this);
|
|
896
3129
|
this.update = this.update.bind(this);
|
|
@@ -903,30 +3136,35 @@ class Viewer extends EventEmitter2 {
|
|
|
903
3136
|
}
|
|
904
3137
|
initialize(canvas, onProgress) {
|
|
905
3138
|
this.addEventListener("optionschange", (event => this.syncOptions(event.data)));
|
|
906
|
-
this.scene = new
|
|
3139
|
+
this.scene = new Scene;
|
|
3140
|
+
this.helpers = new Scene;
|
|
907
3141
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
908
3142
|
const width = rect.width || 1;
|
|
909
3143
|
const height = rect.height || 1;
|
|
910
|
-
this.camera = new
|
|
3144
|
+
this.camera = new PerspectiveCamera(45, width / height, .01, 1e3);
|
|
911
3145
|
this.camera.up.set(0, 0, 1);
|
|
912
|
-
this.renderer = new
|
|
3146
|
+
this.renderer = new WebGLRenderer({
|
|
913
3147
|
canvas: canvas,
|
|
914
|
-
antialias: true
|
|
3148
|
+
antialias: true,
|
|
3149
|
+
preserveDrawingBuffer: true
|
|
915
3150
|
});
|
|
916
3151
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
917
3152
|
this.renderer.setSize(width, height);
|
|
918
|
-
this.renderer.toneMapping =
|
|
3153
|
+
this.renderer.toneMapping = LinearToneMapping;
|
|
919
3154
|
this.canvas = canvas;
|
|
920
3155
|
this.canvasEvents.forEach((x => canvas.addEventListener(x, this.canvaseventlistener)));
|
|
3156
|
+
this.components.push(new ExtentsComponent(this));
|
|
921
3157
|
this.components.push(new LightComponent(this));
|
|
922
3158
|
this.components.push(new BackgroundComponent(this));
|
|
923
|
-
this.components.push(new
|
|
3159
|
+
this.components.push(new DefaultPositionComponent(this));
|
|
924
3160
|
this.components.push(new ResizeCanvasComponent(this));
|
|
925
3161
|
this.components.push(new RenderLoopComponent(this));
|
|
3162
|
+
this.components.push(new SelectionComponent(this));
|
|
3163
|
+
this.components.push(new WCSHelperComponent(this));
|
|
926
3164
|
this.syncOptions();
|
|
927
3165
|
this.renderTime = performance.now();
|
|
928
3166
|
this.render(this.renderTime);
|
|
929
|
-
if (onProgress) onProgress(new ProgressEvent("progress", {
|
|
3167
|
+
if (typeof onProgress === "function") onProgress(new ProgressEvent("progress", {
|
|
930
3168
|
lengthComputable: true,
|
|
931
3169
|
loaded: 1,
|
|
932
3170
|
total: 1
|
|
@@ -951,6 +3189,7 @@ class Viewer extends EventEmitter2 {
|
|
|
951
3189
|
this.components = [];
|
|
952
3190
|
this.setActiveDragger("");
|
|
953
3191
|
this.removeAllListeners();
|
|
3192
|
+
this.clear();
|
|
954
3193
|
if (this.canvas) {
|
|
955
3194
|
this.canvasEvents.forEach((x => this.canvas.removeEventListener(x, this.canvaseventlistener)));
|
|
956
3195
|
this.canvas = undefined;
|
|
@@ -959,6 +3198,7 @@ class Viewer extends EventEmitter2 {
|
|
|
959
3198
|
this.renderer = undefined;
|
|
960
3199
|
this.camera = undefined;
|
|
961
3200
|
this.scene = undefined;
|
|
3201
|
+
this.helpers = undefined;
|
|
962
3202
|
return this;
|
|
963
3203
|
}
|
|
964
3204
|
isInitialized() {
|
|
@@ -967,10 +3207,15 @@ class Viewer extends EventEmitter2 {
|
|
|
967
3207
|
render(time) {
|
|
968
3208
|
if (!this.renderNeeded) return;
|
|
969
3209
|
if (!this.renderer) return;
|
|
970
|
-
if (!this.scene) return;
|
|
971
|
-
if (!this.camera) return;
|
|
972
|
-
this.renderer.render(this.scene, this.camera);
|
|
973
3210
|
this.renderNeeded = false;
|
|
3211
|
+
this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
|
|
3212
|
+
this.renderer.autoClear = true;
|
|
3213
|
+
this.renderer.render(this.scene, this.camera);
|
|
3214
|
+
const clippingPlanes = this.renderer.clippingPlanes;
|
|
3215
|
+
this.renderer.clippingPlanes = [];
|
|
3216
|
+
this.renderer.autoClear = false;
|
|
3217
|
+
this.renderer.render(this.helpers, this.camera);
|
|
3218
|
+
this.renderer.clippingPlanes = clippingPlanes;
|
|
974
3219
|
const deltaTime = (time - this.renderTime) / 1e3;
|
|
975
3220
|
this.renderTime = time;
|
|
976
3221
|
this.emitEvent({
|
|
@@ -1055,6 +3300,7 @@ class Viewer extends EventEmitter2 {
|
|
|
1055
3300
|
this.models.push(gltf);
|
|
1056
3301
|
this.scene.add(gltf.scene);
|
|
1057
3302
|
this.update();
|
|
3303
|
+
this.resetActiveDragger();
|
|
1058
3304
|
this.emitEvent({
|
|
1059
3305
|
type: "databasechunk"
|
|
1060
3306
|
});
|
|
@@ -1074,6 +3320,7 @@ class Viewer extends EventEmitter2 {
|
|
|
1074
3320
|
return this;
|
|
1075
3321
|
}
|
|
1076
3322
|
clear() {
|
|
3323
|
+
if (!this.renderer) return this;
|
|
1077
3324
|
function disposeMaterial(material) {
|
|
1078
3325
|
const materials = Array.isArray(material) ? material : [ material ];
|
|
1079
3326
|
materials.forEach((material => {
|
|
@@ -1084,49 +3331,97 @@ class Viewer extends EventEmitter2 {
|
|
|
1084
3331
|
if (object.geometry) object.geometry.dispose();
|
|
1085
3332
|
if (object.material) disposeMaterial(object.material);
|
|
1086
3333
|
}
|
|
1087
|
-
this.
|
|
3334
|
+
this.setActiveDragger();
|
|
3335
|
+
this.selected = [];
|
|
3336
|
+
this.renderer.clippingPlanes = [];
|
|
3337
|
+
this.helpers.traverse(disposeObject);
|
|
3338
|
+
this.helpers.clear();
|
|
1088
3339
|
this.models.forEach((gltf => gltf.scene.traverse(disposeObject)));
|
|
1089
3340
|
this.models.forEach((gltf => gltf.scene.removeFromParent()));
|
|
1090
3341
|
this.models = [];
|
|
1091
|
-
this.
|
|
3342
|
+
this.scene.clear();
|
|
1092
3343
|
this.emitEvent({
|
|
1093
3344
|
type: "clear"
|
|
1094
3345
|
});
|
|
3346
|
+
this.update(true);
|
|
1095
3347
|
return this;
|
|
1096
3348
|
}
|
|
3349
|
+
getSelected() {
|
|
3350
|
+
return this.executeCommand("getSelected");
|
|
3351
|
+
}
|
|
3352
|
+
setSelected(handles) {
|
|
3353
|
+
this.executeCommand("setSelected", handles);
|
|
3354
|
+
}
|
|
3355
|
+
clearSelected() {
|
|
3356
|
+
this.executeCommand("clearSelected");
|
|
3357
|
+
}
|
|
3358
|
+
hideSelected() {
|
|
3359
|
+
this.executeCommand("hideSelected");
|
|
3360
|
+
}
|
|
3361
|
+
isolateSelected() {
|
|
3362
|
+
this.executeCommand("isolateSelected");
|
|
3363
|
+
}
|
|
3364
|
+
showAll() {
|
|
3365
|
+
this.executeCommand("showAll");
|
|
3366
|
+
}
|
|
3367
|
+
explode(index = 0) {
|
|
3368
|
+
this.executeCommand("explode", index);
|
|
3369
|
+
}
|
|
3370
|
+
collect() {
|
|
3371
|
+
this.executeCommand("collect");
|
|
3372
|
+
}
|
|
1097
3373
|
activeDragger() {
|
|
1098
3374
|
return this._activeDragger;
|
|
1099
3375
|
}
|
|
1100
|
-
setActiveDragger(name) {
|
|
3376
|
+
setActiveDragger(name = "") {
|
|
1101
3377
|
if (!this._activeDragger || this._activeDragger.name !== name) {
|
|
1102
3378
|
if (this._activeDragger) {
|
|
1103
3379
|
this._activeDragger.dispose();
|
|
1104
3380
|
this._activeDragger = null;
|
|
1105
3381
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
3382
|
+
if (this.isInitialized()) {
|
|
3383
|
+
const Constructor = this.draggerFactory[name];
|
|
3384
|
+
if (Constructor) {
|
|
3385
|
+
this._activeDragger = new Constructor(this);
|
|
3386
|
+
this._activeDragger.name = name;
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
const canvas = this.canvas;
|
|
3390
|
+
if (canvas) {
|
|
3391
|
+
canvas.className = canvas.className.split(" ").filter((x => !x.startsWith("oda-cursor-"))).filter((x => x)).concat(`oda-cursor-${name.toLowerCase()}`).join(" ");
|
|
1110
3392
|
}
|
|
3393
|
+
this.emitEvent({
|
|
3394
|
+
type: "changeactivedragger",
|
|
3395
|
+
data: name
|
|
3396
|
+
});
|
|
1111
3397
|
}
|
|
1112
3398
|
return this._activeDragger;
|
|
1113
3399
|
}
|
|
1114
3400
|
resetActiveDragger() {
|
|
1115
3401
|
const dragger = this._activeDragger;
|
|
1116
3402
|
if (dragger) {
|
|
1117
|
-
this.setActiveDragger(
|
|
3403
|
+
this.setActiveDragger();
|
|
1118
3404
|
this.setActiveDragger(dragger.name);
|
|
1119
3405
|
}
|
|
1120
3406
|
}
|
|
1121
3407
|
is3D() {
|
|
1122
|
-
return
|
|
3408
|
+
return true;
|
|
1123
3409
|
}
|
|
1124
3410
|
executeCommand(id, ...args) {
|
|
1125
3411
|
return commands("ThreeJS").executeCommand(id, this, ...args);
|
|
1126
3412
|
}
|
|
3413
|
+
getComponent(type) {
|
|
3414
|
+
return this.components.find((component => component instanceof type));
|
|
3415
|
+
}
|
|
1127
3416
|
drawViewpoint(viewpoint) {}
|
|
1128
3417
|
createViewpoint() {
|
|
1129
|
-
|
|
3418
|
+
var _a;
|
|
3419
|
+
const viewpoint = {};
|
|
3420
|
+
viewpoint.snapshot = {
|
|
3421
|
+
data: (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.toDataURL("image/jpeg", .25)
|
|
3422
|
+
};
|
|
3423
|
+
viewpoint.description = (new Date).toDateString();
|
|
3424
|
+
return viewpoint;
|
|
1130
3425
|
}
|
|
1131
3426
|
}
|
|
1132
3427
|
|