instancedMesh instead of drei instances: much higher performance
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import type { ObjectType, RuntimeGameObjectInstance, RuntimeObjectInstance } from "../types";
|
import type { ObjectType, RuntimeGameObjectInstance, RuntimeObjectInstance } from "../types";
|
||||||
import { useEffect, useImperativeHandle, useRef, type Ref } from "react";
|
import type { VoxelGroup } from "../types/runtime/voxelGroup";
|
||||||
import { Euler, Quaternion, type Group } from "three";
|
import { useEffect, useImperativeHandle, useLayoutEffect, useRef, type Ref, memo } from "react";
|
||||||
import { Instance, Instances } from "@react-three/drei";
|
import { Euler, Matrix4, Quaternion, type Group, type InstancedMesh } from "three";
|
||||||
import type { ThreeEvent } from "@react-three/fiber";
|
import type { ThreeEvent } from "@react-three/fiber";
|
||||||
import { ConvexHullCollider, RapierRigidBody } from "@react-three/rapier";
|
import { ConvexHullCollider, RapierRigidBody } from "@react-three/rapier";
|
||||||
import { SyncRigidBody } from "./SyncRigidBody";
|
import { SyncRigidBody } from "./SyncRigidBody";
|
||||||
@@ -9,6 +9,30 @@ import { reaction, runInAction } from "mobx";
|
|||||||
import { v3toRapier } from "../utils";
|
import { v3toRapier } from "../utils";
|
||||||
import { state } from "../state";
|
import { state } from "../state";
|
||||||
|
|
||||||
|
const _m4 = new Matrix4();
|
||||||
|
|
||||||
|
const VoxelGroupMesh = memo(function VoxelGroupMesh({ vg }: { vg: VoxelGroup }) {
|
||||||
|
const ref = useRef<InstancedMesh>(null);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const mesh = ref.current;
|
||||||
|
if (!mesh)
|
||||||
|
return;
|
||||||
|
vg.positions.forEach(([x, y, z], i) => {
|
||||||
|
mesh.setMatrixAt(i, _m4.makeTranslation(x, y, z));
|
||||||
|
});
|
||||||
|
mesh.instanceMatrix.needsUpdate = true;
|
||||||
|
mesh.computeBoundingSphere();
|
||||||
|
}, [vg]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<instancedMesh ref={ref} args={[undefined, undefined, vg.positions.length]}>
|
||||||
|
<boxGeometry args={[1, 1, 1]} />
|
||||||
|
<meshStandardMaterial color={vg.color} opacity={vg.opacity} transparent={vg.opacity < 1} />
|
||||||
|
</instancedMesh>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export type ObjectViewInternalHandle = {
|
export type ObjectViewInternalHandle = {
|
||||||
group: Group | null;
|
group: Group | null;
|
||||||
rb: RapierRigidBody | null;
|
rb: RapierRigidBody | null;
|
||||||
@@ -118,11 +142,7 @@ export const ObjectViewInternal = function ({ object, objectType, ref, ...props
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
object.cache.voxelGroups.map((vg) =>
|
object.cache.voxelGroups.map((vg) =>
|
||||||
<Instances key={`${vg.id}-${object.cache.updatedAt}`} limit={vg.positions.length}>
|
<VoxelGroupMesh key={`${vg.id}-${object.cache.updatedAt}`} vg={vg} />
|
||||||
<boxGeometry args={[1, 1, 1]} />
|
|
||||||
<meshStandardMaterial color={vg.color} opacity={vg.opacity} transparent={vg.opacity < 1} />
|
|
||||||
{vg.positions.map((pos, i) => <Instance key={i} position={pos} />)}
|
|
||||||
</Instances>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{object.cache.colliderMesh && <ConvexHullCollider args={[object.cache.colliderMesh[0]]} />}
|
{object.cache.colliderMesh && <ConvexHullCollider args={[object.cache.colliderMesh[0]]} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user