mujoco-react 1.0.0 → 3.0.0
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.
- package/README.md +89 -124
- package/dist/index.d.ts +4 -10
- package/dist/index.js +561 -558
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ContactMarkers.tsx +2 -2
- package/src/components/Debug.tsx +2 -2
- package/src/components/DragInteraction.tsx +2 -2
- package/src/components/FlexRenderer.tsx +2 -2
- package/src/components/IkController.tsx +2 -2
- package/src/components/IkGizmo.tsx +2 -2
- package/src/components/SceneRenderer.tsx +2 -2
- package/src/components/TendonRenderer.tsx +2 -2
- package/src/core/MujocoCanvas.tsx +2 -2
- package/src/core/MujocoPhysics.tsx +2 -2
- package/src/core/MujocoProvider.tsx +1 -1
- package/src/core/MujocoSimProvider.tsx +6 -4
- package/src/core/createController.tsx +1 -1
- package/src/hooks/useActuators.ts +2 -2
- package/src/hooks/useBodyState.ts +2 -2
- package/src/hooks/useContacts.ts +2 -2
- package/src/hooks/useCtrl.ts +2 -2
- package/src/hooks/useCtrlNoise.ts +2 -2
- package/src/hooks/useGamepad.ts +2 -2
- package/src/hooks/useJointState.ts +2 -2
- package/src/hooks/useKeyboardTeleop.ts +2 -2
- package/src/hooks/usePolicy.ts +2 -2
- package/src/hooks/useSceneLights.ts +2 -2
- package/src/hooks/useSensor.ts +3 -3
- package/src/hooks/useSitePosition.ts +2 -2
- package/src/hooks/useTrajectoryPlayer.ts +2 -2
- package/src/hooks/useTrajectoryRecorder.ts +2 -2
- package/src/index.ts +2 -3
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ var MujocoContext = createContext({
|
|
|
11
11
|
status: "loading",
|
|
12
12
|
error: null
|
|
13
13
|
});
|
|
14
|
-
function
|
|
14
|
+
function useMujocoWasm() {
|
|
15
15
|
return useContext(MujocoContext);
|
|
16
16
|
}
|
|
17
17
|
function MujocoProvider({ wasmUrl, timeout = 3e4, children, onError }) {
|
|
@@ -67,6 +67,248 @@ function getContact(data, i) {
|
|
|
67
67
|
return void 0;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
var CapsuleGeometry = class extends THREE11.BufferGeometry {
|
|
71
|
+
parameters;
|
|
72
|
+
constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
|
|
73
|
+
super();
|
|
74
|
+
this.type = "CapsuleGeometry";
|
|
75
|
+
this.parameters = { radius, length, capSegments, radialSegments };
|
|
76
|
+
const path = new THREE11.Path();
|
|
77
|
+
path.absarc(0, -length / 2, radius, Math.PI * 1.5, 0, false);
|
|
78
|
+
path.absarc(0, length / 2, radius, 0, Math.PI * 0.5, false);
|
|
79
|
+
const latheGeometry = new THREE11.LatheGeometry(path.getPoints(capSegments), radialSegments);
|
|
80
|
+
const self = this;
|
|
81
|
+
self.setIndex(latheGeometry.getIndex());
|
|
82
|
+
self.setAttribute("position", latheGeometry.getAttribute("position"));
|
|
83
|
+
self.setAttribute("normal", latheGeometry.getAttribute("normal"));
|
|
84
|
+
self.setAttribute("uv", latheGeometry.getAttribute("uv"));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var Reflector = class extends THREE11.Mesh {
|
|
88
|
+
isReflector = true;
|
|
89
|
+
camera;
|
|
90
|
+
reflectorPlane = new THREE11.Plane();
|
|
91
|
+
normal = new THREE11.Vector3();
|
|
92
|
+
reflectorWorldPosition = new THREE11.Vector3();
|
|
93
|
+
cameraWorldPosition = new THREE11.Vector3();
|
|
94
|
+
rotationMatrix = new THREE11.Matrix4();
|
|
95
|
+
lookAtPosition = new THREE11.Vector3(0, 0, -1);
|
|
96
|
+
clipPlane = new THREE11.Vector4();
|
|
97
|
+
view = new THREE11.Vector3();
|
|
98
|
+
target = new THREE11.Vector3();
|
|
99
|
+
q = new THREE11.Vector4();
|
|
100
|
+
textureMatrix = new THREE11.Matrix4();
|
|
101
|
+
virtualCamera;
|
|
102
|
+
renderTarget;
|
|
103
|
+
constructor(geometry, options = {}) {
|
|
104
|
+
super(geometry);
|
|
105
|
+
this.type = "Reflector";
|
|
106
|
+
this.camera = new THREE11.PerspectiveCamera();
|
|
107
|
+
const color = options.color !== void 0 ? new THREE11.Color(options.color) : new THREE11.Color(8355711);
|
|
108
|
+
const textureWidth = options.textureWidth || 512;
|
|
109
|
+
const textureHeight = options.textureHeight || 512;
|
|
110
|
+
const clipBias = options.clipBias || 0;
|
|
111
|
+
const multisample = options.multisample !== void 0 ? options.multisample : 4;
|
|
112
|
+
const blendTexture = options.texture || void 0;
|
|
113
|
+
const mixStrength = options.mixStrength !== void 0 ? options.mixStrength : 0.25;
|
|
114
|
+
this.virtualCamera = this.camera;
|
|
115
|
+
this.renderTarget = new THREE11.WebGLRenderTarget(textureWidth, textureHeight, {
|
|
116
|
+
samples: multisample,
|
|
117
|
+
type: THREE11.HalfFloatType
|
|
118
|
+
});
|
|
119
|
+
this.material = new THREE11.MeshPhysicalMaterial({
|
|
120
|
+
map: blendTexture,
|
|
121
|
+
color,
|
|
122
|
+
roughness: 0.5,
|
|
123
|
+
metalness: 0.1
|
|
124
|
+
});
|
|
125
|
+
this.material.onBeforeCompile = (shader) => {
|
|
126
|
+
shader.uniforms.tDiffuse = { value: this.renderTarget.texture };
|
|
127
|
+
shader.uniforms.textureMatrix = { value: this.textureMatrix };
|
|
128
|
+
shader.uniforms.mixStrength = { value: mixStrength };
|
|
129
|
+
const bodyStart = shader.vertexShader.indexOf("void main() {");
|
|
130
|
+
shader.vertexShader = "uniform mat4 textureMatrix;\nvarying vec4 vUvReflection;\n" + shader.vertexShader.slice(0, bodyStart) + shader.vertexShader.slice(bodyStart, -1) + " vUvReflection = textureMatrix * vec4( position, 1.0 );\n}";
|
|
131
|
+
const fragmentBodyStart = shader.fragmentShader.indexOf("void main() {");
|
|
132
|
+
shader.fragmentShader = "uniform sampler2D tDiffuse;\nuniform float mixStrength;\nvarying vec4 vUvReflection;\n" + shader.fragmentShader.slice(0, fragmentBodyStart) + shader.fragmentShader.slice(fragmentBodyStart, -1) + " vec4 reflectionColor = texture2DProj( tDiffuse, vUvReflection );\n gl_FragColor = vec4( mix( gl_FragColor.rgb, reflectionColor.rgb, mixStrength ), gl_FragColor.a );\n}";
|
|
133
|
+
};
|
|
134
|
+
this.receiveShadow = true;
|
|
135
|
+
this.onBeforeRender = (renderer, scene, camera) => {
|
|
136
|
+
this.reflectorWorldPosition.setFromMatrixPosition(this.matrixWorld);
|
|
137
|
+
this.cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
|
|
138
|
+
this.rotationMatrix.extractRotation(this.matrixWorld);
|
|
139
|
+
this.normal.set(0, 0, 1);
|
|
140
|
+
this.normal.applyMatrix4(this.rotationMatrix);
|
|
141
|
+
this.view.subVectors(this.reflectorWorldPosition, this.cameraWorldPosition);
|
|
142
|
+
if (this.view.dot(this.normal) > 0) return;
|
|
143
|
+
this.view.reflect(this.normal).negate();
|
|
144
|
+
this.view.add(this.reflectorWorldPosition);
|
|
145
|
+
this.rotationMatrix.extractRotation(camera.matrixWorld);
|
|
146
|
+
this.lookAtPosition.set(0, 0, -1);
|
|
147
|
+
this.lookAtPosition.applyMatrix4(this.rotationMatrix);
|
|
148
|
+
this.lookAtPosition.add(this.cameraWorldPosition);
|
|
149
|
+
this.target.subVectors(this.reflectorWorldPosition, this.lookAtPosition);
|
|
150
|
+
this.target.reflect(this.normal).negate();
|
|
151
|
+
this.target.add(this.reflectorWorldPosition);
|
|
152
|
+
this.virtualCamera.position.copy(this.view);
|
|
153
|
+
this.virtualCamera.up.set(0, 1, 0);
|
|
154
|
+
this.virtualCamera.up.applyMatrix4(this.rotationMatrix);
|
|
155
|
+
this.virtualCamera.up.reflect(this.normal);
|
|
156
|
+
this.virtualCamera.lookAt(this.target);
|
|
157
|
+
this.virtualCamera.far = camera.far;
|
|
158
|
+
this.virtualCamera.updateMatrixWorld();
|
|
159
|
+
this.virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
|
|
160
|
+
this.textureMatrix.set(
|
|
161
|
+
0.5,
|
|
162
|
+
0,
|
|
163
|
+
0,
|
|
164
|
+
0.5,
|
|
165
|
+
0,
|
|
166
|
+
0.5,
|
|
167
|
+
0,
|
|
168
|
+
0.5,
|
|
169
|
+
0,
|
|
170
|
+
0,
|
|
171
|
+
0.5,
|
|
172
|
+
0.5,
|
|
173
|
+
0,
|
|
174
|
+
0,
|
|
175
|
+
0,
|
|
176
|
+
1
|
|
177
|
+
);
|
|
178
|
+
this.textureMatrix.multiply(this.virtualCamera.projectionMatrix);
|
|
179
|
+
this.textureMatrix.multiply(this.virtualCamera.matrixWorldInverse);
|
|
180
|
+
this.textureMatrix.multiply(this.matrixWorld);
|
|
181
|
+
this.reflectorPlane.setFromNormalAndCoplanarPoint(this.normal, this.reflectorWorldPosition);
|
|
182
|
+
this.reflectorPlane.applyMatrix4(this.virtualCamera.matrixWorldInverse);
|
|
183
|
+
this.clipPlane.set(this.reflectorPlane.normal.x, this.reflectorPlane.normal.y, this.reflectorPlane.normal.z, this.reflectorPlane.constant);
|
|
184
|
+
const projectionMatrix = this.virtualCamera.projectionMatrix;
|
|
185
|
+
this.q.x = (Math.sign(this.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
|
|
186
|
+
this.q.y = (Math.sign(this.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
|
|
187
|
+
this.q.z = -1;
|
|
188
|
+
this.q.w = (1 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
|
|
189
|
+
this.clipPlane.multiplyScalar(2 / this.clipPlane.dot(this.q));
|
|
190
|
+
projectionMatrix.elements[2] = this.clipPlane.x;
|
|
191
|
+
projectionMatrix.elements[6] = this.clipPlane.y;
|
|
192
|
+
projectionMatrix.elements[10] = this.clipPlane.z + 1 - clipBias;
|
|
193
|
+
projectionMatrix.elements[14] = this.clipPlane.w;
|
|
194
|
+
this.visible = false;
|
|
195
|
+
const currentRenderTarget = renderer.getRenderTarget();
|
|
196
|
+
const currentXrEnabled = renderer.xr.enabled;
|
|
197
|
+
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
|
198
|
+
renderer.xr.enabled = false;
|
|
199
|
+
renderer.shadowMap.autoUpdate = false;
|
|
200
|
+
renderer.setRenderTarget(this.renderTarget);
|
|
201
|
+
renderer.state.buffers.depth.setMask(true);
|
|
202
|
+
if (renderer.autoClear === false) renderer.clear();
|
|
203
|
+
renderer.render(scene, this.virtualCamera);
|
|
204
|
+
renderer.xr.enabled = currentXrEnabled;
|
|
205
|
+
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
|
206
|
+
renderer.setRenderTarget(currentRenderTarget);
|
|
207
|
+
const viewport = camera.viewport;
|
|
208
|
+
if (viewport !== void 0) {
|
|
209
|
+
renderer.state.viewport(viewport);
|
|
210
|
+
}
|
|
211
|
+
this.visible = true;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
getRenderTarget() {
|
|
215
|
+
return this.renderTarget;
|
|
216
|
+
}
|
|
217
|
+
dispose() {
|
|
218
|
+
this.renderTarget.dispose();
|
|
219
|
+
const mesh = this;
|
|
220
|
+
if (Array.isArray(mesh.material)) {
|
|
221
|
+
mesh.material.forEach((m) => m.dispose());
|
|
222
|
+
} else {
|
|
223
|
+
mesh.material.dispose();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/rendering/GeomBuilder.ts
|
|
229
|
+
var GeomBuilder = class {
|
|
230
|
+
mujoco;
|
|
231
|
+
constructor(mujoco) {
|
|
232
|
+
this.mujoco = mujoco;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Creates a Three.js Object3D (usually a Mesh) for a specific geometry in the MuJoCo model.
|
|
236
|
+
* Returns null if the geometry shouldn't be rendered (e.g., invisible collision triggers).
|
|
237
|
+
*/
|
|
238
|
+
create(mjModel, g) {
|
|
239
|
+
if (mjModel.geom_group[g] === 3) return null;
|
|
240
|
+
const type = mjModel.geom_type[g];
|
|
241
|
+
const size = mjModel.geom_size.subarray(g * 3, g * 3 + 3);
|
|
242
|
+
const pos = mjModel.geom_pos.subarray(g * 3, g * 3 + 3);
|
|
243
|
+
const quat = mjModel.geom_quat.subarray(g * 4, g * 4 + 4);
|
|
244
|
+
const matId = mjModel.geom_matid[g];
|
|
245
|
+
const color = new THREE11.Color(16777215);
|
|
246
|
+
let opacity = 1;
|
|
247
|
+
if (matId >= 0) {
|
|
248
|
+
const rgba = mjModel.mat_rgba.subarray(matId * 4, matId * 4 + 4);
|
|
249
|
+
color.setRGB(rgba[0], rgba[1], rgba[2]);
|
|
250
|
+
opacity = rgba[3];
|
|
251
|
+
} else {
|
|
252
|
+
const rgba = mjModel.geom_rgba.subarray(g * 4, g * 4 + 4);
|
|
253
|
+
color.setRGB(rgba[0], rgba[1], rgba[2]);
|
|
254
|
+
opacity = rgba[3];
|
|
255
|
+
}
|
|
256
|
+
const MG = this.mujoco.mjtGeom;
|
|
257
|
+
let geo = null;
|
|
258
|
+
const getVal = (v) => v?.value ?? v;
|
|
259
|
+
if (type === getVal(MG.mjGEOM_PLANE)) {
|
|
260
|
+
geo = new THREE11.PlaneGeometry(size[0] * 2 || 5, size[1] * 2 || 5);
|
|
261
|
+
} else if (type === getVal(MG.mjGEOM_SPHERE)) {
|
|
262
|
+
geo = new THREE11.SphereGeometry(size[0], 24, 24);
|
|
263
|
+
} else if (type === getVal(MG.mjGEOM_CAPSULE)) {
|
|
264
|
+
geo = new CapsuleGeometry(size[0], size[1] * 2, 24, 12);
|
|
265
|
+
geo.rotateX(Math.PI / 2);
|
|
266
|
+
} else if (type === getVal(MG.mjGEOM_BOX)) {
|
|
267
|
+
geo = new THREE11.BoxGeometry(size[0] * 2, size[1] * 2, size[2] * 2);
|
|
268
|
+
} else if (type === getVal(MG.mjGEOM_CYLINDER)) {
|
|
269
|
+
geo = new THREE11.CylinderGeometry(size[0], size[0], size[1] * 2, 24);
|
|
270
|
+
geo.rotateX(Math.PI / 2);
|
|
271
|
+
} else if (type === getVal(MG.mjGEOM_MESH)) {
|
|
272
|
+
const mId = mjModel.geom_dataid[g];
|
|
273
|
+
const vAdr = mjModel.mesh_vertadr[mId];
|
|
274
|
+
const vNum = mjModel.mesh_vertnum[mId];
|
|
275
|
+
const fAdr = mjModel.mesh_faceadr[mId];
|
|
276
|
+
const fNum = mjModel.mesh_facenum[mId];
|
|
277
|
+
geo = new THREE11.BufferGeometry();
|
|
278
|
+
geo.setAttribute("position", new THREE11.Float32BufferAttribute(mjModel.mesh_vert.subarray(vAdr * 3, (vAdr + vNum) * 3), 3));
|
|
279
|
+
geo.setIndex(Array.from(mjModel.mesh_face.subarray(fAdr * 3, (fAdr + fNum) * 3)));
|
|
280
|
+
geo.computeVertexNormals();
|
|
281
|
+
}
|
|
282
|
+
if (geo) {
|
|
283
|
+
let mesh;
|
|
284
|
+
if (type === getVal(MG.mjGEOM_PLANE)) {
|
|
285
|
+
mesh = new Reflector(geo, {
|
|
286
|
+
clipBias: 3e-3,
|
|
287
|
+
textureWidth: 1024,
|
|
288
|
+
textureHeight: 1024,
|
|
289
|
+
color,
|
|
290
|
+
mixStrength: 0.25
|
|
291
|
+
});
|
|
292
|
+
} else {
|
|
293
|
+
mesh = new THREE11.Mesh(geo, new THREE11.MeshStandardMaterial({
|
|
294
|
+
color,
|
|
295
|
+
transparent: opacity < 1,
|
|
296
|
+
opacity,
|
|
297
|
+
roughness: 0.6,
|
|
298
|
+
metalness: 0.2
|
|
299
|
+
}));
|
|
300
|
+
mesh.castShadow = true;
|
|
301
|
+
mesh.receiveShadow = true;
|
|
302
|
+
}
|
|
303
|
+
mesh.position.set(pos[0], pos[1], pos[2]);
|
|
304
|
+
mesh.quaternion.set(quat[1], quat[2], quat[3], quat[0]);
|
|
305
|
+
mesh.userData.bodyID = mjModel.geom_bodyid[g];
|
|
306
|
+
mesh.userData.geomID = g;
|
|
307
|
+
return mesh;
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
70
312
|
|
|
71
313
|
// src/core/SceneLoader.ts
|
|
72
314
|
function getName(mjModel, address) {
|
|
@@ -265,19 +507,97 @@ function scanDependencies(xmlString, currentFile, parser, downloaded, queue) {
|
|
|
265
507
|
if (!downloaded.has(fullPath)) queue.push(fullPath);
|
|
266
508
|
});
|
|
267
509
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
510
|
+
function SceneRenderer(props) {
|
|
511
|
+
const { mjModelRef, mjDataRef, mujocoRef, onSelectionRef, status } = useMujoco();
|
|
512
|
+
const groupRef = useRef(null);
|
|
513
|
+
const bodyRefs = useRef([]);
|
|
514
|
+
const prevModelRef = useRef(null);
|
|
515
|
+
const geomBuilder = useMemo(() => {
|
|
516
|
+
if (status !== "ready") return null;
|
|
517
|
+
return new GeomBuilder(mujocoRef.current);
|
|
518
|
+
}, [status, mujocoRef]);
|
|
519
|
+
useEffect(() => {
|
|
520
|
+
if (status !== "ready" || !geomBuilder) return;
|
|
521
|
+
const model = mjModelRef.current;
|
|
522
|
+
const group = groupRef.current;
|
|
523
|
+
if (!model || !group) return;
|
|
524
|
+
if (prevModelRef.current === model) return;
|
|
525
|
+
prevModelRef.current = model;
|
|
526
|
+
while (group.children.length > 0) {
|
|
527
|
+
group.remove(group.children[0]);
|
|
528
|
+
}
|
|
529
|
+
const refs = [];
|
|
530
|
+
for (let i = 0; i < model.nbody; i++) {
|
|
531
|
+
const bodyGroup = new THREE11.Group();
|
|
532
|
+
bodyGroup.userData.bodyID = i;
|
|
533
|
+
for (let g = 0; g < model.ngeom; g++) {
|
|
534
|
+
if (model.geom_bodyid[g] === i) {
|
|
535
|
+
const mesh = geomBuilder.create(model, g);
|
|
536
|
+
if (mesh) bodyGroup.add(mesh);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
group.add(bodyGroup);
|
|
540
|
+
refs.push(bodyGroup);
|
|
541
|
+
}
|
|
542
|
+
bodyRefs.current = refs;
|
|
543
|
+
}, [status, geomBuilder, mjModelRef]);
|
|
544
|
+
useFrame(() => {
|
|
545
|
+
const data = mjDataRef.current;
|
|
546
|
+
if (!data) return;
|
|
547
|
+
const bodies = bodyRefs.current;
|
|
548
|
+
for (let i = 0; i < bodies.length; i++) {
|
|
549
|
+
const ref = bodies[i];
|
|
550
|
+
if (!ref) continue;
|
|
551
|
+
ref.position.set(
|
|
552
|
+
data.xpos[i * 3],
|
|
553
|
+
data.xpos[i * 3 + 1],
|
|
554
|
+
data.xpos[i * 3 + 2]
|
|
555
|
+
);
|
|
556
|
+
ref.quaternion.set(
|
|
557
|
+
data.xquat[i * 4 + 1],
|
|
558
|
+
data.xquat[i * 4 + 2],
|
|
559
|
+
data.xquat[i * 4 + 3],
|
|
560
|
+
data.xquat[i * 4]
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
return /* @__PURE__ */ jsx(
|
|
565
|
+
"group",
|
|
566
|
+
{
|
|
567
|
+
...props,
|
|
568
|
+
ref: groupRef,
|
|
569
|
+
onDoubleClick: (e) => {
|
|
570
|
+
if (typeof props.onDoubleClick === "function") props.onDoubleClick(e);
|
|
571
|
+
e.stopPropagation();
|
|
572
|
+
let obj = e.object;
|
|
573
|
+
while (obj && obj.userData.bodyID === void 0 && obj.parent) {
|
|
574
|
+
obj = obj.parent;
|
|
575
|
+
}
|
|
576
|
+
const bodyID = obj?.userData.bodyID;
|
|
577
|
+
if (typeof bodyID === "number" && bodyID > 0) {
|
|
578
|
+
const model = mjModelRef.current;
|
|
579
|
+
if (model && bodyID < model.nbody && onSelectionRef.current) {
|
|
580
|
+
const name = getName(model, model.name_bodyadr[bodyID]);
|
|
581
|
+
onSelectionRef.current(bodyID, name);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
var JOINT_TYPE_NAMES = ["free", "ball", "slide", "hinge"];
|
|
589
|
+
var GEOM_TYPE_NAMES = ["plane", "hfield", "sphere", "capsule", "ellipsoid", "cylinder", "box", "mesh"];
|
|
590
|
+
var SENSOR_TYPE_NAMES = {
|
|
591
|
+
0: "touch",
|
|
592
|
+
1: "accelerometer",
|
|
593
|
+
2: "velocimeter",
|
|
594
|
+
3: "gyro",
|
|
595
|
+
4: "force",
|
|
596
|
+
5: "torque",
|
|
597
|
+
6: "magnetometer",
|
|
598
|
+
7: "rangefinder",
|
|
599
|
+
8: "camprojection",
|
|
600
|
+
9: "jointpos",
|
|
281
601
|
10: "jointvel",
|
|
282
602
|
11: "tendonpos",
|
|
283
603
|
12: "tendonvel",
|
|
@@ -327,14 +647,14 @@ var _rayGeomId = new Int32Array(1);
|
|
|
327
647
|
var _projRaycaster = new THREE11.Raycaster();
|
|
328
648
|
var _projNdc = new THREE11.Vector2();
|
|
329
649
|
var MujocoSimContext = createContext(null);
|
|
330
|
-
function
|
|
650
|
+
function useMujoco() {
|
|
331
651
|
const ctx = useContext(MujocoSimContext);
|
|
332
652
|
if (!ctx)
|
|
333
|
-
throw new Error("
|
|
653
|
+
throw new Error("useMujoco must be used inside <MujocoSimProvider>");
|
|
334
654
|
return ctx;
|
|
335
655
|
}
|
|
336
656
|
function useBeforePhysicsStep(callback) {
|
|
337
|
-
const { beforeStepCallbacks } =
|
|
657
|
+
const { beforeStepCallbacks } = useMujoco();
|
|
338
658
|
const callbackRef = useRef(callback);
|
|
339
659
|
callbackRef.current = callback;
|
|
340
660
|
useEffect(() => {
|
|
@@ -346,7 +666,7 @@ function useBeforePhysicsStep(callback) {
|
|
|
346
666
|
}, [beforeStepCallbacks]);
|
|
347
667
|
}
|
|
348
668
|
function useAfterPhysicsStep(callback) {
|
|
349
|
-
const { afterStepCallbacks } =
|
|
669
|
+
const { afterStepCallbacks } = useMujoco();
|
|
350
670
|
const callbackRef = useRef(callback);
|
|
351
671
|
callbackRef.current = callback;
|
|
352
672
|
useEffect(() => {
|
|
@@ -1095,7 +1415,10 @@ function MujocoSimProvider({
|
|
|
1095
1415
|
}),
|
|
1096
1416
|
[api, status]
|
|
1097
1417
|
);
|
|
1098
|
-
return /* @__PURE__ */
|
|
1418
|
+
return /* @__PURE__ */ jsxs(MujocoSimContext.Provider, { value: contextValue, children: [
|
|
1419
|
+
/* @__PURE__ */ jsx(SceneRenderer, {}),
|
|
1420
|
+
children
|
|
1421
|
+
] });
|
|
1099
1422
|
}
|
|
1100
1423
|
var MujocoCanvas = forwardRef(
|
|
1101
1424
|
function MujocoCanvas2({
|
|
@@ -1113,7 +1436,7 @@ var MujocoCanvas = forwardRef(
|
|
|
1113
1436
|
children,
|
|
1114
1437
|
...canvasProps
|
|
1115
1438
|
}, ref) {
|
|
1116
|
-
const { mujoco, status: wasmStatus, error: wasmError } =
|
|
1439
|
+
const { mujoco, status: wasmStatus, error: wasmError } = useMujocoWasm();
|
|
1117
1440
|
useEffect(() => {
|
|
1118
1441
|
if (wasmStatus === "error" && onError) {
|
|
1119
1442
|
onError(new Error(wasmError ?? "WASM load failed"));
|
|
@@ -1144,7 +1467,7 @@ var MujocoCanvas = forwardRef(
|
|
|
1144
1467
|
);
|
|
1145
1468
|
var MujocoPhysics = forwardRef(
|
|
1146
1469
|
function MujocoPhysics2({ onError, children, ...props }, ref) {
|
|
1147
|
-
const { mujoco, status: wasmStatus, error: wasmError } =
|
|
1470
|
+
const { mujoco, status: wasmStatus, error: wasmError } = useMujocoWasm();
|
|
1148
1471
|
useEffect(() => {
|
|
1149
1472
|
if (wasmStatus === "error" && onError) {
|
|
1150
1473
|
onError(new Error(wasmError ?? "WASM load failed"));
|
|
@@ -1447,534 +1770,214 @@ function syncGizmoToSite(data, siteId, target) {
|
|
|
1447
1770
|
0,
|
|
1448
1771
|
siteMat[6],
|
|
1449
1772
|
siteMat[7],
|
|
1450
|
-
siteMat[8],
|
|
1451
|
-
0,
|
|
1452
|
-
0,
|
|
1453
|
-
0,
|
|
1454
|
-
0,
|
|
1455
|
-
1
|
|
1456
|
-
);
|
|
1457
|
-
target.quaternion.setFromRotationMatrix(_syncMat4);
|
|
1458
|
-
}
|
|
1459
|
-
function IkControllerImpl({
|
|
1460
|
-
config,
|
|
1461
|
-
children
|
|
1462
|
-
}) {
|
|
1463
|
-
const { mjModelRef, mjDataRef, mujocoRef, configRef, resetCallbacks, status } =
|
|
1464
|
-
const ikEnabledRef = useRef(false);
|
|
1465
|
-
const ikCalculatingRef = useRef(false);
|
|
1466
|
-
const ikTargetRef = useRef(new THREE11.Group());
|
|
1467
|
-
const siteIdRef = useRef(-1);
|
|
1468
|
-
const genericIkRef = useRef(new GenericIK(mujocoRef.current));
|
|
1469
|
-
const firstIkEnableRef = useRef(true);
|
|
1470
|
-
const needsInitialSync = useRef(true);
|
|
1471
|
-
const gizmoAnimRef = useRef({
|
|
1472
|
-
active: false,
|
|
1473
|
-
startPos: new THREE11.Vector3(),
|
|
1474
|
-
endPos: new THREE11.Vector3(),
|
|
1475
|
-
startRot: new THREE11.Quaternion(),
|
|
1476
|
-
endRot: new THREE11.Quaternion(),
|
|
1477
|
-
startTime: 0,
|
|
1478
|
-
duration: 1e3
|
|
1479
|
-
});
|
|
1480
|
-
useEffect(() => {
|
|
1481
|
-
const model = mjModelRef.current;
|
|
1482
|
-
if (!model || status !== "ready") {
|
|
1483
|
-
siteIdRef.current = -1;
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
siteIdRef.current = findSiteByName(model, config.siteName);
|
|
1487
|
-
const data = mjDataRef.current;
|
|
1488
|
-
if (data && ikTargetRef.current) {
|
|
1489
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1490
|
-
}
|
|
1491
|
-
}, [config.siteName, status, mjModelRef, mjDataRef]);
|
|
1492
|
-
const ikSolveFn = useCallback(
|
|
1493
|
-
(pos, quat, currentQ) => {
|
|
1494
|
-
if (config.ikSolveFn) return config.ikSolveFn(pos, quat, currentQ);
|
|
1495
|
-
const model = mjModelRef.current;
|
|
1496
|
-
const data = mjDataRef.current;
|
|
1497
|
-
if (!model || !data || siteIdRef.current === -1) return null;
|
|
1498
|
-
return genericIkRef.current.solve(
|
|
1499
|
-
model,
|
|
1500
|
-
data,
|
|
1501
|
-
siteIdRef.current,
|
|
1502
|
-
config.numJoints,
|
|
1503
|
-
pos,
|
|
1504
|
-
quat,
|
|
1505
|
-
currentQ,
|
|
1506
|
-
{
|
|
1507
|
-
damping: config.damping,
|
|
1508
|
-
maxIterations: config.maxIterations
|
|
1509
|
-
}
|
|
1510
|
-
);
|
|
1511
|
-
},
|
|
1512
|
-
[config.ikSolveFn, config.numJoints, config.damping, config.maxIterations, mjModelRef, mjDataRef]
|
|
1513
|
-
);
|
|
1514
|
-
const ikSolveFnRef = useRef(ikSolveFn);
|
|
1515
|
-
ikSolveFnRef.current = ikSolveFn;
|
|
1516
|
-
useFrame(() => {
|
|
1517
|
-
if (needsInitialSync.current && siteIdRef.current !== -1) {
|
|
1518
|
-
const data = mjDataRef.current;
|
|
1519
|
-
if (data && ikTargetRef.current) {
|
|
1520
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1521
|
-
needsInitialSync.current = false;
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
const ga = gizmoAnimRef.current;
|
|
1525
|
-
const target = ikTargetRef.current;
|
|
1526
|
-
if (!ga.active || !target) return;
|
|
1527
|
-
const now = performance.now();
|
|
1528
|
-
const elapsed = now - ga.startTime;
|
|
1529
|
-
const t = Math.min(elapsed / ga.duration, 1);
|
|
1530
|
-
const ease = 1 - Math.pow(1 - t, 3);
|
|
1531
|
-
target.position.lerpVectors(ga.startPos, ga.endPos, ease);
|
|
1532
|
-
target.quaternion.slerpQuaternions(ga.startRot, ga.endRot, ease);
|
|
1533
|
-
if (t >= 1) ga.active = false;
|
|
1534
|
-
});
|
|
1535
|
-
useBeforePhysicsStep((model, data) => {
|
|
1536
|
-
if (!ikEnabledRef.current) {
|
|
1537
|
-
ikCalculatingRef.current = false;
|
|
1538
|
-
return;
|
|
1539
|
-
}
|
|
1540
|
-
const target = ikTargetRef.current;
|
|
1541
|
-
if (!target) return;
|
|
1542
|
-
ikCalculatingRef.current = true;
|
|
1543
|
-
const numJoints = config.numJoints;
|
|
1544
|
-
const currentQ = [];
|
|
1545
|
-
for (let i = 0; i < numJoints; i++) currentQ.push(data.qpos[i]);
|
|
1546
|
-
const solution = ikSolveFnRef.current(target.position, target.quaternion, currentQ);
|
|
1547
|
-
if (solution) {
|
|
1548
|
-
for (let i = 0; i < numJoints; i++) data.ctrl[i] = solution[i];
|
|
1549
|
-
}
|
|
1550
|
-
});
|
|
1551
|
-
useEffect(() => {
|
|
1552
|
-
const cb = () => {
|
|
1553
|
-
const data = mjDataRef.current;
|
|
1554
|
-
if (data && ikTargetRef.current) {
|
|
1555
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1556
|
-
}
|
|
1557
|
-
gizmoAnimRef.current.active = false;
|
|
1558
|
-
firstIkEnableRef.current = true;
|
|
1559
|
-
ikEnabledRef.current = false;
|
|
1560
|
-
needsInitialSync.current = true;
|
|
1561
|
-
};
|
|
1562
|
-
resetCallbacks.current.add(cb);
|
|
1563
|
-
return () => {
|
|
1564
|
-
resetCallbacks.current.delete(cb);
|
|
1565
|
-
};
|
|
1566
|
-
}, [resetCallbacks, mjDataRef]);
|
|
1567
|
-
const setIkEnabled = useCallback(
|
|
1568
|
-
(enabled) => {
|
|
1569
|
-
ikEnabledRef.current = enabled;
|
|
1570
|
-
const data = mjDataRef.current;
|
|
1571
|
-
if (enabled && data && !gizmoAnimRef.current.active && ikTargetRef.current) {
|
|
1572
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1573
|
-
firstIkEnableRef.current = false;
|
|
1574
|
-
}
|
|
1575
|
-
},
|
|
1576
|
-
[mjDataRef]
|
|
1577
|
-
);
|
|
1578
|
-
const syncTargetToSiteApi = useCallback(() => {
|
|
1579
|
-
const data = mjDataRef.current;
|
|
1580
|
-
const target = ikTargetRef.current;
|
|
1581
|
-
if (data && target) syncGizmoToSite(data, siteIdRef.current, target);
|
|
1582
|
-
}, [mjDataRef]);
|
|
1583
|
-
const solveIK = useCallback(
|
|
1584
|
-
(pos, quat, currentQ) => {
|
|
1585
|
-
return ikSolveFnRef.current(pos, quat, currentQ);
|
|
1586
|
-
},
|
|
1587
|
-
[]
|
|
1588
|
-
);
|
|
1589
|
-
const moveTarget = useCallback(
|
|
1590
|
-
(pos, duration = 0) => {
|
|
1591
|
-
if (!ikEnabledRef.current) setIkEnabled(true);
|
|
1592
|
-
const target = ikTargetRef.current;
|
|
1593
|
-
if (!target) return;
|
|
1594
|
-
const targetPos = pos.clone();
|
|
1595
|
-
const targetRot = new THREE11.Quaternion().setFromEuler(
|
|
1596
|
-
new THREE11.Euler(Math.PI, 0, 0)
|
|
1597
|
-
);
|
|
1598
|
-
if (duration > 0) {
|
|
1599
|
-
const ga = gizmoAnimRef.current;
|
|
1600
|
-
ga.active = true;
|
|
1601
|
-
ga.startPos.copy(target.position);
|
|
1602
|
-
ga.endPos.copy(targetPos);
|
|
1603
|
-
ga.startRot.copy(target.quaternion);
|
|
1604
|
-
ga.endRot.copy(targetRot);
|
|
1605
|
-
ga.startTime = performance.now();
|
|
1606
|
-
ga.duration = duration;
|
|
1607
|
-
} else {
|
|
1608
|
-
gizmoAnimRef.current.active = false;
|
|
1609
|
-
target.position.copy(targetPos);
|
|
1610
|
-
target.quaternion.copy(targetRot);
|
|
1611
|
-
}
|
|
1612
|
-
},
|
|
1613
|
-
[setIkEnabled]
|
|
1614
|
-
);
|
|
1615
|
-
const getGizmoStats = useCallback(
|
|
1616
|
-
() => {
|
|
1617
|
-
const target = ikTargetRef.current;
|
|
1618
|
-
if (!ikCalculatingRef.current || !target) return null;
|
|
1619
|
-
return {
|
|
1620
|
-
pos: target.position.clone(),
|
|
1621
|
-
rot: new THREE11.Euler().setFromQuaternion(target.quaternion)
|
|
1622
|
-
};
|
|
1623
|
-
},
|
|
1624
|
-
[]
|
|
1625
|
-
);
|
|
1626
|
-
const contextValue = useMemo(
|
|
1627
|
-
() => ({
|
|
1628
|
-
ikEnabledRef,
|
|
1629
|
-
ikCalculatingRef,
|
|
1630
|
-
ikTargetRef,
|
|
1631
|
-
siteIdRef,
|
|
1632
|
-
setIkEnabled,
|
|
1633
|
-
moveTarget,
|
|
1634
|
-
syncTargetToSite: syncTargetToSiteApi,
|
|
1635
|
-
solveIK,
|
|
1636
|
-
getGizmoStats
|
|
1637
|
-
}),
|
|
1638
|
-
[setIkEnabled, moveTarget, syncTargetToSiteApi, solveIK, getGizmoStats]
|
|
1639
|
-
);
|
|
1640
|
-
return /* @__PURE__ */ jsx(IkContext.Provider, { value: contextValue, children });
|
|
1641
|
-
}
|
|
1642
|
-
var IkController = createController(
|
|
1643
|
-
{
|
|
1644
|
-
name: "IkController",
|
|
1645
|
-
defaultConfig: {
|
|
1646
|
-
damping: 0.01,
|
|
1647
|
-
maxIterations: 50
|
|
1648
|
-
}
|
|
1649
|
-
},
|
|
1650
|
-
IkControllerImpl
|
|
1651
|
-
);
|
|
1652
|
-
var CapsuleGeometry = class extends THREE11.BufferGeometry {
|
|
1653
|
-
parameters;
|
|
1654
|
-
constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
|
|
1655
|
-
super();
|
|
1656
|
-
this.type = "CapsuleGeometry";
|
|
1657
|
-
this.parameters = { radius, length, capSegments, radialSegments };
|
|
1658
|
-
const path = new THREE11.Path();
|
|
1659
|
-
path.absarc(0, -length / 2, radius, Math.PI * 1.5, 0, false);
|
|
1660
|
-
path.absarc(0, length / 2, radius, 0, Math.PI * 0.5, false);
|
|
1661
|
-
const latheGeometry = new THREE11.LatheGeometry(path.getPoints(capSegments), radialSegments);
|
|
1662
|
-
const self = this;
|
|
1663
|
-
self.setIndex(latheGeometry.getIndex());
|
|
1664
|
-
self.setAttribute("position", latheGeometry.getAttribute("position"));
|
|
1665
|
-
self.setAttribute("normal", latheGeometry.getAttribute("normal"));
|
|
1666
|
-
self.setAttribute("uv", latheGeometry.getAttribute("uv"));
|
|
1667
|
-
}
|
|
1668
|
-
};
|
|
1669
|
-
var Reflector = class extends THREE11.Mesh {
|
|
1670
|
-
isReflector = true;
|
|
1671
|
-
camera;
|
|
1672
|
-
reflectorPlane = new THREE11.Plane();
|
|
1673
|
-
normal = new THREE11.Vector3();
|
|
1674
|
-
reflectorWorldPosition = new THREE11.Vector3();
|
|
1675
|
-
cameraWorldPosition = new THREE11.Vector3();
|
|
1676
|
-
rotationMatrix = new THREE11.Matrix4();
|
|
1677
|
-
lookAtPosition = new THREE11.Vector3(0, 0, -1);
|
|
1678
|
-
clipPlane = new THREE11.Vector4();
|
|
1679
|
-
view = new THREE11.Vector3();
|
|
1680
|
-
target = new THREE11.Vector3();
|
|
1681
|
-
q = new THREE11.Vector4();
|
|
1682
|
-
textureMatrix = new THREE11.Matrix4();
|
|
1683
|
-
virtualCamera;
|
|
1684
|
-
renderTarget;
|
|
1685
|
-
constructor(geometry, options = {}) {
|
|
1686
|
-
super(geometry);
|
|
1687
|
-
this.type = "Reflector";
|
|
1688
|
-
this.camera = new THREE11.PerspectiveCamera();
|
|
1689
|
-
const color = options.color !== void 0 ? new THREE11.Color(options.color) : new THREE11.Color(8355711);
|
|
1690
|
-
const textureWidth = options.textureWidth || 512;
|
|
1691
|
-
const textureHeight = options.textureHeight || 512;
|
|
1692
|
-
const clipBias = options.clipBias || 0;
|
|
1693
|
-
const multisample = options.multisample !== void 0 ? options.multisample : 4;
|
|
1694
|
-
const blendTexture = options.texture || void 0;
|
|
1695
|
-
const mixStrength = options.mixStrength !== void 0 ? options.mixStrength : 0.25;
|
|
1696
|
-
this.virtualCamera = this.camera;
|
|
1697
|
-
this.renderTarget = new THREE11.WebGLRenderTarget(textureWidth, textureHeight, {
|
|
1698
|
-
samples: multisample,
|
|
1699
|
-
type: THREE11.HalfFloatType
|
|
1700
|
-
});
|
|
1701
|
-
this.material = new THREE11.MeshPhysicalMaterial({
|
|
1702
|
-
map: blendTexture,
|
|
1703
|
-
color,
|
|
1704
|
-
roughness: 0.5,
|
|
1705
|
-
metalness: 0.1
|
|
1706
|
-
});
|
|
1707
|
-
this.material.onBeforeCompile = (shader) => {
|
|
1708
|
-
shader.uniforms.tDiffuse = { value: this.renderTarget.texture };
|
|
1709
|
-
shader.uniforms.textureMatrix = { value: this.textureMatrix };
|
|
1710
|
-
shader.uniforms.mixStrength = { value: mixStrength };
|
|
1711
|
-
const bodyStart = shader.vertexShader.indexOf("void main() {");
|
|
1712
|
-
shader.vertexShader = "uniform mat4 textureMatrix;\nvarying vec4 vUvReflection;\n" + shader.vertexShader.slice(0, bodyStart) + shader.vertexShader.slice(bodyStart, -1) + " vUvReflection = textureMatrix * vec4( position, 1.0 );\n}";
|
|
1713
|
-
const fragmentBodyStart = shader.fragmentShader.indexOf("void main() {");
|
|
1714
|
-
shader.fragmentShader = "uniform sampler2D tDiffuse;\nuniform float mixStrength;\nvarying vec4 vUvReflection;\n" + shader.fragmentShader.slice(0, fragmentBodyStart) + shader.fragmentShader.slice(fragmentBodyStart, -1) + " vec4 reflectionColor = texture2DProj( tDiffuse, vUvReflection );\n gl_FragColor = vec4( mix( gl_FragColor.rgb, reflectionColor.rgb, mixStrength ), gl_FragColor.a );\n}";
|
|
1715
|
-
};
|
|
1716
|
-
this.receiveShadow = true;
|
|
1717
|
-
this.onBeforeRender = (renderer, scene, camera) => {
|
|
1718
|
-
this.reflectorWorldPosition.setFromMatrixPosition(this.matrixWorld);
|
|
1719
|
-
this.cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
|
|
1720
|
-
this.rotationMatrix.extractRotation(this.matrixWorld);
|
|
1721
|
-
this.normal.set(0, 0, 1);
|
|
1722
|
-
this.normal.applyMatrix4(this.rotationMatrix);
|
|
1723
|
-
this.view.subVectors(this.reflectorWorldPosition, this.cameraWorldPosition);
|
|
1724
|
-
if (this.view.dot(this.normal) > 0) return;
|
|
1725
|
-
this.view.reflect(this.normal).negate();
|
|
1726
|
-
this.view.add(this.reflectorWorldPosition);
|
|
1727
|
-
this.rotationMatrix.extractRotation(camera.matrixWorld);
|
|
1728
|
-
this.lookAtPosition.set(0, 0, -1);
|
|
1729
|
-
this.lookAtPosition.applyMatrix4(this.rotationMatrix);
|
|
1730
|
-
this.lookAtPosition.add(this.cameraWorldPosition);
|
|
1731
|
-
this.target.subVectors(this.reflectorWorldPosition, this.lookAtPosition);
|
|
1732
|
-
this.target.reflect(this.normal).negate();
|
|
1733
|
-
this.target.add(this.reflectorWorldPosition);
|
|
1734
|
-
this.virtualCamera.position.copy(this.view);
|
|
1735
|
-
this.virtualCamera.up.set(0, 1, 0);
|
|
1736
|
-
this.virtualCamera.up.applyMatrix4(this.rotationMatrix);
|
|
1737
|
-
this.virtualCamera.up.reflect(this.normal);
|
|
1738
|
-
this.virtualCamera.lookAt(this.target);
|
|
1739
|
-
this.virtualCamera.far = camera.far;
|
|
1740
|
-
this.virtualCamera.updateMatrixWorld();
|
|
1741
|
-
this.virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
|
|
1742
|
-
this.textureMatrix.set(
|
|
1743
|
-
0.5,
|
|
1744
|
-
0,
|
|
1745
|
-
0,
|
|
1746
|
-
0.5,
|
|
1747
|
-
0,
|
|
1748
|
-
0.5,
|
|
1749
|
-
0,
|
|
1750
|
-
0.5,
|
|
1751
|
-
0,
|
|
1752
|
-
0,
|
|
1753
|
-
0.5,
|
|
1754
|
-
0.5,
|
|
1755
|
-
0,
|
|
1756
|
-
0,
|
|
1757
|
-
0,
|
|
1758
|
-
1
|
|
1759
|
-
);
|
|
1760
|
-
this.textureMatrix.multiply(this.virtualCamera.projectionMatrix);
|
|
1761
|
-
this.textureMatrix.multiply(this.virtualCamera.matrixWorldInverse);
|
|
1762
|
-
this.textureMatrix.multiply(this.matrixWorld);
|
|
1763
|
-
this.reflectorPlane.setFromNormalAndCoplanarPoint(this.normal, this.reflectorWorldPosition);
|
|
1764
|
-
this.reflectorPlane.applyMatrix4(this.virtualCamera.matrixWorldInverse);
|
|
1765
|
-
this.clipPlane.set(this.reflectorPlane.normal.x, this.reflectorPlane.normal.y, this.reflectorPlane.normal.z, this.reflectorPlane.constant);
|
|
1766
|
-
const projectionMatrix = this.virtualCamera.projectionMatrix;
|
|
1767
|
-
this.q.x = (Math.sign(this.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
|
|
1768
|
-
this.q.y = (Math.sign(this.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
|
|
1769
|
-
this.q.z = -1;
|
|
1770
|
-
this.q.w = (1 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
|
|
1771
|
-
this.clipPlane.multiplyScalar(2 / this.clipPlane.dot(this.q));
|
|
1772
|
-
projectionMatrix.elements[2] = this.clipPlane.x;
|
|
1773
|
-
projectionMatrix.elements[6] = this.clipPlane.y;
|
|
1774
|
-
projectionMatrix.elements[10] = this.clipPlane.z + 1 - clipBias;
|
|
1775
|
-
projectionMatrix.elements[14] = this.clipPlane.w;
|
|
1776
|
-
this.visible = false;
|
|
1777
|
-
const currentRenderTarget = renderer.getRenderTarget();
|
|
1778
|
-
const currentXrEnabled = renderer.xr.enabled;
|
|
1779
|
-
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
|
1780
|
-
renderer.xr.enabled = false;
|
|
1781
|
-
renderer.shadowMap.autoUpdate = false;
|
|
1782
|
-
renderer.setRenderTarget(this.renderTarget);
|
|
1783
|
-
renderer.state.buffers.depth.setMask(true);
|
|
1784
|
-
if (renderer.autoClear === false) renderer.clear();
|
|
1785
|
-
renderer.render(scene, this.virtualCamera);
|
|
1786
|
-
renderer.xr.enabled = currentXrEnabled;
|
|
1787
|
-
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
|
1788
|
-
renderer.setRenderTarget(currentRenderTarget);
|
|
1789
|
-
const viewport = camera.viewport;
|
|
1790
|
-
if (viewport !== void 0) {
|
|
1791
|
-
renderer.state.viewport(viewport);
|
|
1792
|
-
}
|
|
1793
|
-
this.visible = true;
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1796
|
-
getRenderTarget() {
|
|
1797
|
-
return this.renderTarget;
|
|
1798
|
-
}
|
|
1799
|
-
dispose() {
|
|
1800
|
-
this.renderTarget.dispose();
|
|
1801
|
-
const mesh = this;
|
|
1802
|
-
if (Array.isArray(mesh.material)) {
|
|
1803
|
-
mesh.material.forEach((m) => m.dispose());
|
|
1804
|
-
} else {
|
|
1805
|
-
mesh.material.dispose();
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
};
|
|
1809
|
-
|
|
1810
|
-
// src/rendering/GeomBuilder.ts
|
|
1811
|
-
var GeomBuilder = class {
|
|
1812
|
-
mujoco;
|
|
1813
|
-
constructor(mujoco) {
|
|
1814
|
-
this.mujoco = mujoco;
|
|
1815
|
-
}
|
|
1816
|
-
/**
|
|
1817
|
-
* Creates a Three.js Object3D (usually a Mesh) for a specific geometry in the MuJoCo model.
|
|
1818
|
-
* Returns null if the geometry shouldn't be rendered (e.g., invisible collision triggers).
|
|
1819
|
-
*/
|
|
1820
|
-
create(mjModel, g) {
|
|
1821
|
-
if (mjModel.geom_group[g] === 3) return null;
|
|
1822
|
-
const type = mjModel.geom_type[g];
|
|
1823
|
-
const size = mjModel.geom_size.subarray(g * 3, g * 3 + 3);
|
|
1824
|
-
const pos = mjModel.geom_pos.subarray(g * 3, g * 3 + 3);
|
|
1825
|
-
const quat = mjModel.geom_quat.subarray(g * 4, g * 4 + 4);
|
|
1826
|
-
const matId = mjModel.geom_matid[g];
|
|
1827
|
-
const color = new THREE11.Color(16777215);
|
|
1828
|
-
let opacity = 1;
|
|
1829
|
-
if (matId >= 0) {
|
|
1830
|
-
const rgba = mjModel.mat_rgba.subarray(matId * 4, matId * 4 + 4);
|
|
1831
|
-
color.setRGB(rgba[0], rgba[1], rgba[2]);
|
|
1832
|
-
opacity = rgba[3];
|
|
1833
|
-
} else {
|
|
1834
|
-
const rgba = mjModel.geom_rgba.subarray(g * 4, g * 4 + 4);
|
|
1835
|
-
color.setRGB(rgba[0], rgba[1], rgba[2]);
|
|
1836
|
-
opacity = rgba[3];
|
|
1837
|
-
}
|
|
1838
|
-
const MG = this.mujoco.mjtGeom;
|
|
1839
|
-
let geo = null;
|
|
1840
|
-
const getVal = (v) => v?.value ?? v;
|
|
1841
|
-
if (type === getVal(MG.mjGEOM_PLANE)) {
|
|
1842
|
-
geo = new THREE11.PlaneGeometry(size[0] * 2 || 5, size[1] * 2 || 5);
|
|
1843
|
-
} else if (type === getVal(MG.mjGEOM_SPHERE)) {
|
|
1844
|
-
geo = new THREE11.SphereGeometry(size[0], 24, 24);
|
|
1845
|
-
} else if (type === getVal(MG.mjGEOM_CAPSULE)) {
|
|
1846
|
-
geo = new CapsuleGeometry(size[0], size[1] * 2, 24, 12);
|
|
1847
|
-
geo.rotateX(Math.PI / 2);
|
|
1848
|
-
} else if (type === getVal(MG.mjGEOM_BOX)) {
|
|
1849
|
-
geo = new THREE11.BoxGeometry(size[0] * 2, size[1] * 2, size[2] * 2);
|
|
1850
|
-
} else if (type === getVal(MG.mjGEOM_CYLINDER)) {
|
|
1851
|
-
geo = new THREE11.CylinderGeometry(size[0], size[0], size[1] * 2, 24);
|
|
1852
|
-
geo.rotateX(Math.PI / 2);
|
|
1853
|
-
} else if (type === getVal(MG.mjGEOM_MESH)) {
|
|
1854
|
-
const mId = mjModel.geom_dataid[g];
|
|
1855
|
-
const vAdr = mjModel.mesh_vertadr[mId];
|
|
1856
|
-
const vNum = mjModel.mesh_vertnum[mId];
|
|
1857
|
-
const fAdr = mjModel.mesh_faceadr[mId];
|
|
1858
|
-
const fNum = mjModel.mesh_facenum[mId];
|
|
1859
|
-
geo = new THREE11.BufferGeometry();
|
|
1860
|
-
geo.setAttribute("position", new THREE11.Float32BufferAttribute(mjModel.mesh_vert.subarray(vAdr * 3, (vAdr + vNum) * 3), 3));
|
|
1861
|
-
geo.setIndex(Array.from(mjModel.mesh_face.subarray(fAdr * 3, (fAdr + fNum) * 3)));
|
|
1862
|
-
geo.computeVertexNormals();
|
|
1863
|
-
}
|
|
1864
|
-
if (geo) {
|
|
1865
|
-
let mesh;
|
|
1866
|
-
if (type === getVal(MG.mjGEOM_PLANE)) {
|
|
1867
|
-
mesh = new Reflector(geo, {
|
|
1868
|
-
clipBias: 3e-3,
|
|
1869
|
-
textureWidth: 1024,
|
|
1870
|
-
textureHeight: 1024,
|
|
1871
|
-
color,
|
|
1872
|
-
mixStrength: 0.25
|
|
1873
|
-
});
|
|
1874
|
-
} else {
|
|
1875
|
-
mesh = new THREE11.Mesh(geo, new THREE11.MeshStandardMaterial({
|
|
1876
|
-
color,
|
|
1877
|
-
transparent: opacity < 1,
|
|
1878
|
-
opacity,
|
|
1879
|
-
roughness: 0.6,
|
|
1880
|
-
metalness: 0.2
|
|
1881
|
-
}));
|
|
1882
|
-
mesh.castShadow = true;
|
|
1883
|
-
mesh.receiveShadow = true;
|
|
1884
|
-
}
|
|
1885
|
-
mesh.position.set(pos[0], pos[1], pos[2]);
|
|
1886
|
-
mesh.quaternion.set(quat[1], quat[2], quat[3], quat[0]);
|
|
1887
|
-
mesh.userData.bodyID = mjModel.geom_bodyid[g];
|
|
1888
|
-
mesh.userData.geomID = g;
|
|
1889
|
-
return mesh;
|
|
1890
|
-
}
|
|
1891
|
-
return null;
|
|
1892
|
-
}
|
|
1893
|
-
};
|
|
1894
|
-
function SceneRenderer(props) {
|
|
1895
|
-
const { mjModelRef, mjDataRef, mujocoRef, onSelectionRef, status } = useMujocoSim();
|
|
1896
|
-
const groupRef = useRef(null);
|
|
1897
|
-
const bodyRefs = useRef([]);
|
|
1898
|
-
const prevModelRef = useRef(null);
|
|
1899
|
-
const geomBuilder = useMemo(() => {
|
|
1900
|
-
if (status !== "ready") return null;
|
|
1901
|
-
return new GeomBuilder(mujocoRef.current);
|
|
1902
|
-
}, [status, mujocoRef]);
|
|
1773
|
+
siteMat[8],
|
|
1774
|
+
0,
|
|
1775
|
+
0,
|
|
1776
|
+
0,
|
|
1777
|
+
0,
|
|
1778
|
+
1
|
|
1779
|
+
);
|
|
1780
|
+
target.quaternion.setFromRotationMatrix(_syncMat4);
|
|
1781
|
+
}
|
|
1782
|
+
function IkControllerImpl({
|
|
1783
|
+
config,
|
|
1784
|
+
children
|
|
1785
|
+
}) {
|
|
1786
|
+
const { mjModelRef, mjDataRef, mujocoRef, configRef, resetCallbacks, status } = useMujoco();
|
|
1787
|
+
const ikEnabledRef = useRef(false);
|
|
1788
|
+
const ikCalculatingRef = useRef(false);
|
|
1789
|
+
const ikTargetRef = useRef(new THREE11.Group());
|
|
1790
|
+
const siteIdRef = useRef(-1);
|
|
1791
|
+
const genericIkRef = useRef(new GenericIK(mujocoRef.current));
|
|
1792
|
+
const firstIkEnableRef = useRef(true);
|
|
1793
|
+
const needsInitialSync = useRef(true);
|
|
1794
|
+
const gizmoAnimRef = useRef({
|
|
1795
|
+
active: false,
|
|
1796
|
+
startPos: new THREE11.Vector3(),
|
|
1797
|
+
endPos: new THREE11.Vector3(),
|
|
1798
|
+
startRot: new THREE11.Quaternion(),
|
|
1799
|
+
endRot: new THREE11.Quaternion(),
|
|
1800
|
+
startTime: 0,
|
|
1801
|
+
duration: 1e3
|
|
1802
|
+
});
|
|
1903
1803
|
useEffect(() => {
|
|
1904
|
-
if (status !== "ready" || !geomBuilder) return;
|
|
1905
1804
|
const model = mjModelRef.current;
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
prevModelRef.current = model;
|
|
1910
|
-
while (group.children.length > 0) {
|
|
1911
|
-
group.remove(group.children[0]);
|
|
1805
|
+
if (!model || status !== "ready") {
|
|
1806
|
+
siteIdRef.current = -1;
|
|
1807
|
+
return;
|
|
1912
1808
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1809
|
+
siteIdRef.current = findSiteByName(model, config.siteName);
|
|
1810
|
+
const data = mjDataRef.current;
|
|
1811
|
+
if (data && ikTargetRef.current) {
|
|
1812
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1813
|
+
}
|
|
1814
|
+
}, [config.siteName, status, mjModelRef, mjDataRef]);
|
|
1815
|
+
const ikSolveFn = useCallback(
|
|
1816
|
+
(pos, quat, currentQ) => {
|
|
1817
|
+
if (config.ikSolveFn) return config.ikSolveFn(pos, quat, currentQ);
|
|
1818
|
+
const model = mjModelRef.current;
|
|
1819
|
+
const data = mjDataRef.current;
|
|
1820
|
+
if (!model || !data || siteIdRef.current === -1) return null;
|
|
1821
|
+
return genericIkRef.current.solve(
|
|
1822
|
+
model,
|
|
1823
|
+
data,
|
|
1824
|
+
siteIdRef.current,
|
|
1825
|
+
config.numJoints,
|
|
1826
|
+
pos,
|
|
1827
|
+
quat,
|
|
1828
|
+
currentQ,
|
|
1829
|
+
{
|
|
1830
|
+
damping: config.damping,
|
|
1831
|
+
maxIterations: config.maxIterations
|
|
1921
1832
|
}
|
|
1833
|
+
);
|
|
1834
|
+
},
|
|
1835
|
+
[config.ikSolveFn, config.numJoints, config.damping, config.maxIterations, mjModelRef, mjDataRef]
|
|
1836
|
+
);
|
|
1837
|
+
const ikSolveFnRef = useRef(ikSolveFn);
|
|
1838
|
+
ikSolveFnRef.current = ikSolveFn;
|
|
1839
|
+
useFrame(() => {
|
|
1840
|
+
if (needsInitialSync.current && siteIdRef.current !== -1) {
|
|
1841
|
+
const data = mjDataRef.current;
|
|
1842
|
+
if (data && ikTargetRef.current) {
|
|
1843
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1844
|
+
needsInitialSync.current = false;
|
|
1922
1845
|
}
|
|
1923
|
-
group.add(bodyGroup);
|
|
1924
|
-
refs.push(bodyGroup);
|
|
1925
1846
|
}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1847
|
+
const ga = gizmoAnimRef.current;
|
|
1848
|
+
const target = ikTargetRef.current;
|
|
1849
|
+
if (!ga.active || !target) return;
|
|
1850
|
+
const now = performance.now();
|
|
1851
|
+
const elapsed = now - ga.startTime;
|
|
1852
|
+
const t = Math.min(elapsed / ga.duration, 1);
|
|
1853
|
+
const ease = 1 - Math.pow(1 - t, 3);
|
|
1854
|
+
target.position.lerpVectors(ga.startPos, ga.endPos, ease);
|
|
1855
|
+
target.quaternion.slerpQuaternions(ga.startRot, ga.endRot, ease);
|
|
1856
|
+
if (t >= 1) ga.active = false;
|
|
1857
|
+
});
|
|
1858
|
+
useBeforePhysicsStep((model, data) => {
|
|
1859
|
+
if (!ikEnabledRef.current) {
|
|
1860
|
+
ikCalculatingRef.current = false;
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
const target = ikTargetRef.current;
|
|
1864
|
+
if (!target) return;
|
|
1865
|
+
ikCalculatingRef.current = true;
|
|
1866
|
+
const numJoints = config.numJoints;
|
|
1867
|
+
const currentQ = [];
|
|
1868
|
+
for (let i = 0; i < numJoints; i++) currentQ.push(data.qpos[i]);
|
|
1869
|
+
const solution = ikSolveFnRef.current(target.position, target.quaternion, currentQ);
|
|
1870
|
+
if (solution) {
|
|
1871
|
+
for (let i = 0; i < numJoints; i++) data.ctrl[i] = solution[i];
|
|
1946
1872
|
}
|
|
1947
1873
|
});
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
onDoubleClick: (e) => {
|
|
1954
|
-
if (typeof props.onDoubleClick === "function") props.onDoubleClick(e);
|
|
1955
|
-
e.stopPropagation();
|
|
1956
|
-
let obj = e.object;
|
|
1957
|
-
while (obj && obj.userData.bodyID === void 0 && obj.parent) {
|
|
1958
|
-
obj = obj.parent;
|
|
1959
|
-
}
|
|
1960
|
-
const bodyID = obj?.userData.bodyID;
|
|
1961
|
-
if (typeof bodyID === "number" && bodyID > 0) {
|
|
1962
|
-
const model = mjModelRef.current;
|
|
1963
|
-
if (model && bodyID < model.nbody && onSelectionRef.current) {
|
|
1964
|
-
const name = getName(model, model.name_bodyadr[bodyID]);
|
|
1965
|
-
onSelectionRef.current(bodyID, name);
|
|
1966
|
-
}
|
|
1967
|
-
}
|
|
1874
|
+
useEffect(() => {
|
|
1875
|
+
const cb = () => {
|
|
1876
|
+
const data = mjDataRef.current;
|
|
1877
|
+
if (data && ikTargetRef.current) {
|
|
1878
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1968
1879
|
}
|
|
1969
|
-
|
|
1880
|
+
gizmoAnimRef.current.active = false;
|
|
1881
|
+
firstIkEnableRef.current = true;
|
|
1882
|
+
ikEnabledRef.current = false;
|
|
1883
|
+
needsInitialSync.current = true;
|
|
1884
|
+
};
|
|
1885
|
+
resetCallbacks.current.add(cb);
|
|
1886
|
+
return () => {
|
|
1887
|
+
resetCallbacks.current.delete(cb);
|
|
1888
|
+
};
|
|
1889
|
+
}, [resetCallbacks, mjDataRef]);
|
|
1890
|
+
const setIkEnabled = useCallback(
|
|
1891
|
+
(enabled) => {
|
|
1892
|
+
ikEnabledRef.current = enabled;
|
|
1893
|
+
const data = mjDataRef.current;
|
|
1894
|
+
if (enabled && data && !gizmoAnimRef.current.active && ikTargetRef.current) {
|
|
1895
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1896
|
+
firstIkEnableRef.current = false;
|
|
1897
|
+
}
|
|
1898
|
+
},
|
|
1899
|
+
[mjDataRef]
|
|
1900
|
+
);
|
|
1901
|
+
const syncTargetToSiteApi = useCallback(() => {
|
|
1902
|
+
const data = mjDataRef.current;
|
|
1903
|
+
const target = ikTargetRef.current;
|
|
1904
|
+
if (data && target) syncGizmoToSite(data, siteIdRef.current, target);
|
|
1905
|
+
}, [mjDataRef]);
|
|
1906
|
+
const solveIK = useCallback(
|
|
1907
|
+
(pos, quat, currentQ) => {
|
|
1908
|
+
return ikSolveFnRef.current(pos, quat, currentQ);
|
|
1909
|
+
},
|
|
1910
|
+
[]
|
|
1911
|
+
);
|
|
1912
|
+
const moveTarget = useCallback(
|
|
1913
|
+
(pos, duration = 0) => {
|
|
1914
|
+
if (!ikEnabledRef.current) setIkEnabled(true);
|
|
1915
|
+
const target = ikTargetRef.current;
|
|
1916
|
+
if (!target) return;
|
|
1917
|
+
const targetPos = pos.clone();
|
|
1918
|
+
const targetRot = new THREE11.Quaternion().setFromEuler(
|
|
1919
|
+
new THREE11.Euler(Math.PI, 0, 0)
|
|
1920
|
+
);
|
|
1921
|
+
if (duration > 0) {
|
|
1922
|
+
const ga = gizmoAnimRef.current;
|
|
1923
|
+
ga.active = true;
|
|
1924
|
+
ga.startPos.copy(target.position);
|
|
1925
|
+
ga.endPos.copy(targetPos);
|
|
1926
|
+
ga.startRot.copy(target.quaternion);
|
|
1927
|
+
ga.endRot.copy(targetRot);
|
|
1928
|
+
ga.startTime = performance.now();
|
|
1929
|
+
ga.duration = duration;
|
|
1930
|
+
} else {
|
|
1931
|
+
gizmoAnimRef.current.active = false;
|
|
1932
|
+
target.position.copy(targetPos);
|
|
1933
|
+
target.quaternion.copy(targetRot);
|
|
1934
|
+
}
|
|
1935
|
+
},
|
|
1936
|
+
[setIkEnabled]
|
|
1937
|
+
);
|
|
1938
|
+
const getGizmoStats = useCallback(
|
|
1939
|
+
() => {
|
|
1940
|
+
const target = ikTargetRef.current;
|
|
1941
|
+
if (!ikCalculatingRef.current || !target) return null;
|
|
1942
|
+
return {
|
|
1943
|
+
pos: target.position.clone(),
|
|
1944
|
+
rot: new THREE11.Euler().setFromQuaternion(target.quaternion)
|
|
1945
|
+
};
|
|
1946
|
+
},
|
|
1947
|
+
[]
|
|
1948
|
+
);
|
|
1949
|
+
const contextValue = useMemo(
|
|
1950
|
+
() => ({
|
|
1951
|
+
ikEnabledRef,
|
|
1952
|
+
ikCalculatingRef,
|
|
1953
|
+
ikTargetRef,
|
|
1954
|
+
siteIdRef,
|
|
1955
|
+
setIkEnabled,
|
|
1956
|
+
moveTarget,
|
|
1957
|
+
syncTargetToSite: syncTargetToSiteApi,
|
|
1958
|
+
solveIK,
|
|
1959
|
+
getGizmoStats
|
|
1960
|
+
}),
|
|
1961
|
+
[setIkEnabled, moveTarget, syncTargetToSiteApi, solveIK, getGizmoStats]
|
|
1970
1962
|
);
|
|
1963
|
+
return /* @__PURE__ */ jsx(IkContext.Provider, { value: contextValue, children });
|
|
1971
1964
|
}
|
|
1965
|
+
var IkController = createController(
|
|
1966
|
+
{
|
|
1967
|
+
name: "IkController",
|
|
1968
|
+
defaultConfig: {
|
|
1969
|
+
damping: 0.01,
|
|
1970
|
+
maxIterations: 50
|
|
1971
|
+
}
|
|
1972
|
+
},
|
|
1973
|
+
IkControllerImpl
|
|
1974
|
+
);
|
|
1972
1975
|
var _mat4 = new THREE11.Matrix4();
|
|
1973
1976
|
var _pos = new THREE11.Vector3();
|
|
1974
1977
|
var _quat = new THREE11.Quaternion();
|
|
1975
1978
|
var _scale = new THREE11.Vector3(1, 1, 1);
|
|
1976
1979
|
function IkGizmo({ siteName, scale = 0.18, onDrag }) {
|
|
1977
|
-
const { mjModelRef, mjDataRef, status } =
|
|
1980
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
1978
1981
|
const { ikTargetRef, siteIdRef, ikEnabledRef, setIkEnabled } = useIk();
|
|
1979
1982
|
const wrapperRef = useRef(null);
|
|
1980
1983
|
const pivotRef = useRef(null);
|
|
@@ -2072,7 +2075,7 @@ function ContactMarkers({
|
|
|
2072
2075
|
visible = true,
|
|
2073
2076
|
...groupProps
|
|
2074
2077
|
} = {}) {
|
|
2075
|
-
const { mjDataRef, status } =
|
|
2078
|
+
const { mjDataRef, status } = useMujoco();
|
|
2076
2079
|
const meshRef = useRef(null);
|
|
2077
2080
|
useFrame(() => {
|
|
2078
2081
|
const mesh = meshRef.current;
|
|
@@ -2116,7 +2119,7 @@ function DragInteraction({
|
|
|
2116
2119
|
showArrow = true,
|
|
2117
2120
|
...groupProps
|
|
2118
2121
|
}) {
|
|
2119
|
-
const { mjDataRef, mujocoRef, mjModelRef, status } =
|
|
2122
|
+
const { mjDataRef, mujocoRef, mjModelRef, status } = useMujoco();
|
|
2120
2123
|
const { gl, camera, scene, controls } = useThree();
|
|
2121
2124
|
const draggingRef = useRef(false);
|
|
2122
2125
|
const bodyIdRef = useRef(-1);
|
|
@@ -2274,7 +2277,7 @@ function DragInteraction({
|
|
|
2274
2277
|
return /* @__PURE__ */ jsx("group", { ...groupProps, ref: groupRef });
|
|
2275
2278
|
}
|
|
2276
2279
|
function useSceneLights(intensity = 1) {
|
|
2277
|
-
const { mjModelRef, status } =
|
|
2280
|
+
const { mjModelRef, status } = useMujoco();
|
|
2278
2281
|
const { scene } = useThree();
|
|
2279
2282
|
const lightsRef = useRef([]);
|
|
2280
2283
|
const targetsRef = useRef([]);
|
|
@@ -2395,7 +2398,7 @@ function Debug({
|
|
|
2395
2398
|
showTendons = false,
|
|
2396
2399
|
...groupProps
|
|
2397
2400
|
}) {
|
|
2398
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2401
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
2399
2402
|
const { scene } = useThree();
|
|
2400
2403
|
const groupRef = useRef(null);
|
|
2401
2404
|
const debugGeometry = useMemo(() => {
|
|
@@ -2665,7 +2668,7 @@ var DEFAULT_TENDON_COLOR = new THREE11.Color(0.3, 0.3, 0.8);
|
|
|
2665
2668
|
var DEFAULT_TENDON_WIDTH = 2e-3;
|
|
2666
2669
|
new THREE11.Vector3();
|
|
2667
2670
|
function TendonRenderer(props) {
|
|
2668
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2671
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
2669
2672
|
const groupRef = useRef(null);
|
|
2670
2673
|
const meshesRef = useRef([]);
|
|
2671
2674
|
const curvesRef = useRef([]);
|
|
@@ -2769,7 +2772,7 @@ function TendonRenderer(props) {
|
|
|
2769
2772
|
return /* @__PURE__ */ jsx("group", { ...props, ref: groupRef });
|
|
2770
2773
|
}
|
|
2771
2774
|
function FlexRenderer(props) {
|
|
2772
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2775
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
2773
2776
|
const groupRef = useRef(null);
|
|
2774
2777
|
const meshesRef = useRef([]);
|
|
2775
2778
|
useEffect(() => {
|
|
@@ -2849,7 +2852,7 @@ function getGeomNameCached(model, geomId) {
|
|
|
2849
2852
|
return name;
|
|
2850
2853
|
}
|
|
2851
2854
|
function useContacts(bodyName, callback) {
|
|
2852
|
-
const { mjModelRef, status } =
|
|
2855
|
+
const { mjModelRef, status } = useMujoco();
|
|
2853
2856
|
const contactsRef = useRef([]);
|
|
2854
2857
|
const bodyIdRef = useRef(-1);
|
|
2855
2858
|
const bodyResolvedRef = useRef(false);
|
|
@@ -2948,7 +2951,7 @@ function ContactListener({
|
|
|
2948
2951
|
return null;
|
|
2949
2952
|
}
|
|
2950
2953
|
function useTrajectoryPlayer(trajectory, options = {}) {
|
|
2951
|
-
const { mjModelRef, mjDataRef, mujocoRef, pausedRef } =
|
|
2954
|
+
const { mjModelRef, mjDataRef, mujocoRef, pausedRef } = useMujoco();
|
|
2952
2955
|
const fps = options.fps ?? 30;
|
|
2953
2956
|
const loop = options.loop ?? false;
|
|
2954
2957
|
const playingRef = useRef(false);
|
|
@@ -3103,7 +3106,7 @@ function SelectionHighlight({
|
|
|
3103
3106
|
return null;
|
|
3104
3107
|
}
|
|
3105
3108
|
function useActuators() {
|
|
3106
|
-
const { mjModelRef, status } =
|
|
3109
|
+
const { mjModelRef, status } = useMujoco();
|
|
3107
3110
|
return useMemo(() => {
|
|
3108
3111
|
if (status !== "ready") return [];
|
|
3109
3112
|
const model = mjModelRef.current;
|
|
@@ -3122,7 +3125,7 @@ function useActuators() {
|
|
|
3122
3125
|
}
|
|
3123
3126
|
var _mat42 = new THREE11.Matrix4();
|
|
3124
3127
|
function useSitePosition(siteName) {
|
|
3125
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3128
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
3126
3129
|
const siteIdRef = useRef(-1);
|
|
3127
3130
|
const positionRef = useRef(new THREE11.Vector3());
|
|
3128
3131
|
const quaternionRef = useRef(new THREE11.Quaternion());
|
|
@@ -3179,7 +3182,7 @@ function useGravityCompensation(enabled = true) {
|
|
|
3179
3182
|
});
|
|
3180
3183
|
}
|
|
3181
3184
|
function useSensor(name) {
|
|
3182
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3185
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
3183
3186
|
const sensorIdRef = useRef(-1);
|
|
3184
3187
|
const sensorAdrRef = useRef(0);
|
|
3185
3188
|
const sensorDimRef = useRef(0);
|
|
@@ -3209,7 +3212,7 @@ function useSensor(name) {
|
|
|
3209
3212
|
return { value: valueRef, size: sensorDimRef.current };
|
|
3210
3213
|
}
|
|
3211
3214
|
function useSensors() {
|
|
3212
|
-
const { mjModelRef, status } =
|
|
3215
|
+
const { mjModelRef, status } = useMujoco();
|
|
3213
3216
|
return useMemo(() => {
|
|
3214
3217
|
const model = mjModelRef.current;
|
|
3215
3218
|
if (!model || status !== "ready") return [];
|
|
@@ -3246,7 +3249,7 @@ function useSensors() {
|
|
|
3246
3249
|
}, [mjModelRef, status]);
|
|
3247
3250
|
}
|
|
3248
3251
|
function useJointState(name) {
|
|
3249
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3252
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
3250
3253
|
const jointIdRef = useRef(-1);
|
|
3251
3254
|
const qposAdrRef = useRef(0);
|
|
3252
3255
|
const dofAdrRef = useRef(0);
|
|
@@ -3306,7 +3309,7 @@ function useJointState(name) {
|
|
|
3306
3309
|
return { position: positionRef, velocity: velocityRef };
|
|
3307
3310
|
}
|
|
3308
3311
|
function useBodyState(name) {
|
|
3309
|
-
const { mjModelRef, status } =
|
|
3312
|
+
const { mjModelRef, status } = useMujoco();
|
|
3310
3313
|
const bodyIdRef = useRef(-1);
|
|
3311
3314
|
const position = useRef(new THREE11.Vector3());
|
|
3312
3315
|
const quaternion = useRef(new THREE11.Quaternion());
|
|
@@ -3338,7 +3341,7 @@ function useBodyState(name) {
|
|
|
3338
3341
|
return { position, quaternion, linearVelocity, angularVelocity };
|
|
3339
3342
|
}
|
|
3340
3343
|
function useCtrl(name) {
|
|
3341
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3344
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
3342
3345
|
const actuatorIdRef = useRef(-1);
|
|
3343
3346
|
const valueRef = useRef(0);
|
|
3344
3347
|
useEffect(() => {
|
|
@@ -3355,7 +3358,7 @@ function useCtrl(name) {
|
|
|
3355
3358
|
return [valueRef, setValue];
|
|
3356
3359
|
}
|
|
3357
3360
|
function useKeyboardTeleop(config) {
|
|
3358
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3361
|
+
const { mjModelRef, mjDataRef, status } = useMujoco();
|
|
3359
3362
|
const pressedRef = useRef(/* @__PURE__ */ new Set());
|
|
3360
3363
|
const toggleStateRef = useRef(/* @__PURE__ */ new Map());
|
|
3361
3364
|
const enabledRef = useRef(config.enabled ?? true);
|
|
@@ -3418,7 +3421,7 @@ function useKeyboardTeleop(config) {
|
|
|
3418
3421
|
});
|
|
3419
3422
|
}
|
|
3420
3423
|
function usePolicy(config) {
|
|
3421
|
-
const { mjModelRef } =
|
|
3424
|
+
const { mjModelRef } = useMujoco();
|
|
3422
3425
|
const lastActionTimeRef = useRef(0);
|
|
3423
3426
|
const lastActionRef = useRef(null);
|
|
3424
3427
|
const isRunningRef = useRef(true);
|
|
@@ -3452,7 +3455,7 @@ function usePolicy(config) {
|
|
|
3452
3455
|
};
|
|
3453
3456
|
}
|
|
3454
3457
|
function useTrajectoryRecorder(options = {}) {
|
|
3455
|
-
const { mjModelRef } =
|
|
3458
|
+
const { mjModelRef } = useMujoco();
|
|
3456
3459
|
const recordingRef = useRef(false);
|
|
3457
3460
|
const framesRef = useRef([]);
|
|
3458
3461
|
const fields = options.fields ?? ["qpos"];
|
|
@@ -3528,7 +3531,7 @@ function useTrajectoryRecorder(options = {}) {
|
|
|
3528
3531
|
};
|
|
3529
3532
|
}
|
|
3530
3533
|
function useGamepad(config) {
|
|
3531
|
-
const { mjModelRef, status } =
|
|
3534
|
+
const { mjModelRef, status } = useMujoco();
|
|
3532
3535
|
const configRef = useRef(config);
|
|
3533
3536
|
configRef.current = config;
|
|
3534
3537
|
const axisCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -3624,7 +3627,7 @@ function useVideoRecorder(options = {}) {
|
|
|
3624
3627
|
};
|
|
3625
3628
|
}
|
|
3626
3629
|
function useCtrlNoise(config = {}) {
|
|
3627
|
-
const { mjModelRef } =
|
|
3630
|
+
const { mjModelRef } = useMujoco();
|
|
3628
3631
|
const configRef = useRef(config);
|
|
3629
3632
|
configRef.current = config;
|
|
3630
3633
|
const noiseRef = useRef(null);
|
|
@@ -3720,6 +3723,10 @@ function useCameraAnimation() {
|
|
|
3720
3723
|
* @license
|
|
3721
3724
|
* SPDX-License-Identifier: Apache-2.0
|
|
3722
3725
|
*/
|
|
3726
|
+
/**
|
|
3727
|
+
* @license
|
|
3728
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3729
|
+
*/
|
|
3723
3730
|
/**
|
|
3724
3731
|
* @license
|
|
3725
3732
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -3739,10 +3746,6 @@ function useCameraAnimation() {
|
|
|
3739
3746
|
* IkController — composable IK controller plugin.
|
|
3740
3747
|
* Extracts all IK logic from MujocoSimProvider into an opt-in component.
|
|
3741
3748
|
*/
|
|
3742
|
-
/**
|
|
3743
|
-
* @license
|
|
3744
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
3745
|
-
*/
|
|
3746
3749
|
/**
|
|
3747
3750
|
* @license
|
|
3748
3751
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -3904,6 +3907,6 @@ function useCameraAnimation() {
|
|
|
3904
3907
|
* useCameraAnimation — composable camera animation hook.
|
|
3905
3908
|
*/
|
|
3906
3909
|
|
|
3907
|
-
export { ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkController, IkGizmo, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights,
|
|
3910
|
+
export { ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkController, IkGizmo, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, SelectionHighlight, TendonRenderer, TrajectoryPlayer, createController, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getContact, getName, loadScene, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIk, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
|
|
3908
3911
|
//# sourceMappingURL=index.js.map
|
|
3909
3912
|
//# sourceMappingURL=index.js.map
|