diff --git a/source/engine/main.js b/source/engine/main.js index 91a6deb..87404b7 100644 --- a/source/engine/main.js +++ b/source/engine/main.js @@ -66,7 +66,7 @@ import { Unit } from './model/unit.js'; import { ParameterListBuilder, ParameterListParser, CreateUrlBuilder, CreateUrlParser, CreateModelUrlParameters, ParameterConverter } from './parameters/parameterlist.js'; import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ThreeMaterialHandler, ThreeMeshMaterialHandler, ConvertModelToThreeObject, MaterialGeometryType } from './threejs/threeconverter.js'; import { ThreeModelLoader } from './threejs/threemodelloader.js'; -import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js'; +import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, GetLineSegmentsProjectedDistance, ShadingType } from './threejs/threeutils.js'; import { Camera, CameraIsEqual3D, NavigationMode, ProjectionMode } from './viewer/camera.js'; import { GetIntegerFromStyle, GetDomElementExternalWidth, GetDomElementExternalHeight, GetDomElementInnerDimensions, GetDomElementClientCoordinates, CreateDomElement, AddDomElement, AddDiv, ClearDomElement, InsertDomElementBefore, InsertDomElementAfter, ShowDomElement, IsDomElementVisible, SetDomElementWidth, SetDomElementHeight, GetDomElementOuterWidth, GetDomElementOuterHeight, SetDomElementOuterWidth, SetDomElementOuterHeight, CreateDiv } from './viewer/domutils.js'; import { EmbeddedViewer, Init3DViewerFromUrlList, Init3DViewerFromFileList, Init3DViewerElements } from './viewer/embeddedviewer.js'; @@ -305,6 +305,7 @@ export { CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, + GetLineSegmentsProjectedDistance, ShadingType, Camera, CameraIsEqual3D, diff --git a/source/engine/threejs/threeutils.js b/source/engine/threejs/threeutils.js index 132373b..7e54f34 100644 --- a/source/engine/threejs/threeutils.js +++ b/source/engine/threejs/threeutils.js @@ -1,5 +1,6 @@ import { Coord2D } from '../geometry/coord2d.js'; import { Coord3D } from '../geometry/coord3d.js'; +import { Segment2D, SegmentPointDistance2D } from '../geometry/line2d.js'; import { RGBColorFromFloatComponents } from '../model/color.js'; import { MaterialType } from '../model/material.js'; import { Mesh } from '../model/mesh.js'; @@ -272,3 +273,33 @@ export function DisposeThreeObjects (mainObject) } }); } + +export function GetLineSegmentsProjectedDistance (camera, canvasWidth, canvasHeight, lineSegments, screenPoint) +{ + function GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, index) + { + let vertex = new THREE.Vector3 ( + vertices[3 * index], + vertices[3 * index + 1], + vertices[3 * index + 2] + ); + vertex.applyMatrix4 (lineSegments.matrixWorld); + let projected = vertex.project (camera); + return new Coord2D ( + (projected.x + 1.0) * canvasWidth / 2.0, + -(projected.y - 1.0) * canvasHeight / 2.0 + ); + } + + let vertices = lineSegments.geometry.attributes.position.array; + let segmentCount = vertices.length / 6; + let distance = Infinity; + for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) { + let segment = new Segment2D ( + GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex), + GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex + 1) + ); + distance = Math.min (distance, SegmentPointDistance2D (segment, screenPoint)); + } + return distance; +} diff --git a/source/engine/viewer/viewermodel.js b/source/engine/viewer/viewermodel.js index 0e128c5..c210af3 100644 --- a/source/engine/viewer/viewermodel.js +++ b/source/engine/viewer/viewermodel.js @@ -1,8 +1,10 @@ import { RGBColor } from '../model/color.js'; -import { ConvertColorToThreeColor, DisposeThreeObjects } from '../threejs/threeutils.js'; +import { ConvertColorToThreeColor, DisposeThreeObjects, GetLineSegmentsProjectedDistance } from '../threejs/threeutils.js'; import * as THREE from 'three'; +const LineThresholdInPixels = 10.0; + export const IntersectionMode = { MeshOnly : 1, @@ -127,7 +129,6 @@ export class ViewerMainModel this.edgeSettings = new EdgeSettings (false, new RGBColor (0, 0, 0), 1); this.hasLines = false; this.hasPolygonOffset = false; - this.fullBoundingBox = null; } SetMainObject (mainObject) @@ -135,7 +136,6 @@ export class ViewerMainModel this.mainModel.SetRootObject (mainObject); this.hasLines = false; this.hasPolygonOffset = false; - this.fullBoundingBox = null; this.EnumerateLines ((line) => { this.hasLines = true; @@ -200,17 +200,6 @@ export class ViewerMainModel this.UpdatePolygonOffset (); } - GetFullBoundingBox () - { - if (this.fullBoundingBox !== null) { - return this.fullBoundingBox; - } - this.fullBoundingBox = this.GetBoundingBox (() => { - return true; - }); - return this.fullBoundingBox; - } - GetBoundingBox (needToProcess) { let hasMesh = false; @@ -311,18 +300,6 @@ export class ViewerMainModel GetMeshIntersectionUnderMouse (intersectionMode, mouseCoords, camera, width, height) { - function CalculateLineThreshold (mousePos, camera, boundingBoxCenter) - { - let thresholdInScreenCoordinates = 15.0; - let frustumRange = camera.far - camera.near; - let cameraDistanceFromCenter = boundingBoxCenter.distanceTo (camera.position); - let distanceInFrustumRatio = cameraDistanceFromCenter / frustumRange; - let zValue = -1.0 + 2.0 * distanceInFrustumRatio; - let referencePoint1 = new THREE.Vector3 (mousePos.x, mousePos.y, zValue).unproject (camera); - let referencePoint2 = new THREE.Vector3 (mousePos.x + thresholdInScreenCoordinates, mousePos.y, zValue).unproject (camera); - return referencePoint1.distanceTo (referencePoint2); - } - if (this.mainModel.IsEmpty ()) { return null; } @@ -336,16 +313,9 @@ export class ViewerMainModel mousePos.y = -(mouseCoords.y / height) * 2 + 1; let raycaster = new THREE.Raycaster (); - if (this.hasLines) { - let boundingBox = this.GetFullBoundingBox (); - if (boundingBox !== null) { - let boundingBoxCenter = new THREE.Vector3 (0.0, 0.0, 0.0); - boundingBox.getCenter (boundingBoxCenter); - raycaster.params.Line.threshold = CalculateLineThreshold (mousePos, camera, boundingBoxCenter); - } - } - raycaster.setFromCamera (mousePos, camera); + raycaster.params.Line.threshold = 10.0; + let iSectObjects = raycaster.intersectObject (this.mainModel.GetRootObject (), true); for (let i = 0; i < iSectObjects.length; i++) { let iSectObject = iSectObjects[i]; @@ -355,7 +325,13 @@ export class ViewerMainModel if (intersectionMode === IntersectionMode.MeshOnly && iSectObject.object.isLineSegments) { continue; } - if (iSectObject.object.isMesh || iSectObject.object.isLineSegments) { + if (iSectObject.object.isMesh) { + return iSectObject; + } else if (iSectObject.object.isLineSegments) { + let distance = GetLineSegmentsProjectedDistance (camera, width, height, iSectObject.object, mouseCoords); + if (distance > LineThresholdInPixels) { + continue; + } return iSectObject; } }