1 | import { BindMode } from "../constants.js";
|
2 | import { BufferGeometry } from "../core/BufferGeometry.js";
|
3 | import { JSONMeta, Object3DEventMap } from "../core/Object3D.js";
|
4 | import { Material } from "../materials/Material.js";
|
5 | import { Box3 } from "../math/Box3.js";
|
6 | import { Matrix4, Matrix4Tuple } from "../math/Matrix4.js";
|
7 | import { Sphere } from "../math/Sphere.js";
|
8 | import { Vector3 } from "../math/Vector3.js";
|
9 | import { Mesh, MeshJSON, MeshJSONObject } from "./Mesh.js";
|
10 | import { Skeleton } from "./Skeleton.js";
|
11 |
|
12 | export interface SkinnedMeshJSONObject extends MeshJSONObject {
|
13 | bindMode: BindMode;
|
14 | bindMatrix: Matrix4Tuple;
|
15 | skeleton?: string;
|
16 | }
|
17 |
|
18 | export interface SkinnedMeshJSON extends MeshJSON {
|
19 | object: SkinnedMeshJSONObject;
|
20 | }
|
21 |
|
22 | /**
|
23 | * A mesh that has a {@link THREE.Skeleton | Skeleton} with {@link Bone | bones} that can then be used to animate the vertices of the geometry.
|
24 | * @example
|
25 | * ```typescript
|
26 | * const geometry = new THREE.CylinderGeometry(5, 5, 5, 5, 15, 5, 30);
|
27 | * // create the skin indices and skin weights manually
|
28 | * // (typically a loader would read this data from a 3D model for you)
|
29 | * const position = geometry.attributes.position;
|
30 | * const vertex = new THREE.Vector3();
|
31 | * const skinIndices = [];
|
32 | * const skinWeights = [];
|
33 | * for (let i = 0; i & lt; position.count; i++) {
|
34 | * vertex.fromBufferAttribute(position, i);
|
35 | * // compute skinIndex and skinWeight based on some configuration data
|
36 | * const y = (vertex.y + sizing.halfHeight);
|
37 | * const skinIndex = Math.floor(y / sizing.segmentHeight);
|
38 | * const skinWeight = (y % sizing.segmentHeight) / sizing.segmentHeight;
|
39 | * skinIndices.push(skinIndex, skinIndex + 1, 0, 0);
|
40 | * skinWeights.push(1 - skinWeight, skinWeight, 0, 0);
|
41 | * }
|
42 | * geometry.setAttribute('skinIndex', new THREE.Uint16BufferAttribute(skinIndices, 4));
|
43 | * geometry.setAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeights, 4));
|
44 | * // create skinned mesh and skeleton
|
45 | * const mesh = new THREE.SkinnedMesh(geometry, material);
|
46 | * const skeleton = new THREE.Skeleton(bones);
|
47 | * // see example from THREE.Skeleton
|
48 | * const rootBone = skeleton.bones[0];
|
49 | * mesh.add(rootBone);
|
50 | * // bind the skeleton to the mesh
|
51 | * mesh.bind(skeleton);
|
52 | * // move the bones and manipulate the model
|
53 | * skeleton.bones[0].rotation.x = -0.1;
|
54 | * skeleton.bones[1].rotation.x = 0.2;
|
55 | * ```
|
56 | * @see {@link https://threejs.org/docs/index.html#api/en/objects/SkinnedMesh | Official Documentation}
|
57 | * @see {@link https://github.com/mrdoob/three.js/blob/master/src/objects/SkinnedMesh.js | Source}
|
58 | */
|
59 | export class SkinnedMesh<
|
60 | TGeometry extends BufferGeometry = BufferGeometry,
|
61 | TMaterial extends Material | Material[] = Material | Material[],
|
62 | TEventMap extends Object3DEventMap = Object3DEventMap,
|
63 | > extends Mesh<TGeometry, TMaterial, TEventMap> {
|
64 | /**
|
65 | * Create a new instance of {@link SkinnedMesh}
|
66 | * @param geometry An instance of {@link THREE.BufferGeometry | BufferGeometry}. Default {@link THREE.BufferGeometry | `new THREE.BufferGeometry()`}.
|
67 | * @param material A single or an array of {@link THREE.Material | Material}. Default {@link THREE.MeshBasicMaterial | `new THREE.MeshBasicMaterial()`}.
|
68 | */
|
69 | constructor(geometry?: TGeometry, material?: TMaterial, useVertexTexture?: boolean);
|
70 |
|
71 | /**
|
72 | * Read-only flag to check if a given object is of type { SkinnedMesh}.
|
73 | * This is a _constant_ value
|
74 | * `true`
|
75 | */
|
76 | readonly isSkinnedMesh: true;
|
77 |
|
78 | /**
|
79 | * @override
|
80 | * @defaultValue `SkinnedMesh`
|
81 | */
|
82 | override readonly type: string | "SkinnedMesh";
|
83 |
|
84 | /**
|
85 | * Either {@link AttachedBindMode} or {@link DetachedBindMode}. {@link AttachedBindMode} means the skinned mesh
|
86 | * shares the same world space as the skeleton. This is not true when using {@link DetachedBindMode} which is useful
|
87 | * when sharing a skeleton across multiple skinned meshes.
|
88 | * @defaultValue `AttachedBindMode`
|
89 | */
|
90 | bindMode: BindMode;
|
91 |
|
92 | /**
|
93 | * The base matrix that is used for the bound bone transforms.
|
94 | */
|
95 | bindMatrix: Matrix4;
|
96 | /**
|
97 | * The base matrix that is used for resetting the bound bone transforms.
|
98 | */
|
99 | bindMatrixInverse: Matrix4;
|
100 |
|
101 | /**
|
102 | * The bounding box of the SkinnedMesh. Can be calculated with {@link computeBoundingBox | .computeBoundingBox()}.
|
103 | * @default `null`
|
104 | */
|
105 | boundingBox: Box3;
|
106 |
|
107 | /**
|
108 | * The bounding box of the SkinnedMesh. Can be calculated with {@link computeBoundingSphere | .computeBoundingSphere()}.
|
109 | * @default `null`
|
110 | */
|
111 | boundingSphere: Sphere;
|
112 |
|
113 | /**
|
114 | * {@link THREE.Skeleton | Skeleton} representing the bone hierarchy of the skinned mesh.
|
115 | */
|
116 | skeleton: Skeleton;
|
117 |
|
118 | /**
|
119 | * Bind a skeleton to the skinned mesh
|
120 | * @remarks
|
121 | * The bindMatrix gets saved to .bindMatrix property and the .bindMatrixInverse gets calculated.
|
122 | * @param skeleton {@link THREE.Skeleton | Skeleton} created from a {@link Bone | Bones} tree.
|
123 | * @param bindMatrix {@link THREE.Matrix4 | Matrix4} that represents the base transform of the skeleton.
|
124 | */
|
125 | bind(skeleton: Skeleton, bindMatrix?: Matrix4): void;
|
126 |
|
127 | /**
|
128 | * Computes the bounding box of the skinned mesh, and updates the {@link .boundingBox} attribute. The bounding box
|
129 | * is not computed by the engine; it must be computed by your app. If the skinned mesh is animated, the bounding box
|
130 | * should be recomputed per frame.
|
131 | */
|
132 | computeBoundingBox(): void;
|
133 |
|
134 | /**
|
135 | * Computes the bounding sphere of the skinned mesh, and updates the {@link .boundingSphere} attribute. The bounding
|
136 | * sphere is automatically computed by the engine when it is needed, e.g., for ray casting and view frustum culling.
|
137 | * If the skinned mesh is animated, the bounding sphere should be recomputed per frame.
|
138 | */
|
139 | computeBoundingSphere(): void;
|
140 |
|
141 | /**
|
142 | * This method sets the skinned mesh in the rest pose (resets the pose).
|
143 | */
|
144 | pose(): void;
|
145 |
|
146 | /**
|
147 | * Normalizes the skin weights.
|
148 | */
|
149 | normalizeSkinWeights(): void;
|
150 |
|
151 | /**
|
152 | * Applies the bone transform associated with the given index to the given position vector
|
153 | * @remarks Returns the updated vector.
|
154 | * @param index Expects a `Integer`
|
155 | * @param vector
|
156 | */
|
157 | applyBoneTransform(index: number, vector: Vector3): Vector3;
|
158 |
|
159 | toJSON(meta?: JSONMeta): SkinnedMeshJSON;
|
160 | }
|