From 352a9b9ffbf3e98afee27e843f19d1d3c0234fba Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 9 Dec 2021 20:11:23 +0100 Subject: [PATCH 1/4] uvFromPoint added testing (npm test doesn't test anything due to unknown reason) added entry in docs.json --- docker-compose.yaml | 11 ++++++++ .../model-viewer/src/features/scene-graph.ts | 26 +++++++++++++++++-- .../model-viewer/src/model-viewer-base.ts | 18 ++++++++++++- .../test/features/scene-graph/model-spec.ts | 19 ++++++++++++++ .../src/three-components/ModelScene.ts | 26 +++++++++++++++++++ packages/modelviewer.dev/data/docs.json | 5 ++++ 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 docker-compose.yaml diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000000..bac6651636 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,11 @@ +version: "3.9" +services: + frontend: + image: node:14-alpine + working_dir: /repo + ports: + - "8080:8080" + volumes: + - .:/repo + entrypoint: ["/bin/sh", "-c" , "apk --update add curl git && npm install && tail -f /dev/null"] # && npm run serve + \ No newline at end of file diff --git a/packages/model-viewer/src/features/scene-graph.ts b/packages/model-viewer/src/features/scene-graph.ts index eea26d2f32..3d68cb12b5 100644 --- a/packages/model-viewer/src/features/scene-graph.ts +++ b/packages/model-viewer/src/features/scene-graph.ts @@ -17,7 +17,7 @@ import {property} from 'lit-element'; import {Euler, RepeatWrapping, RGBFormat, sRGBEncoding, Texture, TextureLoader} from 'three'; import {GLTFExporter, GLTFExporterOptions} from 'three/examples/jsm/exporters/GLTFExporter'; -import ModelViewerElementBase, {$needsRender, $onModelLoad, $renderer, $scene} from '../model-viewer-base.js'; +import ModelViewerElementBase, {$needsRender, $onModelLoad, $renderer, $scene, toVector2D, Vector2D} from '../model-viewer-base.js'; import {normalizeUnit} from '../styles/conversions.js'; import {NumberNode, parseExpressions} from '../styles/parsers.js'; import {GLTF} from '../three-components/gltf-instance/gltf-defaulted.js'; @@ -59,9 +59,17 @@ export interface SceneGraphInterface { * objects were intersected. * @param pixelX X coordinate of the mouse. * @param pixelY Y coordinate of the mouse. - * @returns a material, if no intersection is made than null is returned. + * @returns a material, if no intersection is made then null is returned. */ materialFromPoint(pixelX: number, pixelY: number): Material|null; + /** + * Intersects a ray with the scene and returns the texture-coordinate of + * intersected objects. + * @param pixelX X coordinate of the mouse. + * @param pixelY Y coordinate of the mouse. + * @returns a Vector2, if no intersection is made then null is returned. + */ + uvFromPoint(pixelX: number, pixelY: number): Vector2D|null; } /** @@ -274,6 +282,20 @@ export const SceneGraphMixin = >( return this[$model]![$materialFromPoint](scene.raycaster); } + + uvFromPoint(pixelX: number, pixelY: number): Vector2D|null { + const scene = this[$scene]; + const ndcCoords = scene.getNDC(pixelX, pixelY); + scene.raycaster.setFromCamera(ndcCoords, scene.getCamera()); + + const textcoord = scene.uvFromPoint(ndcCoords); + if (textcoord == null) { + return null; + } + const uv = toVector2D(textcoord); + + return uv; + } } return SceneGraphModelViewerElement; diff --git a/packages/model-viewer/src/model-viewer-base.ts b/packages/model-viewer/src/model-viewer-base.ts index e062984e32..3024971178 100644 --- a/packages/model-viewer/src/model-viewer-base.ts +++ b/packages/model-viewer/src/model-viewer-base.ts @@ -15,7 +15,7 @@ import {property} from 'lit-element'; import {UpdatingElement} from 'lit-element/lib/updating-element'; -import {Event as ThreeEvent, Vector3} from 'three'; +import {Event as ThreeEvent, Vector3, Vector2} from 'three'; import {HAS_INTERSECTION_OBSERVER, HAS_RESIZE_OBSERVER} from './constants.js'; import {makeTemplate} from './template.js'; @@ -83,6 +83,22 @@ export const toVector3D = (v: Vector3) => { }; }; +export interface Vector2D { + x: number + y: number + toString(): string +} + +export const toVector2D = (v: Vector2) => { + return { + x: v.x, + y: v.y, + toString() { + return `u:${this.x} v:${this.y}`; + } + }; +}; + interface ToBlobOptions { mimeType?: string, qualityArgument?: number, idealAspect?: boolean } diff --git a/packages/model-viewer/src/test/features/scene-graph/model-spec.ts b/packages/model-viewer/src/test/features/scene-graph/model-spec.ts index 99b0d42b7a..22b502c982 100644 --- a/packages/model-viewer/src/test/features/scene-graph/model-spec.ts +++ b/packages/model-viewer/src/test/features/scene-graph/model-spec.ts @@ -186,6 +186,25 @@ suite('scene-graph/model', () => { element[$scene].width, element[$scene].height)!; expect(material).to.be.null; }); + test('uvFromPoint returns texture-coordinates', async () => { + await loadModel(ASTRONAUT_GLB_PATH); + + const uv = element.uvFromPoint( + element[$scene].width / 2, element[$scene].height / 2)!; + + expect(uv).to.be.ok; + }); + + test( + 'uvFromPoint returns null when intersect fails', async () => { + await loadModel(ASTRONAUT_GLB_PATH); + + await timePasses(1000); + + const uv = element.uvFromPoint( + element[$scene].width, element[$scene].height)!; + expect(uv).to.be.null; + }); }); }); }); diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 6ffe7332ea..965cf78916 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -679,6 +679,32 @@ export class ModelScene extends Scene { return {position: hit.point, normal: hit.face.normal}; } + /** + * This method returns the x and y texture-coordinate of the point + * on the mesh corresponding to the input pixel coordinates given relative to + * the model-viewer element. If the mesh is not hit, the result is null. + */ + uvFromPoint(ndcPosition: Vector2, object: Object3D = this): Vector2|null { + this.raycaster.setFromCamera(ndcPosition, this.getCamera()); + const hits = this.raycaster.intersectObject(object, true); + + if (hits.length === 0) { + return null; + } + + const hit = hits[0]; + + if (hit.face == null) { + return null; + } + + if (hit.uv == null) { + return null; + } + + return hit.uv; + } + /** * The following methods are for operating on the set of Hotspot objects * attached to the scene. These come from DOM elements, provided to slots by diff --git a/packages/modelviewer.dev/data/docs.json b/packages/modelviewer.dev/data/docs.json index 84b0bd2d86..ca49bcf6ef 100644 --- a/packages/modelviewer.dev/data/docs.json +++ b/packages/modelviewer.dev/data/docs.json @@ -952,6 +952,11 @@ "links": [ "Related examples" ] + }, + { + "name": "uvFromPoint(clientX, clientY)", + "htmlName": "uvFromPoint", + "description": "Returns the x and y texture-coordinate of the point on the mesh corresponding to the input pixel coordinates given relative to the screen. The texture-coordinate is returned as Vector2D, which has a method toString(). The function returns null if no object is hit." } ], "Events": [ From cb5c0991e18848434563516a47dc63b1ac4c50ea Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 9 Dec 2021 20:15:15 +0100 Subject: [PATCH 2/4] uvFromPoint ready for Merging --- docker-compose.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 docker-compose.yaml diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index bac6651636..0000000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: "3.9" -services: - frontend: - image: node:14-alpine - working_dir: /repo - ports: - - "8080:8080" - volumes: - - .:/repo - entrypoint: ["/bin/sh", "-c" , "apk --update add curl git && npm install && tail -f /dev/null"] # && npm run serve - \ No newline at end of file From 361cd7a3958cffb5031eab5ce35653dd3b6ebc94 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 11 Dec 2021 21:41:37 +0100 Subject: [PATCH 3/4] requested changes Removed method from scene-graph and return uv from previous existing positionAndNormalfromPoint(). --- .../model-viewer/src/features/annotation.ts | 21 +++++++++------- .../model-viewer/src/features/scene-graph.ts | 24 +------------------ .../model-viewer/src/model-viewer-base.ts | 10 ++++---- .../src/test/features/annotation-spec.ts | 13 +++++++--- .../test/features/scene-graph/model-spec.ts | 19 --------------- .../src/three-components/ModelScene.ts | 17 +++++++++---- packages/modelviewer.dev/data/docs.json | 7 +----- 7 files changed, 41 insertions(+), 70 deletions(-) diff --git a/packages/model-viewer/src/features/annotation.ts b/packages/model-viewer/src/features/annotation.ts index 69b7f285c5..948c915b32 100644 --- a/packages/model-viewer/src/features/annotation.ts +++ b/packages/model-viewer/src/features/annotation.ts @@ -16,7 +16,7 @@ import {Matrix3, Matrix4} from 'three'; -import ModelViewerElementBase, {$needsRender, $scene, $tick, toVector3D, Vector3D} from '../model-viewer-base.js'; +import ModelViewerElementBase, {$needsRender, $scene, $tick, toVector3D, Vector3D, toVector2D, Vector2D} from '../model-viewer-base.js'; import {Hotspot, HotspotConfiguration} from '../three-components/Hotspot.js'; import {Constructor} from '../utilities.js'; @@ -34,7 +34,7 @@ const worldToModelNormal = new Matrix3(); export declare interface AnnotationInterface { updateHotspot(config: HotspotConfiguration): void; positionAndNormalFromPoint(pixelX: number, pixelY: number): - {position: Vector3D, normal: Vector3D}|null + {position: Vector3D, normal: Vector3D, uv: Vector2D}|null } /** @@ -127,14 +127,15 @@ export const AnnotationMixin = >( } /** - * This method returns the model position and normal of the point on the - * mesh corresponding to the input pixel coordinates given relative to the - * model-viewer element. The position and normal are returned as strings in - * the format suitable for putting in a hotspot's data-position and - * data-normal attributes. If the mesh is not hit, the result is null. + * This method returns the model position, normal and texture coordinate + * of the point on the mesh corresponding to the input pixel coordinates + * given relative to the model-viewer element. The position and normal + * are returned as strings in the format suitable for putting in a + * hotspot's data-position and data-normal attributes. If the mesh is + * not hit, the result is null. */ positionAndNormalFromPoint(pixelX: number, pixelY: number): - {position: Vector3D, normal: Vector3D}|null { + {position: Vector3D, normal: Vector3D, uv: Vector2D}|null { const scene = this[$scene]; const ndcPosition = scene.getNDC(pixelX, pixelY); @@ -150,7 +151,9 @@ export const AnnotationMixin = >( const normal = toVector3D(hit.normal.applyNormalMatrix(worldToModelNormal)); - return {position: position, normal: normal}; + const uv = toVector2D(hit.uv); + + return {position: position, normal: normal, uv: uv}; } private[$addHotspot](node: Node) { diff --git a/packages/model-viewer/src/features/scene-graph.ts b/packages/model-viewer/src/features/scene-graph.ts index 3d68cb12b5..b740561ca7 100644 --- a/packages/model-viewer/src/features/scene-graph.ts +++ b/packages/model-viewer/src/features/scene-graph.ts @@ -17,7 +17,7 @@ import {property} from 'lit-element'; import {Euler, RepeatWrapping, RGBFormat, sRGBEncoding, Texture, TextureLoader} from 'three'; import {GLTFExporter, GLTFExporterOptions} from 'three/examples/jsm/exporters/GLTFExporter'; -import ModelViewerElementBase, {$needsRender, $onModelLoad, $renderer, $scene, toVector2D, Vector2D} from '../model-viewer-base.js'; +import ModelViewerElementBase, {$needsRender, $onModelLoad, $renderer, $scene} from '../model-viewer-base.js'; import {normalizeUnit} from '../styles/conversions.js'; import {NumberNode, parseExpressions} from '../styles/parsers.js'; import {GLTF} from '../three-components/gltf-instance/gltf-defaulted.js'; @@ -62,14 +62,6 @@ export interface SceneGraphInterface { * @returns a material, if no intersection is made then null is returned. */ materialFromPoint(pixelX: number, pixelY: number): Material|null; - /** - * Intersects a ray with the scene and returns the texture-coordinate of - * intersected objects. - * @param pixelX X coordinate of the mouse. - * @param pixelY Y coordinate of the mouse. - * @returns a Vector2, if no intersection is made then null is returned. - */ - uvFromPoint(pixelX: number, pixelY: number): Vector2D|null; } /** @@ -282,20 +274,6 @@ export const SceneGraphMixin = >( return this[$model]![$materialFromPoint](scene.raycaster); } - - uvFromPoint(pixelX: number, pixelY: number): Vector2D|null { - const scene = this[$scene]; - const ndcCoords = scene.getNDC(pixelX, pixelY); - scene.raycaster.setFromCamera(ndcCoords, scene.getCamera()); - - const textcoord = scene.uvFromPoint(ndcCoords); - if (textcoord == null) { - return null; - } - const uv = toVector2D(textcoord); - - return uv; - } } return SceneGraphModelViewerElement; diff --git a/packages/model-viewer/src/model-viewer-base.ts b/packages/model-viewer/src/model-viewer-base.ts index 3024971178..fa8c9f25f8 100644 --- a/packages/model-viewer/src/model-viewer-base.ts +++ b/packages/model-viewer/src/model-viewer-base.ts @@ -84,17 +84,17 @@ export const toVector3D = (v: Vector3) => { }; export interface Vector2D { - x: number - y: number + u: number + v: number toString(): string } export const toVector2D = (v: Vector2) => { return { - x: v.x, - y: v.y, + u: v.x, + v: v.y, toString() { - return `u:${this.x} v:${this.y}`; + return `${this.u} ${this.v}`; } }; }; diff --git a/packages/model-viewer/src/test/features/annotation-spec.ts b/packages/model-viewer/src/test/features/annotation-spec.ts index 970364ac7e..9892d0525f 100644 --- a/packages/model-viewer/src/test/features/annotation-spec.ts +++ b/packages/model-viewer/src/test/features/annotation-spec.ts @@ -16,7 +16,7 @@ import {Vector3} from 'three'; import {AnnotationInterface, AnnotationMixin} from '../../features/annotation'; -import ModelViewerElementBase, {$needsRender, $scene, Vector3D} from '../../model-viewer-base'; +import ModelViewerElementBase, {$needsRender, $scene, Vector2D, Vector3D} from '../../model-viewer-base'; import {Hotspot} from '../../three-components/Hotspot.js'; import {ModelScene} from '../../three-components/ModelScene'; import {timePasses, waitForEvent} from '../../utilities'; @@ -49,6 +49,11 @@ const closeToVector3 = (a: Vector3D, b: Vector3) => { expect(a.z).to.be.closeTo(b.z, delta); }; +const withinRange = (a: Vector2D, start: number, finish: number) => { + expect(a.u).to.be.within(start, finish); + expect(a.v).to.be.within(start, finish); +} + suite('ModelViewerElementBase with AnnotationMixin', () => { let nextId = 0; let tagName: string; @@ -205,9 +210,10 @@ suite('ModelViewerElementBase with AnnotationMixin', () => { const hitResult = element.positionAndNormalFromPoint(width / 2, height / 2); expect(hitResult).to.be.ok; - const {position, normal} = hitResult!; + const {position, normal, uv} = hitResult!; closeToVector3(position, new Vector3(0, 0, 0.5)); closeToVector3(normal, new Vector3(0, 0, 1)); + withinRange(uv, 0, 1); }); test('gets expected hit result when turned', () => { @@ -216,9 +222,10 @@ suite('ModelViewerElementBase with AnnotationMixin', () => { const hitResult = element.positionAndNormalFromPoint(width / 2, height / 2); expect(hitResult).to.be.ok; - const {position, normal} = hitResult!; + const {position, normal, uv} = hitResult!; closeToVector3(position, new Vector3(0.5, 0, 0)); closeToVector3(normal, new Vector3(1, 0, 0)); + withinRange(uv, 0, 1); }); }); }); \ No newline at end of file diff --git a/packages/model-viewer/src/test/features/scene-graph/model-spec.ts b/packages/model-viewer/src/test/features/scene-graph/model-spec.ts index 22b502c982..99b0d42b7a 100644 --- a/packages/model-viewer/src/test/features/scene-graph/model-spec.ts +++ b/packages/model-viewer/src/test/features/scene-graph/model-spec.ts @@ -186,25 +186,6 @@ suite('scene-graph/model', () => { element[$scene].width, element[$scene].height)!; expect(material).to.be.null; }); - test('uvFromPoint returns texture-coordinates', async () => { - await loadModel(ASTRONAUT_GLB_PATH); - - const uv = element.uvFromPoint( - element[$scene].width / 2, element[$scene].height / 2)!; - - expect(uv).to.be.ok; - }); - - test( - 'uvFromPoint returns null when intersect fails', async () => { - await loadModel(ASTRONAUT_GLB_PATH); - - await timePasses(1000); - - const uv = element.uvFromPoint( - element[$scene].width, element[$scene].height)!; - expect(uv).to.be.null; - }); }); }); }); diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 965cf78916..1fe9117197 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -655,12 +655,13 @@ export class ModelScene extends Scene { } /** - * This method returns the world position and model-space normal of the point - * on the mesh corresponding to the input pixel coordinates given relative to - * the model-viewer element. If the mesh is not hit, the result is null. + * This method returns the world position, model-space normal and texture + * coordinate of the point on the mesh corresponding to the input pixel + * coordinates given relative to the model-viewer element. If the mesh + * is not hit, the result is null. */ positionAndNormalFromPoint(ndcPosition: Vector2, object: Object3D = this): - {position: Vector3, normal: Vector3}|null { + {position: Vector3, normal: Vector3, uv: Vector2}|null { this.raycaster.setFromCamera(ndcPosition, this.getCamera()); const hits = this.raycaster.intersectObject(object, true); @@ -673,10 +674,14 @@ export class ModelScene extends Scene { return null; } + if (hit.uv == null) { + return null; + } + hit.face.normal.applyNormalMatrix( new Matrix3().getNormalMatrix(hit.object.matrixWorld)); - return {position: hit.point, normal: hit.face.normal}; + return {position: hit.point, normal: hit.face.normal, uv: hit.uv}; } /** @@ -684,6 +689,7 @@ export class ModelScene extends Scene { * on the mesh corresponding to the input pixel coordinates given relative to * the model-viewer element. If the mesh is not hit, the result is null. */ + /* uvFromPoint(ndcPosition: Vector2, object: Object3D = this): Vector2|null { this.raycaster.setFromCamera(ndcPosition, this.getCamera()); const hits = this.raycaster.intersectObject(object, true); @@ -704,6 +710,7 @@ export class ModelScene extends Scene { return hit.uv; } + */ /** * The following methods are for operating on the set of Hotspot objects diff --git a/packages/modelviewer.dev/data/docs.json b/packages/modelviewer.dev/data/docs.json index ca49bcf6ef..797b0fe315 100644 --- a/packages/modelviewer.dev/data/docs.json +++ b/packages/modelviewer.dev/data/docs.json @@ -714,7 +714,7 @@ { "name": "positionAndNormalFromPoint(clientX, clientY)", "htmlName": "positionAndNormalFromPoint", - "description": "Returns the world position and normal of the point on the mesh corresponding to the input pixel coordinates given relative to the screen. The position and normal are returned as Vector3D, which has a method toString() that outputs a format suitable for putting in a hotspot's data-position and data-normal attributes. The function returns null if no object is hit.", + "description": "Returns the world position, normal and texture coordinate of the point on the mesh corresponding to the input pixel coordinates given relative to the screen. The position and normal are returned as Vector3D, which has a method toString() that outputs a format suitable for putting in a hotspot's data-position and data-normal attributes. The texture coordinate is returned as Vector2D, which has also a own toString() method. The function returns null if no object is hit.", "links": [ "positionAndNormalFromPoint example" ] @@ -952,11 +952,6 @@ "links": [ "Related examples" ] - }, - { - "name": "uvFromPoint(clientX, clientY)", - "htmlName": "uvFromPoint", - "description": "Returns the x and y texture-coordinate of the point on the mesh corresponding to the input pixel coordinates given relative to the screen. The texture-coordinate is returned as Vector2D, which has a method toString(). The function returns null if no object is hit." } ], "Events": [ From e2e52090c8292d142b01145ae2a52c34535c2ee9 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 20 Dec 2021 14:25:43 +0100 Subject: [PATCH 4/4] minding return of null in UV's also deleted old comments --- .../model-viewer/src/features/annotation.ts | 9 ++++-- .../src/test/features/annotation-spec.ts | 8 +++-- .../src/three-components/ModelScene.ts | 32 ++----------------- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/packages/model-viewer/src/features/annotation.ts b/packages/model-viewer/src/features/annotation.ts index 948c915b32..212335ff4b 100644 --- a/packages/model-viewer/src/features/annotation.ts +++ b/packages/model-viewer/src/features/annotation.ts @@ -34,7 +34,7 @@ const worldToModelNormal = new Matrix3(); export declare interface AnnotationInterface { updateHotspot(config: HotspotConfiguration): void; positionAndNormalFromPoint(pixelX: number, pixelY: number): - {position: Vector3D, normal: Vector3D, uv: Vector2D}|null + {position: Vector3D, normal: Vector3D, uv: Vector2D | null}|null } /** @@ -135,7 +135,7 @@ export const AnnotationMixin = >( * not hit, the result is null. */ positionAndNormalFromPoint(pixelX: number, pixelY: number): - {position: Vector3D, normal: Vector3D, uv: Vector2D}|null { + {position: Vector3D, normal: Vector3D, uv: Vector2D | null}|null { const scene = this[$scene]; const ndcPosition = scene.getNDC(pixelX, pixelY); @@ -151,7 +151,10 @@ export const AnnotationMixin = >( const normal = toVector3D(hit.normal.applyNormalMatrix(worldToModelNormal)); - const uv = toVector2D(hit.uv); + let uv = null; + if (hit.uv != null){ + uv = toVector2D(hit.uv); + } return {position: position, normal: normal, uv: uv}; } diff --git a/packages/model-viewer/src/test/features/annotation-spec.ts b/packages/model-viewer/src/test/features/annotation-spec.ts index 9892d0525f..bddcfee72c 100644 --- a/packages/model-viewer/src/test/features/annotation-spec.ts +++ b/packages/model-viewer/src/test/features/annotation-spec.ts @@ -213,7 +213,9 @@ suite('ModelViewerElementBase with AnnotationMixin', () => { const {position, normal, uv} = hitResult!; closeToVector3(position, new Vector3(0, 0, 0.5)); closeToVector3(normal, new Vector3(0, 0, 1)); - withinRange(uv, 0, 1); + if(uv != null){ + withinRange(uv, 0, 1); + } }); test('gets expected hit result when turned', () => { @@ -225,7 +227,9 @@ suite('ModelViewerElementBase with AnnotationMixin', () => { const {position, normal, uv} = hitResult!; closeToVector3(position, new Vector3(0.5, 0, 0)); closeToVector3(normal, new Vector3(1, 0, 0)); - withinRange(uv, 0, 1); + if(uv != null){ + withinRange(uv, 0, 1); + } }); }); }); \ No newline at end of file diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 1fe9117197..eb85617a58 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -661,7 +661,7 @@ export class ModelScene extends Scene { * is not hit, the result is null. */ positionAndNormalFromPoint(ndcPosition: Vector2, object: Object3D = this): - {position: Vector3, normal: Vector3, uv: Vector2}|null { + {position: Vector3, normal: Vector3, uv: Vector2 | null}|null { this.raycaster.setFromCamera(ndcPosition, this.getCamera()); const hits = this.raycaster.intersectObject(object, true); @@ -675,7 +675,7 @@ export class ModelScene extends Scene { } if (hit.uv == null) { - return null; + return {position: hit.point, normal: hit.face.normal, uv: null}; } hit.face.normal.applyNormalMatrix( @@ -684,34 +684,6 @@ export class ModelScene extends Scene { return {position: hit.point, normal: hit.face.normal, uv: hit.uv}; } - /** - * This method returns the x and y texture-coordinate of the point - * on the mesh corresponding to the input pixel coordinates given relative to - * the model-viewer element. If the mesh is not hit, the result is null. - */ - /* - uvFromPoint(ndcPosition: Vector2, object: Object3D = this): Vector2|null { - this.raycaster.setFromCamera(ndcPosition, this.getCamera()); - const hits = this.raycaster.intersectObject(object, true); - - if (hits.length === 0) { - return null; - } - - const hit = hits[0]; - - if (hit.face == null) { - return null; - } - - if (hit.uv == null) { - return null; - } - - return hit.uv; - } - */ - /** * The following methods are for operating on the set of Hotspot objects * attached to the scene. These come from DOM elements, provided to slots by