Refactor AssetBoundingBox to use cylinders for edges and improve bounding box rendering logic; update Model component to adjust line width for better visibility; enhance distanceWorker to utilize Vector3 for distance calculations.
This commit is contained in:
@@ -1,47 +1,67 @@
|
|||||||
import { Line } from "@react-three/drei";
|
import { Box3, Vector3, Quaternion } from "three";
|
||||||
import { Box3, Vector3 } from "three";
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
import { Cylinder } from "@react-three/drei";
|
||||||
|
|
||||||
export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth }: { name: string; boundingBox: Box3 | null; color: string; lineWidth: number; }) => {
|
export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth, }: { name: string; boundingBox: Box3 | null; color: string; lineWidth: number; }) => {
|
||||||
const { points, size, center } = useMemo(() => {
|
const { edgeCylinders, center, size } = useMemo(() => {
|
||||||
if (!boundingBox) { return { points: [], center: new Vector3(), size: new Vector3(), }; }
|
if (!boundingBox) return { edgeCylinders: [], center: new Vector3(), size: new Vector3() };
|
||||||
|
|
||||||
const min = boundingBox.min;
|
const min = boundingBox.min;
|
||||||
const max = boundingBox.max;
|
const max = boundingBox.max;
|
||||||
const center = boundingBox.getCenter(new Vector3());
|
const center = boundingBox.getCenter(new Vector3());
|
||||||
const size = boundingBox.getSize(new Vector3());
|
const size = boundingBox.getSize(new Vector3());
|
||||||
|
|
||||||
const edges: Array<[number, number, number]> = [
|
const corners = [
|
||||||
[min.x, min.y, min.z], [max.x, min.y, min.z],
|
new Vector3(min.x, min.y, min.z),
|
||||||
[max.x, min.y, min.z], [max.x, max.y, min.z],
|
new Vector3(max.x, min.y, min.z),
|
||||||
[max.x, max.y, min.z], [min.x, max.y, min.z],
|
new Vector3(max.x, max.y, min.z),
|
||||||
[min.x, max.y, min.z], [min.x, min.y, min.z],
|
new Vector3(min.x, max.y, min.z),
|
||||||
|
new Vector3(min.x, min.y, max.z),
|
||||||
[min.x, min.y, max.z], [max.x, min.y, max.z],
|
new Vector3(max.x, min.y, max.z),
|
||||||
[max.x, min.y, max.z], [max.x, max.y, max.z],
|
new Vector3(max.x, max.y, max.z),
|
||||||
[max.x, max.y, max.z], [min.x, max.y, max.z],
|
new Vector3(min.x, max.y, max.z),
|
||||||
[min.x, max.y, max.z], [min.x, min.y, max.z],
|
|
||||||
|
|
||||||
[min.x, min.y, min.z], [min.x, min.y, max.z],
|
|
||||||
[max.x, min.y, min.z], [max.x, min.y, max.z],
|
|
||||||
[max.x, max.y, min.z], [max.x, max.y, max.z],
|
|
||||||
[min.x, max.y, min.z], [min.x, max.y, max.z],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return { points: edges, center, size };
|
const edgeIndices: [number, number][] = [
|
||||||
}, [boundingBox]);
|
[0, 1], [1, 2], [2, 3], [3, 0],
|
||||||
|
[4, 5], [5, 6], [6, 7], [7, 4],
|
||||||
|
[0, 4], [1, 5], [2, 6], [3, 7],
|
||||||
|
];
|
||||||
|
|
||||||
|
const radius = 0.005 * lineWidth;
|
||||||
|
|
||||||
|
const edgeCylinders = edgeIndices.map(([startIdx, endIdx], i) => {
|
||||||
|
const start = corners[startIdx];
|
||||||
|
const end = corners[endIdx];
|
||||||
|
const direction = new Vector3().subVectors(end, start);
|
||||||
|
const length = direction.length();
|
||||||
|
const midPoint = new Vector3().addVectors(start, end).multiplyScalar(0.5);
|
||||||
|
const quaternion = new Quaternion().setFromUnitVectors(
|
||||||
|
new Vector3(0, 1, 0),
|
||||||
|
direction.clone().normalize()
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: `edge-cylinder-${i}`,
|
||||||
|
position: midPoint,
|
||||||
|
rotation: quaternion,
|
||||||
|
length,
|
||||||
|
radius,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return { edgeCylinders, center, size };
|
||||||
|
}, [boundingBox, lineWidth]);
|
||||||
|
|
||||||
if (!boundingBox) return null;
|
if (!boundingBox) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group name={name}>
|
<group name={name}>
|
||||||
<Line
|
{edgeCylinders.map(({ key, position, rotation, length, radius }) => (
|
||||||
segments
|
<Cylinder key={key} args={[radius, radius, length, 6]} position={position} quaternion={rotation} >
|
||||||
depthWrite={false}
|
<meshBasicMaterial color={color} depthWrite={false} />
|
||||||
points={points}
|
</Cylinder>
|
||||||
color={color}
|
))}
|
||||||
lineWidth={lineWidth}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<mesh visible={false} position={center}>
|
<mesh visible={false} position={center}>
|
||||||
<boxGeometry args={[size.x, size.y, size.z]} />
|
<boxGeometry args={[size.x, size.y, size.z]} />
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import { upsertProductOrEventApi } from '../../../../../services/simulation/prod
|
|||||||
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
|
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
|
||||||
import { ModelAnimator } from './animator/modelAnimator';
|
import { ModelAnimator } from './animator/modelAnimator';
|
||||||
|
|
||||||
|
const distanceWorker = new Worker(new URL("../../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url));
|
||||||
|
|
||||||
function Model({ asset }: { readonly asset: Asset }) {
|
function Model({ asset }: { readonly asset: Asset }) {
|
||||||
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
const savedTheme: string = localStorage.getItem("theme") || "light";
|
const savedTheme: string = localStorage.getItem("theme") || "light";
|
||||||
@@ -59,6 +61,7 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
const { selectedAssets } = useSelectedAssets();
|
const { selectedAssets } = useSelectedAssets();
|
||||||
|
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
const updateBackend = (
|
const updateBackend = (
|
||||||
productName: string,
|
productName: string,
|
||||||
@@ -474,7 +477,7 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<AssetBoundingBox name='Asset Fallback' boundingBox={boundingBox} color='gray' lineWidth={1} />
|
<AssetBoundingBox name='Asset Fallback' boundingBox={boundingBox} color='gray' lineWidth={2.5} />
|
||||||
)}
|
)}
|
||||||
{isSelected &&
|
{isSelected &&
|
||||||
<AssetBoundingBox name='Asset BBox' boundingBox={boundingBox} color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"} lineWidth={2.7} />
|
<AssetBoundingBox name='Asset BBox' boundingBox={boundingBox} color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"} lineWidth={2.7} />
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ function MoveControls2D({
|
|||||||
return new THREE.Vector3().subVectors(pointPosition, hitPoint);
|
return new THREE.Vector3().subVectors(pointPosition, hitPoint);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const movePoints = useCallback(() => {
|
const movePoints = (() => {
|
||||||
if (selectedPoints.length === 0) return;
|
if (selectedPoints.length === 0) return;
|
||||||
|
|
||||||
const states: Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }> = {};
|
const states: Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }> = {};
|
||||||
@@ -192,9 +192,9 @@ function MoveControls2D({
|
|||||||
|
|
||||||
setMovedObjects(selectedPoints);
|
setMovedObjects(selectedPoints);
|
||||||
setIsMoving(true);
|
setIsMoving(true);
|
||||||
}, [selectedPoints, camera, pointer, plane, raycaster, calculateDragOffset]);
|
});
|
||||||
|
|
||||||
const resetToInitialPositions = useCallback(() => {
|
const resetToInitialPositions = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
movedObjects.forEach((movedPoint: THREE.Object3D) => {
|
movedObjects.forEach((movedPoint: THREE.Object3D) => {
|
||||||
if (movedPoint.userData.pointUuid && initialStates[movedPoint.uuid]) {
|
if (movedPoint.userData.pointUuid && initialStates[movedPoint.uuid]) {
|
||||||
@@ -218,7 +218,7 @@ function MoveControls2D({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 0)
|
}, 0)
|
||||||
}, [movedObjects, initialStates, setAislePosition, setWallPosition, setFloorPosition, setZonePosition]);
|
};
|
||||||
|
|
||||||
const placeMovedAssets = () => {
|
const placeMovedAssets = () => {
|
||||||
if (movedObjects.length === 0) return;
|
if (movedObjects.length === 0) return;
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
|
import { Vector3 } from "three";
|
||||||
|
|
||||||
onmessage = function (e) {
|
onmessage = function (e) {
|
||||||
const { assetPosition, cameraPosition, limitDistance, renderDistance, isRendered } = e.data;
|
const { modelUuid, assetPosition, cameraPosition, limitDistance, renderDistance, isRendered } = e.data;
|
||||||
|
|
||||||
if (limitDistance && assetPosition) {
|
if (limitDistance && assetPosition) {
|
||||||
const distance = Math.sqrt(
|
if (!isRendered && new Vector3(assetPosition.x, assetPosition.y, assetPosition.z).distanceTo(cameraPosition) <= renderDistance) {
|
||||||
Math.pow(assetPosition.x - cameraPosition.x, 2) +
|
postMessage({ shouldRender: true, modelUuid });
|
||||||
Math.pow(assetPosition.y - cameraPosition.y, 2) +
|
} else if (isRendered && new Vector3(assetPosition.x, assetPosition.y, assetPosition.z).distanceTo(cameraPosition) > renderDistance) {
|
||||||
Math.pow(assetPosition.z - cameraPosition.z, 2)
|
postMessage({ shouldRender: false, modelUuid });
|
||||||
);
|
|
||||||
|
|
||||||
if (!isRendered && distance <= renderDistance) {
|
|
||||||
postMessage({ shouldRender: true });
|
|
||||||
} else if (isRendered && distance > renderDistance) {
|
|
||||||
postMessage({ shouldRender: false });
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isRendered) {
|
if (!isRendered) {
|
||||||
postMessage({ shouldRender: true });
|
postMessage({ shouldRender: true, modelUuid });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user