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 handles position/rotation/scale via the instances prop.
95
- // We pass scale in instances and let the library manage matrix updates.
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
- // InstancedRigidBodies expects { key, position, rotation, scale }
98
- const rigidBodyInstances = useMemo(() => instances.map(({ id, position, rotation, scale }) => ({ key: id, position, rotation, scale })), [instances]);
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,6 +1,6 @@
1
1
  {
2
2
  "name": "react-three-game",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "description": "Batteries included React Three Fiber game engine",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -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 handles position/rotation/scale via the instances prop.
168
- // We pass scale in instances and let the library manage matrix updates.
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
- // InstancedRigidBodies expects { key, position, rotation, scale }
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, scale }) => ({ key: id, position, rotation, scale })),
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