removed multiray hittest helper
This commit is contained in:
parent
b583eaee29
commit
cf45752848
|
|
@ -7,10 +7,10 @@ export const HitTestView = observer(function () {
|
|||
<div id="hit-test">
|
||||
<pre>
|
||||
{
|
||||
state.hitTest.objects.map((obj) =>
|
||||
<div key={obj.object.uuid}>
|
||||
{JSON.stringify(obj.point.toArray())}
|
||||
{JSON.stringify(obj.object.userData)}
|
||||
state.hitTest.hits.map((hit) =>
|
||||
<div key={hit.object.uuid}>
|
||||
{JSON.stringify(hit.point.toArray())}
|
||||
{JSON.stringify(hit.object.userData)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import { useEffect, useRef } from "react";
|
|||
import * as THREE from 'three';
|
||||
import { useInteraction, type InteractionMouseEventArgs } from "../helpers/hooks/useInteration";
|
||||
import { db } from "../backend/db";
|
||||
import { HitTestFactory, type HitTest } from "../helpers/hitTest";
|
||||
import { model } from "../model/model";
|
||||
import { SceneHelper } from "../helpers/sceneHelper";
|
||||
import type { HitResults } from "../helpers/circularFrustumIntersect";
|
||||
|
||||
export type ThreeViewEventArgs = {
|
||||
camera: THREE.Camera,
|
||||
|
|
@ -17,7 +17,7 @@ export type ThreeViewTickEventArgs = ThreeViewEventArgs & {
|
|||
}
|
||||
|
||||
export type ThreeViewMouseEventArgs = ThreeViewEventArgs & {
|
||||
hitTest: HitTest,
|
||||
hitResults: HitResults,
|
||||
}
|
||||
|
||||
export type ThreeViewProps = {
|
||||
|
|
@ -102,38 +102,27 @@ export const ThreeView = function (props: ThreeViewProps) {
|
|||
window.addEventListener("resize", handleWindowResize);
|
||||
|
||||
handleHover = (e: InteractionMouseEventArgs) => {
|
||||
|
||||
const ht = props.sceneHelper.hitTest(
|
||||
const hitResults = props.sceneHelper.hitTest(
|
||||
e.position,
|
||||
e.screenSize,
|
||||
);
|
||||
console.log(JSON.stringify(ht.map((h) => h.object.userData)));
|
||||
|
||||
const hitTest = HitTestFactory.hitTest(
|
||||
props.sceneHelper,
|
||||
new THREE.Vector2(e.position.x, e.position.y),
|
||||
camera,
|
||||
{ tolerancePixels: 3, cameraPixelSize: e.pixelSize }
|
||||
);
|
||||
props.onMouseMove?.({
|
||||
camera,
|
||||
scene,
|
||||
hitTest,
|
||||
hitResults,
|
||||
});
|
||||
};
|
||||
|
||||
handleClick = (e: InteractionMouseEventArgs) => {
|
||||
const hitTest = HitTestFactory.hitTest(
|
||||
props.sceneHelper,
|
||||
new THREE.Vector2(e.position.x, e.position.y),
|
||||
camera,
|
||||
{ tolerancePixels: 3, cameraPixelSize: e.pixelSize }
|
||||
const hitResults = props.sceneHelper.hitTest(
|
||||
e.position,
|
||||
e.screenSize,
|
||||
);
|
||||
props.onClick?.({
|
||||
camera,
|
||||
scene,
|
||||
hitTest,
|
||||
})
|
||||
hitResults,
|
||||
});
|
||||
};
|
||||
|
||||
// --- Animation loop ---
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ export const Viewport = function () {
|
|||
const sceneHelper = useSceneHelper();
|
||||
|
||||
function handleMouseMove(e: ThreeViewMouseEventArgs) {
|
||||
state.setHitTest(e.hitTest);
|
||||
state.setHitTest(e.hitResults);
|
||||
|
||||
sceneHelper.clear();
|
||||
if (e.hitTest.objects.length) {
|
||||
e.hitTest.objects.forEach((obj) => {
|
||||
sceneHelper.showPoint(obj.object.uuid, obj.point);
|
||||
if (e.hitResults.hits.length) {
|
||||
e.hitResults.hits.forEach((hit) => {
|
||||
sceneHelper.showPoint(hit.object.uuid, hit.point);
|
||||
})
|
||||
// console.log(e.position);
|
||||
// console.log(e.hitTest.objects.map((o) => o));
|
||||
|
|
@ -20,7 +20,7 @@ export const Viewport = function () {
|
|||
}
|
||||
// raycaster.setFromCamera(new THREE.Vector2(e.x, e.y), camera);
|
||||
// const hits = raycaster.intersectObjects(sync.meshes);
|
||||
const hoveredFaceIds = e.hitTest.objects.map(hit => hit.object.userData.faceId);
|
||||
const hoveredFaceIds = e.hitResults.hits.map((hit) => hit.object.userData.faceId);
|
||||
// if (hoveredFaceIds.length)
|
||||
// console.log(hoveredFaceIds);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ import * as THREE from 'three';
|
|||
import { CONTAINED, ExtendedTriangle, INTERSECTED, NOT_INTERSECTED } from 'three-mesh-bvh';
|
||||
import { CircularFrustum } from './circularFrustum';
|
||||
|
||||
export type FrustumHitResult = {
|
||||
export type HitResults = {
|
||||
hits: HitResult[];
|
||||
}
|
||||
|
||||
export type HitResult = {
|
||||
object: THREE.Object3D;
|
||||
point: THREE.Vector3; // world-space closest hit point
|
||||
depth: number; // depth along frustum axis
|
||||
|
|
@ -119,7 +123,7 @@ export class CircularFrustumIntersection {
|
|||
public intersectMesh(
|
||||
mesh: THREE.Mesh,
|
||||
findAll: boolean,
|
||||
): FrustumHitResult[] {
|
||||
): HitResult[] {
|
||||
const geometry = mesh.geometry;
|
||||
if (!geometry)
|
||||
return [];
|
||||
|
|
@ -136,7 +140,7 @@ export class CircularFrustumIntersection {
|
|||
if (this.insersectsSphere(boundingSphere) === 'NOT_INTERSECTED')
|
||||
return [];
|
||||
|
||||
const results: FrustumHitResult[] = [];
|
||||
const results: HitResult[] = [];
|
||||
|
||||
if (!geometry.boundsTree)
|
||||
geometry.computeBoundsTree();
|
||||
|
|
@ -240,8 +244,8 @@ export class CircularFrustumIntersection {
|
|||
public intersectObject(
|
||||
obj: THREE.Object3D,
|
||||
options: CircularFrustumIntersectionOptions = {},
|
||||
): FrustumHitResult[] {
|
||||
const results: FrustumHitResult[] = [];
|
||||
): HitResult[] {
|
||||
const results: HitResult[] = [];
|
||||
|
||||
obj.traverseVisible((object) => {
|
||||
if (options.filter && !options.filter(object))
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
import * as THREE from 'three';
|
||||
import type { SceneHelper } from './sceneHelper';
|
||||
import './bvh';
|
||||
|
||||
export type HitTest = {
|
||||
objects: THREE.Intersection<THREE.Object3D>[];
|
||||
}
|
||||
|
||||
export type HitTestRaycasterOptions = {
|
||||
cameraPixelSize: THREE.Vector2Like;
|
||||
tolerancePixels: number;
|
||||
}
|
||||
|
||||
export type HitTestOptions = HitTestRaycasterOptions & {
|
||||
}
|
||||
|
||||
export class HitTestFactory {
|
||||
|
||||
private static raycasters: [THREE.Vector2, THREE.Raycaster][] = Array(9).fill(0).map(() => [new THREE.Vector2(), new THREE.Raycaster()]);
|
||||
|
||||
private static setupRaycasters(cursor: THREE.Vector2, camera: THREE.PerspectiveCamera, options: HitTestRaycasterOptions) {
|
||||
|
||||
this.raycasters[0][0].copy(cursor);
|
||||
this.raycasters[0][1].setFromCamera(cursor, camera);
|
||||
|
||||
const count = HitTestFactory.raycasters.length - 1;
|
||||
const step = Math.PI * 2 / count;
|
||||
|
||||
for (let angle = 0, idx = 0; idx < count; angle += step, idx++) {
|
||||
const pos = {
|
||||
x: Math.cos(angle) * options.tolerancePixels * options.cameraPixelSize.x,
|
||||
y: Math.sin(angle) * options.tolerancePixels * options.cameraPixelSize.y,
|
||||
};
|
||||
const v = HitTestFactory.raycasters[idx + 1][0];
|
||||
v.copy(cursor).add(pos);
|
||||
HitTestFactory.raycasters[idx + 1][1].setFromCamera(v, camera);
|
||||
}
|
||||
}
|
||||
|
||||
public static getRaycasterPosition(index: number): THREE.Vector2 {
|
||||
return HitTestFactory.raycasters[index][0];
|
||||
}
|
||||
|
||||
public static get raycasterCount(): number {
|
||||
return HitTestFactory.raycasters.length;
|
||||
}
|
||||
|
||||
public static hitTest(scene: SceneHelper, cursor: THREE.Vector2, camera: THREE.PerspectiveCamera, options: HitTestOptions): HitTest {
|
||||
|
||||
HitTestFactory.setupRaycasters(cursor, camera, options);
|
||||
|
||||
const objects: THREE.Object3D[] = scene.objects;
|
||||
|
||||
const hitTest: Record<string, THREE.Intersection<THREE.Object3D>> = {};
|
||||
|
||||
HitTestFactory.raycasters.forEach((raycaster) => {
|
||||
const hits = raycaster[1].intersectObjects(objects);
|
||||
for (const hit of hits) {
|
||||
hitTest[hit.object.uuid] = hit;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
objects: Object.values(hitTest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import type { ColorRepresentation, Object3D, Object3DEventMap, OrthographicCamer
|
|||
import { SceneSync } from "../layers/sceneSync";
|
||||
import { GeometryCache } from "../layers/geometryCache";
|
||||
import type { Id } from "../types";
|
||||
import { CircularFrustumIntersection, type FrustumHitResult } from "./circularFrustumIntersect";
|
||||
import { CircularFrustumIntersection, type HitResult, type HitResults } from "./circularFrustumIntersect";
|
||||
import { CircularFrustum } from "./circularFrustum";
|
||||
import './bvh';
|
||||
import { VolatileGeometryHelper, type VolatileGeometryOptions } from "./volatileGeometryHelper";
|
||||
|
|
@ -30,7 +30,7 @@ export class SceneHelper {
|
|||
public buildMouseFrustum(
|
||||
mouseNormalized: Vector2Like,
|
||||
screenSize: Vector2Like,
|
||||
radius: number = 15,
|
||||
radius: number = 5,
|
||||
): void {
|
||||
if (!this.camera)
|
||||
throw new Error('Camera is not initialized');
|
||||
|
|
@ -46,13 +46,16 @@ export class SceneHelper {
|
|||
public hitTest(
|
||||
mouseNormalized: Vector2Like,
|
||||
screenSize: Vector2Like,
|
||||
): FrustumHitResult[] {
|
||||
): HitResults {
|
||||
this.buildMouseFrustum(mouseNormalized, screenSize);
|
||||
|
||||
const result: FrustumHitResult[] = [];
|
||||
const hits: HitResult[] = [];
|
||||
for (const object of this.objects)
|
||||
result.push(...this.mouseFrustum.intersectObject(object));
|
||||
return result;
|
||||
hits.push(...this.mouseFrustum.intersectObject(object));
|
||||
|
||||
return {
|
||||
hits,
|
||||
};
|
||||
}
|
||||
|
||||
public setSelection(faceIds: Id[]) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { makeAutoObservable } from "mobx";
|
||||
import type { Id } from "../types";
|
||||
import type { HitTest } from "../helpers/hitTest";
|
||||
import type { HitResults } from "../helpers/circularFrustumIntersect";
|
||||
|
||||
export class Root {
|
||||
public selectedPrimitiveIds: Id[] = [];
|
||||
public hitTest: HitTest = { objects: [] };
|
||||
public hitTest: HitResults = { hits: [] };
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
|
|
@ -14,7 +14,7 @@ export class Root {
|
|||
this.selectedPrimitiveIds = value;
|
||||
}
|
||||
|
||||
public setHitTest(value: HitTest) {
|
||||
public setHitTest(value: HitResults) {
|
||||
this.hitTest = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue