plane geometry added with physics
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
import * as THREE from 'three';
|
||||
import { CollisionPayload, RapierRigidBody, RigidBody } from '@react-three/rapier';
|
||||
import { CollisionPayload, RigidBody } from '@react-three/rapier';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useFrame } from '@react-three/fiber';
|
||||
import CurvedPlane from '../../../../scene/physics/curvedPlane';
|
||||
|
||||
function ConveyorCollider({ boundingBox, asset, modelName, conveyorPlaneSize, scene }: {
|
||||
function ConveyorCollider({ boundingBox, asset, conveyorPlaneSize }: {
|
||||
boundingBox: THREE.Box3 | null,
|
||||
asset: Asset,
|
||||
modelName: string,
|
||||
scene: THREE.Scene,
|
||||
conveyorPlaneSize: [number, number] | null,
|
||||
}) {
|
||||
const conveyorRef = useRef<any>(null);
|
||||
@@ -18,9 +15,9 @@ function ConveyorCollider({ boundingBox, asset, modelName, conveyorPlaneSize, sc
|
||||
useEffect(() => {
|
||||
if (!boundingBox || !conveyorPlaneSize) return;
|
||||
const [width, depth] = conveyorPlaneSize;
|
||||
if (width < depth) { //z-axis conveyor
|
||||
if (width < depth) {
|
||||
conveyorDirection.current.set(0, 0, 1);
|
||||
} else {//x-axis conveyor
|
||||
} else {
|
||||
conveyorDirection.current.set(1, 0, 0);
|
||||
}
|
||||
const rotation = new THREE.Euler().fromArray(asset.rotation || [0, 0, 0]);
|
||||
@@ -123,7 +120,6 @@ function ConveyorCollider({ boundingBox, asset, modelName, conveyorPlaneSize, sc
|
||||
colliders="cuboid"
|
||||
>
|
||||
<mesh>
|
||||
{/* <CurvedPlane modelName={modelName} scene={scene} /> */}
|
||||
<planeGeometry args={conveyorPlaneSize} />
|
||||
<meshBasicMaterial
|
||||
color="green"
|
||||
|
||||
@@ -19,10 +19,12 @@ import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useVersionContext } from '../../../version/versionContext';
|
||||
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
|
||||
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
|
||||
import ConveyorCollider from './conveyorCollider';
|
||||
|
||||
import { ModelAnimator } from './animator/modelAnimator';
|
||||
|
||||
import ConveyorCollider from './conveyorCollider';
|
||||
import RibbonCollider from './ribbonCollider';
|
||||
|
||||
function Model({ asset, isRendered }: { readonly asset: Asset, isRendered: boolean }) {
|
||||
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
const { controls, gl, scene } = useThree();
|
||||
@@ -459,13 +461,13 @@ function Model({ asset, isRendered }: { readonly asset: Asset, isRendered: boole
|
||||
{isRendered ? (
|
||||
<>
|
||||
|
||||
<RigidBody
|
||||
{/* <RigidBody
|
||||
type="fixed"
|
||||
colliders='cuboid'
|
||||
colliders='hull'
|
||||
ref={rigidBodyRef}
|
||||
>
|
||||
> */}
|
||||
<primitive object={gltfScene} />
|
||||
</ RigidBody>
|
||||
{/* </ RigidBody> */}
|
||||
|
||||
<ModelAnimator asset={asset} gltfScene={gltfScene} />
|
||||
|
||||
@@ -474,10 +476,13 @@ function Model({ asset, isRendered }: { readonly asset: Asset, isRendered: boole
|
||||
<AssetBoundingBox name='Asset Fallback' boundingBox={boundingBox} color='gray' lineWidth={2.5} />
|
||||
)}
|
||||
|
||||
<ConveyorCollider boundingBox={boundingBox}
|
||||
{/* <ConveyorCollider boundingBox={boundingBox}
|
||||
asset={asset}
|
||||
conveyorPlaneSize={conveyorPlaneSize}
|
||||
/> */}
|
||||
|
||||
<RibbonCollider boundingBox={boundingBox}
|
||||
asset={asset}
|
||||
modelName={asset.modelName}
|
||||
scene={scene}
|
||||
conveyorPlaneSize={conveyorPlaneSize}
|
||||
/>
|
||||
|
||||
|
||||
182
app/src/modules/builder/asset/models/model/ribbonCollider.tsx
Normal file
182
app/src/modules/builder/asset/models/model/ribbonCollider.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import * as THREE from 'three';
|
||||
import { CollisionPayload, RigidBody } from '@react-three/rapier';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useFrame } from '@react-three/fiber';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../../../simulation/products/productContext';
|
||||
|
||||
function RibbonCollider({ boundingBox, asset, conveyorPlaneSize }: {
|
||||
boundingBox: THREE.Box3 | null,
|
||||
asset: Asset,
|
||||
conveyorPlaneSize: [number, number] | null,
|
||||
}) {
|
||||
const { productStore } = useSceneContext();
|
||||
const { getEventByModelUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const conveyorRef = useRef<any>(null);
|
||||
const [objectsOnConveyor, setObjectsOnConveyor] = useState<Set<any>>(new Set());
|
||||
const conveyorDirection = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||
const conveyorSpeed = 2;
|
||||
const [geometryKey, setGeometryKey] = useState(0);
|
||||
|
||||
const event = getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
asset.modelUuid
|
||||
) as ConveyorEventSchema | undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (!boundingBox || !conveyorPlaneSize) return;
|
||||
const [width, depth] = conveyorPlaneSize;
|
||||
if (width < depth) {
|
||||
conveyorDirection.current.set(0, 0, 1);
|
||||
} else {
|
||||
conveyorDirection.current.set(1, 0, 0);
|
||||
}
|
||||
const rotation = new THREE.Euler().fromArray(asset.rotation || [0, 0, 0]);
|
||||
conveyorDirection.current.applyEuler(rotation);
|
||||
}, [boundingBox, conveyorPlaneSize, asset.rotation]);
|
||||
|
||||
const handleMaterialEnter = (e: CollisionPayload) => {
|
||||
if (e.other.rigidBody) {
|
||||
setObjectsOnConveyor(prev => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.add(e.other.rigidBody);
|
||||
return newSet;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleMaterialExit = (e: CollisionPayload) => {
|
||||
if (e.other.rigidBody) {
|
||||
setObjectsOnConveyor(prev => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.delete(e.other.rigidBody);
|
||||
return newSet;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useFrame(() => {
|
||||
if (!event?.points || event.points.length < 2) return;
|
||||
|
||||
const curve = new THREE.CatmullRomCurve3(
|
||||
event.points.map(p => new THREE.Vector3(...p.position))
|
||||
);
|
||||
|
||||
const assetPos = new THREE.Vector3(...(asset.position || [0, 0, 0]));
|
||||
const assetRot = new THREE.Euler(...(asset.rotation || [0, 0, 0]));
|
||||
const assetQuat = new THREE.Quaternion().setFromEuler(assetRot);
|
||||
const inverseAssetQuat = assetQuat.clone().invert();
|
||||
|
||||
objectsOnConveyor.forEach(rigidBody => {
|
||||
if (!rigidBody) return;
|
||||
|
||||
const worldPos = new THREE.Vector3().copy(rigidBody.translation());
|
||||
|
||||
const localPos = worldPos.clone().sub(assetPos).applyQuaternion(inverseAssetQuat);
|
||||
|
||||
const curvePoints = curve.getPoints(100);
|
||||
let closestIndex = 0;
|
||||
let minDist = Infinity;
|
||||
|
||||
for (let i = 0; i < curvePoints.length; i++) {
|
||||
const dist = curvePoints[i].distanceToSquared(localPos);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
const point = curvePoints[closestIndex];
|
||||
const prev = curvePoints[closestIndex - 1] || point;
|
||||
const next = curvePoints[closestIndex + 1] || point;
|
||||
|
||||
const tangentLocal = new THREE.Vector3().subVectors(next, prev).normalize();
|
||||
const sideLocal = new THREE.Vector3().crossVectors(tangentLocal, new THREE.Vector3(0, 1, 0)).normalize();
|
||||
|
||||
const relative = new THREE.Vector3().subVectors(localPos, point);
|
||||
const sideOffset = relative.dot(sideLocal);
|
||||
|
||||
const centeringStrength = 10;
|
||||
const centeringForceLocal = sideLocal.clone().multiplyScalar(-sideOffset * centeringStrength);
|
||||
const forwardForceLocal = tangentLocal.clone().multiplyScalar(conveyorSpeed);
|
||||
|
||||
const totalForceLocal = forwardForceLocal.add(centeringForceLocal);
|
||||
|
||||
const totalForceWorld = totalForceLocal.applyQuaternion(assetQuat);
|
||||
|
||||
rigidBody.setAngvel({ x: 0, y: 0, z: 0 }, true);
|
||||
rigidBody.setLinvel(totalForceWorld, true);
|
||||
});
|
||||
});
|
||||
|
||||
const geometry = useMemo(() => {
|
||||
if (asset.eventData?.type !== 'Conveyor' || !conveyorPlaneSize) return null;
|
||||
const width = 1;
|
||||
const segments = 30;
|
||||
const vertices: number[] = [];
|
||||
const indices: number[] = [];
|
||||
|
||||
if (!event || !event.points || event.points.length < 2) return null;
|
||||
|
||||
const points = event.points.map(p => new THREE.Vector3(p.position[0], p.position[1], p.position[2]));
|
||||
|
||||
if (points.length < 2) return null;
|
||||
|
||||
const curve = new THREE.CatmullRomCurve3(points);
|
||||
const curvePoints = curve.getPoints((points.length - 1) * segments);
|
||||
|
||||
for (let i = 0; i < curvePoints.length; i++) {
|
||||
const point = curvePoints[i];
|
||||
const prev = curvePoints[i - 1] || curvePoints[i];
|
||||
const next = curvePoints[i + 1] || curvePoints[i];
|
||||
|
||||
const tangent = new THREE.Vector3().subVectors(next, prev).normalize();
|
||||
const normal = new THREE.Vector3().crossVectors(tangent, new THREE.Vector3(0, 1, 0)).normalize();
|
||||
|
||||
const left = new THREE.Vector3().copy(point).addScaledVector(normal, -width / 2);
|
||||
const right = new THREE.Vector3().copy(point).addScaledVector(normal, width / 2);
|
||||
|
||||
vertices.push(...left.toArray());
|
||||
vertices.push(...right.toArray());
|
||||
}
|
||||
|
||||
const totalSegments = curvePoints.length - 1;
|
||||
for (let i = 0; i < totalSegments; i++) {
|
||||
const base = i * 2;
|
||||
indices.push(base, base + 1, base + 2);
|
||||
indices.push(base + 1, base + 3, base + 2);
|
||||
}
|
||||
|
||||
const ribbonGeometry = new THREE.BufferGeometry();
|
||||
ribbonGeometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
|
||||
ribbonGeometry.setIndex(indices);
|
||||
ribbonGeometry.computeVertexNormals();
|
||||
setGeometryKey((k) => k + 1);
|
||||
return ribbonGeometry;
|
||||
}, [asset.eventData, event]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{asset.eventData?.type === 'Conveyor' && conveyorPlaneSize && geometry && (
|
||||
<RigidBody
|
||||
key={geometryKey}
|
||||
ref={conveyorRef}
|
||||
type="fixed"
|
||||
position={[0, 0.001, 0]}
|
||||
userData={{ isConveyor: true }}
|
||||
onCollisionEnter={handleMaterialEnter}
|
||||
onCollisionExit={handleMaterialExit}
|
||||
colliders="trimesh"
|
||||
>
|
||||
<mesh geometry={geometry} >
|
||||
<meshStandardMaterial color="skyblue" side={THREE.DoubleSide} opacity={0.5} transparent />
|
||||
</mesh>
|
||||
</RigidBody>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default RibbonCollider;
|
||||
@@ -1,15 +1,19 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import ColliderInstance from './colliderInstance/colliderInstance';
|
||||
import { useToggleView } from '../../../../store/builder/store';
|
||||
|
||||
function ColliderCreator() {
|
||||
const { camera, gl, scene, raycaster, pointer } = useThree();
|
||||
const [colliders, setColliders] = useState<
|
||||
{ id: string; position: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[]
|
||||
{ id: string; position: [number, number, number]; rotation: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[]
|
||||
>([]);
|
||||
const drag = useRef(false);
|
||||
const isLeftMouseDown = useRef(false);
|
||||
const { toggleView } = useToggleView();
|
||||
|
||||
const handleCtrlClick = (e: MouseEvent) => {
|
||||
if (!e.ctrlKey) return;
|
||||
if (!e.ctrlKey || drag.current || toggleView) return;
|
||||
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
|
||||
@@ -25,6 +29,7 @@ function ColliderCreator() {
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
position: spawnPosition,
|
||||
rotation: [0, 0, 0],
|
||||
colliderType: 'Default material',
|
||||
}
|
||||
]);
|
||||
@@ -33,22 +38,49 @@ function ColliderCreator() {
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = gl.domElement;
|
||||
|
||||
const onMouseDown = (evt: any) => {
|
||||
if (evt.button === 0) {
|
||||
isLeftMouseDown.current = true;
|
||||
drag.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = (evt: any) => {
|
||||
if (evt.button === 0) {
|
||||
isLeftMouseDown.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseMove = () => {
|
||||
if (isLeftMouseDown) {
|
||||
drag.current = true;
|
||||
}
|
||||
};
|
||||
|
||||
canvas.addEventListener('click', handleCtrlClick);
|
||||
canvas.addEventListener('mousedown', onMouseDown);
|
||||
canvas.addEventListener('mouseup', onMouseUp);
|
||||
canvas.addEventListener('mousemove', onMouseMove);
|
||||
|
||||
return () => {
|
||||
canvas.removeEventListener('click', handleCtrlClick);
|
||||
canvas.removeEventListener('mousedown', onMouseDown);
|
||||
canvas.removeEventListener('mouseup', onMouseUp);
|
||||
canvas.removeEventListener('mousemove', onMouseMove);
|
||||
};
|
||||
}, [colliders, camera]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{colliders.map(({ id, position }) => (
|
||||
{colliders.map(({ id, position, rotation }) => (
|
||||
<ColliderInstance
|
||||
key={id}
|
||||
id={id}
|
||||
colliders={colliders}
|
||||
setColliders={setColliders}
|
||||
position={position}
|
||||
rotation={rotation}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -4,11 +4,12 @@ import { CollisionPayload, RapierRigidBody, RigidBody } from '@react-three/rapie
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import * as THREE from 'three';
|
||||
|
||||
function ColliderInstance({ id, colliders, setColliders, position }: {
|
||||
function ColliderInstance({ id, colliders, setColliders, position, rotation }: {
|
||||
id: string;
|
||||
colliders: { id: string; position: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[];
|
||||
setColliders: React.Dispatch<React.SetStateAction<{ id: string; position: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[]>>;
|
||||
colliders: { id: string; position: [number, number, number]; rotation: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[];
|
||||
setColliders: React.Dispatch<React.SetStateAction<{ id: string; position: [number, number, number]; rotation: [number, number, number]; colliderType: 'Default material' | 'Material 1' | 'Material 2' | 'Material 3' }[]>>;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
}) {
|
||||
const { camera, gl, pointer, controls } = useThree();
|
||||
const [draggedId, setDraggedId] = useState<string | null>(null);
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import * as THREE from 'three';
|
||||
export default function CurvedPlane({ modelName, scene }: { modelName: string, scene: THREE.Scene }) {
|
||||
// console.log('scene: ', scene);n
|
||||
// console.log('modelName: ', modelName);
|
||||
|
||||
function computeCircleFromPoints(p1: THREE.Vector2, p2: THREE.Vector2, p3: THREE.Vector2) {
|
||||
const temp = p2.clone().sub(p1);
|
||||
const temp2 = p3.clone().sub(p1);
|
||||
const cross = temp.x * temp2.y - temp.y * temp2.x;
|
||||
if (Math.abs(cross) < 1e-10) return null; // colinear
|
||||
|
||||
const A = p1.lengthSq();
|
||||
const B = p2.lengthSq();
|
||||
const C = p3.lengthSq();
|
||||
|
||||
const D = 2 * (p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y));
|
||||
|
||||
const centerX = (A * (p2.y - p3.y) + B * (p3.y - p1.y) + C * (p1.y - p2.y)) / D;
|
||||
const centerY = (A * (p3.x - p2.x) + B * (p1.x - p3.x) + C * (p2.x - p1.x)) / D;
|
||||
|
||||
const center = new THREE.Vector2(centerX, centerY);
|
||||
const radius = center.distanceTo(p1);
|
||||
return { center, radius };
|
||||
}
|
||||
function findFirstMesh(object: THREE.Object3D): THREE.Mesh | null {
|
||||
if ((object as THREE.Mesh).isMesh) return object as THREE.Mesh;
|
||||
|
||||
for (const child of object.children) {
|
||||
const result = findFirstMesh(child);
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const parentObject = scene.getObjectByName(modelName); // this is the group
|
||||
if (!parentObject) return null;
|
||||
|
||||
const mesh = findFirstMesh(parentObject);
|
||||
console.log('mesh: ', mesh);
|
||||
if (!mesh) {
|
||||
console.warn('No mesh found inside group');
|
||||
return null;
|
||||
}
|
||||
|
||||
const geometry = mesh.geometry as THREE.BufferGeometry;
|
||||
const positions = geometry?.attributes?.position;
|
||||
|
||||
const points: THREE.Vector2[] = [];
|
||||
for (let i = 0; i < positions.count; i += 20) { // sample every 20th vertex
|
||||
const x = positions.getX(i);
|
||||
const z = positions.getZ(i); // assuming Y is up
|
||||
points.push(new THREE.Vector2(x, z));
|
||||
}
|
||||
|
||||
console.log('points: ', points);
|
||||
// Use three points to estimate curve
|
||||
const p1 = points[0];
|
||||
const p2 = points[Math.floor(points.length / 2)];
|
||||
const p3 = points[points.length - 1];
|
||||
|
||||
const result = computeCircleFromPoints(p1, p2, p3);
|
||||
if (!result) return null;
|
||||
|
||||
const { center, radius } = result;
|
||||
const angle = p1.clone().sub(center).angleTo(p3.clone().sub(center));
|
||||
|
||||
// Estimate width: take 2 points close to p2 but on either side
|
||||
const width = 3; // placeholder, calculate from mesh later if needed
|
||||
|
||||
const shape = new THREE.Shape();
|
||||
const segments = 32;
|
||||
|
||||
const innerRadius = radius;
|
||||
const outerRadius = radius + width;
|
||||
|
||||
for (let i = 0; i <= segments; i++) {
|
||||
const t = (angle * i) / segments;
|
||||
const x = Math.cos(t) * outerRadius;
|
||||
const y = Math.sin(t) * outerRadius;
|
||||
if (i === 0) shape.moveTo(x, y);
|
||||
else shape.lineTo(x, y);
|
||||
}
|
||||
|
||||
for (let i = segments; i >= 0; i--) {
|
||||
const t = (angle * i) / segments;
|
||||
const x = Math.cos(t) * innerRadius;
|
||||
const y = Math.sin(t) * innerRadius;
|
||||
shape.lineTo(x, y);
|
||||
}
|
||||
const helper = new THREE.BoxHelper(mesh, 0xffff00);
|
||||
scene.add(helper);
|
||||
|
||||
return (
|
||||
<mesh
|
||||
// position={[
|
||||
// mesh.getWorldPosition(new THREE.Vector3()).x,
|
||||
// mesh.getWorldPosition(new THREE.Vector3()).y,
|
||||
// mesh.getWorldPosition(new THREE.Vector3()).z
|
||||
// ]}
|
||||
scale={mesh.getWorldScale(new THREE.Vector3())}
|
||||
rotation={[0, 0, 0]}
|
||||
>
|
||||
<shapeGeometry args={[shape]} />
|
||||
<meshBasicMaterial
|
||||
color="green"
|
||||
transparent
|
||||
opacity={0.3}
|
||||
side={THREE.DoubleSide}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { generateUniqueId } from '../../../functions/generateUniqueId';
|
||||
type MaterialSpawnerProps = {
|
||||
position: [number, number, number];
|
||||
spawnInterval: number;
|
||||
spawnCount?: number;
|
||||
spawnCount: number;
|
||||
};
|
||||
|
||||
function MaterialSpawner({ position, spawnInterval, spawnCount }: MaterialSpawnerProps) {
|
||||
@@ -177,11 +177,15 @@ function MaterialSpawner({ position, spawnInterval, spawnCount }: MaterialSpawne
|
||||
setSpawningPaused(prev => !prev);
|
||||
};
|
||||
|
||||
const handleBoxContextMenu = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh
|
||||
position={position}
|
||||
onClick={handleBoxClick}
|
||||
onContextMenu={handleBoxContextMenu}
|
||||
>
|
||||
<boxGeometry args={[1, 1, 1]} />
|
||||
<meshStandardMaterial color={spawningPaused ? "red" : "white"} transparent opacity={0.2} />
|
||||
@@ -192,12 +196,12 @@ function MaterialSpawner({ position, spawnInterval, spawnCount }: MaterialSpawne
|
||||
key={id}
|
||||
ref={ref}
|
||||
position={position}
|
||||
colliders="cuboid"
|
||||
colliders="hull"
|
||||
angularDamping={0.5}
|
||||
linearDamping={0.5}
|
||||
restitution={0.1}
|
||||
userData={{ materialType, materialUuid: id }}
|
||||
// onSleep={() => handleSleep(id)}
|
||||
onSleep={() => handleSleep(id)}
|
||||
>
|
||||
<MaterialModel
|
||||
materialId={id}
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import React from 'react'
|
||||
import MaterialSpawner from './materialSpawner'
|
||||
import ColliderCreator from './colliders/colliderCreator'
|
||||
|
||||
function PhysicsSimulator() {
|
||||
return (
|
||||
<>
|
||||
{/* <MaterialSpawner
|
||||
|
||||
<MaterialSpawner
|
||||
position={[0, 3, 0]}
|
||||
spawnInterval={1000}
|
||||
spawnCount={15}
|
||||
/>
|
||||
<MaterialSpawner
|
||||
position={[-21, 3, -8]}
|
||||
position={[6, 3, 6]}
|
||||
spawnInterval={1000}
|
||||
spawnCount={5}
|
||||
/>
|
||||
<MaterialSpawner
|
||||
position={[-17, 3, 6]}
|
||||
position={[6, 3, -6]}
|
||||
spawnInterval={1000}
|
||||
spawnCount={50}
|
||||
/> */}
|
||||
spawnCount={5}
|
||||
/>
|
||||
|
||||
<ColliderCreator />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
|
||||
<Setup />
|
||||
<Collaboration />
|
||||
<Physics gravity={[0, -9.81, 0]} allowedLinearError={50} numSolverIterations={50} debug >
|
||||
{/* <Physics gravity={[0, -9.81, 0]} allowedLinearError={50} numSolverIterations={50} > */}
|
||||
<Builder />
|
||||
|
||||
<Simulation />
|
||||
|
||||
<PhysicsSimulator />
|
||||
|
||||
@@ -5,6 +5,7 @@ import Controls from '../controls/controls';
|
||||
import { Environment } from '@react-three/drei'
|
||||
|
||||
import background from "../../../assets/textures/hdr/mudroadpuresky2k.hdr";
|
||||
|
||||
import SecondaryCamera from '../../secondaryCamera/secondaryCamera';
|
||||
|
||||
function Setup() {
|
||||
@@ -21,7 +22,8 @@ function Setup() {
|
||||
{/* <MovingClouds /> */}
|
||||
|
||||
<Environment files={background} environmentIntensity={1.5} />
|
||||
<SecondaryCamera/>
|
||||
|
||||
{/* <SecondaryCamera /> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ type CameraData = {
|
||||
target: [number, number, number];
|
||||
};
|
||||
|
||||
function SecondaryCameraView() {
|
||||
function SecondaryCamera() {
|
||||
const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
|
||||
const helperRef = useRef<THREE.CameraHelper | null>(null);
|
||||
const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
|
||||
@@ -166,4 +166,4 @@ function SecondaryCameraView() {
|
||||
);
|
||||
}
|
||||
|
||||
export default SecondaryCameraView;
|
||||
export default SecondaryCamera;
|
||||
|
||||
@@ -134,7 +134,7 @@ const Project: React.FC = () => {
|
||||
</VersionProvider>
|
||||
</SceneProvider>
|
||||
|
||||
<SecondaryCanvas />
|
||||
{/* <SecondaryCanvas /> */}
|
||||
|
||||
{selectedUser && <FollowPerson />}
|
||||
{isLogListVisible && (
|
||||
|
||||
Reference in New Issue
Block a user