mujoco-react 10.9.0 → 12.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 +5 -0
- package/dist/{chunk-5WFYM73E.js → chunk-7BCIHJMW.js} +2 -2
- package/dist/chunk-7BCIHJMW.js.map +1 -0
- package/dist/index.d.ts +21 -23
- package/dist/index.js +563 -427
- package/dist/index.js.map +1 -1
- package/dist/onnx.d.ts +1 -1
- package/dist/spark.d.ts +1 -1
- package/dist/spark.js +1 -1
- package/dist/{types-Bu8Aki_j.d.ts → types-BjHt_Urb.d.ts} +59 -5
- package/package.json +6 -5
- package/src/components/FlexRenderer.tsx +13 -14
- package/src/core/GenericIK.ts +247 -232
- package/src/core/MujocoCanvas.tsx +2 -0
- package/src/core/MujocoPhysics.tsx +3 -0
- package/src/core/MujocoProvider.tsx +23 -9
- package/src/core/MujocoSimProvider.tsx +31 -34
- package/src/core/SceneLoader.ts +63 -30
- package/src/core/engineState.ts +58 -0
- package/src/hooks/useActuators.ts +3 -13
- package/src/hooks/useControlGroup.ts +2 -2
- package/src/hooks/useCtrl.ts +7 -6
- package/src/hooks/useGamepad.ts +3 -3
- package/src/hooks/useKeyboardTeleop.ts +2 -2
- package/src/index.ts +2 -0
- package/src/rendering/flexTopology.ts +24 -0
- package/src/types.ts +50 -4
- package/dist/chunk-5WFYM73E.js.map +0 -1
package/dist/onnx.d.ts
CHANGED
package/dist/spark.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _sparkjsdev_spark from '@sparkjsdev/spark';
|
|
3
|
-
import {
|
|
3
|
+
import { p as SplatEnvironmentProps, s as PairedSplatEnvironmentConfig, S as SceneConfig, v as SplatEnvironmentReadiness, q as VisualScenarioConfig } from './types-BjHt_Urb.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import '@react-three/fiber';
|
|
6
6
|
import 'three';
|
package/dist/spark.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useSplatSceneConfig, useSplatEnvironment, SplatEnvironment, CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY } from './chunk-
|
|
1
|
+
import { useSplatSceneConfig, useSplatEnvironment, SplatEnvironment, CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY } from './chunk-7BCIHJMW.js';
|
|
2
2
|
import { useThree } from '@react-three/fiber';
|
|
3
3
|
import { useMemo, useState, useEffect, useCallback, useRef } from 'react';
|
|
4
4
|
import * as THREE from 'three';
|
|
@@ -242,6 +242,7 @@ interface MujocoModel {
|
|
|
242
242
|
ngeom: number;
|
|
243
243
|
nsite: number;
|
|
244
244
|
nu: number;
|
|
245
|
+
nactuator: number;
|
|
245
246
|
njnt: number;
|
|
246
247
|
nq: number;
|
|
247
248
|
nv: number;
|
|
@@ -314,6 +315,9 @@ interface MujocoModel {
|
|
|
314
315
|
mesh_texcoord?: Float32Array;
|
|
315
316
|
mesh_facetexcoord?: Int32Array;
|
|
316
317
|
site_bodyid: Int32Array;
|
|
318
|
+
actuator_ctrladr: Int32Array;
|
|
319
|
+
actuator_ctrlnum: Int32Array;
|
|
320
|
+
actuator_ctrllimited: Uint8Array;
|
|
317
321
|
actuator_trnid: Int32Array;
|
|
318
322
|
actuator_ctrlrange: Float64Array;
|
|
319
323
|
actuator_trntype: Int32Array;
|
|
@@ -353,14 +357,23 @@ interface MujocoModel {
|
|
|
353
357
|
ten_width: Float64Array;
|
|
354
358
|
flex_vertadr: Int32Array;
|
|
355
359
|
flex_vertnum: Int32Array;
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
360
|
+
flex_dim: Int32Array;
|
|
361
|
+
flex_elemadr: Int32Array;
|
|
362
|
+
flex_elemnum: Int32Array;
|
|
363
|
+
flex_elemdataadr: Int32Array;
|
|
364
|
+
flex_elem: Int32Array;
|
|
365
|
+
flex_shelldataadr: Int32Array;
|
|
366
|
+
flex_shellnum: Int32Array;
|
|
367
|
+
flex_shell: Int32Array;
|
|
359
368
|
flex_rgba: Float32Array;
|
|
369
|
+
/** Number of stateful plastic deformation coordinates. */
|
|
370
|
+
nplastic: number;
|
|
371
|
+
jnt_plasticadr: Int32Array;
|
|
360
372
|
opt: {
|
|
361
373
|
timestep: number;
|
|
362
374
|
gravity: Float64Array;
|
|
363
375
|
integrator: number;
|
|
376
|
+
enableflags: number;
|
|
364
377
|
[key: string]: unknown;
|
|
365
378
|
};
|
|
366
379
|
delete: () => void;
|
|
@@ -373,6 +386,8 @@ interface MujocoData {
|
|
|
373
386
|
time: number;
|
|
374
387
|
qpos: Float64Array;
|
|
375
388
|
qvel: Float64Array;
|
|
389
|
+
/** Plastic rest offsets, included in full integration snapshots. */
|
|
390
|
+
plastic: Float64Array;
|
|
376
391
|
ctrl: Float64Array;
|
|
377
392
|
act: Float64Array;
|
|
378
393
|
xpos: Float64Array;
|
|
@@ -402,7 +417,30 @@ interface MujocoData {
|
|
|
402
417
|
/**
|
|
403
418
|
* Minimal interface for the MuJoCo WASM Module.
|
|
404
419
|
*/
|
|
420
|
+
interface MujocoBuffer {
|
|
421
|
+
GetView(): Float64Array;
|
|
422
|
+
delete(): void;
|
|
423
|
+
}
|
|
405
424
|
interface MujocoModule {
|
|
425
|
+
mjtEnableBit: {
|
|
426
|
+
mjENBL_SPECULATIVE: {
|
|
427
|
+
value: number;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
DoubleBuffer: new (size: number) => MujocoBuffer;
|
|
431
|
+
mj_jacSite(model: MujocoModel, data: MujocoData, jacp: MujocoBuffer | null, jacr: MujocoBuffer | null, site: number): void;
|
|
432
|
+
mj_integratePos(model: MujocoModel, qpos: MujocoBuffer, velocity: number[], dt: number): void;
|
|
433
|
+
mj_stateSize(model: MujocoModel, signature: number): number;
|
|
434
|
+
mj_getState(model: MujocoModel, data: MujocoData, state: MujocoBuffer, signature: number): void;
|
|
435
|
+
mj_setState(model: MujocoModel, data: MujocoData, state: number[], signature: number): void;
|
|
436
|
+
mjtState: {
|
|
437
|
+
mjSTATE_INTEGRATION: {
|
|
438
|
+
value: number;
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
mj_resetCtrl(model: MujocoModel, data: MujocoData): void;
|
|
442
|
+
mj_actuatorInputName(model: MujocoModel, id: number, input: number): string;
|
|
443
|
+
mju_threadpool(data: MujocoData, threads: number): void;
|
|
406
444
|
MjModel: {
|
|
407
445
|
from_xml_path?: (path: string) => MujocoModel;
|
|
408
446
|
from_xml_string?: (xml: string, vfs?: unknown) => MujocoModel;
|
|
@@ -559,6 +597,8 @@ interface SceneMarker {
|
|
|
559
597
|
interface PhysicsConfig {
|
|
560
598
|
gravity?: [number, number, number];
|
|
561
599
|
timestep?: number;
|
|
600
|
+
/** Override the MJCF integrator. Omit to preserve model settings. */
|
|
601
|
+
integrator?: MujocoIntegrator;
|
|
562
602
|
substeps?: number;
|
|
563
603
|
paused?: boolean;
|
|
564
604
|
speed?: number;
|
|
@@ -607,6 +647,12 @@ interface SelectionCallbackInput {
|
|
|
607
647
|
}
|
|
608
648
|
type PhysicsStepCallback = (input: PhysicsStepInput) => void;
|
|
609
649
|
interface StateSnapshot {
|
|
650
|
+
/** Complete engine integration state. Absent on legacy snapshots. */
|
|
651
|
+
integration?: {
|
|
652
|
+
signature: number;
|
|
653
|
+
values: Float64Array;
|
|
654
|
+
model: MujocoModel;
|
|
655
|
+
};
|
|
610
656
|
time: number;
|
|
611
657
|
qpos: Float64Array;
|
|
612
658
|
qvel: Float64Array;
|
|
@@ -647,8 +693,13 @@ interface SiteInfo {
|
|
|
647
693
|
interface ActuatorInfo {
|
|
648
694
|
id: number;
|
|
649
695
|
name: string;
|
|
696
|
+
/** Range of the first input; use ranges for multi-input actuators. */
|
|
650
697
|
range: [number, number];
|
|
698
|
+
ctrlAdr: number;
|
|
699
|
+
ctrlCount: number;
|
|
700
|
+
ranges: [number, number][];
|
|
651
701
|
}
|
|
702
|
+
type ActuatorControlValue = number | readonly number[];
|
|
652
703
|
interface ActuatedJointInfo extends JointInfo {
|
|
653
704
|
actuatorId: number;
|
|
654
705
|
actuatorName: string;
|
|
@@ -749,6 +800,7 @@ interface ImagePointProjectionResult extends RayHit {
|
|
|
749
800
|
/** Camera pose provenance, matching camera-frame capture results. */
|
|
750
801
|
source: CameraFrameCaptureSource;
|
|
751
802
|
}
|
|
803
|
+
type MujocoIntegrator = 'Euler' | 'RK4' | 'implicit' | 'implicitfast' | 'discrete';
|
|
752
804
|
interface ModelOptions {
|
|
753
805
|
timestep: number;
|
|
754
806
|
gravity: [number, number, number];
|
|
@@ -1247,7 +1299,7 @@ interface MujocoSimAPI {
|
|
|
1247
1299
|
setQvel(values: Float64Array | number[]): void;
|
|
1248
1300
|
getQpos(): Float64Array;
|
|
1249
1301
|
getQvel(): Float64Array;
|
|
1250
|
-
setCtrl(nameOrValues: Actuators | Record<Actuators,
|
|
1302
|
+
setCtrl(nameOrValues: Actuators | Record<Actuators, ActuatorControlValue>, value?: ActuatorControlValue): void;
|
|
1251
1303
|
getCtrl(): Float64Array;
|
|
1252
1304
|
getControlMap(): ControlGroupInfo;
|
|
1253
1305
|
getActuatedJoints(): ActuatedJointInfo[];
|
|
@@ -1584,6 +1636,8 @@ type MujocoCanvasProps = Omit<CanvasProps, 'onError'> & {
|
|
|
1584
1636
|
onSelection?: (input: SelectionCallbackInput) => void;
|
|
1585
1637
|
gravity?: [number, number, number];
|
|
1586
1638
|
timestep?: number;
|
|
1639
|
+
/** Override the MJCF integrator. Omit to preserve model settings. */
|
|
1640
|
+
integrator?: MujocoIntegrator;
|
|
1587
1641
|
substeps?: number;
|
|
1588
1642
|
paused?: boolean;
|
|
1589
1643
|
speed?: number;
|
|
@@ -1659,4 +1713,4 @@ interface ArrayJointStateResult {
|
|
|
1659
1713
|
velocity: React__default.RefObject<Float64Array>;
|
|
1660
1714
|
}
|
|
1661
1715
|
|
|
1662
|
-
export { type
|
|
1716
|
+
export { type SensorInfo as $, type ActuatedJointInfo as A, type BodyProps as B, type ControlGroupInfo as C, type DragInteractionProps as D, type VisualScenarioExecutionContextInput as E, type VisualScenarioExecutionContext as F, type ScenarioLightingPreset as G, type SplatEnvironmentMetadataInput as H, type IkConfig as I, type SplatEnvironmentMetadata as J, type SplatSceneInput as K, type CameraFrameCaptureOptions as L, type MujocoContextValue as M, type DebugProps as N, type ObservationConfig as O, type PhysicsStepCallback as P, type GeomInfo as Q, type ReadyCallbackInput as R, type SceneConfig as S, type ContactListenerProps as T, type TrajectoryPlayerProps as U, type VisualScenarioEffectsProps as V, type ActuatorInfo as W, type Sites as X, type SitePositionResult as Y, type Sensors as Z, type SensorHandle as _, type MujocoCanvasProps as a, type FrameCaptureTarget as a$, type Joints as a0, type ScalarJointStateResult as a1, type ArrayJointStateResult as a2, type JointStateOptions as a3, type JointStateResult as a4, type Bodies as a5, type BodyStateResult as a6, type Geoms as a7, type Actuators as a8, type CtrlHandle as a9, type FrameCaptureStatus as aA, type PolicyCameraFrameCaptureAPI as aB, type CameraFrameCaptureTensorOptions as aC, type CameraFrameTensorResult as aD, type CameraFrameSequenceRecorderAPI as aE, type ImagePointCoordinateSpace as aF, type ImagePointProjectionOptions as aG, type ImagePointProjectionResult as aH, type PolicyVector as aI, type ActuatorControlValue as aJ, type BodyInfo as aK, CAMERA_FRAME_CAPTURE_PRE_RENDER_USER_DATA_KEY as aL, CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY as aM, CAPTURE_EXCLUDE_KEY as aN, type CameraFrameCaptureBlobResult as aO, type CameraFrameCaptureQuaternion as aP, type CameraFrameCaptureResult as aQ, type CameraFrameCaptureSession as aR, type CameraFrameCaptureVector3 as aS, type CameraFramePixelsResult as aT, type CameraFrameSequenceCameraSummary as aU, type CameraFrameSequenceFrame as aV, type CameraFrameSequenceSampleInput as aW, type CameraFrameSequenceStepInput as aX, type CameraInfo as aY, type ControlJointInfo as aZ, type DebugVirtualCamera as a_, type ContactInfo as aa, type KeyboardTeleopConfig as ab, type KeyboardIkTargetConfig as ac, type PolicyConfig as ad, type PolicyAPI as ae, type RemotePolicyConfig as af, type RemotePolicyAPI as ag, type ObservationHandle as ah, type ObservationOutput as ai, type TrajectoryInput as aj, type TrajectoryStateChangeInput as ak, type PlaybackState as al, type TrajectoryFrame as am, type FrameCaptureOptions as an, type FrameCaptureResult as ao, type FrameCaptureBlobResult as ap, type FrameCaptureAPI as aq, type CameraFrameCaptureAPI as ar, type Cameras as as, type CameraFrameSequenceCamera as at, type CameraFrameCaptureSource as au, type CameraFrameSequenceOptions as av, type CameraFrameSequenceResult as aw, type PolicyCameraFrameStream as ax, type PolicyCameraFrameCaptureOptions as ay, type PolicyCameraFrameCaptureResult as az, type MujocoSimAPI as b, type XmlPatch as b$, type FrameCaptureTargetRef as b0, type IKSolveFn as b1, type IkGizmoDragInput as b2, type IkSolveInput as b3, type JointInfo as b4, type JointStateKind as b5, type KeyBinding as b6, type KeyboardIkTargetAction as b7, type KeyboardIkTargetBinding as b8, type Keyframes as b9, type PolicyInferenceInput as bA, type PolicyInferenceOutput as bB, type PolicyInferenceResult as bC, type PolicyObservationInput as bD, type RayHit as bE, type Register as bF, type RegisteredModelMap as bG, type RemotePolicyRequestInfo as bH, type RemotePolicyRequestInput as bI, type RemotePolicyResponseInfo as bJ, type RemotePolicyStatus as bK, type ResetCallbackInput as bL, type ResolvedScenarioCameraConfig as bM, type ResolvedScenarioMaterialConfig as bN, type ResourceSelector as bO, type ScenarioCameraConfig as bP, type ScenarioMaterialConfig as bQ, type SceneMarker as bR, type SceneObject as bS, type SensorResult as bT, type SiteInfo as bU, type SplatAssetConfig as bV, type SplatScenarioConfig as bW, type StateSnapshot as bX, type TrajectoryData as bY, type TrajectoryFrameCallbackInput as bZ, type VisualScenarioMaterialFilterInput as b_, ModelActuators as ba, ModelBodies as bb, ModelCameras as bc, ModelGeoms as bd, ModelJoints as be, ModelKeyframes as bf, type ModelOptions as bg, type ModelResource as bh, ModelResources as bi, ModelSensors as bj, ModelSites as bk, type Models as bl, type MujocoContact as bm, type MujocoContactArray as bn, type MujocoFrameCaptureOptions as bo, type ObservationLayoutItem as bp, type PhysicsConfig as bq, type PhysicsStepInput as br, type PolicyActionChunk as bs, type PolicyActionInput as bt, type PolicyImageTensorLayout as bu, type PolicyImageTensorOptions as bv, type PolicyImageTensorPixelOptions as bw, type PolicyImageTensorRange as bx, type PolicyImageTensorResult as by, type PolicyImageTensorSourceOrigin as bz, type StepCallbackInput as c, captureCameraFrame as c0, captureCameraFrameBlob as c1, captureCameraFrameTensor as c2, createCameraFrameCaptureSession as c3, dataUrlToPolicyImageTensor as c4, getContact as c5, imageDataToPolicyImageTensor as c6, pixelsToPolicyImageTensor as c7, registerModelResources as c8, renderCameraFrameToCanvas as c9, type SelectionCallbackInput as d, type MujocoIntegrator as e, type MujocoModule as f, type MujocoRenderOptions as g, type MujocoModel as h, type MujocoData as i, type ControlGroupSelector as j, type ObservationResult as k, type IkContextValue as l, type IkGizmoProps as m, type SceneLightsProps as n, type ScenarioLightingProps as o, type SplatEnvironmentProps as p, type VisualScenarioConfig as q, type SplatRendererKind as r, type PairedSplatEnvironmentConfig as s, type SplatFormat as t, type SplatCollisionProxyConfig as u, type SplatEnvironmentReadiness as v, type SplatCollisionPrimitive as w, SplatEnvironmentReadinessStatus as x, type SplatSceneConfigInput as y, type SplatSceneConfigState as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mujoco-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Composable React Three Fiber building blocks for MuJoCo WASM simulations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -62,15 +62,16 @@
|
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsup",
|
|
64
64
|
"dev": "tsup --watch",
|
|
65
|
-
"typecheck": "tsc --noEmit"
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"test:runtime": "tsup --config tests/tsup.config.ts && node --test .test-dist/runtime.js"
|
|
66
67
|
},
|
|
67
68
|
"peerDependencies": {
|
|
68
69
|
"@react-three/drei": ">=9",
|
|
69
70
|
"@react-three/fiber": ">=8",
|
|
70
71
|
"@sparkjsdev/spark": ">=2.1.0",
|
|
72
|
+
"onnxruntime-web": ">=1.20.0",
|
|
71
73
|
"react": ">=18",
|
|
72
|
-
"three": ">=0.180.0"
|
|
73
|
-
"onnxruntime-web": ">=1.20.0"
|
|
74
|
+
"three": ">=0.180.0"
|
|
74
75
|
},
|
|
75
76
|
"peerDependenciesMeta": {
|
|
76
77
|
"@sparkjsdev/spark": {
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
}
|
|
82
83
|
},
|
|
83
84
|
"dependencies": {
|
|
84
|
-
"@mujoco/mujoco": "
|
|
85
|
+
"@mujoco/mujoco": "4.0.1"
|
|
85
86
|
},
|
|
86
87
|
"devDependencies": {
|
|
87
88
|
"@react-three/drei": "^10.7.7",
|
|
@@ -9,6 +9,7 @@ import { useEffect, useRef } from 'react';
|
|
|
9
9
|
import { useFrame } from '@react-three/fiber';
|
|
10
10
|
import type { ThreeElements } from '@react-three/fiber';
|
|
11
11
|
import * as THREE from 'three';
|
|
12
|
+
import { getFlexTopology } from '../rendering/flexTopology';
|
|
12
13
|
import { useMujocoContext } from '../core/MujocoSimProvider';
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -18,7 +19,7 @@ import { useMujocoContext } from '../core/MujocoSimProvider';
|
|
|
18
19
|
export function FlexRenderer(props: Omit<ThreeElements['group'], 'ref'>) {
|
|
19
20
|
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
20
21
|
const groupRef = useRef<THREE.Group>(null);
|
|
21
|
-
const meshesRef = useRef<THREE.Mesh
|
|
22
|
+
const meshesRef = useRef<Array<THREE.Mesh | THREE.LineSegments | THREE.Points>>([]);
|
|
22
23
|
|
|
23
24
|
// Build flex meshes once when model is ready
|
|
24
25
|
useEffect(() => {
|
|
@@ -39,11 +40,8 @@ export function FlexRenderer(props: Omit<ThreeElements['group'], 'ref'>) {
|
|
|
39
40
|
const positions = new Float32Array(vertNum * 3);
|
|
40
41
|
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// face arrays, index-based triangle rendering can be added here.
|
|
45
|
-
|
|
46
|
-
geometry.computeVertexNormals();
|
|
43
|
+
const topology = getFlexTopology(model, f);
|
|
44
|
+
if (topology.indices.length) geometry.setIndex(topology.indices);
|
|
47
45
|
|
|
48
46
|
let color = new THREE.Color(0.5, 0.5, 0.5);
|
|
49
47
|
if (model.flex_rgba) {
|
|
@@ -54,13 +52,14 @@ export function FlexRenderer(props: Omit<ThreeElements['group'], 'ref'>) {
|
|
|
54
52
|
);
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
side: THREE.DoubleSide
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
const opacity = model.flex_rgba[4 * f + 3];
|
|
56
|
+
const materialOptions = { color, opacity, transparent: opacity < 1 };
|
|
57
|
+
const mesh = topology.kind === 'mesh'
|
|
58
|
+
? new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ ...materialOptions, roughness: 0.7, side: THREE.DoubleSide }))
|
|
59
|
+
: topology.kind === 'lines'
|
|
60
|
+
? new THREE.LineSegments(geometry, new THREE.LineBasicMaterial(materialOptions))
|
|
61
|
+
: new THREE.Points(geometry, new THREE.PointsMaterial({ ...materialOptions, size: 0.01 }));
|
|
62
|
+
mesh.frustumCulled = false;
|
|
64
63
|
mesh.userData.flexId = f;
|
|
65
64
|
mesh.userData.vertAdr = vertAdr;
|
|
66
65
|
mesh.userData.vertNum = vertNum;
|
|
@@ -94,7 +93,7 @@ export function FlexRenderer(props: Omit<ThreeElements['group'], 'ref'>) {
|
|
|
94
93
|
posAttr.setXYZ(v, data.flexvert_xpos[srcIdx], data.flexvert_xpos[srcIdx + 1], data.flexvert_xpos[srcIdx + 2]);
|
|
95
94
|
}
|
|
96
95
|
posAttr.needsUpdate = true;
|
|
97
|
-
mesh.geometry.computeVertexNormals();
|
|
96
|
+
if (mesh instanceof THREE.Mesh) mesh.geometry.computeVertexNormals();
|
|
98
97
|
}
|
|
99
98
|
});
|
|
100
99
|
|