@inweb/viewer-three 25.9.7 → 25.10.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 +10315 -6179
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -2
- package/dist/viewer-three.module.js +1881 -322
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/IDisposable.d.ts +6 -0
- package/lib/Viewer/Viewer.d.ts +113 -14
- package/lib/Viewer/commands/ApplyModelTransform.d.ts +1 -0
- package/lib/Viewer/commands/ClearMarkup.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/Unselect.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 +9 -5
- 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 +7 -6
- package/src/Viewer/IDisposable.ts +29 -0
- package/src/Viewer/Viewer.ts +218 -49
- package/src/Viewer/commands/ApplyModelTransform.ts +33 -0
- package/src/Viewer/commands/ClearMarkup.ts +29 -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/Unselect.ts +37 -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/WalkControls.ts +221 -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 +47 -22
- 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,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Box3, Vector3, Sphere, Vector2, Raycaster, MeshBasicMaterial, LoadingManager, LoaderUtils, MOUSE, TOUCH, EventDispatcher, Clock, Quaternion, 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
|
|
|
@@ -380,6 +380,478 @@ class Dragger {
|
|
|
380
380
|
updatePreview() {}
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
function applyModelTransform(viewer, model) {
|
|
384
|
+
console.warn("applyModelTransform not implemented");
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
commands("ThreeJS").registerCommand("applyModelTransform", applyModelTransform);
|
|
388
|
+
|
|
389
|
+
commands("ThreeJS").registerCommand("clearMarkup", (viewer => console.warn("clearMarkup not implemented")));
|
|
390
|
+
|
|
391
|
+
commands("ThreeJS").registerCommandAlias("clearMarkup", "clearOverlay");
|
|
392
|
+
|
|
393
|
+
function clearSlices(viewer) {
|
|
394
|
+
viewer.renderer.clippingPlanes = [];
|
|
395
|
+
viewer.update();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
commands("ThreeJS").registerCommand("clearSlices", clearSlices);
|
|
399
|
+
|
|
400
|
+
function createPreview(viewer, type = "image/jpeg", encoderOptions = .25) {
|
|
401
|
+
viewer.update(true);
|
|
402
|
+
return viewer.canvas.toDataURL(type, encoderOptions);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
commands("ThreeJS").registerCommand("createPreview", createPreview);
|
|
406
|
+
|
|
407
|
+
function calcObjectDepth(object, depth) {
|
|
408
|
+
let res = depth;
|
|
409
|
+
object.children.forEach((x => {
|
|
410
|
+
const objectDepth = calcObjectDepth(x, depth + 1);
|
|
411
|
+
if (res < objectDepth) res = objectDepth;
|
|
412
|
+
}));
|
|
413
|
+
object.originalPosition = object.position.clone();
|
|
414
|
+
return res;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function explodeScene(scene, scale = 0) {
|
|
418
|
+
scale /= 100;
|
|
419
|
+
if (!scene.maxDepth) scene.maxDepth = calcObjectDepth(scene, 1);
|
|
420
|
+
const maxDepth = scene.maxDepth;
|
|
421
|
+
let explodeDepth = scale * (maxDepth - 1) + 1;
|
|
422
|
+
if (maxDepth === 1) explodeDepth = 1;
|
|
423
|
+
function explodeObject(object, depth, parentCenter, parentOffset) {
|
|
424
|
+
const objectBox = (new Box3).setFromObject(object);
|
|
425
|
+
const objectCenter = objectBox.getCenter(new Vector3);
|
|
426
|
+
const objectOffset = parentOffset.clone();
|
|
427
|
+
if (depth > 0 && depth <= explodeDepth) {
|
|
428
|
+
const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
|
|
429
|
+
objectOffset.add(offset);
|
|
430
|
+
}
|
|
431
|
+
object.children.forEach((object => explodeObject(object, depth + 1, objectCenter, objectOffset)));
|
|
432
|
+
const originalPosition = object.originalPosition;
|
|
433
|
+
object.position.copy(originalPosition);
|
|
434
|
+
if (scale > 0) {
|
|
435
|
+
const direction = objectCenter.sub(parentCenter).normalize();
|
|
436
|
+
object.position.add(direction.add(objectOffset));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const sceneExtents = (new Box3).setFromObject(scene);
|
|
440
|
+
const sceneCenter = sceneExtents.getCenter(new Vector3);
|
|
441
|
+
explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function explode(viewer, index = 0) {
|
|
445
|
+
viewer.models.forEach((gltf => explodeScene(gltf.scene, index)));
|
|
446
|
+
viewer.update();
|
|
447
|
+
viewer.emit({
|
|
448
|
+
type: "explode",
|
|
449
|
+
data: index
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
commands("ThreeJS").registerCommand("explode", explode);
|
|
454
|
+
|
|
455
|
+
commands("ThreeJS").registerCommand("collect", (viewer => explode(viewer, 0)));
|
|
456
|
+
|
|
457
|
+
const defaultViewPositions = {
|
|
458
|
+
top: new Vector3(0, 0, 1),
|
|
459
|
+
bottom: new Vector3(0, 0, -1),
|
|
460
|
+
left: new Vector3(-1, 0, 0),
|
|
461
|
+
right: new Vector3(1, 0, 0),
|
|
462
|
+
front: new Vector3(0, 1, 0),
|
|
463
|
+
back: new Vector3(0, -1, 0),
|
|
464
|
+
sw: new Vector3(-.5, -.5, 1).normalize(),
|
|
465
|
+
se: new Vector3(.5, -.5, 1).normalize(),
|
|
466
|
+
ne: new Vector3(.5, .5, 1).normalize(),
|
|
467
|
+
nw: new Vector3(-.5, .5, 1).normalize()
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
function setDefaultViewPosition(viewer, position) {
|
|
471
|
+
const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
|
|
472
|
+
const camera = viewer.camera;
|
|
473
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
474
|
+
const sphere = viewer.extents.getBoundingSphere(new Sphere);
|
|
475
|
+
const offset = (new Vector3).copy(direction).multiplyScalar(sphere.radius);
|
|
476
|
+
camera.position.copy(center);
|
|
477
|
+
camera.position.add(offset);
|
|
478
|
+
camera.rotation.set(0, 0, 0);
|
|
479
|
+
camera.lookAt(center);
|
|
480
|
+
camera.updateProjectionMatrix();
|
|
481
|
+
viewer.update();
|
|
482
|
+
viewer.emit({
|
|
483
|
+
type: "viewposition",
|
|
484
|
+
data: position
|
|
485
|
+
});
|
|
486
|
+
viewer.executeCommand("zoomToExtents");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
commands("ThreeJS").registerCommand("setDefaultViewPosition", setDefaultViewPosition);
|
|
490
|
+
|
|
491
|
+
commands("ThreeJS").registerCommand("top", (viewer => setDefaultViewPosition(viewer, "top")));
|
|
492
|
+
|
|
493
|
+
commands("ThreeJS").registerCommand("bottom", (viewer => setDefaultViewPosition(viewer, "bottom")));
|
|
494
|
+
|
|
495
|
+
commands("ThreeJS").registerCommand("left", (viewer => setDefaultViewPosition(viewer, "left")));
|
|
496
|
+
|
|
497
|
+
commands("ThreeJS").registerCommand("right", (viewer => setDefaultViewPosition(viewer, "right")));
|
|
498
|
+
|
|
499
|
+
commands("ThreeJS").registerCommand("front", (viewer => setDefaultViewPosition(viewer, "front")));
|
|
500
|
+
|
|
501
|
+
commands("ThreeJS").registerCommand("back", (viewer => setDefaultViewPosition(viewer, "back")));
|
|
502
|
+
|
|
503
|
+
commands("ThreeJS").registerCommand("sw", (viewer => setDefaultViewPosition(viewer, "sw")));
|
|
504
|
+
|
|
505
|
+
commands("ThreeJS").registerCommand("se", (viewer => setDefaultViewPosition(viewer, "se")));
|
|
506
|
+
|
|
507
|
+
commands("ThreeJS").registerCommand("ne", (viewer => setDefaultViewPosition(viewer, "ne")));
|
|
508
|
+
|
|
509
|
+
commands("ThreeJS").registerCommand("nw", (viewer => setDefaultViewPosition(viewer, "nw")));
|
|
510
|
+
|
|
511
|
+
commands("ThreeJS").registerCommandAlias("top", "k3DViewTop");
|
|
512
|
+
|
|
513
|
+
commands("ThreeJS").registerCommandAlias("bottom", "k3DViewBottom");
|
|
514
|
+
|
|
515
|
+
commands("ThreeJS").registerCommandAlias("left", "k3DViewLeft");
|
|
516
|
+
|
|
517
|
+
commands("ThreeJS").registerCommandAlias("right", "k3DViewRight");
|
|
518
|
+
|
|
519
|
+
commands("ThreeJS").registerCommandAlias("front", "k3DViewFront");
|
|
520
|
+
|
|
521
|
+
commands("ThreeJS").registerCommandAlias("back", "k3DViewBack");
|
|
522
|
+
|
|
523
|
+
commands("ThreeJS").registerCommandAlias("se", "k3DViewSE");
|
|
524
|
+
|
|
525
|
+
commands("ThreeJS").registerCommandAlias("sw", "k3DViewSW");
|
|
526
|
+
|
|
527
|
+
commands("ThreeJS").registerCommandAlias("ne", "k3DViewNE");
|
|
528
|
+
|
|
529
|
+
commands("ThreeJS").registerCommandAlias("nw", "k3DViewNW");
|
|
530
|
+
|
|
531
|
+
function getDefaultViewPositions() {
|
|
532
|
+
return Object.keys(defaultViewPositions);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
commands("ThreeJS").registerCommand("getDefaultViewPositions", getDefaultViewPositions);
|
|
536
|
+
|
|
537
|
+
function getModels(viewer) {
|
|
538
|
+
const handles = viewer.models.map((model => model.userData.handle || "")).filter((handle => handle));
|
|
539
|
+
return handles;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
commands("ThreeJS").registerCommand("getModels", getModels);
|
|
543
|
+
|
|
544
|
+
function getSelected(viewer) {
|
|
545
|
+
return viewer.selected.map((object => {
|
|
546
|
+
var _a;
|
|
547
|
+
return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle;
|
|
548
|
+
})).filter((handle => handle));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
commands("ThreeJS").registerCommand("getSelected", getSelected);
|
|
552
|
+
|
|
553
|
+
class SelectionComponent {
|
|
554
|
+
constructor(viewer) {
|
|
555
|
+
this.onPointerDown = event => {
|
|
556
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
557
|
+
this.getMousePosition(event, this.downPosition);
|
|
558
|
+
};
|
|
559
|
+
this.onPointerUp = event => {
|
|
560
|
+
if (!event.isPrimary) return;
|
|
561
|
+
const upPosition = this.getMousePosition(event, new Vector2);
|
|
562
|
+
if (this.downPosition.distanceTo(upPosition) !== 0) return;
|
|
563
|
+
const intersects = this.getPointerIntersects(upPosition);
|
|
564
|
+
this.clearSelection();
|
|
565
|
+
if (intersects.length > 0) this.select(intersects[0].object);
|
|
566
|
+
this.viewer.update();
|
|
567
|
+
this.viewer.emitEvent({
|
|
568
|
+
type: "select",
|
|
569
|
+
data: undefined,
|
|
570
|
+
handles: this.viewer.getSelected()
|
|
571
|
+
});
|
|
572
|
+
};
|
|
573
|
+
this.onDoubleClick = event => {
|
|
574
|
+
if (event.button !== 0) return;
|
|
575
|
+
this.viewer.executeCommand("zoomToSelected");
|
|
576
|
+
};
|
|
577
|
+
this.optionsChange = () => {
|
|
578
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
|
|
579
|
+
this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
580
|
+
this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
581
|
+
this.viewer.update();
|
|
582
|
+
};
|
|
583
|
+
this.viewer = viewer;
|
|
584
|
+
this.raycaster = new Raycaster;
|
|
585
|
+
this.downPosition = new Vector2;
|
|
586
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
|
|
587
|
+
this.facesMaterial = new MeshBasicMaterial;
|
|
588
|
+
this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
589
|
+
this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
590
|
+
this.facesMaterial.transparent = true;
|
|
591
|
+
this.viewer.addEventListener("pointerdown", this.onPointerDown);
|
|
592
|
+
this.viewer.addEventListener("pointerup", this.onPointerUp);
|
|
593
|
+
this.viewer.addEventListener("dblclick", this.onDoubleClick);
|
|
594
|
+
this.viewer.addEventListener("optionschange", this.optionsChange);
|
|
595
|
+
}
|
|
596
|
+
dispose() {
|
|
597
|
+
this.facesMaterial.dispose();
|
|
598
|
+
this.viewer.removeEventListener("pointerdown", this.onPointerDown);
|
|
599
|
+
this.viewer.removeEventListener("pointerup", this.onPointerUp);
|
|
600
|
+
this.viewer.removeEventListener("dblclick", this.onDoubleClick);
|
|
601
|
+
this.viewer.removeEventListener("optionschange", this.optionsChange);
|
|
602
|
+
}
|
|
603
|
+
getMousePosition(event, position) {
|
|
604
|
+
const rect = this.viewer.canvas.getBoundingClientRect();
|
|
605
|
+
position.setX((event.clientX - rect.left) / rect.width);
|
|
606
|
+
position.setY((event.clientY - rect.top) / rect.height);
|
|
607
|
+
return position;
|
|
608
|
+
}
|
|
609
|
+
getPointerIntersects(position) {
|
|
610
|
+
const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
|
|
611
|
+
this.raycaster.setFromCamera(mouse, this.viewer.camera);
|
|
612
|
+
const objects = [];
|
|
613
|
+
this.viewer.scene.traverseVisible((child => objects.push(child)));
|
|
614
|
+
return this.raycaster.intersectObjects(objects, false);
|
|
615
|
+
}
|
|
616
|
+
select(object) {
|
|
617
|
+
if (object.isSelected) return;
|
|
618
|
+
object.isSelected = true;
|
|
619
|
+
object.originalMaterial = object.material;
|
|
620
|
+
object.material = this.facesMaterial;
|
|
621
|
+
this.viewer.selected.push(object);
|
|
622
|
+
}
|
|
623
|
+
clearSelection() {
|
|
624
|
+
this.viewer.selected.forEach((object => {
|
|
625
|
+
object.isSelected = false;
|
|
626
|
+
object.material = object.originalMaterial;
|
|
627
|
+
}));
|
|
628
|
+
this.viewer.selected.length = 0;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function hideSelected(viewer) {
|
|
633
|
+
viewer.selected.forEach((object => object.visible = false));
|
|
634
|
+
const selection = new SelectionComponent(viewer);
|
|
635
|
+
selection.clearSelection();
|
|
636
|
+
selection.dispose();
|
|
637
|
+
viewer.update();
|
|
638
|
+
viewer.emit({
|
|
639
|
+
type: "hide"
|
|
640
|
+
});
|
|
641
|
+
viewer.emit({
|
|
642
|
+
type: "select",
|
|
643
|
+
data: undefined,
|
|
644
|
+
handles: []
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
commands("ThreeJS").registerCommand("hideSelected", hideSelected);
|
|
649
|
+
|
|
650
|
+
function isolateSelected(viewer) {
|
|
651
|
+
const selectedSet = new Set(viewer.selected);
|
|
652
|
+
function isolateObject(object, depth) {
|
|
653
|
+
let canBeIsolated = true;
|
|
654
|
+
object.children.forEach((object => {
|
|
655
|
+
if (selectedSet.has(object)) canBeIsolated = false; else isolateObject(object, depth + 1);
|
|
656
|
+
}));
|
|
657
|
+
if (canBeIsolated && depth > 0) object.visible = false;
|
|
658
|
+
return canBeIsolated;
|
|
659
|
+
}
|
|
660
|
+
isolateObject(viewer.scene, 0);
|
|
661
|
+
viewer.update();
|
|
662
|
+
viewer.emit({
|
|
663
|
+
type: "isolate"
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
commands("ThreeJS").registerCommand("isolateSelected", isolateSelected);
|
|
668
|
+
|
|
669
|
+
function regenerateAll(viewer) {
|
|
670
|
+
console.warn("regenerateAll not implemented");
|
|
671
|
+
viewer.emit({
|
|
672
|
+
type: "regenerateall"
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
commands("ThreeJS").registerCommand("regenerateAll", regenerateAll);
|
|
677
|
+
|
|
678
|
+
function resetView(viewer) {
|
|
679
|
+
viewer.executeCommand("setActiveDragger", "");
|
|
680
|
+
viewer.executeCommand("clearSlices");
|
|
681
|
+
viewer.executeCommand("clearOverlay");
|
|
682
|
+
viewer.executeCommand("setMarkupColor");
|
|
683
|
+
viewer.executeCommand("unselect");
|
|
684
|
+
viewer.executeCommand("showAll");
|
|
685
|
+
viewer.executeCommand("explode", 0);
|
|
686
|
+
viewer.executeCommand("zoomToExtents", true);
|
|
687
|
+
viewer.executeCommand("k3DViewSW");
|
|
688
|
+
viewer.emit({
|
|
689
|
+
type: "resetview"
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
commands("ThreeJS").registerCommand("resetView", resetView);
|
|
694
|
+
|
|
695
|
+
function selectModel(viewer, handle) {
|
|
696
|
+
console.warn("selectModel not implemented");
|
|
697
|
+
viewer.emit({
|
|
698
|
+
type: "select",
|
|
699
|
+
data: []
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
commands("ThreeJS").registerCommand("selectModel", selectModel);
|
|
704
|
+
|
|
705
|
+
commands("ThreeJS").registerCommand("setActiveDragger", ((viewer, dragger = "") => {
|
|
706
|
+
viewer.setActiveDragger(dragger);
|
|
707
|
+
}));
|
|
708
|
+
|
|
709
|
+
commands("ThreeJS").registerCommand("setMarkupColor", ((viewer, r = 255, g = 0, b = 0) => {
|
|
710
|
+
console.warn("setMarkupColor not implemented");
|
|
711
|
+
}));
|
|
712
|
+
|
|
713
|
+
function setSelected(viewer, handles = []) {
|
|
714
|
+
const handleSet = new Set(handles);
|
|
715
|
+
const objects = [];
|
|
716
|
+
viewer.scene.traverseVisible((child => {
|
|
717
|
+
var _a;
|
|
718
|
+
if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
|
|
719
|
+
}));
|
|
720
|
+
const selection = new SelectionComponent(viewer);
|
|
721
|
+
selection.clearSelection();
|
|
722
|
+
objects.forEach((object => selection.select(object)));
|
|
723
|
+
selection.dispose();
|
|
724
|
+
viewer.update();
|
|
725
|
+
viewer.emit({
|
|
726
|
+
type: "select",
|
|
727
|
+
data: undefined,
|
|
728
|
+
handles: handles
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
commands("ThreeJS").registerCommand("setSelected", setSelected);
|
|
733
|
+
|
|
734
|
+
function showAll(viewer) {
|
|
735
|
+
viewer.scene.traverse((object => object.visible = true));
|
|
736
|
+
viewer.update();
|
|
737
|
+
viewer.emit({
|
|
738
|
+
type: "showall"
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
commands("ThreeJS").registerCommand("showAll", showAll);
|
|
743
|
+
|
|
744
|
+
function unselect(viewer) {
|
|
745
|
+
const selection = new SelectionComponent(viewer);
|
|
746
|
+
selection.clearSelection();
|
|
747
|
+
selection.dispose();
|
|
748
|
+
viewer.update();
|
|
749
|
+
viewer.emit({
|
|
750
|
+
type: "select",
|
|
751
|
+
data: undefined,
|
|
752
|
+
handles: []
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
commands("ThreeJS").registerCommand("unselect", unselect);
|
|
757
|
+
|
|
758
|
+
function zoomToExtents(viewer) {
|
|
759
|
+
if (viewer.extents.isEmpty()) return;
|
|
760
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
761
|
+
const distance = viewer.extents.getBoundingSphere(new Sphere).radius;
|
|
762
|
+
const delta = new Vector3(0, 0, 1);
|
|
763
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
764
|
+
delta.multiplyScalar(distance * 3);
|
|
765
|
+
viewer.camera.position.copy(center).add(delta);
|
|
766
|
+
viewer.target.copy(center);
|
|
767
|
+
viewer.update();
|
|
768
|
+
viewer.emitEvent({
|
|
769
|
+
type: "zoom"
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
commands("ThreeJS").registerCommand("zoomToExtents", zoomToExtents);
|
|
774
|
+
|
|
775
|
+
commands("ThreeJS").registerCommandAlias("zoomToExtents", "zoomExtents");
|
|
776
|
+
|
|
777
|
+
function zoomToObjects(viewer, handles = []) {
|
|
778
|
+
const handleSet = new Set(handles);
|
|
779
|
+
const objects = [];
|
|
780
|
+
viewer.scene.traverseVisible((child => {
|
|
781
|
+
var _a;
|
|
782
|
+
if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
|
|
783
|
+
}));
|
|
784
|
+
const extents = objects.reduce(((result, object) => {
|
|
785
|
+
const objectExtents = (new Box3).setFromObject(object);
|
|
786
|
+
return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
|
|
787
|
+
}), new Box3);
|
|
788
|
+
const center = extents.getCenter(new Vector3);
|
|
789
|
+
const distance = extents.getBoundingSphere(new Sphere).radius;
|
|
790
|
+
const delta = new Vector3(0, 0, 1);
|
|
791
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
792
|
+
delta.multiplyScalar(distance * 3);
|
|
793
|
+
viewer.camera.position.copy(center).add(delta);
|
|
794
|
+
viewer.target.copy(center);
|
|
795
|
+
viewer.update();
|
|
796
|
+
viewer.emitEvent({
|
|
797
|
+
type: "zoom"
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
commands("ThreeJS").registerCommand("zoomToObjects", zoomToObjects);
|
|
802
|
+
|
|
803
|
+
function zoomToSelected(viewer) {
|
|
804
|
+
const extents = viewer.selected.reduce(((result, object) => {
|
|
805
|
+
const objectExtents = (new Box3).setFromObject(object);
|
|
806
|
+
return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
|
|
807
|
+
}), new Box3);
|
|
808
|
+
if (extents.isEmpty()) extents.copy(viewer.extents);
|
|
809
|
+
const center = extents.getCenter(new Vector3);
|
|
810
|
+
const distance = extents.getBoundingSphere(new Sphere).radius;
|
|
811
|
+
const delta = new Vector3(0, 0, 1);
|
|
812
|
+
delta.applyQuaternion(viewer.camera.quaternion);
|
|
813
|
+
delta.multiplyScalar(distance * 3);
|
|
814
|
+
viewer.camera.position.copy(center).add(delta);
|
|
815
|
+
viewer.target.copy(center);
|
|
816
|
+
viewer.update();
|
|
817
|
+
viewer.emitEvent({
|
|
818
|
+
type: "zoom"
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
commands("ThreeJS").registerCommand("zoomToSelected", zoomToSelected);
|
|
823
|
+
|
|
824
|
+
class GLTFLoadingManager extends LoadingManager {
|
|
825
|
+
constructor(file, externalData = new Map, params = {}) {
|
|
826
|
+
super();
|
|
827
|
+
this.path = "";
|
|
828
|
+
this.resourcePath = "";
|
|
829
|
+
this.fileURL = "";
|
|
830
|
+
this.dataURLs = new Map;
|
|
831
|
+
this.path = params.path || "";
|
|
832
|
+
if (typeof file === "string") {
|
|
833
|
+
this.fileURL = file;
|
|
834
|
+
this.resourcePath = LoaderUtils.extractUrlBase(file);
|
|
835
|
+
} else {
|
|
836
|
+
externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
|
|
837
|
+
externalData.set(this.fileURL, file);
|
|
838
|
+
}
|
|
839
|
+
externalData.forEach(((value, key) => {
|
|
840
|
+
let dataURL;
|
|
841
|
+
if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
|
|
842
|
+
this.dataURLs.set(key, dataURL);
|
|
843
|
+
}));
|
|
844
|
+
this.setURLModifier((url => {
|
|
845
|
+
const key = decodeURI(url).replace(this.path, "").replace(this.resourcePath, "").replace(/^(\.?\/)/, "");
|
|
846
|
+
const dataURL = this.dataURLs.get(key);
|
|
847
|
+
return dataURL !== null && dataURL !== void 0 ? dataURL : url;
|
|
848
|
+
}));
|
|
849
|
+
}
|
|
850
|
+
dispose() {
|
|
851
|
+
this.dataURLs.forEach(URL.revokeObjectURL);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
383
855
|
class EventEmitter2 {
|
|
384
856
|
constructor() {
|
|
385
857
|
this._listeners = {};
|
|
@@ -419,83 +891,67 @@ class EventEmitter2 {
|
|
|
419
891
|
}
|
|
420
892
|
}
|
|
421
893
|
|
|
422
|
-
class
|
|
423
|
-
constructor(file, externalData = new Map, params = {}) {
|
|
424
|
-
super();
|
|
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
|
-
}
|
|
452
|
-
|
|
453
|
-
class OrbitDragger extends OrbitControls {
|
|
894
|
+
class OrbitDragger {
|
|
454
895
|
constructor(viewer) {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this.maxDistance = size * 10;
|
|
461
|
-
this.update();
|
|
896
|
+
this.updateControls = () => {
|
|
897
|
+
this.orbit.maxDistance = this.viewer.camera.far;
|
|
898
|
+
this.orbit.minDistance = this.viewer.camera.near;
|
|
899
|
+
this.orbit.target.copy(this.viewer.target);
|
|
900
|
+
this.orbit.update();
|
|
462
901
|
};
|
|
463
|
-
this.
|
|
902
|
+
this.controlsStart = () => {
|
|
903
|
+
this.changed = false;
|
|
904
|
+
};
|
|
905
|
+
this.controlsChange = () => {
|
|
906
|
+
this.viewer.target.copy(this.orbit.target);
|
|
464
907
|
this.viewer.update();
|
|
908
|
+
this.changed = true;
|
|
909
|
+
};
|
|
910
|
+
this.stopContextMenu = event => {
|
|
911
|
+
if (this.changed) {
|
|
912
|
+
event.preventDefault();
|
|
913
|
+
event.stopPropagation();
|
|
914
|
+
}
|
|
465
915
|
};
|
|
466
|
-
this.
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
916
|
+
this.orbit = new OrbitControls(viewer.camera, viewer.canvas);
|
|
917
|
+
this.orbit.mouseButtons = {
|
|
918
|
+
LEFT: MOUSE.ROTATE,
|
|
919
|
+
MIDDLE: MOUSE.PAN,
|
|
920
|
+
RIGHT: MOUSE.PAN
|
|
470
921
|
};
|
|
471
|
-
this.touches = {
|
|
472
|
-
ONE:
|
|
473
|
-
TWO:
|
|
922
|
+
this.orbit.touches = {
|
|
923
|
+
ONE: TOUCH.ROTATE,
|
|
924
|
+
TWO: TOUCH.DOLLY_PAN
|
|
474
925
|
};
|
|
475
|
-
this.screenSpacePanning = true;
|
|
476
|
-
this.rotateSpeed = .33;
|
|
926
|
+
this.orbit.screenSpacePanning = true;
|
|
927
|
+
this.orbit.rotateSpeed = .33;
|
|
928
|
+
this.orbit.addEventListener("start", this.controlsStart);
|
|
929
|
+
this.orbit.addEventListener("change", this.controlsChange);
|
|
930
|
+
this.changed = false;
|
|
477
931
|
this.viewer = viewer;
|
|
478
|
-
this.viewer.
|
|
479
|
-
this.
|
|
932
|
+
this.viewer.on("geometryend", this.updateControls);
|
|
933
|
+
this.viewer.on("viewposition", this.updateControls);
|
|
934
|
+
this.viewer.on("zoom", this.updateControls);
|
|
935
|
+
this.viewer.on("contextmenu", this.stopContextMenu);
|
|
936
|
+
this.updateControls();
|
|
480
937
|
}
|
|
481
938
|
dispose() {
|
|
482
|
-
this.
|
|
483
|
-
this.viewer.
|
|
484
|
-
|
|
939
|
+
this.viewer.off("contextmenu", this.stopContextMenu);
|
|
940
|
+
this.viewer.off("zoom", this.updateControls);
|
|
941
|
+
this.viewer.off("viewposition", this.updateControls);
|
|
942
|
+
this.viewer.off("geometryend", this.updateControls);
|
|
943
|
+
this.orbit.removeEventListener("change", this.controlsChange);
|
|
944
|
+
this.orbit.dispose();
|
|
485
945
|
}
|
|
486
946
|
}
|
|
487
947
|
|
|
488
948
|
class PanDragger extends OrbitDragger {
|
|
489
949
|
constructor(viewer) {
|
|
490
950
|
super(viewer);
|
|
491
|
-
this.mouseButtons = {
|
|
492
|
-
LEFT:
|
|
493
|
-
MIDDLE:
|
|
494
|
-
RIGHT:
|
|
495
|
-
};
|
|
496
|
-
this.touches = {
|
|
497
|
-
ONE: THREE.TOUCH.PAN,
|
|
498
|
-
TWO: THREE.TOUCH.DOLLY_ROTATE
|
|
951
|
+
this.orbit.mouseButtons = {
|
|
952
|
+
LEFT: MOUSE.PAN,
|
|
953
|
+
MIDDLE: MOUSE.PAN,
|
|
954
|
+
RIGHT: MOUSE.PAN
|
|
499
955
|
};
|
|
500
956
|
}
|
|
501
957
|
}
|
|
@@ -503,283 +959,1253 @@ class PanDragger extends OrbitDragger {
|
|
|
503
959
|
class ZoomDragger extends OrbitDragger {
|
|
504
960
|
constructor(viewer) {
|
|
505
961
|
super(viewer);
|
|
506
|
-
this.mouseButtons = {
|
|
507
|
-
LEFT:
|
|
508
|
-
MIDDLE:
|
|
509
|
-
RIGHT:
|
|
510
|
-
};
|
|
511
|
-
this.touches = {
|
|
512
|
-
ONE: THREE.TOUCH.DOLLY_PAN,
|
|
513
|
-
TWO: THREE.TOUCH.DOLLY_PAN
|
|
962
|
+
this.orbit.mouseButtons = {
|
|
963
|
+
LEFT: MOUSE.DOLLY,
|
|
964
|
+
MIDDLE: MOUSE.PAN,
|
|
965
|
+
RIGHT: MOUSE.PAN
|
|
514
966
|
};
|
|
515
967
|
}
|
|
516
968
|
}
|
|
517
969
|
|
|
518
|
-
|
|
519
|
-
|
|
970
|
+
const _changeEvent$1 = {
|
|
971
|
+
type: "change"
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
class WalkControls extends EventDispatcher {
|
|
975
|
+
constructor(camera, canvas) {
|
|
976
|
+
super();
|
|
977
|
+
this.movementSpeed = .2;
|
|
978
|
+
this.lookSpeed = 5;
|
|
979
|
+
this.multiplier = 5;
|
|
980
|
+
this.moveWheel = 0;
|
|
981
|
+
this.mouseDragOn = false;
|
|
982
|
+
this.onPointerDown = event => {
|
|
983
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
984
|
+
this.canvas.setPointerCapture(event.pointerId);
|
|
985
|
+
this.downPosition.set(event.clientX, event.clientY);
|
|
986
|
+
this.quaternion.copy(this.camera.quaternion);
|
|
987
|
+
this.mouseDragOn = true;
|
|
988
|
+
};
|
|
989
|
+
this.onPointerMove = event => {
|
|
990
|
+
if (!event.isPrimary || !this.mouseDragOn) return;
|
|
991
|
+
const movePosition = new Vector2(event.clientX, event.clientY);
|
|
992
|
+
if (this.downPosition.distanceTo(movePosition) === 0) return;
|
|
993
|
+
this.rotateDelta.copy(this.downPosition).sub(movePosition);
|
|
994
|
+
this.rotateCamera(this.rotateDelta);
|
|
995
|
+
this.dispatchEvent(_changeEvent$1);
|
|
996
|
+
};
|
|
997
|
+
this.onPointerUp = event => {
|
|
998
|
+
if (!event.isPrimary || event.button !== 0) return;
|
|
999
|
+
this.canvas.releasePointerCapture(event.pointerId);
|
|
1000
|
+
this.mouseDragOn = false;
|
|
1001
|
+
};
|
|
1002
|
+
this.onPointerCancel = event => {
|
|
1003
|
+
this.canvas.dispatchEvent(new PointerEvent("pointerup", event));
|
|
1004
|
+
};
|
|
1005
|
+
this.onWheel = event => {
|
|
1006
|
+
this.moveWheel = event.deltaY;
|
|
1007
|
+
this.update();
|
|
1008
|
+
};
|
|
520
1009
|
this.onKeyDown = event => {
|
|
521
1010
|
switch (event.code) {
|
|
522
|
-
case "
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
this.
|
|
1011
|
+
case "NumpadSubtract":
|
|
1012
|
+
case "Minus":
|
|
1013
|
+
if (this.multiplier > 1) {
|
|
1014
|
+
this.multiplier = this.multiplier - 1;
|
|
1015
|
+
this.dispatchEvent({
|
|
1016
|
+
type: "walkspeedchange",
|
|
1017
|
+
data: this.multiplier
|
|
1018
|
+
});
|
|
527
1019
|
}
|
|
528
1020
|
break;
|
|
529
1021
|
|
|
530
|
-
case "
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
this.
|
|
1022
|
+
case "NumpadAdd":
|
|
1023
|
+
case "Equal":
|
|
1024
|
+
if (this.multiplier < 10) {
|
|
1025
|
+
this.multiplier = this.multiplier + 1;
|
|
1026
|
+
this.dispatchEvent({
|
|
1027
|
+
type: "walkspeedchange",
|
|
1028
|
+
data: this.multiplier
|
|
1029
|
+
});
|
|
535
1030
|
}
|
|
536
1031
|
break;
|
|
537
1032
|
|
|
1033
|
+
case "ArrowLeft":
|
|
1034
|
+
case "ArrowRight":
|
|
1035
|
+
case "ArrowUp":
|
|
1036
|
+
case "ArrowDown":
|
|
1037
|
+
case "KeyW":
|
|
1038
|
+
case "KeyS":
|
|
538
1039
|
case "KeyA":
|
|
539
|
-
if (event.shiftKey) {
|
|
540
|
-
this.speed.x = this.walkSpeed * this.boostSpeed;
|
|
541
|
-
} else {
|
|
542
|
-
this.speed.x = this.walkSpeed;
|
|
543
|
-
}
|
|
544
|
-
break;
|
|
545
|
-
|
|
546
1040
|
case "KeyD":
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
1041
|
+
case "KeyQ":
|
|
1042
|
+
case "KeyE":
|
|
1043
|
+
this.moveKeys.add(event.code);
|
|
1044
|
+
this.update();
|
|
552
1045
|
break;
|
|
553
1046
|
}
|
|
554
1047
|
};
|
|
555
1048
|
this.onKeyUp = event => {
|
|
556
1049
|
switch (event.code) {
|
|
1050
|
+
case "ArrowLeft":
|
|
1051
|
+
case "ArrowRight":
|
|
1052
|
+
case "ArrowUp":
|
|
1053
|
+
case "ArrowDown":
|
|
557
1054
|
case "KeyW":
|
|
558
|
-
this.speed.z = 0;
|
|
559
|
-
break;
|
|
560
|
-
|
|
561
1055
|
case "KeyS":
|
|
562
|
-
this.speed.z = 0;
|
|
563
|
-
break;
|
|
564
|
-
|
|
565
1056
|
case "KeyA":
|
|
566
|
-
this.speed.x = 0;
|
|
567
|
-
break;
|
|
568
|
-
|
|
569
1057
|
case "KeyD":
|
|
570
|
-
|
|
1058
|
+
case "KeyQ":
|
|
1059
|
+
case "KeyE":
|
|
1060
|
+
this.moveKeys.delete(event.code);
|
|
1061
|
+
this.update();
|
|
571
1062
|
break;
|
|
572
1063
|
}
|
|
573
1064
|
};
|
|
574
|
-
this.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
1065
|
+
this.camera = camera;
|
|
1066
|
+
this.canvas = canvas;
|
|
1067
|
+
this.moveKeys = new Set;
|
|
1068
|
+
this.moveClock = new Clock;
|
|
1069
|
+
this.quaternion = camera.quaternion.clone();
|
|
1070
|
+
this.downPosition = new Vector2(0, 0);
|
|
1071
|
+
this.rotateDelta = new Vector2(0, 0);
|
|
1072
|
+
this.canvas.addEventListener("pointerdown", this.onPointerDown);
|
|
1073
|
+
this.canvas.addEventListener("pointermove", this.onPointerMove);
|
|
1074
|
+
this.canvas.addEventListener("pointerup", this.onPointerUp);
|
|
1075
|
+
this.canvas.addEventListener("pointercancel", this.onPointerCancel);
|
|
1076
|
+
this.canvas.addEventListener("wheel", this.onWheel);
|
|
1077
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
1078
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
1079
|
+
}
|
|
1080
|
+
dispose() {
|
|
1081
|
+
this.canvas.removeEventListener("pointerdown", this.onPointerDown);
|
|
1082
|
+
this.canvas.removeEventListener("pointermove", this.onPointerMove);
|
|
1083
|
+
this.canvas.removeEventListener("pointerup", this.onPointerUp);
|
|
1084
|
+
this.canvas.removeEventListener("pointercancel", this.onPointerCancel);
|
|
1085
|
+
this.canvas.removeEventListener("wheel", this.onWheel);
|
|
1086
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
1087
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
1088
|
+
}
|
|
1089
|
+
update() {
|
|
1090
|
+
if (this.moveKeys.size > 0) {
|
|
1091
|
+
const timeDelta = this.moveClock.getDelta();
|
|
1092
|
+
const moveDelta = timeDelta * this.movementSpeed * this.multiplier;
|
|
1093
|
+
if (this.moveKeys.has("KeyW")) this.camera.translateZ(-moveDelta);
|
|
1094
|
+
if (this.moveKeys.has("KeyS")) this.camera.translateZ(moveDelta);
|
|
1095
|
+
if (this.moveKeys.has("KeyA")) this.camera.translateX(-moveDelta);
|
|
1096
|
+
if (this.moveKeys.has("KeyD")) this.camera.translateX(moveDelta);
|
|
1097
|
+
if (this.moveKeys.has("KeyQ")) this.camera.translateY(moveDelta);
|
|
1098
|
+
if (this.moveKeys.has("KeyE")) this.camera.translateY(-moveDelta);
|
|
1099
|
+
const lookDelta = this.lookSpeed + (this.multiplier - 1);
|
|
1100
|
+
if (this.moveKeys.has("ArrowUp")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, -lookDelta / 2)));
|
|
1101
|
+
if (this.moveKeys.has("ArrowDown")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, lookDelta / 2)));
|
|
1102
|
+
if (this.moveKeys.has("ArrowLeft")) this.rotateCamera(this.rotateDelta.add(new Vector2(lookDelta, 0)));
|
|
1103
|
+
if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
|
|
1104
|
+
this.moveWheel = 0;
|
|
1105
|
+
this.dispatchEvent(_changeEvent$1);
|
|
1106
|
+
}
|
|
1107
|
+
if (this.moveWheel !== 0) {
|
|
1108
|
+
const moveDelta = this.moveWheel * 1e-4 * this.movementSpeed * this.multiplier;
|
|
1109
|
+
this.camera.translateZ(-moveDelta);
|
|
1110
|
+
this.moveWheel += -1 * Math.sign(this.moveWheel);
|
|
1111
|
+
this.dispatchEvent(_changeEvent$1);
|
|
1112
|
+
}
|
|
1113
|
+
if (this.moveKeys.size === 0 && this.moveWheel === 0) {
|
|
1114
|
+
this.moveClock.stop();
|
|
1115
|
+
this.moveClock.autoStart = true;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
rotateCamera(delta) {
|
|
1119
|
+
const rotateX = Math.PI * delta.x / this.canvas.clientWidth;
|
|
1120
|
+
const rotateY = Math.PI * delta.y / this.canvas.clientHeight;
|
|
1121
|
+
const xRotation = new Quaternion;
|
|
1122
|
+
xRotation.setFromAxisAngle(this.camera.up, rotateX);
|
|
1123
|
+
const yRotation = new Quaternion;
|
|
1124
|
+
yRotation.setFromAxisAngle(new Vector3(1, 0, 0), rotateY);
|
|
1125
|
+
const quaternion = this.quaternion.clone();
|
|
1126
|
+
quaternion.premultiply(xRotation).multiply(yRotation).normalize();
|
|
1127
|
+
this.camera.setRotationFromQuaternion(quaternion);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
class WalkDragger {
|
|
1132
|
+
constructor(viewer) {
|
|
1133
|
+
this.updateControls = () => {
|
|
1134
|
+
const size = this.viewer.extents.getSize(new Vector3);
|
|
1135
|
+
this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
|
|
580
1136
|
};
|
|
581
|
-
this.
|
|
582
|
-
|
|
583
|
-
this.mouseDelta.set(this.mouseStart.x - clientX, this.mouseStart.y - clientY);
|
|
584
|
-
this.rotateCamera(this.mouseDelta);
|
|
1137
|
+
this.controlsChange = () => {
|
|
1138
|
+
this.viewer.update();
|
|
585
1139
|
};
|
|
586
|
-
this.
|
|
587
|
-
this.
|
|
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);
|
|
1140
|
+
this.walkspeedChange = event => {
|
|
1141
|
+
this.viewer.emitEvent(event);
|
|
592
1142
|
};
|
|
593
|
-
this.
|
|
594
|
-
|
|
595
|
-
if (-event.deltaY < 0) {
|
|
596
|
-
this.walkSpeed = Math.max(.001, this.walkSpeed - 1);
|
|
597
|
-
} else if (-event.deltaY > 0) {
|
|
598
|
-
this.walkSpeed++;
|
|
599
|
-
}
|
|
1143
|
+
this.viewerRender = () => {
|
|
1144
|
+
this.controls.update();
|
|
600
1145
|
};
|
|
601
|
-
this.
|
|
602
|
-
|
|
603
|
-
event.preventDefault();
|
|
604
|
-
event.stopImmediatePropagation();
|
|
1146
|
+
this.viewerZoom = () => {
|
|
1147
|
+
this.controls.rotateDelta.set(0, 0);
|
|
605
1148
|
};
|
|
606
|
-
this.
|
|
607
|
-
|
|
608
|
-
|
|
1149
|
+
this.controls = new WalkControls(viewer.camera, viewer.canvas);
|
|
1150
|
+
this.controls.addEventListener("change", this.controlsChange);
|
|
1151
|
+
this.controls.addEventListener("walkspeedchange", this.walkspeedChange);
|
|
1152
|
+
this.viewer = viewer;
|
|
1153
|
+
this.viewer.on("render", this.viewerRender);
|
|
1154
|
+
this.viewer.on("zoom", this.viewerZoom);
|
|
1155
|
+
this.updateControls();
|
|
1156
|
+
}
|
|
1157
|
+
dispose() {
|
|
1158
|
+
this.viewer.off("render", this.viewerRender);
|
|
1159
|
+
this.viewer.off("zoom", this.viewerZoom);
|
|
1160
|
+
this.controls.removeEventListener("walkspeedchange", this.walkspeedChange);
|
|
1161
|
+
this.controls.removeEventListener("change", this.controlsChange);
|
|
1162
|
+
this.controls.dispose();
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
const _raycaster = new Raycaster;
|
|
1167
|
+
|
|
1168
|
+
const _tempVector = new Vector3;
|
|
1169
|
+
|
|
1170
|
+
const _tempVector2 = new Vector3;
|
|
1171
|
+
|
|
1172
|
+
const _tempQuaternion = new Quaternion;
|
|
1173
|
+
|
|
1174
|
+
const _unit = {
|
|
1175
|
+
X: new Vector3(1, 0, 0),
|
|
1176
|
+
Y: new Vector3(0, 1, 0),
|
|
1177
|
+
Z: new Vector3(0, 0, 1)
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
const _changeEvent = {
|
|
1181
|
+
type: "change"
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
const _mouseDownEvent = {
|
|
1185
|
+
type: "mouseDown"
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1188
|
+
const _mouseUpEvent = {
|
|
1189
|
+
type: "mouseUp",
|
|
1190
|
+
mode: null
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
const _objectChangeEvent = {
|
|
1194
|
+
type: "objectChange"
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1197
|
+
class TransformControls extends Object3D {
|
|
1198
|
+
constructor(camera, domElement) {
|
|
1199
|
+
super();
|
|
1200
|
+
if (domElement === undefined) {
|
|
1201
|
+
console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.');
|
|
1202
|
+
domElement = document;
|
|
1203
|
+
}
|
|
1204
|
+
this.isTransformControls = true;
|
|
1205
|
+
this.visible = false;
|
|
1206
|
+
this.domElement = domElement;
|
|
1207
|
+
this.domElement.style.touchAction = "none";
|
|
1208
|
+
const _gizmo = new TransformControlsGizmo;
|
|
1209
|
+
this._gizmo = _gizmo;
|
|
1210
|
+
this.add(_gizmo);
|
|
1211
|
+
const _plane = new TransformControlsPlane;
|
|
1212
|
+
this._plane = _plane;
|
|
1213
|
+
this.add(_plane);
|
|
1214
|
+
const scope = this;
|
|
1215
|
+
function defineProperty(propName, defaultValue) {
|
|
1216
|
+
let propValue = defaultValue;
|
|
1217
|
+
Object.defineProperty(scope, propName, {
|
|
1218
|
+
get: function() {
|
|
1219
|
+
return propValue !== undefined ? propValue : defaultValue;
|
|
1220
|
+
},
|
|
1221
|
+
set: function(value) {
|
|
1222
|
+
if (propValue !== value) {
|
|
1223
|
+
propValue = value;
|
|
1224
|
+
_plane[propName] = value;
|
|
1225
|
+
_gizmo[propName] = value;
|
|
1226
|
+
scope.dispatchEvent({
|
|
1227
|
+
type: propName + "-changed",
|
|
1228
|
+
value: value
|
|
1229
|
+
});
|
|
1230
|
+
scope.dispatchEvent(_changeEvent);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
scope[propName] = defaultValue;
|
|
1235
|
+
_plane[propName] = defaultValue;
|
|
1236
|
+
_gizmo[propName] = defaultValue;
|
|
1237
|
+
}
|
|
1238
|
+
defineProperty("camera", camera);
|
|
1239
|
+
defineProperty("object", undefined);
|
|
1240
|
+
defineProperty("enabled", true);
|
|
1241
|
+
defineProperty("axis", null);
|
|
1242
|
+
defineProperty("mode", "translate");
|
|
1243
|
+
defineProperty("translationSnap", null);
|
|
1244
|
+
defineProperty("rotationSnap", null);
|
|
1245
|
+
defineProperty("scaleSnap", null);
|
|
1246
|
+
defineProperty("space", "world");
|
|
1247
|
+
defineProperty("size", 1);
|
|
1248
|
+
defineProperty("dragging", false);
|
|
1249
|
+
defineProperty("showX", true);
|
|
1250
|
+
defineProperty("showY", true);
|
|
1251
|
+
defineProperty("showZ", true);
|
|
1252
|
+
const worldPosition = new Vector3;
|
|
1253
|
+
const worldPositionStart = new Vector3;
|
|
1254
|
+
const worldQuaternion = new Quaternion;
|
|
1255
|
+
const worldQuaternionStart = new Quaternion;
|
|
1256
|
+
const cameraPosition = new Vector3;
|
|
1257
|
+
const cameraQuaternion = new Quaternion;
|
|
1258
|
+
const pointStart = new Vector3;
|
|
1259
|
+
const pointEnd = new Vector3;
|
|
1260
|
+
const rotationAxis = new Vector3;
|
|
1261
|
+
const rotationAngle = 0;
|
|
1262
|
+
const eye = new Vector3;
|
|
1263
|
+
defineProperty("worldPosition", worldPosition);
|
|
1264
|
+
defineProperty("worldPositionStart", worldPositionStart);
|
|
1265
|
+
defineProperty("worldQuaternion", worldQuaternion);
|
|
1266
|
+
defineProperty("worldQuaternionStart", worldQuaternionStart);
|
|
1267
|
+
defineProperty("cameraPosition", cameraPosition);
|
|
1268
|
+
defineProperty("cameraQuaternion", cameraQuaternion);
|
|
1269
|
+
defineProperty("pointStart", pointStart);
|
|
1270
|
+
defineProperty("pointEnd", pointEnd);
|
|
1271
|
+
defineProperty("rotationAxis", rotationAxis);
|
|
1272
|
+
defineProperty("rotationAngle", rotationAngle);
|
|
1273
|
+
defineProperty("eye", eye);
|
|
1274
|
+
this._offset = new Vector3;
|
|
1275
|
+
this._startNorm = new Vector3;
|
|
1276
|
+
this._endNorm = new Vector3;
|
|
1277
|
+
this._cameraScale = new Vector3;
|
|
1278
|
+
this._parentPosition = new Vector3;
|
|
1279
|
+
this._parentQuaternion = new Quaternion;
|
|
1280
|
+
this._parentQuaternionInv = new Quaternion;
|
|
1281
|
+
this._parentScale = new Vector3;
|
|
1282
|
+
this._worldScaleStart = new Vector3;
|
|
1283
|
+
this._worldQuaternionInv = new Quaternion;
|
|
1284
|
+
this._worldScale = new Vector3;
|
|
1285
|
+
this._positionStart = new Vector3;
|
|
1286
|
+
this._quaternionStart = new Quaternion;
|
|
1287
|
+
this._scaleStart = new Vector3;
|
|
1288
|
+
this._getPointer = getPointer.bind(this);
|
|
1289
|
+
this._onPointerDown = onPointerDown.bind(this);
|
|
1290
|
+
this._onPointerHover = onPointerHover.bind(this);
|
|
1291
|
+
this._onPointerMove = onPointerMove.bind(this);
|
|
1292
|
+
this._onPointerUp = onPointerUp.bind(this);
|
|
1293
|
+
this.domElement.addEventListener("pointerdown", this._onPointerDown);
|
|
1294
|
+
this.domElement.addEventListener("pointermove", this._onPointerHover);
|
|
1295
|
+
this.domElement.addEventListener("pointerup", this._onPointerUp);
|
|
1296
|
+
}
|
|
1297
|
+
updateMatrixWorld() {
|
|
1298
|
+
if (this.object !== undefined) {
|
|
1299
|
+
this.object.updateMatrixWorld();
|
|
1300
|
+
if (this.object.parent === null) {
|
|
1301
|
+
console.error("TransformControls: The attached 3D object must be a part of the scene graph.");
|
|
609
1302
|
} else {
|
|
610
|
-
|
|
611
|
-
this.mouseStart.set(clientX, clientY);
|
|
612
|
-
this.mouseDelta.set(0, 0);
|
|
613
|
-
this.quaternion.copy(this.viewer.camera.quaternion);
|
|
1303
|
+
this.object.parent.matrixWorld.decompose(this._parentPosition, this._parentQuaternion, this._parentScale);
|
|
614
1304
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
1305
|
+
this.object.matrixWorld.decompose(this.worldPosition, this.worldQuaternion, this._worldScale);
|
|
1306
|
+
this._parentQuaternionInv.copy(this._parentQuaternion).invert();
|
|
1307
|
+
this._worldQuaternionInv.copy(this.worldQuaternion).invert();
|
|
1308
|
+
}
|
|
1309
|
+
this.camera.updateMatrixWorld();
|
|
1310
|
+
this.camera.matrixWorld.decompose(this.cameraPosition, this.cameraQuaternion, this._cameraScale);
|
|
1311
|
+
if (this.camera.isOrthographicCamera) {
|
|
1312
|
+
this.camera.getWorldDirection(this.eye).negate();
|
|
1313
|
+
} else {
|
|
1314
|
+
this.eye.copy(this.cameraPosition).sub(this.worldPosition).normalize();
|
|
1315
|
+
}
|
|
1316
|
+
super.updateMatrixWorld(this);
|
|
1317
|
+
}
|
|
1318
|
+
pointerHover(pointer) {
|
|
1319
|
+
if (this.object === undefined || this.dragging === true) return;
|
|
1320
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
1321
|
+
const intersect = intersectObjectWithRay(this._gizmo.picker[this.mode], _raycaster);
|
|
1322
|
+
if (intersect) {
|
|
1323
|
+
this.axis = intersect.object.name;
|
|
1324
|
+
} else {
|
|
1325
|
+
this.axis = null;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
pointerDown(pointer) {
|
|
1329
|
+
if (this.object === undefined || this.dragging === true || pointer.button !== 0) return;
|
|
1330
|
+
if (this.axis !== null) {
|
|
1331
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
1332
|
+
const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
|
|
1333
|
+
if (planeIntersect) {
|
|
1334
|
+
this.object.updateMatrixWorld();
|
|
1335
|
+
this.object.parent.updateMatrixWorld();
|
|
1336
|
+
this._positionStart.copy(this.object.position);
|
|
1337
|
+
this._quaternionStart.copy(this.object.quaternion);
|
|
1338
|
+
this._scaleStart.copy(this.object.scale);
|
|
1339
|
+
this.object.matrixWorld.decompose(this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart);
|
|
1340
|
+
this.pointStart.copy(planeIntersect.point).sub(this.worldPositionStart);
|
|
619
1341
|
}
|
|
620
|
-
this.
|
|
621
|
-
this.
|
|
622
|
-
this.
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
1342
|
+
this.dragging = true;
|
|
1343
|
+
_mouseDownEvent.mode = this.mode;
|
|
1344
|
+
this.dispatchEvent(_mouseDownEvent);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
pointerMove(pointer) {
|
|
1348
|
+
const axis = this.axis;
|
|
1349
|
+
const mode = this.mode;
|
|
1350
|
+
const object = this.object;
|
|
1351
|
+
let space = this.space;
|
|
1352
|
+
if (mode === "scale") {
|
|
1353
|
+
space = "local";
|
|
1354
|
+
} else if (axis === "E" || axis === "XYZE" || axis === "XYZ") {
|
|
1355
|
+
space = "world";
|
|
1356
|
+
}
|
|
1357
|
+
if (object === undefined || axis === null || this.dragging === false || pointer.button !== -1) return;
|
|
1358
|
+
_raycaster.setFromCamera(pointer, this.camera);
|
|
1359
|
+
const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
|
|
1360
|
+
if (!planeIntersect) return;
|
|
1361
|
+
this.pointEnd.copy(planeIntersect.point).sub(this.worldPositionStart);
|
|
1362
|
+
if (mode === "translate") {
|
|
1363
|
+
this._offset.copy(this.pointEnd).sub(this.pointStart);
|
|
1364
|
+
if (space === "local" && axis !== "XYZ") {
|
|
1365
|
+
this._offset.applyQuaternion(this._worldQuaternionInv);
|
|
630
1366
|
}
|
|
631
|
-
if (
|
|
632
|
-
|
|
633
|
-
|
|
1367
|
+
if (axis.indexOf("X") === -1) this._offset.x = 0;
|
|
1368
|
+
if (axis.indexOf("Y") === -1) this._offset.y = 0;
|
|
1369
|
+
if (axis.indexOf("Z") === -1) this._offset.z = 0;
|
|
1370
|
+
if (space === "local" && axis !== "XYZ") {
|
|
1371
|
+
this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale);
|
|
1372
|
+
} else {
|
|
1373
|
+
this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale);
|
|
634
1374
|
}
|
|
1375
|
+
object.position.copy(this._offset).add(this._positionStart);
|
|
1376
|
+
if (this.translationSnap) {
|
|
1377
|
+
if (space === "local") {
|
|
1378
|
+
object.position.applyQuaternion(_tempQuaternion.copy(this._quaternionStart).invert());
|
|
1379
|
+
if (axis.search("X") !== -1) {
|
|
1380
|
+
object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
|
|
1381
|
+
}
|
|
1382
|
+
if (axis.search("Y") !== -1) {
|
|
1383
|
+
object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
|
|
1384
|
+
}
|
|
1385
|
+
if (axis.search("Z") !== -1) {
|
|
1386
|
+
object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
|
|
1387
|
+
}
|
|
1388
|
+
object.position.applyQuaternion(this._quaternionStart);
|
|
1389
|
+
}
|
|
1390
|
+
if (space === "world") {
|
|
1391
|
+
if (object.parent) {
|
|
1392
|
+
object.position.add(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
|
|
1393
|
+
}
|
|
1394
|
+
if (axis.search("X") !== -1) {
|
|
1395
|
+
object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
|
|
1396
|
+
}
|
|
1397
|
+
if (axis.search("Y") !== -1) {
|
|
1398
|
+
object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
|
|
1399
|
+
}
|
|
1400
|
+
if (axis.search("Z") !== -1) {
|
|
1401
|
+
object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
|
|
1402
|
+
}
|
|
1403
|
+
if (object.parent) {
|
|
1404
|
+
object.position.sub(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
} else if (mode === "scale") {
|
|
1409
|
+
if (axis.search("XYZ") !== -1) {
|
|
1410
|
+
let d = this.pointEnd.length() / this.pointStart.length();
|
|
1411
|
+
if (this.pointEnd.dot(this.pointStart) < 0) d *= -1;
|
|
1412
|
+
_tempVector2.set(d, d, d);
|
|
1413
|
+
} else {
|
|
1414
|
+
_tempVector.copy(this.pointStart);
|
|
1415
|
+
_tempVector2.copy(this.pointEnd);
|
|
1416
|
+
_tempVector.applyQuaternion(this._worldQuaternionInv);
|
|
1417
|
+
_tempVector2.applyQuaternion(this._worldQuaternionInv);
|
|
1418
|
+
_tempVector2.divide(_tempVector);
|
|
1419
|
+
if (axis.search("X") === -1) {
|
|
1420
|
+
_tempVector2.x = 1;
|
|
1421
|
+
}
|
|
1422
|
+
if (axis.search("Y") === -1) {
|
|
1423
|
+
_tempVector2.y = 1;
|
|
1424
|
+
}
|
|
1425
|
+
if (axis.search("Z") === -1) {
|
|
1426
|
+
_tempVector2.z = 1;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
object.scale.copy(this._scaleStart).multiply(_tempVector2);
|
|
1430
|
+
if (this.scaleSnap) {
|
|
1431
|
+
if (axis.search("X") !== -1) {
|
|
1432
|
+
object.scale.x = Math.round(object.scale.x / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
1433
|
+
}
|
|
1434
|
+
if (axis.search("Y") !== -1) {
|
|
1435
|
+
object.scale.y = Math.round(object.scale.y / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
1436
|
+
}
|
|
1437
|
+
if (axis.search("Z") !== -1) {
|
|
1438
|
+
object.scale.z = Math.round(object.scale.z / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
} else if (mode === "rotate") {
|
|
1442
|
+
this._offset.copy(this.pointEnd).sub(this.pointStart);
|
|
1443
|
+
const ROTATION_SPEED = 20 / this.worldPosition.distanceTo(_tempVector.setFromMatrixPosition(this.camera.matrixWorld));
|
|
1444
|
+
if (axis === "E") {
|
|
1445
|
+
this.rotationAxis.copy(this.eye);
|
|
1446
|
+
this.rotationAngle = this.pointEnd.angleTo(this.pointStart);
|
|
1447
|
+
this._startNorm.copy(this.pointStart).normalize();
|
|
1448
|
+
this._endNorm.copy(this.pointEnd).normalize();
|
|
1449
|
+
this.rotationAngle *= this._endNorm.cross(this._startNorm).dot(this.eye) < 0 ? 1 : -1;
|
|
1450
|
+
} else if (axis === "XYZE") {
|
|
1451
|
+
this.rotationAxis.copy(this._offset).cross(this.eye).normalize();
|
|
1452
|
+
this.rotationAngle = this._offset.dot(_tempVector.copy(this.rotationAxis).cross(this.eye)) * ROTATION_SPEED;
|
|
1453
|
+
} else if (axis === "X" || axis === "Y" || axis === "Z") {
|
|
1454
|
+
this.rotationAxis.copy(_unit[axis]);
|
|
1455
|
+
_tempVector.copy(_unit[axis]);
|
|
1456
|
+
if (space === "local") {
|
|
1457
|
+
_tempVector.applyQuaternion(this.worldQuaternion);
|
|
1458
|
+
}
|
|
1459
|
+
this.rotationAngle = this._offset.dot(_tempVector.cross(this.eye).normalize()) * ROTATION_SPEED;
|
|
1460
|
+
}
|
|
1461
|
+
if (this.rotationSnap) this.rotationAngle = Math.round(this.rotationAngle / this.rotationSnap) * this.rotationSnap;
|
|
1462
|
+
if (space === "local" && axis !== "E" && axis !== "XYZE") {
|
|
1463
|
+
object.quaternion.copy(this._quaternionStart);
|
|
1464
|
+
object.quaternion.multiply(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle)).normalize();
|
|
1465
|
+
} else {
|
|
1466
|
+
this.rotationAxis.applyQuaternion(this._parentQuaternionInv);
|
|
1467
|
+
object.quaternion.copy(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle));
|
|
1468
|
+
object.quaternion.multiply(this._quaternionStart).normalize();
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
this.dispatchEvent(_changeEvent);
|
|
1472
|
+
this.dispatchEvent(_objectChangeEvent);
|
|
1473
|
+
}
|
|
1474
|
+
pointerUp(pointer) {
|
|
1475
|
+
if (pointer.button !== 0) return;
|
|
1476
|
+
if (this.dragging && this.axis !== null) {
|
|
1477
|
+
_mouseUpEvent.mode = this.mode;
|
|
1478
|
+
this.dispatchEvent(_mouseUpEvent);
|
|
1479
|
+
}
|
|
1480
|
+
this.dragging = false;
|
|
1481
|
+
this.axis = null;
|
|
1482
|
+
}
|
|
1483
|
+
dispose() {
|
|
1484
|
+
this.domElement.removeEventListener("pointerdown", this._onPointerDown);
|
|
1485
|
+
this.domElement.removeEventListener("pointermove", this._onPointerHover);
|
|
1486
|
+
this.domElement.removeEventListener("pointermove", this._onPointerMove);
|
|
1487
|
+
this.domElement.removeEventListener("pointerup", this._onPointerUp);
|
|
1488
|
+
this.traverse((function(child) {
|
|
1489
|
+
if (child.geometry) child.geometry.dispose();
|
|
1490
|
+
if (child.material) child.material.dispose();
|
|
1491
|
+
}));
|
|
1492
|
+
}
|
|
1493
|
+
attach(object) {
|
|
1494
|
+
this.object = object;
|
|
1495
|
+
this.visible = true;
|
|
1496
|
+
return this;
|
|
1497
|
+
}
|
|
1498
|
+
detach() {
|
|
1499
|
+
this.object = undefined;
|
|
1500
|
+
this.visible = false;
|
|
1501
|
+
this.axis = null;
|
|
1502
|
+
return this;
|
|
1503
|
+
}
|
|
1504
|
+
reset() {
|
|
1505
|
+
if (!this.enabled) return;
|
|
1506
|
+
if (this.dragging) {
|
|
1507
|
+
this.object.position.copy(this._positionStart);
|
|
1508
|
+
this.object.quaternion.copy(this._quaternionStart);
|
|
1509
|
+
this.object.scale.copy(this._scaleStart);
|
|
1510
|
+
this.dispatchEvent(_changeEvent);
|
|
1511
|
+
this.dispatchEvent(_objectChangeEvent);
|
|
1512
|
+
this.pointStart.copy(this.pointEnd);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
getRaycaster() {
|
|
1516
|
+
return _raycaster;
|
|
1517
|
+
}
|
|
1518
|
+
getMode() {
|
|
1519
|
+
return this.mode;
|
|
1520
|
+
}
|
|
1521
|
+
setMode(mode) {
|
|
1522
|
+
this.mode = mode;
|
|
1523
|
+
}
|
|
1524
|
+
setTranslationSnap(translationSnap) {
|
|
1525
|
+
this.translationSnap = translationSnap;
|
|
1526
|
+
}
|
|
1527
|
+
setRotationSnap(rotationSnap) {
|
|
1528
|
+
this.rotationSnap = rotationSnap;
|
|
1529
|
+
}
|
|
1530
|
+
setScaleSnap(scaleSnap) {
|
|
1531
|
+
this.scaleSnap = scaleSnap;
|
|
1532
|
+
}
|
|
1533
|
+
setSize(size) {
|
|
1534
|
+
this.size = size;
|
|
1535
|
+
}
|
|
1536
|
+
setSpace(space) {
|
|
1537
|
+
this.space = space;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
function getPointer(event) {
|
|
1542
|
+
if (this.domElement.ownerDocument.pointerLockElement) {
|
|
1543
|
+
return {
|
|
1544
|
+
x: 0,
|
|
1545
|
+
y: 0,
|
|
1546
|
+
button: event.button
|
|
635
1547
|
};
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
1548
|
+
} else {
|
|
1549
|
+
const rect = this.domElement.getBoundingClientRect();
|
|
1550
|
+
return {
|
|
1551
|
+
x: (event.clientX - rect.left) / rect.width * 2 - 1,
|
|
1552
|
+
y: -(event.clientY - rect.top) / rect.height * 2 + 1,
|
|
1553
|
+
button: event.button
|
|
640
1554
|
};
|
|
641
|
-
this.viewer = viewer;
|
|
642
|
-
this._target = new THREE.Vector3;
|
|
643
|
-
this.quaternion = this.viewer.camera.quaternion.clone();
|
|
644
|
-
this.xRotation = new THREE.Quaternion;
|
|
645
|
-
this.yRotation = new THREE.Quaternion;
|
|
646
|
-
this.mouseStart = new THREE.Vector2;
|
|
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);
|
|
667
1555
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
this.
|
|
676
|
-
|
|
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);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
function onPointerHover(event) {
|
|
1559
|
+
if (!this.enabled) return;
|
|
1560
|
+
switch (event.pointerType) {
|
|
1561
|
+
case "mouse":
|
|
1562
|
+
case "pen":
|
|
1563
|
+
this.pointerHover(this._getPointer(event));
|
|
1564
|
+
break;
|
|
697
1565
|
}
|
|
698
1566
|
}
|
|
699
1567
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1568
|
+
function onPointerDown(event) {
|
|
1569
|
+
if (!this.enabled) return;
|
|
1570
|
+
if (!document.pointerLockElement) {
|
|
1571
|
+
this.domElement.setPointerCapture(event.pointerId);
|
|
1572
|
+
}
|
|
1573
|
+
this.domElement.addEventListener("pointermove", this._onPointerMove);
|
|
1574
|
+
this.pointerHover(this._getPointer(event));
|
|
1575
|
+
this.pointerDown(this._getPointer(event));
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
function onPointerMove(event) {
|
|
1579
|
+
if (!this.enabled) return;
|
|
1580
|
+
this.pointerMove(this._getPointer(event));
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
function onPointerUp(event) {
|
|
1584
|
+
if (!this.enabled) return;
|
|
1585
|
+
this.domElement.releasePointerCapture(event.pointerId);
|
|
1586
|
+
this.domElement.removeEventListener("pointermove", this._onPointerMove);
|
|
1587
|
+
this.pointerUp(this._getPointer(event));
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
function intersectObjectWithRay(object, raycaster, includeInvisible) {
|
|
1591
|
+
const allIntersections = raycaster.intersectObject(object, true);
|
|
1592
|
+
for (let i = 0; i < allIntersections.length; i++) {
|
|
1593
|
+
if (allIntersections[i].object.visible || includeInvisible) {
|
|
1594
|
+
return allIntersections[i];
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
return false;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
const _tempEuler = new Euler;
|
|
1601
|
+
|
|
1602
|
+
const _alignVector = new Vector3(0, 1, 0);
|
|
1603
|
+
|
|
1604
|
+
const _zeroVector = new Vector3(0, 0, 0);
|
|
1605
|
+
|
|
1606
|
+
const _lookAtMatrix = new Matrix4;
|
|
1607
|
+
|
|
1608
|
+
const _tempQuaternion2 = new Quaternion;
|
|
1609
|
+
|
|
1610
|
+
const _identityQuaternion = new Quaternion;
|
|
1611
|
+
|
|
1612
|
+
const _dirVector = new Vector3;
|
|
1613
|
+
|
|
1614
|
+
const _tempMatrix = new Matrix4;
|
|
1615
|
+
|
|
1616
|
+
const _unitX = new Vector3(1, 0, 0);
|
|
1617
|
+
|
|
1618
|
+
const _unitY = new Vector3(0, 1, 0);
|
|
1619
|
+
|
|
1620
|
+
const _unitZ = new Vector3(0, 0, 1);
|
|
1621
|
+
|
|
1622
|
+
const _v1 = new Vector3;
|
|
1623
|
+
|
|
1624
|
+
const _v2 = new Vector3;
|
|
1625
|
+
|
|
1626
|
+
const _v3 = new Vector3;
|
|
1627
|
+
|
|
1628
|
+
class TransformControlsGizmo extends Object3D {
|
|
1629
|
+
constructor() {
|
|
1630
|
+
super();
|
|
1631
|
+
this.isTransformControlsGizmo = true;
|
|
1632
|
+
this.type = "TransformControlsGizmo";
|
|
1633
|
+
const gizmoMaterial = new MeshBasicMaterial({
|
|
1634
|
+
depthTest: false,
|
|
1635
|
+
depthWrite: false,
|
|
1636
|
+
fog: false,
|
|
1637
|
+
toneMapped: false,
|
|
1638
|
+
transparent: true
|
|
1639
|
+
});
|
|
1640
|
+
const gizmoLineMaterial = new LineBasicMaterial({
|
|
1641
|
+
depthTest: false,
|
|
1642
|
+
depthWrite: false,
|
|
1643
|
+
fog: false,
|
|
1644
|
+
toneMapped: false,
|
|
1645
|
+
transparent: true
|
|
1646
|
+
});
|
|
1647
|
+
const matInvisible = gizmoMaterial.clone();
|
|
1648
|
+
matInvisible.opacity = .15;
|
|
1649
|
+
const matHelper = gizmoLineMaterial.clone();
|
|
1650
|
+
matHelper.opacity = .5;
|
|
1651
|
+
const matRed = gizmoMaterial.clone();
|
|
1652
|
+
matRed.color.setHex(16711680);
|
|
1653
|
+
const matGreen = gizmoMaterial.clone();
|
|
1654
|
+
matGreen.color.setHex(65280);
|
|
1655
|
+
const matBlue = gizmoMaterial.clone();
|
|
1656
|
+
matBlue.color.setHex(255);
|
|
1657
|
+
const matRedTransparent = gizmoMaterial.clone();
|
|
1658
|
+
matRedTransparent.color.setHex(16711680);
|
|
1659
|
+
matRedTransparent.opacity = .5;
|
|
1660
|
+
const matGreenTransparent = gizmoMaterial.clone();
|
|
1661
|
+
matGreenTransparent.color.setHex(65280);
|
|
1662
|
+
matGreenTransparent.opacity = .5;
|
|
1663
|
+
const matBlueTransparent = gizmoMaterial.clone();
|
|
1664
|
+
matBlueTransparent.color.setHex(255);
|
|
1665
|
+
matBlueTransparent.opacity = .5;
|
|
1666
|
+
const matWhiteTransparent = gizmoMaterial.clone();
|
|
1667
|
+
matWhiteTransparent.opacity = .25;
|
|
1668
|
+
const matYellowTransparent = gizmoMaterial.clone();
|
|
1669
|
+
matYellowTransparent.color.setHex(16776960);
|
|
1670
|
+
matYellowTransparent.opacity = .25;
|
|
1671
|
+
const matYellow = gizmoMaterial.clone();
|
|
1672
|
+
matYellow.color.setHex(16776960);
|
|
1673
|
+
const matGray = gizmoMaterial.clone();
|
|
1674
|
+
matGray.color.setHex(7895160);
|
|
1675
|
+
const arrowGeometry = new CylinderGeometry(0, .04, .1, 12);
|
|
1676
|
+
arrowGeometry.translate(0, .05, 0);
|
|
1677
|
+
const scaleHandleGeometry = new BoxGeometry(.08, .08, .08);
|
|
1678
|
+
scaleHandleGeometry.translate(0, .04, 0);
|
|
1679
|
+
const lineGeometry = new BufferGeometry;
|
|
1680
|
+
lineGeometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 0, 0 ], 3));
|
|
1681
|
+
const lineGeometry2 = new CylinderGeometry(.0075, .0075, .5, 3);
|
|
1682
|
+
lineGeometry2.translate(0, .25, 0);
|
|
1683
|
+
function CircleGeometry(radius, arc) {
|
|
1684
|
+
const geometry = new TorusGeometry(radius, .0075, 3, 64, arc * Math.PI * 2);
|
|
1685
|
+
geometry.rotateY(Math.PI / 2);
|
|
1686
|
+
geometry.rotateX(Math.PI / 2);
|
|
1687
|
+
return geometry;
|
|
1688
|
+
}
|
|
1689
|
+
function TranslateHelperGeometry() {
|
|
1690
|
+
const geometry = new BufferGeometry;
|
|
1691
|
+
geometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 1, 1 ], 3));
|
|
1692
|
+
return geometry;
|
|
1693
|
+
}
|
|
1694
|
+
const gizmoTranslate = {
|
|
1695
|
+
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 ] ] ],
|
|
1696
|
+
Y: [ [ new Mesh(arrowGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(arrowGeometry, matGreen), [ 0, -.5, 0 ], [ Math.PI, 0, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ] ],
|
|
1697
|
+
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 ] ] ],
|
|
1698
|
+
XYZ: [ [ new Mesh(new OctahedronGeometry(.1, 0), matWhiteTransparent.clone()), [ 0, 0, 0 ] ] ],
|
|
1699
|
+
XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent.clone()), [ .15, .15, 0 ] ] ],
|
|
1700
|
+
YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent.clone()), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
1701
|
+
XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent.clone()), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
|
|
709
1702
|
};
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
1703
|
+
const pickerTranslate = {
|
|
1704
|
+
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 ] ] ],
|
|
1705
|
+
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 ] ] ],
|
|
1706
|
+
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 ] ] ],
|
|
1707
|
+
XYZ: [ [ new Mesh(new OctahedronGeometry(.2, 0), matInvisible) ] ],
|
|
1708
|
+
XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
|
|
1709
|
+
YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
1710
|
+
XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
|
|
1711
|
+
};
|
|
1712
|
+
const helperTranslate = {
|
|
1713
|
+
START: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
|
|
1714
|
+
END: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
|
|
1715
|
+
DELTA: [ [ new Line(TranslateHelperGeometry(), matHelper), null, null, null, "helper" ] ],
|
|
1716
|
+
X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
|
|
1717
|
+
Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
|
|
1718
|
+
Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
|
|
1719
|
+
};
|
|
1720
|
+
const gizmoRotate = {
|
|
1721
|
+
XYZE: [ [ new Mesh(CircleGeometry(.5, 1), matGray), null, [ 0, Math.PI / 2, 0 ] ] ],
|
|
1722
|
+
X: [ [ new Mesh(CircleGeometry(.5, .5), matRed) ] ],
|
|
1723
|
+
Y: [ [ new Mesh(CircleGeometry(.5, .5), matGreen), null, [ 0, 0, -Math.PI / 2 ] ] ],
|
|
1724
|
+
Z: [ [ new Mesh(CircleGeometry(.5, .5), matBlue), null, [ 0, Math.PI / 2, 0 ] ] ],
|
|
1725
|
+
E: [ [ new Mesh(CircleGeometry(.75, 1), matYellowTransparent), null, [ 0, Math.PI / 2, 0 ] ] ]
|
|
1726
|
+
};
|
|
1727
|
+
const helperRotate = {
|
|
1728
|
+
AXIS: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ]
|
|
1729
|
+
};
|
|
1730
|
+
const pickerRotate = {
|
|
1731
|
+
XYZE: [ [ new Mesh(new SphereGeometry(.25, 10, 8), matInvisible) ] ],
|
|
1732
|
+
X: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ] ],
|
|
1733
|
+
Y: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ] ],
|
|
1734
|
+
Z: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] ],
|
|
1735
|
+
E: [ [ new Mesh(new TorusGeometry(.75, .1, 2, 24), matInvisible) ] ]
|
|
1736
|
+
};
|
|
1737
|
+
const gizmoScale = {
|
|
1738
|
+
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 ] ] ],
|
|
1739
|
+
Y: [ [ new Mesh(scaleHandleGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ], [ new Mesh(scaleHandleGeometry, matGreen), [ 0, -.5, 0 ], [ 0, 0, Math.PI ] ] ],
|
|
1740
|
+
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 ] ] ],
|
|
1741
|
+
XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent), [ .15, .15, 0 ] ] ],
|
|
1742
|
+
YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
1743
|
+
XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
1744
|
+
XYZ: [ [ new Mesh(new BoxGeometry(.1, .1, .1), matWhiteTransparent.clone()) ] ]
|
|
1745
|
+
};
|
|
1746
|
+
const pickerScale = {
|
|
1747
|
+
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 ] ] ],
|
|
1748
|
+
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 ] ] ],
|
|
1749
|
+
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 ] ] ],
|
|
1750
|
+
XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
|
|
1751
|
+
YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
|
|
1752
|
+
XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
|
|
1753
|
+
XYZ: [ [ new Mesh(new BoxGeometry(.2, .2, .2), matInvisible), [ 0, 0, 0 ] ] ]
|
|
1754
|
+
};
|
|
1755
|
+
const helperScale = {
|
|
1756
|
+
X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
|
|
1757
|
+
Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
|
|
1758
|
+
Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
|
|
1759
|
+
};
|
|
1760
|
+
function setupGizmo(gizmoMap) {
|
|
1761
|
+
const gizmo = new Object3D;
|
|
1762
|
+
for (const name in gizmoMap) {
|
|
1763
|
+
for (let i = gizmoMap[name].length; i--; ) {
|
|
1764
|
+
const object = gizmoMap[name][i][0].clone();
|
|
1765
|
+
const position = gizmoMap[name][i][1];
|
|
1766
|
+
const rotation = gizmoMap[name][i][2];
|
|
1767
|
+
const scale = gizmoMap[name][i][3];
|
|
1768
|
+
const tag = gizmoMap[name][i][4];
|
|
1769
|
+
object.name = name;
|
|
1770
|
+
object.tag = tag;
|
|
1771
|
+
if (position) {
|
|
1772
|
+
object.position.set(position[0], position[1], position[2]);
|
|
1773
|
+
}
|
|
1774
|
+
if (rotation) {
|
|
1775
|
+
object.rotation.set(rotation[0], rotation[1], rotation[2]);
|
|
1776
|
+
}
|
|
1777
|
+
if (scale) {
|
|
1778
|
+
object.scale.set(scale[0], scale[1], scale[2]);
|
|
1779
|
+
}
|
|
1780
|
+
object.updateMatrix();
|
|
1781
|
+
const tempGeometry = object.geometry.clone();
|
|
1782
|
+
tempGeometry.applyMatrix4(object.matrix);
|
|
1783
|
+
object.geometry = tempGeometry;
|
|
1784
|
+
object.renderOrder = Infinity;
|
|
1785
|
+
object.position.set(0, 0, 0);
|
|
1786
|
+
object.rotation.set(0, 0, 0);
|
|
1787
|
+
object.scale.set(1, 1, 1);
|
|
1788
|
+
gizmo.add(object);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
return gizmo;
|
|
1792
|
+
}
|
|
1793
|
+
this.gizmo = {};
|
|
1794
|
+
this.picker = {};
|
|
1795
|
+
this.helper = {};
|
|
1796
|
+
this.add(this.gizmo["translate"] = setupGizmo(gizmoTranslate));
|
|
1797
|
+
this.add(this.gizmo["rotate"] = setupGizmo(gizmoRotate));
|
|
1798
|
+
this.add(this.gizmo["scale"] = setupGizmo(gizmoScale));
|
|
1799
|
+
this.add(this.picker["translate"] = setupGizmo(pickerTranslate));
|
|
1800
|
+
this.add(this.picker["rotate"] = setupGizmo(pickerRotate));
|
|
1801
|
+
this.add(this.picker["scale"] = setupGizmo(pickerScale));
|
|
1802
|
+
this.add(this.helper["translate"] = setupGizmo(helperTranslate));
|
|
1803
|
+
this.add(this.helper["rotate"] = setupGizmo(helperRotate));
|
|
1804
|
+
this.add(this.helper["scale"] = setupGizmo(helperScale));
|
|
1805
|
+
this.picker["translate"].visible = false;
|
|
1806
|
+
this.picker["rotate"].visible = false;
|
|
1807
|
+
this.picker["scale"].visible = false;
|
|
1808
|
+
}
|
|
1809
|
+
updateMatrixWorld(force) {
|
|
1810
|
+
const space = this.mode === "scale" ? "local" : this.space;
|
|
1811
|
+
const quaternion = space === "local" ? this.worldQuaternion : _identityQuaternion;
|
|
1812
|
+
this.gizmo["translate"].visible = this.mode === "translate";
|
|
1813
|
+
this.gizmo["rotate"].visible = this.mode === "rotate";
|
|
1814
|
+
this.gizmo["scale"].visible = this.mode === "scale";
|
|
1815
|
+
this.helper["translate"].visible = this.mode === "translate";
|
|
1816
|
+
this.helper["rotate"].visible = this.mode === "rotate";
|
|
1817
|
+
this.helper["scale"].visible = this.mode === "scale";
|
|
1818
|
+
let handles = [];
|
|
1819
|
+
handles = handles.concat(this.picker[this.mode].children);
|
|
1820
|
+
handles = handles.concat(this.gizmo[this.mode].children);
|
|
1821
|
+
handles = handles.concat(this.helper[this.mode].children);
|
|
1822
|
+
for (let i = 0; i < handles.length; i++) {
|
|
1823
|
+
const handle = handles[i];
|
|
1824
|
+
handle.visible = true;
|
|
1825
|
+
handle.rotation.set(0, 0, 0);
|
|
1826
|
+
handle.position.copy(this.worldPosition);
|
|
1827
|
+
let factor;
|
|
1828
|
+
if (this.camera.isOrthographicCamera) {
|
|
1829
|
+
factor = (this.camera.top - this.camera.bottom) / this.camera.zoom;
|
|
716
1830
|
} else {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1831
|
+
factor = this.worldPosition.distanceTo(this.cameraPosition) * Math.min(1.9 * Math.tan(Math.PI * this.camera.fov / 360) / this.camera.zoom, 7);
|
|
1832
|
+
}
|
|
1833
|
+
handle.scale.set(1, 1, 1).multiplyScalar(factor * this.size / 4);
|
|
1834
|
+
if (handle.tag === "helper") {
|
|
1835
|
+
handle.visible = false;
|
|
1836
|
+
if (handle.name === "AXIS") {
|
|
1837
|
+
handle.visible = !!this.axis;
|
|
1838
|
+
if (this.axis === "X") {
|
|
1839
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0));
|
|
1840
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
1841
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
1842
|
+
handle.visible = false;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
if (this.axis === "Y") {
|
|
1846
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, 0, Math.PI / 2));
|
|
1847
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
1848
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
1849
|
+
handle.visible = false;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
if (this.axis === "Z") {
|
|
1853
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
|
|
1854
|
+
handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
|
|
1855
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > .9) {
|
|
1856
|
+
handle.visible = false;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
if (this.axis === "XYZE") {
|
|
1860
|
+
_tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
|
|
1861
|
+
_alignVector.copy(this.rotationAxis);
|
|
1862
|
+
handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY));
|
|
1863
|
+
handle.quaternion.multiply(_tempQuaternion);
|
|
1864
|
+
handle.visible = this.dragging;
|
|
1865
|
+
}
|
|
1866
|
+
if (this.axis === "E") {
|
|
1867
|
+
handle.visible = false;
|
|
1868
|
+
}
|
|
1869
|
+
} else if (handle.name === "START") {
|
|
1870
|
+
handle.position.copy(this.worldPositionStart);
|
|
1871
|
+
handle.visible = this.dragging;
|
|
1872
|
+
} else if (handle.name === "END") {
|
|
1873
|
+
handle.position.copy(this.worldPosition);
|
|
1874
|
+
handle.visible = this.dragging;
|
|
1875
|
+
} else if (handle.name === "DELTA") {
|
|
1876
|
+
handle.position.copy(this.worldPositionStart);
|
|
1877
|
+
handle.quaternion.copy(this.worldQuaternionStart);
|
|
1878
|
+
_tempVector.set(1e-10, 1e-10, 1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1);
|
|
1879
|
+
_tempVector.applyQuaternion(this.worldQuaternionStart.clone().invert());
|
|
1880
|
+
handle.scale.copy(_tempVector);
|
|
1881
|
+
handle.visible = this.dragging;
|
|
1882
|
+
} else {
|
|
1883
|
+
handle.quaternion.copy(quaternion);
|
|
1884
|
+
if (this.dragging) {
|
|
1885
|
+
handle.position.copy(this.worldPositionStart);
|
|
1886
|
+
} else {
|
|
1887
|
+
handle.position.copy(this.worldPosition);
|
|
1888
|
+
}
|
|
1889
|
+
if (this.axis) {
|
|
1890
|
+
handle.visible = this.axis.search(handle.name) !== -1;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
continue;
|
|
1894
|
+
}
|
|
1895
|
+
handle.quaternion.copy(quaternion);
|
|
1896
|
+
if (this.mode === "translate" || this.mode === "scale") {
|
|
1897
|
+
const AXIS_HIDE_THRESHOLD = .99;
|
|
1898
|
+
const PLANE_HIDE_THRESHOLD = .2;
|
|
1899
|
+
if (handle.name === "X") {
|
|
1900
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
1901
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1902
|
+
handle.visible = false;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
if (handle.name === "Y") {
|
|
1906
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
1907
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1908
|
+
handle.visible = false;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
if (handle.name === "Z") {
|
|
1912
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
|
|
1913
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1914
|
+
handle.visible = false;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
if (handle.name === "XY") {
|
|
1918
|
+
if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
1919
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1920
|
+
handle.visible = false;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
if (handle.name === "YZ") {
|
|
1924
|
+
if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
1925
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1926
|
+
handle.visible = false;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
if (handle.name === "XZ") {
|
|
1930
|
+
if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
|
|
1931
|
+
handle.scale.set(1e-10, 1e-10, 1e-10);
|
|
1932
|
+
handle.visible = false;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
} else if (this.mode === "rotate") {
|
|
1936
|
+
_tempQuaternion2.copy(quaternion);
|
|
1937
|
+
_alignVector.copy(this.eye).applyQuaternion(_tempQuaternion.copy(quaternion).invert());
|
|
1938
|
+
if (handle.name.search("E") !== -1) {
|
|
1939
|
+
handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY));
|
|
1940
|
+
}
|
|
1941
|
+
if (handle.name === "X") {
|
|
1942
|
+
_tempQuaternion.setFromAxisAngle(_unitX, Math.atan2(-_alignVector.y, _alignVector.z));
|
|
1943
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
1944
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
1945
|
+
}
|
|
1946
|
+
if (handle.name === "Y") {
|
|
1947
|
+
_tempQuaternion.setFromAxisAngle(_unitY, Math.atan2(_alignVector.x, _alignVector.z));
|
|
1948
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
1949
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
1950
|
+
}
|
|
1951
|
+
if (handle.name === "Z") {
|
|
1952
|
+
_tempQuaternion.setFromAxisAngle(_unitZ, Math.atan2(_alignVector.y, _alignVector.x));
|
|
1953
|
+
_tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
|
|
1954
|
+
handle.quaternion.copy(_tempQuaternion);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
handle.visible = handle.visible && (handle.name.indexOf("X") === -1 || this.showX);
|
|
1958
|
+
handle.visible = handle.visible && (handle.name.indexOf("Y") === -1 || this.showY);
|
|
1959
|
+
handle.visible = handle.visible && (handle.name.indexOf("Z") === -1 || this.showZ);
|
|
1960
|
+
handle.visible = handle.visible && (handle.name.indexOf("E") === -1 || this.showX && this.showY && this.showZ);
|
|
1961
|
+
handle.material._color = handle.material._color || handle.material.color.clone();
|
|
1962
|
+
handle.material._opacity = handle.material._opacity || handle.material.opacity;
|
|
1963
|
+
handle.material.color.copy(handle.material._color);
|
|
1964
|
+
handle.material.opacity = handle.material._opacity;
|
|
1965
|
+
if (this.enabled && this.axis) {
|
|
1966
|
+
if (handle.name === this.axis) {
|
|
1967
|
+
handle.material.color.setHex(16776960);
|
|
1968
|
+
handle.material.opacity = 1;
|
|
1969
|
+
} else if (this.axis.split("").some((function(a) {
|
|
1970
|
+
return handle.name === a;
|
|
1971
|
+
}))) {
|
|
1972
|
+
handle.material.color.setHex(16776960);
|
|
1973
|
+
handle.material.opacity = 1;
|
|
1974
|
+
}
|
|
720
1975
|
}
|
|
1976
|
+
}
|
|
1977
|
+
super.updateMatrixWorld(force);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
class TransformControlsPlane extends Mesh {
|
|
1982
|
+
constructor() {
|
|
1983
|
+
super(new PlaneGeometry(1e5, 1e5, 2, 2), new MeshBasicMaterial({
|
|
1984
|
+
visible: false,
|
|
1985
|
+
wireframe: true,
|
|
1986
|
+
side: DoubleSide,
|
|
1987
|
+
transparent: true,
|
|
1988
|
+
opacity: .1,
|
|
1989
|
+
toneMapped: false
|
|
1990
|
+
}));
|
|
1991
|
+
this.isTransformControlsPlane = true;
|
|
1992
|
+
this.type = "TransformControlsPlane";
|
|
1993
|
+
}
|
|
1994
|
+
updateMatrixWorld(force) {
|
|
1995
|
+
let space = this.space;
|
|
1996
|
+
this.position.copy(this.worldPosition);
|
|
1997
|
+
if (this.mode === "scale") space = "local";
|
|
1998
|
+
_v1.copy(_unitX).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
1999
|
+
_v2.copy(_unitY).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
2000
|
+
_v3.copy(_unitZ).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
|
|
2001
|
+
_alignVector.copy(_v2);
|
|
2002
|
+
switch (this.mode) {
|
|
2003
|
+
case "translate":
|
|
2004
|
+
case "scale":
|
|
2005
|
+
switch (this.axis) {
|
|
2006
|
+
case "X":
|
|
2007
|
+
_alignVector.copy(this.eye).cross(_v1);
|
|
2008
|
+
_dirVector.copy(_v1).cross(_alignVector);
|
|
2009
|
+
break;
|
|
2010
|
+
|
|
2011
|
+
case "Y":
|
|
2012
|
+
_alignVector.copy(this.eye).cross(_v2);
|
|
2013
|
+
_dirVector.copy(_v2).cross(_alignVector);
|
|
2014
|
+
break;
|
|
2015
|
+
|
|
2016
|
+
case "Z":
|
|
2017
|
+
_alignVector.copy(this.eye).cross(_v3);
|
|
2018
|
+
_dirVector.copy(_v3).cross(_alignVector);
|
|
2019
|
+
break;
|
|
2020
|
+
|
|
2021
|
+
case "XY":
|
|
2022
|
+
_dirVector.copy(_v3);
|
|
2023
|
+
break;
|
|
2024
|
+
|
|
2025
|
+
case "YZ":
|
|
2026
|
+
_dirVector.copy(_v1);
|
|
2027
|
+
break;
|
|
2028
|
+
|
|
2029
|
+
case "XZ":
|
|
2030
|
+
_alignVector.copy(_v3);
|
|
2031
|
+
_dirVector.copy(_v2);
|
|
2032
|
+
break;
|
|
2033
|
+
|
|
2034
|
+
case "XYZ":
|
|
2035
|
+
case "E":
|
|
2036
|
+
_dirVector.set(0, 0, 0);
|
|
2037
|
+
break;
|
|
2038
|
+
}
|
|
2039
|
+
break;
|
|
2040
|
+
|
|
2041
|
+
case "rotate":
|
|
2042
|
+
default:
|
|
2043
|
+
_dirVector.set(0, 0, 0);
|
|
2044
|
+
}
|
|
2045
|
+
if (_dirVector.length() === 0) {
|
|
2046
|
+
this.quaternion.copy(this.cameraQuaternion);
|
|
2047
|
+
} else {
|
|
2048
|
+
_tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector);
|
|
2049
|
+
this.quaternion.setFromRotationMatrix(_tempMatrix);
|
|
2050
|
+
}
|
|
2051
|
+
super.updateMatrixWorld(force);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
class PlaneHelper extends Line {
|
|
2056
|
+
constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
|
|
2057
|
+
const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
|
|
2058
|
+
const geometry = new BufferGeometry;
|
|
2059
|
+
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
2060
|
+
geometry.computeBoundingSphere();
|
|
2061
|
+
super(geometry, new LineBasicMaterial({
|
|
2062
|
+
color: color,
|
|
2063
|
+
toneMapped: false
|
|
2064
|
+
}));
|
|
2065
|
+
this.type = "PlaneHelper";
|
|
2066
|
+
this.plane = plane;
|
|
2067
|
+
this.size = size;
|
|
2068
|
+
this.offset = offset;
|
|
2069
|
+
const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
|
|
2070
|
+
const geometry2 = new BufferGeometry;
|
|
2071
|
+
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
2072
|
+
geometry2.computeBoundingSphere();
|
|
2073
|
+
this.helper = new Mesh(geometry2, new MeshBasicMaterial({
|
|
2074
|
+
color: color,
|
|
2075
|
+
opacity: .2,
|
|
2076
|
+
transparent: true,
|
|
2077
|
+
depthWrite: false,
|
|
2078
|
+
toneMapped: false,
|
|
2079
|
+
side: DoubleSide
|
|
2080
|
+
}));
|
|
2081
|
+
this.add(this.helper);
|
|
2082
|
+
}
|
|
2083
|
+
dispose() {
|
|
2084
|
+
this.geometry.dispose();
|
|
2085
|
+
this.material.dispose();
|
|
2086
|
+
this.children[0].geometry.dispose();
|
|
2087
|
+
this.children[0].material.dispose();
|
|
2088
|
+
}
|
|
2089
|
+
updateMatrixWorld(force) {
|
|
2090
|
+
this.position.set(0, 0, 0);
|
|
2091
|
+
this.lookAt(this.plane.normal);
|
|
2092
|
+
this.position.copy(this.offset);
|
|
2093
|
+
this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
|
|
2094
|
+
this.scale.set(.5 * this.size, .5 * this.size, 1);
|
|
2095
|
+
super.updateMatrixWorld(force);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
class CuttingPlaneDragger extends OrbitDragger {
|
|
2100
|
+
constructor(viewer, normal, color) {
|
|
2101
|
+
super(viewer);
|
|
2102
|
+
this.transformChange = () => {
|
|
2103
|
+
this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
|
|
2104
|
+
this.viewer.update();
|
|
721
2105
|
};
|
|
722
|
-
this.
|
|
723
|
-
|
|
724
|
-
this.end.set(offsetX, offsetY, .5);
|
|
725
|
-
this.end = this.screenToPlane(this.end);
|
|
726
|
-
this.delta.copy(this.end).sub(this.start);
|
|
727
|
-
this.start.copy(this.end);
|
|
728
|
-
const plane = this.plane;
|
|
729
|
-
plane.translate(this.delta);
|
|
2106
|
+
this.transformDrag = event => {
|
|
2107
|
+
this.orbit.enabled = !event.value;
|
|
730
2108
|
};
|
|
731
|
-
this.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
this.
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
2109
|
+
this.viewerExplode = () => {
|
|
2110
|
+
this.planeHelper.size = this.viewer.extents.getSize(new Vector3).length();
|
|
2111
|
+
this.viewer.update();
|
|
2112
|
+
};
|
|
2113
|
+
this.onDoubleClick = event => {
|
|
2114
|
+
event.stopPropagation();
|
|
2115
|
+
this.plane.negate();
|
|
2116
|
+
this.viewer.update();
|
|
2117
|
+
};
|
|
2118
|
+
const size = viewer.extents.getSize(new Vector3).length();
|
|
2119
|
+
const center = viewer.extents.getCenter(new Vector3);
|
|
2120
|
+
const constant = -center.dot(normal);
|
|
2121
|
+
this.plane = new Plane(normal, constant);
|
|
2122
|
+
if (!viewer.renderer.clippingPlanes) viewer.renderer.clippingPlanes = [];
|
|
2123
|
+
viewer.renderer.clippingPlanes.push(this.plane);
|
|
2124
|
+
this.planeHelper = new PlaneHelper(this.plane, size, color, center);
|
|
2125
|
+
this.viewer.helpers.add(this.planeHelper);
|
|
2126
|
+
this.planeCenter = new Object3D;
|
|
2127
|
+
this.planeCenter.position.copy(viewer.extents.getCenter(new Vector3));
|
|
2128
|
+
this.viewer.helpers.add(this.planeCenter);
|
|
2129
|
+
this.transform = new TransformControls(viewer.camera, viewer.canvas);
|
|
2130
|
+
this.transform.showX = !!normal.x;
|
|
2131
|
+
this.transform.showY = !!normal.y;
|
|
2132
|
+
this.transform.showZ = !!normal.z;
|
|
2133
|
+
this.transform.attach(this.planeCenter);
|
|
2134
|
+
this.transform.addEventListener("change", this.transformChange);
|
|
2135
|
+
this.transform.addEventListener("dragging-changed", this.transformDrag);
|
|
2136
|
+
this.viewer.helpers.add(this.transform);
|
|
2137
|
+
this.viewer.on("explode", this.viewerExplode);
|
|
2138
|
+
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
2139
|
+
this.viewer.update();
|
|
742
2140
|
}
|
|
743
2141
|
dispose() {
|
|
744
|
-
this.viewer.
|
|
745
|
-
this.viewer.removeEventListener("
|
|
746
|
-
this.
|
|
747
|
-
this.
|
|
2142
|
+
this.viewer.off("explode", this.viewerExplode);
|
|
2143
|
+
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
2144
|
+
this.transform.removeEventListener("change", this.transformChange);
|
|
2145
|
+
this.transform.removeEventListener("dragging-changed", this.transformDrag);
|
|
2146
|
+
this.transform.removeFromParent();
|
|
2147
|
+
this.transform.dispose();
|
|
748
2148
|
this.planeHelper.removeFromParent();
|
|
2149
|
+
this.planeHelper.dispose();
|
|
2150
|
+
this.planeCenter.removeFromParent();
|
|
2151
|
+
super.dispose();
|
|
749
2152
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
2156
|
+
constructor(viewer) {
|
|
2157
|
+
super(viewer, new Vector3(1, 0, 0), 16711680);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
2162
|
+
constructor(viewer) {
|
|
2163
|
+
super(viewer, new Vector3(0, 1, 0), 65280);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
2168
|
+
constructor(viewer) {
|
|
2169
|
+
super(viewer, new Vector3(0, 0, 1), 255);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
class ExtentsComponent {
|
|
2174
|
+
constructor(viewer) {
|
|
2175
|
+
this.syncExtents = () => {
|
|
2176
|
+
const extents = this.viewer.models.reduce(((result, gltf) => {
|
|
2177
|
+
const modelExtents = (new Box3).setFromObject(gltf.scene);
|
|
2178
|
+
return result.isEmpty() ? result.copy(modelExtents) : result.union(modelExtents);
|
|
2179
|
+
}), new Box3);
|
|
2180
|
+
this.viewer.extents.copy(extents);
|
|
2181
|
+
this.viewer.target.copy(extents.getCenter(new Vector3));
|
|
2182
|
+
};
|
|
2183
|
+
this.viewer = viewer;
|
|
2184
|
+
this.viewer.addEventListener("geometryend", this.syncExtents);
|
|
2185
|
+
this.viewer.addEventListener("clear", this.syncExtents);
|
|
2186
|
+
this.viewer.on("explode", this.syncExtents);
|
|
2187
|
+
}
|
|
2188
|
+
dispose() {
|
|
2189
|
+
this.viewer.removeEventListener("geometryend", this.syncExtents);
|
|
2190
|
+
this.viewer.removeEventListener("clear", this.syncExtents);
|
|
2191
|
+
this.viewer.off("explode", this.syncExtents);
|
|
768
2192
|
}
|
|
769
2193
|
}
|
|
770
2194
|
|
|
771
2195
|
class LightComponent {
|
|
772
2196
|
constructor(viewer) {
|
|
773
2197
|
this.viewer = viewer;
|
|
774
|
-
this.ambientLight = new
|
|
2198
|
+
this.ambientLight = new AmbientLight(16777215, 0);
|
|
775
2199
|
this.viewer.camera.add(this.ambientLight);
|
|
776
|
-
this.
|
|
777
|
-
this.
|
|
778
|
-
this.viewer.camera.add(this.
|
|
2200
|
+
this.directionalLight = new DirectionalLight(16777215, 1);
|
|
2201
|
+
this.directionalLight.position.set(.5, 0, .866);
|
|
2202
|
+
this.viewer.camera.add(this.directionalLight);
|
|
779
2203
|
}
|
|
780
2204
|
dispose() {
|
|
781
2205
|
this.ambientLight.removeFromParent();
|
|
782
|
-
this.
|
|
2206
|
+
this.ambientLight = undefined;
|
|
2207
|
+
this.directionalLight.removeFromParent();
|
|
2208
|
+
this.directionalLight = undefined;
|
|
783
2209
|
}
|
|
784
2210
|
}
|
|
785
2211
|
|
|
@@ -789,9 +2215,10 @@ class BackgroundComponent {
|
|
|
789
2215
|
this.backgroundColor.setHex(16777215);
|
|
790
2216
|
};
|
|
791
2217
|
this.viewer = viewer;
|
|
792
|
-
this.backgroundColor = new
|
|
2218
|
+
this.backgroundColor = new Color(16777215);
|
|
793
2219
|
const environment = new RoomEnvironment;
|
|
794
|
-
const pmremGenerator = new
|
|
2220
|
+
const pmremGenerator = new PMREMGenerator(this.viewer.renderer);
|
|
2221
|
+
this.viewer.renderer.setClearColor(this.backgroundColor);
|
|
795
2222
|
this.viewer.scene.background = this.backgroundColor;
|
|
796
2223
|
this.viewer.scene.environment = pmremGenerator.fromScene(environment).texture;
|
|
797
2224
|
this.viewer.addEventListener("optionschange", this.syncOptions);
|
|
@@ -804,26 +2231,16 @@ class BackgroundComponent {
|
|
|
804
2231
|
}
|
|
805
2232
|
}
|
|
806
2233
|
|
|
807
|
-
class
|
|
2234
|
+
class DefaultPositionComponent {
|
|
808
2235
|
constructor(viewer) {
|
|
809
2236
|
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;
|
|
2237
|
+
const box = this.viewer.extents;
|
|
2238
|
+
const size = box.getSize(new Vector3).length();
|
|
818
2239
|
this.viewer.camera.near = size / 100;
|
|
819
2240
|
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
2241
|
this.viewer.camera.updateMatrixWorld();
|
|
825
2242
|
this.viewer.camera.updateProjectionMatrix();
|
|
826
|
-
this.viewer.
|
|
2243
|
+
this.viewer.executeCommand("zoomToExtents");
|
|
827
2244
|
};
|
|
828
2245
|
this.viewer = viewer;
|
|
829
2246
|
this.viewer.addEventListener("geometryend", this.geometryEnd);
|
|
@@ -859,38 +2276,136 @@ class ResizeCanvasComponent {
|
|
|
859
2276
|
|
|
860
2277
|
class RenderLoopComponent {
|
|
861
2278
|
constructor(viewer) {
|
|
862
|
-
this.requestID = 0;
|
|
863
2279
|
this.animate = (time = 0) => {
|
|
864
|
-
this.
|
|
2280
|
+
this.requestId = requestAnimationFrame(this.animate);
|
|
865
2281
|
this.viewer.render(time);
|
|
866
2282
|
};
|
|
867
2283
|
this.viewer = viewer;
|
|
868
2284
|
this.animate();
|
|
869
2285
|
}
|
|
870
2286
|
dispose() {
|
|
871
|
-
cancelAnimationFrame(this.
|
|
2287
|
+
cancelAnimationFrame(this.requestId);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
class WCSHelper extends Object3D {
|
|
2292
|
+
constructor(camera) {
|
|
2293
|
+
super();
|
|
2294
|
+
this.camera = camera;
|
|
2295
|
+
this.size = 160;
|
|
2296
|
+
this.orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
|
|
2297
|
+
this.orthoCamera.position.set(0, 0, 2);
|
|
2298
|
+
const matRed = new MeshBasicMaterial({
|
|
2299
|
+
toneMapped: false,
|
|
2300
|
+
color: "#aa0000"
|
|
2301
|
+
});
|
|
2302
|
+
const matGreen = new MeshBasicMaterial({
|
|
2303
|
+
toneMapped: false,
|
|
2304
|
+
color: "#00aa00"
|
|
2305
|
+
});
|
|
2306
|
+
const matBlue = new MeshBasicMaterial({
|
|
2307
|
+
toneMapped: false,
|
|
2308
|
+
color: "#0000aa"
|
|
2309
|
+
});
|
|
2310
|
+
const spriteRed = this.getSpriteMaterial(matRed.color, "X");
|
|
2311
|
+
const spriteGreen = this.getSpriteMaterial(matGreen.color, "Y");
|
|
2312
|
+
const spriteBlue = this.getSpriteMaterial(matBlue.color, "Z");
|
|
2313
|
+
const lineGeometry = new CylinderGeometry(.01, .01, 1, 3);
|
|
2314
|
+
lineGeometry.translate(0, .5, 0);
|
|
2315
|
+
const arrowGeometry = new CylinderGeometry(0, .1, .25, 12);
|
|
2316
|
+
arrowGeometry.translate(0, .625, 0);
|
|
2317
|
+
const axesMap = {
|
|
2318
|
+
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 ] ] ],
|
|
2319
|
+
Y: [ [ new Mesh(arrowGeometry, matGreen), [ 0, .5, 0 ], null ], [ new Mesh(lineGeometry, matGreen), null, null ], [ new Sprite(spriteGreen), [ 0, 1.55, 0 ] ] ],
|
|
2320
|
+
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 ] ] ]
|
|
2321
|
+
};
|
|
2322
|
+
Object.keys(axesMap).forEach((key => {
|
|
2323
|
+
axesMap[key].forEach((objects => {
|
|
2324
|
+
const object = objects[0];
|
|
2325
|
+
const position = objects[1];
|
|
2326
|
+
const rotation = objects[2];
|
|
2327
|
+
object.name = key;
|
|
2328
|
+
if (position) object.position.set(position[0], position[1], position[2]);
|
|
2329
|
+
if (rotation) object.rotation.set(rotation[0], rotation[1], rotation[2]);
|
|
2330
|
+
object.updateMatrixWorld();
|
|
2331
|
+
this.add(object);
|
|
2332
|
+
}));
|
|
2333
|
+
}));
|
|
2334
|
+
}
|
|
2335
|
+
dispose() {
|
|
2336
|
+
this.traverse((object => {
|
|
2337
|
+
if (object.geometry) object.geometry.dispose();
|
|
2338
|
+
if (object.material) object.material.dispose();
|
|
2339
|
+
}));
|
|
2340
|
+
}
|
|
2341
|
+
getSpriteMaterial(color, text) {
|
|
2342
|
+
const canvas = document.createElement("canvas");
|
|
2343
|
+
canvas.width = 64;
|
|
2344
|
+
canvas.height = 64;
|
|
2345
|
+
const context = canvas.getContext("2d");
|
|
2346
|
+
context.clearRect(0, 0, 64, 64);
|
|
2347
|
+
context.font = "24px Arial";
|
|
2348
|
+
context.textAlign = "center";
|
|
2349
|
+
context.fillStyle = color.getStyle();
|
|
2350
|
+
context.fillText(text, 32, 41);
|
|
2351
|
+
const texture = new CanvasTexture(canvas);
|
|
2352
|
+
texture.colorSpace = SRGBColorSpace;
|
|
2353
|
+
return new SpriteMaterial({
|
|
2354
|
+
map: texture,
|
|
2355
|
+
toneMapped: false
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
render(renderer) {
|
|
2359
|
+
this.quaternion.copy(this.camera.quaternion).invert();
|
|
2360
|
+
this.updateMatrixWorld();
|
|
2361
|
+
const clippingPlanes = renderer.clippingPlanes;
|
|
2362
|
+
const viewport = renderer.getViewport(new Vector4);
|
|
2363
|
+
renderer.setViewport(this.position.x, this.position.y, this.size, this.size);
|
|
2364
|
+
renderer.clippingPlanes = [];
|
|
2365
|
+
renderer.clearDepth();
|
|
2366
|
+
renderer.render(this, this.orthoCamera);
|
|
2367
|
+
renderer.setViewport(viewport);
|
|
2368
|
+
renderer.clippingPlanes = clippingPlanes;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
class WCSHelperComponent {
|
|
2373
|
+
constructor(viewer) {
|
|
2374
|
+
this.viewerRender = () => {
|
|
2375
|
+
if (!this.viewer.extents.isEmpty()) this.wcsHelper.render(this.viewer.renderer);
|
|
2376
|
+
};
|
|
2377
|
+
this.wcsHelper = new WCSHelper(viewer.camera);
|
|
2378
|
+
this.viewer = viewer;
|
|
2379
|
+
this.viewer.addEventListener("render", this.viewerRender);
|
|
2380
|
+
}
|
|
2381
|
+
dispose() {
|
|
2382
|
+
this.viewer.removeEventListener("render", this.viewerRender);
|
|
2383
|
+
this.wcsHelper.dispose();
|
|
872
2384
|
}
|
|
873
2385
|
}
|
|
874
2386
|
|
|
875
2387
|
class Viewer extends EventEmitter2 {
|
|
876
2388
|
constructor(client) {
|
|
877
2389
|
super();
|
|
878
|
-
this.renderNeeded = false;
|
|
879
2390
|
this._options = new Options(this);
|
|
880
2391
|
this.client = client;
|
|
881
|
-
this.canvasEvents = CANVAS_EVENTS
|
|
2392
|
+
this.canvasEvents = CANVAS_EVENTS;
|
|
882
2393
|
this.canvaseventlistener = event => this.emit(event);
|
|
2394
|
+
this.extents = new Box3;
|
|
2395
|
+
this.target = new Vector3;
|
|
883
2396
|
this.draggerFactory = {
|
|
884
2397
|
Pan: PanDragger,
|
|
885
2398
|
Zoom: ZoomDragger,
|
|
886
2399
|
Orbit: OrbitDragger,
|
|
887
2400
|
Walk: WalkDragger,
|
|
888
|
-
|
|
2401
|
+
CuttingPlaneXAxis: CuttingPlaneXAxisDragger,
|
|
2402
|
+
CuttingPlaneYAxis: CuttingPlaneYAxisDragger,
|
|
2403
|
+
CuttingPlaneZAxis: CuttingPlaneZAxisDragger
|
|
889
2404
|
};
|
|
890
2405
|
this._activeDragger = null;
|
|
891
2406
|
this.models = [];
|
|
892
2407
|
this.components = [];
|
|
893
|
-
this.
|
|
2408
|
+
this.selected = [];
|
|
894
2409
|
this.renderTime = 0;
|
|
895
2410
|
this.render = this.render.bind(this);
|
|
896
2411
|
this.update = this.update.bind(this);
|
|
@@ -903,30 +2418,35 @@ class Viewer extends EventEmitter2 {
|
|
|
903
2418
|
}
|
|
904
2419
|
initialize(canvas, onProgress) {
|
|
905
2420
|
this.addEventListener("optionschange", (event => this.syncOptions(event.data)));
|
|
906
|
-
this.scene = new
|
|
2421
|
+
this.scene = new Scene;
|
|
2422
|
+
this.helpers = new Scene;
|
|
907
2423
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
908
2424
|
const width = rect.width || 1;
|
|
909
2425
|
const height = rect.height || 1;
|
|
910
|
-
this.camera = new
|
|
2426
|
+
this.camera = new PerspectiveCamera(45, width / height, .01, 1e3);
|
|
911
2427
|
this.camera.up.set(0, 0, 1);
|
|
912
|
-
this.renderer = new
|
|
2428
|
+
this.renderer = new WebGLRenderer({
|
|
913
2429
|
canvas: canvas,
|
|
914
|
-
antialias: true
|
|
2430
|
+
antialias: true,
|
|
2431
|
+
preserveDrawingBuffer: true
|
|
915
2432
|
});
|
|
916
2433
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
917
2434
|
this.renderer.setSize(width, height);
|
|
918
|
-
this.renderer.toneMapping =
|
|
2435
|
+
this.renderer.toneMapping = LinearToneMapping;
|
|
919
2436
|
this.canvas = canvas;
|
|
920
2437
|
this.canvasEvents.forEach((x => canvas.addEventListener(x, this.canvaseventlistener)));
|
|
2438
|
+
this.components.push(new ExtentsComponent(this));
|
|
921
2439
|
this.components.push(new LightComponent(this));
|
|
922
2440
|
this.components.push(new BackgroundComponent(this));
|
|
923
|
-
this.components.push(new
|
|
2441
|
+
this.components.push(new DefaultPositionComponent(this));
|
|
924
2442
|
this.components.push(new ResizeCanvasComponent(this));
|
|
925
2443
|
this.components.push(new RenderLoopComponent(this));
|
|
2444
|
+
this.components.push(new SelectionComponent(this));
|
|
2445
|
+
this.components.push(new WCSHelperComponent(this));
|
|
926
2446
|
this.syncOptions();
|
|
927
2447
|
this.renderTime = performance.now();
|
|
928
2448
|
this.render(this.renderTime);
|
|
929
|
-
if (onProgress) onProgress(new ProgressEvent("progress", {
|
|
2449
|
+
if (typeof onProgress === "function") onProgress(new ProgressEvent("progress", {
|
|
930
2450
|
lengthComputable: true,
|
|
931
2451
|
loaded: 1,
|
|
932
2452
|
total: 1
|
|
@@ -951,6 +2471,7 @@ class Viewer extends EventEmitter2 {
|
|
|
951
2471
|
this.components = [];
|
|
952
2472
|
this.setActiveDragger("");
|
|
953
2473
|
this.removeAllListeners();
|
|
2474
|
+
this.clear();
|
|
954
2475
|
if (this.canvas) {
|
|
955
2476
|
this.canvasEvents.forEach((x => this.canvas.removeEventListener(x, this.canvaseventlistener)));
|
|
956
2477
|
this.canvas = undefined;
|
|
@@ -959,6 +2480,7 @@ class Viewer extends EventEmitter2 {
|
|
|
959
2480
|
this.renderer = undefined;
|
|
960
2481
|
this.camera = undefined;
|
|
961
2482
|
this.scene = undefined;
|
|
2483
|
+
this.helpers = undefined;
|
|
962
2484
|
return this;
|
|
963
2485
|
}
|
|
964
2486
|
isInitialized() {
|
|
@@ -967,10 +2489,12 @@ class Viewer extends EventEmitter2 {
|
|
|
967
2489
|
render(time) {
|
|
968
2490
|
if (!this.renderNeeded) return;
|
|
969
2491
|
if (!this.renderer) return;
|
|
970
|
-
|
|
971
|
-
|
|
2492
|
+
const clippingPlanes = this.renderer.clippingPlanes;
|
|
2493
|
+
this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
|
|
972
2494
|
this.renderer.render(this.scene, this.camera);
|
|
973
|
-
this.
|
|
2495
|
+
this.renderer.clippingPlanes = [];
|
|
2496
|
+
this.renderer.autoClear = false;
|
|
2497
|
+
this.renderer.render(this.helpers, this.camera);
|
|
974
2498
|
const deltaTime = (time - this.renderTime) / 1e3;
|
|
975
2499
|
this.renderTime = time;
|
|
976
2500
|
this.emitEvent({
|
|
@@ -978,6 +2502,9 @@ class Viewer extends EventEmitter2 {
|
|
|
978
2502
|
time: time,
|
|
979
2503
|
deltaTime: deltaTime
|
|
980
2504
|
});
|
|
2505
|
+
this.renderer.autoClear = true;
|
|
2506
|
+
this.renderer.clippingPlanes = clippingPlanes;
|
|
2507
|
+
this.renderNeeded = false;
|
|
981
2508
|
}
|
|
982
2509
|
update(force = false) {
|
|
983
2510
|
this.renderNeeded = true;
|
|
@@ -1055,6 +2582,7 @@ class Viewer extends EventEmitter2 {
|
|
|
1055
2582
|
this.models.push(gltf);
|
|
1056
2583
|
this.scene.add(gltf.scene);
|
|
1057
2584
|
this.update();
|
|
2585
|
+
this.resetActiveDragger();
|
|
1058
2586
|
this.emitEvent({
|
|
1059
2587
|
type: "databasechunk"
|
|
1060
2588
|
});
|
|
@@ -1074,6 +2602,7 @@ class Viewer extends EventEmitter2 {
|
|
|
1074
2602
|
return this;
|
|
1075
2603
|
}
|
|
1076
2604
|
clear() {
|
|
2605
|
+
if (!this.renderer) return this;
|
|
1077
2606
|
function disposeMaterial(material) {
|
|
1078
2607
|
const materials = Array.isArray(material) ? material : [ material ];
|
|
1079
2608
|
materials.forEach((material => {
|
|
@@ -1084,49 +2613,79 @@ class Viewer extends EventEmitter2 {
|
|
|
1084
2613
|
if (object.geometry) object.geometry.dispose();
|
|
1085
2614
|
if (object.material) disposeMaterial(object.material);
|
|
1086
2615
|
}
|
|
1087
|
-
this.
|
|
2616
|
+
this.setActiveDragger();
|
|
2617
|
+
this.selected = [];
|
|
2618
|
+
this.renderer.clippingPlanes = [];
|
|
2619
|
+
this.helpers.traverse(disposeObject);
|
|
2620
|
+
this.helpers.clear();
|
|
1088
2621
|
this.models.forEach((gltf => gltf.scene.traverse(disposeObject)));
|
|
1089
2622
|
this.models.forEach((gltf => gltf.scene.removeFromParent()));
|
|
1090
2623
|
this.models = [];
|
|
1091
|
-
this.
|
|
2624
|
+
this.scene.clear();
|
|
1092
2625
|
this.emitEvent({
|
|
1093
2626
|
type: "clear"
|
|
1094
2627
|
});
|
|
2628
|
+
this.update(true);
|
|
1095
2629
|
return this;
|
|
1096
2630
|
}
|
|
1097
2631
|
activeDragger() {
|
|
1098
2632
|
return this._activeDragger;
|
|
1099
2633
|
}
|
|
1100
|
-
setActiveDragger(name) {
|
|
2634
|
+
setActiveDragger(name = "") {
|
|
1101
2635
|
if (!this._activeDragger || this._activeDragger.name !== name) {
|
|
1102
2636
|
if (this._activeDragger) {
|
|
1103
2637
|
this._activeDragger.dispose();
|
|
1104
2638
|
this._activeDragger = null;
|
|
1105
2639
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
2640
|
+
if (this.isInitialized()) {
|
|
2641
|
+
const Constructor = this.draggerFactory[name];
|
|
2642
|
+
if (Constructor) {
|
|
2643
|
+
this._activeDragger = new Constructor(this);
|
|
2644
|
+
this._activeDragger.name = name;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
const canvas = this.canvas;
|
|
2648
|
+
if (canvas) {
|
|
2649
|
+
canvas.className = canvas.className.split(" ").filter((x => !x.startsWith("oda-cursor-"))).filter((x => x)).concat(`oda-cursor-${name.toLowerCase()}`).join(" ");
|
|
1110
2650
|
}
|
|
2651
|
+
this.emitEvent({
|
|
2652
|
+
type: "changeactivedragger",
|
|
2653
|
+
data: name
|
|
2654
|
+
});
|
|
1111
2655
|
}
|
|
1112
2656
|
return this._activeDragger;
|
|
1113
2657
|
}
|
|
1114
2658
|
resetActiveDragger() {
|
|
1115
2659
|
const dragger = this._activeDragger;
|
|
1116
2660
|
if (dragger) {
|
|
1117
|
-
this.setActiveDragger(
|
|
2661
|
+
this.setActiveDragger();
|
|
1118
2662
|
this.setActiveDragger(dragger.name);
|
|
1119
2663
|
}
|
|
1120
2664
|
}
|
|
1121
2665
|
is3D() {
|
|
1122
|
-
return
|
|
2666
|
+
return true;
|
|
2667
|
+
}
|
|
2668
|
+
getSelected() {
|
|
2669
|
+
return this.executeCommand("getSelected");
|
|
2670
|
+
}
|
|
2671
|
+
setSelected(handles) {
|
|
2672
|
+
this.executeCommand("setSelected", handles);
|
|
1123
2673
|
}
|
|
1124
2674
|
executeCommand(id, ...args) {
|
|
1125
2675
|
return commands("ThreeJS").executeCommand(id, this, ...args);
|
|
1126
2676
|
}
|
|
2677
|
+
getComponent(type) {
|
|
2678
|
+
return this.components.find((component => component instanceof type));
|
|
2679
|
+
}
|
|
1127
2680
|
drawViewpoint(viewpoint) {}
|
|
1128
2681
|
createViewpoint() {
|
|
1129
|
-
|
|
2682
|
+
var _a;
|
|
2683
|
+
const viewpoint = {};
|
|
2684
|
+
viewpoint.snapshot = {
|
|
2685
|
+
data: (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.toDataURL("image/jpeg", .25)
|
|
2686
|
+
};
|
|
2687
|
+
viewpoint.description = (new Date).toDateString();
|
|
2688
|
+
return viewpoint;
|
|
1130
2689
|
}
|
|
1131
2690
|
}
|
|
1132
2691
|
|