@zephyr3d/scene 0.9.26 → 0.9.27
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/dist/animation/animationset.js +92 -30
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/joint_dynamics/convex_collider.js +320 -0
- package/dist/animation/joint_dynamics/convex_collider.js.map +1 -0
- package/dist/animation/skeleton.js +21 -1
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/asset/model.js +6 -2
- package/dist/asset/model.js.map +1 -1
- package/dist/camera/camera.js +75 -23
- package/dist/camera/camera.js.map +1 -1
- package/dist/index.d.ts +4764 -3600
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/material/hairstrand.js +235 -235
- package/dist/material/hairstrand.js.map +1 -1
- package/dist/material/material.js +296 -296
- package/dist/material/material.js.map +1 -1
- package/dist/material/mixins/lit.js +33 -1
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/shader/helper.js +404 -3
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/water.js +2057 -72
- package/dist/material/water.js.map +1 -1
- package/dist/posteffect/motionblur.js +663 -58
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/posteffect.js +12 -1
- package/dist/posteffect/posteffect.js.map +1 -1
- package/dist/posteffect/sao.js +46 -44
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/sss.js +30 -2
- package/dist/posteffect/sss.js.map +1 -1
- package/dist/render/abuffer_oit.js +37 -37
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +156 -5
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cull_visitor.js +1 -0
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/dualdepthpeeling_oit.js +49 -49
- package/dist/render/dualdepthpeeling_oit.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +3 -3
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +57 -15
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +127 -20
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/hzb.js +80 -22
- package/dist/render/hzb.js.map +1 -1
- package/dist/render/lightpass.js +6 -3
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/oit.js +11 -11
- package/dist/render/oit.js.map +1 -1
- package/dist/render/render_queue.js +36 -0
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +4 -0
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +1 -0
- package/dist/render/rendergraph/blackboard.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +318 -9
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
- package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
- package/dist/render/rendergraph/history_resources.js +8 -1
- package/dist/render/rendergraph/history_resources.js.map +1 -1
- package/dist/render/underwater.js +624 -0
- package/dist/render/underwater.js.map +1 -0
- package/dist/render/water_caustics.js +1380 -0
- package/dist/render/water_caustics.js.map +1 -0
- package/dist/render/weightedblended_oit.js +33 -33
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/water.js +540 -4
- package/dist/scene/water.js.map +1 -1
- package/dist/shaders/water.js +22 -19
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +56 -0
- package/dist/shaders/water_medium.js.map +1 -0
- package/dist/shadow/shadow_region.js +49 -49
- package/dist/shadow/shadow_region.js.map +1 -1
- package/dist/utility/serialization/manager.js +3 -1
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +31 -2
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +53 -25
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +1101 -21
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/shprojector.js +87 -87
- package/dist/utility/shprojector.js.map +1 -1
- package/package.json +1 -1
- package/dist/render/rendergraph/frame_graph_context.js +0 -41
- package/dist/render/rendergraph/frame_graph_context.js.map +0 -1
- package/dist/shaders/ssgi.js +0 -63
- package/dist/shaders/ssgi.js.map +0 -1
- package/dist/shaders/ssgi_reprojection.js +0 -118
- package/dist/shaders/ssgi_reprojection.js.map +0 -1
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { Matrix4x4, Vector3 } from '@zephyr3d/base';
|
|
2
|
+
import { getVertexFormatComponentCount } from '@zephyr3d/device';
|
|
3
|
+
import '../../scene/scene.js';
|
|
4
|
+
import '../../values.js';
|
|
5
|
+
import '../../render/render_queue.js';
|
|
6
|
+
import '../../render/primitive.js';
|
|
7
|
+
import '../../material/shader/helper.js';
|
|
8
|
+
import '../../material/lambert.js';
|
|
9
|
+
import '../../material/blinn.js';
|
|
10
|
+
import '../../material/unlit.js';
|
|
11
|
+
import '../../material/particle.js';
|
|
12
|
+
import '../../material/subsurfaceprofile.js';
|
|
13
|
+
import '../../material/meshmaterial.js';
|
|
14
|
+
import '../../material/grassmaterial.js';
|
|
15
|
+
import '../../material/terrain-cm.js';
|
|
16
|
+
import '../../material/pbrmr.js';
|
|
17
|
+
import '../../material/pbrsg.js';
|
|
18
|
+
import '../../material/mtoon.js';
|
|
19
|
+
import '../../material/pbrblueprint.js';
|
|
20
|
+
import '../../material/sprite.js';
|
|
21
|
+
import '../../material/sprite_std.js';
|
|
22
|
+
import '../../utility/blueprint/material/texture.js';
|
|
23
|
+
import '../../render/rendergraph/forward_plus_builder.js';
|
|
24
|
+
import '../../render/lightpass.js';
|
|
25
|
+
import '../../render/sky.js';
|
|
26
|
+
import '../../render/clipmap.js';
|
|
27
|
+
import '../../shaders/atmosphere.js';
|
|
28
|
+
import { getSceneMeshAssetBinding } from '../../scene/scene_node.js';
|
|
29
|
+
import '../../shadow/shadowmapper.js';
|
|
30
|
+
import '../../scene/mesh.js';
|
|
31
|
+
import '../../scene/basesprite.js';
|
|
32
|
+
import '../../scene/meshdrawable.js';
|
|
33
|
+
import '../../material/msdf_text.js';
|
|
34
|
+
import '../../scene/water.js';
|
|
35
|
+
import '../../scene/particlesys.js';
|
|
36
|
+
import '../../scene/batchgroup.js';
|
|
37
|
+
import '../../scene/terrain-cm/terrain-cm.js';
|
|
38
|
+
import '../../scene/terrain-cm/grass.js';
|
|
39
|
+
import '../../scene/raycast_visitor.js';
|
|
40
|
+
import { ColliderForce } from './types.js';
|
|
41
|
+
|
|
42
|
+
const EPS = 1e-6;
|
|
43
|
+
/**
|
|
44
|
+
* Generate convex JointDynamics colliders from skinned mesh bone weights.
|
|
45
|
+
*
|
|
46
|
+
* @public
|
|
47
|
+
*/ function generateJointDynamicsConvexCollidersFromSkinWeights(meshes, skinBinding, bones, options = {}) {
|
|
48
|
+
const sources = collectSourcePrimitives(meshes);
|
|
49
|
+
const results = [];
|
|
50
|
+
for (const bone of bones){
|
|
51
|
+
const jointIndex = skinBinding.joints.indexOf(bone);
|
|
52
|
+
if (jointIndex < 0) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const points = collectBonePoints(sources, skinBinding, jointIndex, options);
|
|
56
|
+
if (points.length < (options.minVertexCount ?? 8)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const hull = buildConvexHull(points, options.maxHullVertices ?? 48, options.margin ?? 0);
|
|
60
|
+
if (!hull || hull.vertices.length < 4 || hull.planes.length < 4) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
results.push({
|
|
64
|
+
bone,
|
|
65
|
+
vertexCount: points.length,
|
|
66
|
+
hullVertexCount: hull.vertices.length,
|
|
67
|
+
collider: {
|
|
68
|
+
radius: 0,
|
|
69
|
+
radiusTailScale: 1,
|
|
70
|
+
height: 0,
|
|
71
|
+
friction: options.friction ?? 0,
|
|
72
|
+
isInverseCollider: options.inversed ?? false,
|
|
73
|
+
forceType: ColliderForce.Off,
|
|
74
|
+
convex: hull
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
function collectSourcePrimitives(meshes) {
|
|
81
|
+
const result = [];
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
for (const mesh of meshes){
|
|
84
|
+
const binding = getSceneMeshAssetBinding(mesh);
|
|
85
|
+
const subMesh = binding?.subMesh;
|
|
86
|
+
const primitive = subMesh?.primitive ?? null;
|
|
87
|
+
if (primitive && !seen.has(primitive)) {
|
|
88
|
+
seen.add(primitive);
|
|
89
|
+
result.push({
|
|
90
|
+
primitive,
|
|
91
|
+
subMesh
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function collectBonePoints(sources, skinBinding, jointIndex, options) {
|
|
98
|
+
const points = [];
|
|
99
|
+
const weightThreshold = options.weightThreshold ?? 0.45;
|
|
100
|
+
const dominantBoneOnly = options.dominantBoneOnly ?? true;
|
|
101
|
+
const inverseBind = skinBinding.inverseBindMatrices[jointIndex] ?? Matrix4x4.identity();
|
|
102
|
+
for (const source of sources){
|
|
103
|
+
const primitive = source.primitive;
|
|
104
|
+
const positionInfo = primitive.vertices.position;
|
|
105
|
+
const blendIndexInfo = primitive.vertices.blendIndices;
|
|
106
|
+
const blendWeightInfo = primitive.vertices.blendWeights;
|
|
107
|
+
if (!positionInfo || !blendIndexInfo || !blendWeightInfo) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const positions = positionInfo.data;
|
|
111
|
+
const blendIndices = blendIndexInfo.data;
|
|
112
|
+
const blendWeights = blendWeightInfo.data;
|
|
113
|
+
const posStride = getVertexFormatComponentCount(positionInfo.format);
|
|
114
|
+
const idxStride = getVertexFormatComponentCount(blendIndexInfo.format);
|
|
115
|
+
const weightStride = getVertexFormatComponentCount(blendWeightInfo.format);
|
|
116
|
+
const vertexCount = Math.floor(positions.length / posStride);
|
|
117
|
+
for(let i = 0; i < vertexCount; i++){
|
|
118
|
+
let weight = 0;
|
|
119
|
+
let maxWeight = -1;
|
|
120
|
+
let maxJoint = -1;
|
|
121
|
+
const influenceCount = Math.min(4, idxStride, weightStride);
|
|
122
|
+
for(let k = 0; k < influenceCount; k++){
|
|
123
|
+
const idx = Number(blendIndices[i * idxStride + k]) | 0;
|
|
124
|
+
const w = Number(blendWeights[i * weightStride + k]) || 0;
|
|
125
|
+
if (idx === jointIndex) {
|
|
126
|
+
weight = Math.max(weight, w);
|
|
127
|
+
}
|
|
128
|
+
if (w > maxWeight) {
|
|
129
|
+
maxWeight = w;
|
|
130
|
+
maxJoint = idx;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (weight < weightThreshold || dominantBoneOnly && maxJoint !== jointIndex) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const p = new Vector3(Number(positions[i * posStride]) || 0, Number(positions[i * posStride + 1]) || 0, Number(positions[i * posStride + 2]) || 0);
|
|
137
|
+
points.push(inverseBind.transformPointAffine(p, p));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return uniquePoints(points);
|
|
141
|
+
}
|
|
142
|
+
function uniquePoints(points) {
|
|
143
|
+
const result = [];
|
|
144
|
+
const keys = new Set();
|
|
145
|
+
for (const point of points){
|
|
146
|
+
const key = `${Math.round(point.x * 100000)}:${Math.round(point.y * 100000)}:${Math.round(point.z * 100000)}`;
|
|
147
|
+
if (!keys.has(key)) {
|
|
148
|
+
keys.add(key);
|
|
149
|
+
result.push(point);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
function buildConvexHull(points, maxHullVertices, margin) {
|
|
155
|
+
const sampled = sampleSupportPoints(points, Math.max(8, maxHullVertices));
|
|
156
|
+
if (sampled.length < 4) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const faces = bruteForceHullFaces(sampled);
|
|
160
|
+
if (faces.length < 4) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const planes = mergePlanes(faces);
|
|
164
|
+
if (margin > 0) {
|
|
165
|
+
for (const plane of planes){
|
|
166
|
+
plane.distance -= margin;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
vertices: sampled.map((point)=>point.clone()),
|
|
171
|
+
planes,
|
|
172
|
+
edges: extractHullEdges(sampled, planes)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function sampleSupportPoints(points, maxCount) {
|
|
176
|
+
if (points.length <= maxCount) {
|
|
177
|
+
return [
|
|
178
|
+
...points
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
const dirs = buildSampleDirections(maxCount);
|
|
182
|
+
const selected = [];
|
|
183
|
+
const indices = new Set();
|
|
184
|
+
for (const dir of dirs){
|
|
185
|
+
let bestIndex = -1;
|
|
186
|
+
let bestDot = -Infinity;
|
|
187
|
+
for(let i = 0; i < points.length; i++){
|
|
188
|
+
const d = Vector3.dot(points[i], dir);
|
|
189
|
+
if (d > bestDot) {
|
|
190
|
+
bestDot = d;
|
|
191
|
+
bestIndex = i;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (bestIndex >= 0 && !indices.has(bestIndex)) {
|
|
195
|
+
indices.add(bestIndex);
|
|
196
|
+
selected.push(points[bestIndex]);
|
|
197
|
+
if (selected.length >= maxCount) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return selected.length >= 4 ? selected : [
|
|
203
|
+
...points.slice(0, maxCount)
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
function buildSampleDirections(maxCount) {
|
|
207
|
+
const dirs = [
|
|
208
|
+
new Vector3(1, 0, 0),
|
|
209
|
+
new Vector3(-1, 0, 0),
|
|
210
|
+
new Vector3(0, 1, 0),
|
|
211
|
+
new Vector3(0, -1, 0),
|
|
212
|
+
new Vector3(0, 0, 1),
|
|
213
|
+
new Vector3(0, 0, -1)
|
|
214
|
+
];
|
|
215
|
+
const rings = Math.max(4, Math.ceil(Math.sqrt(maxCount)));
|
|
216
|
+
for(let y = 0; y < rings && dirs.length < maxCount; y++){
|
|
217
|
+
const v = rings === 1 ? 0 : -1 + 2 * y / (rings - 1);
|
|
218
|
+
const r = Math.sqrt(Math.max(0, 1 - v * v));
|
|
219
|
+
for(let x = 0; x < rings * 2 && dirs.length < maxCount; x++){
|
|
220
|
+
const a = x / (rings * 2) * Math.PI * 2;
|
|
221
|
+
dirs.push(new Vector3(Math.cos(a) * r, v, Math.sin(a) * r));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return dirs;
|
|
225
|
+
}
|
|
226
|
+
function bruteForceHullFaces(points) {
|
|
227
|
+
const center = new Vector3();
|
|
228
|
+
for (const point of points){
|
|
229
|
+
Vector3.add(center, point, center);
|
|
230
|
+
}
|
|
231
|
+
Vector3.scale(center, 1 / points.length, center);
|
|
232
|
+
const faces = [];
|
|
233
|
+
const faceKeys = new Set();
|
|
234
|
+
for(let i = 0; i < points.length - 2; i++){
|
|
235
|
+
for(let j = i + 1; j < points.length - 1; j++){
|
|
236
|
+
for(let k = j + 1; k < points.length; k++){
|
|
237
|
+
const ab = Vector3.sub(points[j], points[i]);
|
|
238
|
+
const ac = Vector3.sub(points[k], points[i]);
|
|
239
|
+
const normal = Vector3.cross(ab, ac);
|
|
240
|
+
const len = normal.magnitude;
|
|
241
|
+
if (len <= EPS) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
Vector3.scale(normal, 1 / len, normal);
|
|
245
|
+
let distance = -Vector3.dot(normal, points[i]);
|
|
246
|
+
if (Vector3.dot(normal, center) + distance > 0) {
|
|
247
|
+
Vector3.scale(normal, -1, normal);
|
|
248
|
+
distance = -Vector3.dot(normal, points[i]);
|
|
249
|
+
}
|
|
250
|
+
let valid = true;
|
|
251
|
+
for(let p = 0; p < points.length; p++){
|
|
252
|
+
if (p === i || p === j || p === k) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (Vector3.dot(normal, points[p]) + distance > 1e-5) {
|
|
256
|
+
valid = false;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (!valid) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const key = planeKey(normal, distance);
|
|
264
|
+
if (faceKeys.has(key)) {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
faceKeys.add(key);
|
|
268
|
+
faces.push({
|
|
269
|
+
a: i,
|
|
270
|
+
b: j,
|
|
271
|
+
c: k,
|
|
272
|
+
normal: normal.clone(),
|
|
273
|
+
distance
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return faces;
|
|
279
|
+
}
|
|
280
|
+
function mergePlanes(faces) {
|
|
281
|
+
const planes = [];
|
|
282
|
+
for (const face of faces){
|
|
283
|
+
if (planes.some((plane)=>Math.abs(Vector3.dot(plane.normal, face.normal) - 1) < 1e-4 && Math.abs(plane.distance - face.distance) < 1e-4)) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
planes.push({
|
|
287
|
+
normal: face.normal.clone(),
|
|
288
|
+
distance: face.distance
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return planes;
|
|
292
|
+
}
|
|
293
|
+
function extractHullEdges(vertices, planes) {
|
|
294
|
+
const result = [];
|
|
295
|
+
const keys = new Set();
|
|
296
|
+
for(let i = 0; i < vertices.length - 1; i++){
|
|
297
|
+
for(let j = i + 1; j < vertices.length; j++){
|
|
298
|
+
const sharedPlaneCount = planes.reduce((count, plane)=>{
|
|
299
|
+
const di = Math.abs(Vector3.dot(plane.normal, vertices[i]) + plane.distance);
|
|
300
|
+
const dj = Math.abs(Vector3.dot(plane.normal, vertices[j]) + plane.distance);
|
|
301
|
+
return count + (di < 1e-4 && dj < 1e-4 ? 1 : 0);
|
|
302
|
+
}, 0);
|
|
303
|
+
if (sharedPlaneCount < 2) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
const key = `${i}:${j}`;
|
|
307
|
+
if (!keys.has(key)) {
|
|
308
|
+
keys.add(key);
|
|
309
|
+
result.push(i, j);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
function planeKey(normal, distance) {
|
|
316
|
+
return `${Math.round(normal.x * 10000)}:${Math.round(normal.y * 10000)}:${Math.round(normal.z * 10000)}:${Math.round(distance * 10000)}`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export { generateJointDynamicsConvexCollidersFromSkinWeights };
|
|
320
|
+
//# sourceMappingURL=convex_collider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convex_collider.js","sources":["../../../src/animation/joint_dynamics/convex_collider.ts"],"sourcesContent":["import { Matrix4x4, Vector3 } from '@zephyr3d/base';\nimport { getVertexFormatComponentCount } from '@zephyr3d/device';\nimport type { Mesh, SceneNode } from '../../scene';\nimport { getSceneMeshAssetBinding } from '../../scene';\nimport type { AssetPrimitiveInfo, AssetSubMeshData } from '../../asset';\nimport type { SkinBinding } from '../skeleton';\nimport { ColliderForce, type ColliderR, type ConvexColliderPlane } from './types';\n\n/** @public */\nexport type JointDynamicsConvexColliderGenerationOptions = {\n weightThreshold?: number;\n dominantBoneOnly?: boolean;\n maxHullVertices?: number;\n margin?: number;\n minVertexCount?: number;\n friction?: number;\n inversed?: boolean;\n};\n\n/** @public */\nexport type JointDynamicsConvexColliderGenerationResult = {\n bone: SceneNode;\n collider: ColliderR;\n vertexCount: number;\n hullVertexCount: number;\n};\n\ntype SourcePrimitive = {\n primitive: AssetPrimitiveInfo;\n subMesh?: AssetSubMeshData;\n};\n\ntype Face = {\n a: number;\n b: number;\n c: number;\n normal: Vector3;\n distance: number;\n};\n\nconst EPS = 1e-6;\n\n/**\n * Generate convex JointDynamics colliders from skinned mesh bone weights.\n *\n * @public\n */\nexport function generateJointDynamicsConvexCollidersFromSkinWeights(\n meshes: readonly Mesh[],\n skinBinding: SkinBinding,\n bones: readonly SceneNode[],\n options: JointDynamicsConvexColliderGenerationOptions = {}\n): JointDynamicsConvexColliderGenerationResult[] {\n const sources = collectSourcePrimitives(meshes);\n const results: JointDynamicsConvexColliderGenerationResult[] = [];\n for (const bone of bones) {\n const jointIndex = skinBinding.joints.indexOf(bone);\n if (jointIndex < 0) {\n continue;\n }\n const points = collectBonePoints(sources, skinBinding, jointIndex, options);\n if (points.length < (options.minVertexCount ?? 8)) {\n continue;\n }\n const hull = buildConvexHull(points, options.maxHullVertices ?? 48, options.margin ?? 0);\n if (!hull || hull.vertices.length < 4 || hull.planes.length < 4) {\n continue;\n }\n results.push({\n bone,\n vertexCount: points.length,\n hullVertexCount: hull.vertices.length,\n collider: {\n radius: 0,\n radiusTailScale: 1,\n height: 0,\n friction: options.friction ?? 0,\n isInverseCollider: options.inversed ?? false,\n forceType: ColliderForce.Off,\n convex: hull\n }\n });\n }\n return results;\n}\n\nfunction collectSourcePrimitives(meshes: readonly Mesh[]): SourcePrimitive[] {\n const result: SourcePrimitive[] = [];\n const seen = new Set<AssetPrimitiveInfo>();\n for (const mesh of meshes) {\n const binding = getSceneMeshAssetBinding(mesh);\n const subMesh = binding?.subMesh as AssetSubMeshData | undefined;\n const primitive = subMesh?.primitive ?? null;\n if (primitive && !seen.has(primitive)) {\n seen.add(primitive);\n result.push({ primitive, subMesh });\n }\n }\n return result;\n}\n\nfunction collectBonePoints(\n sources: readonly SourcePrimitive[],\n skinBinding: SkinBinding,\n jointIndex: number,\n options: JointDynamicsConvexColliderGenerationOptions\n): Vector3[] {\n const points: Vector3[] = [];\n const weightThreshold = options.weightThreshold ?? 0.45;\n const dominantBoneOnly = options.dominantBoneOnly ?? true;\n const inverseBind = skinBinding.inverseBindMatrices[jointIndex] ?? Matrix4x4.identity();\n for (const source of sources) {\n const primitive = source.primitive;\n const positionInfo = primitive.vertices.position;\n const blendIndexInfo = primitive.vertices.blendIndices;\n const blendWeightInfo = primitive.vertices.blendWeights;\n if (!positionInfo || !blendIndexInfo || !blendWeightInfo) {\n continue;\n }\n const positions = positionInfo.data;\n const blendIndices = blendIndexInfo.data;\n const blendWeights = blendWeightInfo.data;\n const posStride = getVertexFormatComponentCount(positionInfo.format);\n const idxStride = getVertexFormatComponentCount(blendIndexInfo.format);\n const weightStride = getVertexFormatComponentCount(blendWeightInfo.format);\n const vertexCount = Math.floor(positions.length / posStride);\n for (let i = 0; i < vertexCount; i++) {\n let weight = 0;\n let maxWeight = -1;\n let maxJoint = -1;\n const influenceCount = Math.min(4, idxStride, weightStride);\n for (let k = 0; k < influenceCount; k++) {\n const idx = Number(blendIndices[i * idxStride + k]) | 0;\n const w = Number(blendWeights[i * weightStride + k]) || 0;\n if (idx === jointIndex) {\n weight = Math.max(weight, w);\n }\n if (w > maxWeight) {\n maxWeight = w;\n maxJoint = idx;\n }\n }\n if (weight < weightThreshold || (dominantBoneOnly && maxJoint !== jointIndex)) {\n continue;\n }\n const p = new Vector3(\n Number(positions[i * posStride]) || 0,\n Number(positions[i * posStride + 1]) || 0,\n Number(positions[i * posStride + 2]) || 0\n );\n points.push(inverseBind.transformPointAffine(p, p));\n }\n }\n return uniquePoints(points);\n}\n\nfunction uniquePoints(points: readonly Vector3[]): Vector3[] {\n const result: Vector3[] = [];\n const keys = new Set<string>();\n for (const point of points) {\n const key = `${Math.round(point.x * 100000)}:${Math.round(point.y * 100000)}:${Math.round(point.z * 100000)}`;\n if (!keys.has(key)) {\n keys.add(key);\n result.push(point);\n }\n }\n return result;\n}\n\nfunction buildConvexHull(points: readonly Vector3[], maxHullVertices: number, margin: number) {\n const sampled = sampleSupportPoints(points, Math.max(8, maxHullVertices));\n if (sampled.length < 4) {\n return null;\n }\n const faces = bruteForceHullFaces(sampled);\n if (faces.length < 4) {\n return null;\n }\n const planes = mergePlanes(faces);\n if (margin > 0) {\n for (const plane of planes) {\n plane.distance -= margin;\n }\n }\n return {\n vertices: sampled.map((point) => point.clone()),\n planes,\n edges: extractHullEdges(sampled, planes)\n };\n}\n\nfunction sampleSupportPoints(points: readonly Vector3[], maxCount: number): Vector3[] {\n if (points.length <= maxCount) {\n return [...points];\n }\n const dirs = buildSampleDirections(maxCount);\n const selected: Vector3[] = [];\n const indices = new Set<number>();\n for (const dir of dirs) {\n let bestIndex = -1;\n let bestDot = -Infinity;\n for (let i = 0; i < points.length; i++) {\n const d = Vector3.dot(points[i], dir);\n if (d > bestDot) {\n bestDot = d;\n bestIndex = i;\n }\n }\n if (bestIndex >= 0 && !indices.has(bestIndex)) {\n indices.add(bestIndex);\n selected.push(points[bestIndex]);\n if (selected.length >= maxCount) {\n break;\n }\n }\n }\n return selected.length >= 4 ? selected : [...points.slice(0, maxCount)];\n}\n\nfunction buildSampleDirections(maxCount: number): Vector3[] {\n const dirs = [\n new Vector3(1, 0, 0),\n new Vector3(-1, 0, 0),\n new Vector3(0, 1, 0),\n new Vector3(0, -1, 0),\n new Vector3(0, 0, 1),\n new Vector3(0, 0, -1)\n ];\n const rings = Math.max(4, Math.ceil(Math.sqrt(maxCount)));\n for (let y = 0; y < rings && dirs.length < maxCount; y++) {\n const v = rings === 1 ? 0 : -1 + (2 * y) / (rings - 1);\n const r = Math.sqrt(Math.max(0, 1 - v * v));\n for (let x = 0; x < rings * 2 && dirs.length < maxCount; x++) {\n const a = (x / (rings * 2)) * Math.PI * 2;\n dirs.push(new Vector3(Math.cos(a) * r, v, Math.sin(a) * r));\n }\n }\n return dirs;\n}\n\nfunction bruteForceHullFaces(points: readonly Vector3[]): Face[] {\n const center = new Vector3();\n for (const point of points) {\n Vector3.add(center, point, center);\n }\n Vector3.scale(center, 1 / points.length, center);\n const faces: Face[] = [];\n const faceKeys = new Set<string>();\n for (let i = 0; i < points.length - 2; i++) {\n for (let j = i + 1; j < points.length - 1; j++) {\n for (let k = j + 1; k < points.length; k++) {\n const ab = Vector3.sub(points[j], points[i]);\n const ac = Vector3.sub(points[k], points[i]);\n const normal = Vector3.cross(ab, ac);\n const len = normal.magnitude;\n if (len <= EPS) {\n continue;\n }\n Vector3.scale(normal, 1 / len, normal);\n let distance = -Vector3.dot(normal, points[i]);\n if (Vector3.dot(normal, center) + distance > 0) {\n Vector3.scale(normal, -1, normal);\n distance = -Vector3.dot(normal, points[i]);\n }\n let valid = true;\n for (let p = 0; p < points.length; p++) {\n if (p === i || p === j || p === k) {\n continue;\n }\n if (Vector3.dot(normal, points[p]) + distance > 1e-5) {\n valid = false;\n break;\n }\n }\n if (!valid) {\n continue;\n }\n const key = planeKey(normal, distance);\n if (faceKeys.has(key)) {\n continue;\n }\n faceKeys.add(key);\n faces.push({ a: i, b: j, c: k, normal: normal.clone(), distance });\n }\n }\n }\n return faces;\n}\n\nfunction mergePlanes(faces: readonly Face[]): ConvexColliderPlane[] {\n const planes: ConvexColliderPlane[] = [];\n for (const face of faces) {\n if (\n planes.some(\n (plane) =>\n Math.abs(Vector3.dot(plane.normal, face.normal) - 1) < 1e-4 &&\n Math.abs(plane.distance - face.distance) < 1e-4\n )\n ) {\n continue;\n }\n planes.push({ normal: face.normal.clone(), distance: face.distance });\n }\n return planes;\n}\n\nfunction extractHullEdges(\n vertices: readonly Vector3[],\n planes: readonly ConvexColliderPlane[]\n): number[] {\n const result: number[] = [];\n const keys = new Set<string>();\n for (let i = 0; i < vertices.length - 1; i++) {\n for (let j = i + 1; j < vertices.length; j++) {\n const sharedPlaneCount = planes.reduce((count, plane) => {\n const di = Math.abs(Vector3.dot(plane.normal, vertices[i]) + plane.distance);\n const dj = Math.abs(Vector3.dot(plane.normal, vertices[j]) + plane.distance);\n return count + (di < 1e-4 && dj < 1e-4 ? 1 : 0);\n }, 0);\n if (sharedPlaneCount < 2) {\n continue;\n }\n const key = `${i}:${j}`;\n if (!keys.has(key)) {\n keys.add(key);\n result.push(i, j);\n }\n }\n }\n return result;\n}\n\nfunction planeKey(normal: Vector3, distance: number): string {\n return `${Math.round(normal.x * 10000)}:${Math.round(normal.y * 10000)}:${Math.round(normal.z * 10000)}:${Math.round(distance * 10000)}`;\n}\n"],"names":["EPS","generateJointDynamicsConvexCollidersFromSkinWeights","meshes","skinBinding","bones","options","sources","collectSourcePrimitives","results","bone","jointIndex","joints","indexOf","points","collectBonePoints","length","minVertexCount","hull","buildConvexHull","maxHullVertices","margin","vertices","planes","push","vertexCount","hullVertexCount","collider","radius","radiusTailScale","height","friction","isInverseCollider","inversed","forceType","ColliderForce","Off","convex","result","seen","Set","mesh","binding","getSceneMeshAssetBinding","subMesh","primitive","has","add","weightThreshold","dominantBoneOnly","inverseBind","inverseBindMatrices","Matrix4x4","identity","source","positionInfo","position","blendIndexInfo","blendIndices","blendWeightInfo","blendWeights","positions","data","posStride","getVertexFormatComponentCount","format","idxStride","weightStride","Math","floor","i","weight","maxWeight","maxJoint","influenceCount","min","k","idx","Number","w","max","p","Vector3","transformPointAffine","uniquePoints","keys","point","key","round","x","y","z","sampled","sampleSupportPoints","faces","bruteForceHullFaces","mergePlanes","plane","distance","map","clone","edges","extractHullEdges","maxCount","dirs","buildSampleDirections","selected","indices","dir","bestIndex","bestDot","Infinity","d","dot","slice","rings","ceil","sqrt","v","r","a","PI","cos","sin","center","scale","faceKeys","j","ab","sub","ac","normal","cross","len","magnitude","valid","planeKey","b","c","face","some","abs","sharedPlaneCount","reduce","count","di","dj"],"mappings":"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"}
|
|
@@ -78,6 +78,8 @@ const humanoidHelperJointTokens = new Set([
|
|
|
78
78
|
_joints;
|
|
79
79
|
_bindPoseByJoint;
|
|
80
80
|
_bindPose;
|
|
81
|
+
_retargetPoseByJoint;
|
|
82
|
+
_retargetPose;
|
|
81
83
|
_rootJoint;
|
|
82
84
|
_rootBindPose;
|
|
83
85
|
_playing;
|
|
@@ -93,6 +95,14 @@ const humanoidHelperJointTokens = new Set([
|
|
|
93
95
|
for(let i = 0; i < joints.length; i++){
|
|
94
96
|
this._bindPoseByJoint.set(joints[i], bindPose[i]);
|
|
95
97
|
}
|
|
98
|
+
if (options?.retargetPose && options.retargetPose.length !== joints.length) {
|
|
99
|
+
throw new Error('SkeletonRig(): retarget pose must contain one transform per joint');
|
|
100
|
+
}
|
|
101
|
+
this._retargetPose = options?.retargetPose ?? null;
|
|
102
|
+
this._retargetPoseByJoint = this._retargetPose ? new Map(joints.map((joint, index)=>[
|
|
103
|
+
joint,
|
|
104
|
+
this._retargetPose[index]
|
|
105
|
+
])) : null;
|
|
96
106
|
const skeletonRoot = this.findRootJoint(this._joints);
|
|
97
107
|
this._rootJoint = options?.rootJoint ?? skeletonRoot;
|
|
98
108
|
this._rootBindPose = options?.rootBindPose ?? this.getNodeBindPose(this._rootJoint);
|
|
@@ -145,6 +155,12 @@ const humanoidHelperJointTokens = new Set([
|
|
|
145
155
|
get bindPose() {
|
|
146
156
|
return this._bindPose;
|
|
147
157
|
}
|
|
158
|
+
/** Effective humanoid retarget reference pose. */ get retargetPose() {
|
|
159
|
+
return this._retargetPose ?? this._bindPose;
|
|
160
|
+
}
|
|
161
|
+
/** Whether this rig has a reference pose that is distinct from its bind pose. */ get hasRetargetPose() {
|
|
162
|
+
return !!this._retargetPose;
|
|
163
|
+
}
|
|
148
164
|
get rootJoint() {
|
|
149
165
|
return this._rootJoint;
|
|
150
166
|
}
|
|
@@ -158,6 +174,9 @@ const humanoidHelperJointTokens = new Set([
|
|
|
158
174
|
getBindPoseForJoint(joint) {
|
|
159
175
|
return this._bindPoseByJoint.get(joint) ?? null;
|
|
160
176
|
}
|
|
177
|
+
getRetargetPoseForJoint(joint) {
|
|
178
|
+
return this._retargetPoseByJoint?.get(joint) ?? this.getBindPoseForJoint(joint);
|
|
179
|
+
}
|
|
161
180
|
get humanoidJointMapping() {
|
|
162
181
|
return this._humanoidJointMapping;
|
|
163
182
|
}
|
|
@@ -321,7 +340,8 @@ function sideJointPatterns(side, patterns) {
|
|
|
321
340
|
this._rig = new SkeletonRig(rig.joints, bindPose, {
|
|
322
341
|
rootJoint: rig.rootJoint,
|
|
323
342
|
rootBindPose: rig.rootBindPose,
|
|
324
|
-
humanoidJointMapping: rig.humanoidJointMapping
|
|
343
|
+
humanoidJointMapping: rig.humanoidJointMapping,
|
|
344
|
+
retargetPose: rig.hasRetargetPose ? rig.retargetPose : null
|
|
325
345
|
});
|
|
326
346
|
}
|
|
327
347
|
this.updateJointMatrices();
|