react-three-game 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { createContext, useContext, useMemo, useRef, useState, useEffect, useCallback } from "react";
|
|
3
3
|
import { Merged } from '@react-three/drei';
|
|
4
4
|
import { InstancedRigidBodies } from "@react-three/rapier";
|
|
5
|
-
import { Mesh, Matrix4 } from "three";
|
|
5
|
+
import { Mesh, Matrix4, Quaternion, Vector3 } from "three";
|
|
6
6
|
// --- Helpers ---
|
|
7
7
|
const tupleEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
8
8
|
const instanceChanged = (a, b) => {
|
|
@@ -91,14 +91,34 @@ export function GameInstanceProvider({ children, models, onSelect, registerRef }
|
|
|
91
91
|
})] }));
|
|
92
92
|
}
|
|
93
93
|
// --- Physics Instances ---
|
|
94
|
-
// InstancedRigidBodies
|
|
95
|
-
// We
|
|
94
|
+
// InstancedRigidBodies manages position/rotation from physics simulation.
|
|
95
|
+
// We apply scale once when instances change via useEffect.
|
|
96
96
|
function PhysicsInstances({ instances, physicsType, modelKey, partCount, meshParts }) {
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const meshRefs = useRef([]);
|
|
98
|
+
// InstancedRigidBodies needs position/rotation (scale handled separately)
|
|
99
|
+
const rigidBodyInstances = useMemo(() => instances.map(({ id, position, rotation }) => ({ key: id, position, rotation })), [instances]);
|
|
100
|
+
// Apply scale when instances change
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const matrix = new Matrix4();
|
|
103
|
+
const pos = new Vector3();
|
|
104
|
+
const quat = new Quaternion();
|
|
105
|
+
const scl = new Vector3();
|
|
106
|
+
meshRefs.current.forEach(mesh => {
|
|
107
|
+
if (!mesh)
|
|
108
|
+
return;
|
|
109
|
+
instances.forEach((inst, i) => {
|
|
110
|
+
mesh.getMatrixAt(i, matrix);
|
|
111
|
+
matrix.decompose(pos, quat, scl);
|
|
112
|
+
scl.set(...inst.scale);
|
|
113
|
+
matrix.compose(pos, quat, scl);
|
|
114
|
+
mesh.setMatrixAt(i, matrix);
|
|
115
|
+
});
|
|
116
|
+
mesh.instanceMatrix.needsUpdate = true;
|
|
117
|
+
});
|
|
118
|
+
}, [instances]);
|
|
99
119
|
return (_jsx(InstancedRigidBodies, { instances: rigidBodyInstances, type: physicsType, colliders: physicsType === 'fixed' ? 'trimesh' : 'hull', children: Array.from({ length: partCount }, (_, i) => {
|
|
100
120
|
const mesh = meshParts[`${modelKey}__${i}`];
|
|
101
|
-
return mesh ? (_jsx("instancedMesh", { args: [mesh.geometry, mesh.material, instances.length], frustumCulled: false, castShadow: true, receiveShadow: true }, i)) : null;
|
|
121
|
+
return mesh ? (_jsx("instancedMesh", { ref: el => { meshRefs.current[i] = el; }, args: [mesh.geometry, mesh.material, instances.length], frustumCulled: false, castShadow: true, receiveShadow: true }, i)) : null;
|
|
102
122
|
}) }));
|
|
103
123
|
}
|
|
104
124
|
// --- Static Instances (non-physics) ---
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { createContext, useContext, useMemo, useRef, useState, useEffect, useCallback } from "react";
|
|
2
2
|
import { Merged } from '@react-three/drei';
|
|
3
3
|
import { InstancedRigidBodies, RigidBodyProps } from "@react-three/rapier";
|
|
4
|
-
import { Mesh, Matrix4, Object3D } from "three";
|
|
4
|
+
import { Mesh, Matrix4, Object3D, Quaternion, Vector3, InstancedMesh } from "three";
|
|
5
5
|
|
|
6
6
|
// --- Types ---
|
|
7
7
|
export type InstanceData = {
|
|
@@ -164,8 +164,8 @@ export function GameInstanceProvider({
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// --- Physics Instances ---
|
|
167
|
-
// InstancedRigidBodies
|
|
168
|
-
// We
|
|
167
|
+
// InstancedRigidBodies manages position/rotation from physics simulation.
|
|
168
|
+
// We apply scale once when instances change via useEffect.
|
|
169
169
|
function PhysicsInstances({
|
|
170
170
|
instances,
|
|
171
171
|
physicsType,
|
|
@@ -179,12 +179,35 @@ function PhysicsInstances({
|
|
|
179
179
|
partCount: number;
|
|
180
180
|
meshParts: Record<string, Mesh>;
|
|
181
181
|
}) {
|
|
182
|
-
|
|
182
|
+
const meshRefs = useRef<(InstancedMesh | null)[]>([]);
|
|
183
|
+
|
|
184
|
+
// InstancedRigidBodies needs position/rotation (scale handled separately)
|
|
183
185
|
const rigidBodyInstances = useMemo(() =>
|
|
184
|
-
instances.map(({ id, position, rotation
|
|
186
|
+
instances.map(({ id, position, rotation }) => ({ key: id, position, rotation })),
|
|
185
187
|
[instances]
|
|
186
188
|
);
|
|
187
189
|
|
|
190
|
+
// Apply scale when instances change
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
const matrix = new Matrix4();
|
|
193
|
+
const pos = new Vector3();
|
|
194
|
+
const quat = new Quaternion();
|
|
195
|
+
const scl = new Vector3();
|
|
196
|
+
|
|
197
|
+
meshRefs.current.forEach(mesh => {
|
|
198
|
+
if (!mesh) return;
|
|
199
|
+
|
|
200
|
+
instances.forEach((inst, i) => {
|
|
201
|
+
mesh.getMatrixAt(i, matrix);
|
|
202
|
+
matrix.decompose(pos, quat, scl);
|
|
203
|
+
scl.set(...inst.scale);
|
|
204
|
+
matrix.compose(pos, quat, scl);
|
|
205
|
+
mesh.setMatrixAt(i, matrix);
|
|
206
|
+
});
|
|
207
|
+
mesh.instanceMatrix.needsUpdate = true;
|
|
208
|
+
});
|
|
209
|
+
}, [instances]);
|
|
210
|
+
|
|
188
211
|
return (
|
|
189
212
|
<InstancedRigidBodies
|
|
190
213
|
instances={rigidBodyInstances}
|
|
@@ -196,6 +219,7 @@ function PhysicsInstances({
|
|
|
196
219
|
return mesh ? (
|
|
197
220
|
<instancedMesh
|
|
198
221
|
key={i}
|
|
222
|
+
ref={el => { meshRefs.current[i] = el; }}
|
|
199
223
|
args={[mesh.geometry, mesh.material, instances.length]}
|
|
200
224
|
frustumCulled={false}
|
|
201
225
|
castShadow
|