114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
import React, { useRef, useEffect } from "react";
|
|
import { useFrame } from "@react-three/fiber";
|
|
import * as THREE from "three";
|
|
import { GLTF } from "three-stdlib";
|
|
import { Box3Helper } from "three";
|
|
import { SpawnedObject, ProcessData } from "./types";
|
|
|
|
interface ProcessObjectRendererProps {
|
|
objectId: string;
|
|
object: SpawnedObject;
|
|
process: ProcessData;
|
|
gltf: GLTF;
|
|
showBoundingBox?: boolean;
|
|
}
|
|
|
|
export const ProcessObjectRenderer: React.FC<ProcessObjectRendererProps> = ({
|
|
objectId,
|
|
object,
|
|
process,
|
|
gltf,
|
|
showBoundingBox = false,
|
|
}) => {
|
|
const meshRef = useRef<THREE.Mesh>(null);
|
|
const boxHelperRef = useRef<THREE.Box3Helper | null>(null);
|
|
const boundingBoxRef = useRef<THREE.Box3>(new THREE.Box3());
|
|
|
|
// Issue 1: Can't assign to ref.current as it's read-only
|
|
useEffect(() => {
|
|
if (object.ref && meshRef.current) {
|
|
// Instead of direct assignment, we need to store the mesh reference another way
|
|
// Option 1: If you can modify the SpawnedObject interface, add a setMesh method
|
|
if (typeof (object as any).setMesh === 'function') {
|
|
(object as any).setMesh(meshRef.current);
|
|
}
|
|
|
|
// Option 2: Store the mesh in a property that isn't ref.current
|
|
// This requires modifying your SpawnedObject interface to include this property
|
|
(object as any).meshInstance = meshRef.current;
|
|
|
|
// Option 3: If you need to maintain compatibility, you could use Object.defineProperty
|
|
// But this is a hack and not recommended
|
|
// Object.defineProperty(object.ref, 'current', { value: meshRef.current, writable: true });
|
|
}
|
|
}, [object.ref]);
|
|
|
|
// Create a bounding box helper for visualization
|
|
useFrame(() => {
|
|
if (meshRef.current && showBoundingBox) {
|
|
// Update the bounding box to match the mesh position
|
|
if (!boxHelperRef.current) {
|
|
// Get the size of the mesh
|
|
const size = new THREE.Vector3(1, 1, 1);
|
|
|
|
// If the mesh has geometry, use its dimensions
|
|
if (meshRef.current.geometry) {
|
|
const box = new THREE.Box3().setFromObject(meshRef.current);
|
|
box.getSize(size);
|
|
}
|
|
|
|
// Create a new bounding box centered on the mesh
|
|
boundingBoxRef.current = new THREE.Box3().setFromCenterAndSize(
|
|
meshRef.current.position,
|
|
size
|
|
);
|
|
|
|
// Create a helper to visualize the box
|
|
boxHelperRef.current = new Box3Helper(
|
|
boundingBoxRef.current,
|
|
new THREE.Color(0xff0000)
|
|
);
|
|
|
|
// Add the helper to the scene
|
|
meshRef.current.parent?.add(boxHelperRef.current);
|
|
} else {
|
|
// Update the box position to match the mesh
|
|
boundingBoxRef.current.setFromCenterAndSize(
|
|
meshRef.current.position,
|
|
boundingBoxRef.current.getSize(new THREE.Vector3())
|
|
);
|
|
|
|
// Force the helper to update
|
|
boxHelperRef.current.updateMatrixWorld(true);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (gltf?.scene) {
|
|
return (
|
|
<primitive
|
|
ref={meshRef}
|
|
object={gltf.scene.clone()}
|
|
position={[0, 0, 0]}
|
|
material={object.material}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// Issue 2: Material color type problem
|
|
return (
|
|
<mesh ref={meshRef}>
|
|
<boxGeometry args={[1, 1, 1]} />
|
|
<meshStandardMaterial
|
|
// Fix the color property access
|
|
color={
|
|
object.material && 'color' in object.material
|
|
? (object.material as THREE.MeshStandardMaterial).color
|
|
: "#00ff00"
|
|
}
|
|
metalness={0.5}
|
|
roughness={0.3}
|
|
/>
|
|
</mesh>
|
|
);
|
|
}; |