|
@@ -1,5 +1,5 @@
|
|
|
import { Vector3, Matrix, TmpVectors } from "../Maths/math.vector";
|
|
|
-import { Color3 } from '../Maths/math.color';
|
|
|
+import { Color3, Color4 } from '../Maths/math.color';
|
|
|
import { Scene } from "../scene";
|
|
|
import { Nullable } from "../types";
|
|
|
import { Bone } from "../Bones/bone";
|
|
@@ -300,6 +300,9 @@ export class SkeletonViewer {
|
|
|
/** The SkeletonViewers Mesh. */
|
|
|
private _debugMesh: Nullable<LinesMesh>;
|
|
|
|
|
|
+ /** The local axes Meshes. */
|
|
|
+ private _localAxes: Nullable<LinesMesh> = null;
|
|
|
+
|
|
|
/** If SkeletonViewer is enabled. */
|
|
|
private _isEnabled = false;
|
|
|
|
|
@@ -386,6 +389,8 @@ export class SkeletonViewer {
|
|
|
options.displayOptions.sphereBaseSize = options.displayOptions.sphereBaseSize ?? 0.15;
|
|
|
options.displayOptions.sphereScaleUnit = options.displayOptions.sphereScaleUnit ?? 2;
|
|
|
options.displayOptions.sphereFactor = options.displayOptions.sphereFactor ?? 0.865;
|
|
|
+ options.displayOptions.showLocalAxes = options.displayOptions.showLocalAxes ?? false;
|
|
|
+ options.displayOptions.localAxesSize = options.displayOptions.localAxesSize ?? 0.075;
|
|
|
options.computeBonesUsingShaders = options.computeBonesUsingShaders ?? true;
|
|
|
options.useAllBones = options.useAllBones ?? true;
|
|
|
|
|
@@ -447,6 +452,8 @@ export class SkeletonViewer {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ this._buildLocalAxes();
|
|
|
}
|
|
|
|
|
|
/** Gets or sets a boolean indicating if the viewer is enabled */
|
|
@@ -553,6 +560,17 @@ export class SkeletonViewer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private getAbsoluteRestPose(bone: Nullable<Bone>, matrix: Matrix) {
|
|
|
+ if (bone === null || bone._index === -1) {
|
|
|
+ matrix.copyFrom(Matrix.Identity());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getAbsoluteRestPose(bone.getParent(), matrix);
|
|
|
+ bone.getBindPose().multiplyToRef(matrix, matrix);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/** function to build and bind sphere joint points and spur bone representations. */
|
|
|
private _buildSpheresAndSpurs(spheresOnly = true): void {
|
|
|
|
|
@@ -584,16 +602,6 @@ export class SkeletonViewer {
|
|
|
}
|
|
|
|
|
|
let longestBoneLength = Number.NEGATIVE_INFINITY;
|
|
|
- let getAbsoluteRestPose = function(bone: Nullable<Bone>, matrix: Matrix) {
|
|
|
- if (bone === null || bone._index === -1) {
|
|
|
- matrix.copyFrom(Matrix.Identity());
|
|
|
- return;
|
|
|
- }
|
|
|
- getAbsoluteRestPose(bone.getParent(), matrix);
|
|
|
- bone.getBindPose().multiplyToRef(matrix, matrix);
|
|
|
- return;
|
|
|
- };
|
|
|
-
|
|
|
let displayOptions = this.options.displayOptions || {};
|
|
|
|
|
|
for (let i = 0; i < bones.length; i++) {
|
|
@@ -604,7 +612,7 @@ export class SkeletonViewer {
|
|
|
}
|
|
|
|
|
|
let boneAbsoluteRestTransform = new Matrix();
|
|
|
- getAbsoluteRestPose(bone, boneAbsoluteRestTransform);
|
|
|
+ this.getAbsoluteRestPose(bone, boneAbsoluteRestTransform);
|
|
|
|
|
|
let anchorPoint = new Vector3();
|
|
|
|
|
@@ -735,6 +743,75 @@ export class SkeletonViewer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private _buildLocalAxes(): void {
|
|
|
+ if (this._localAxes) {
|
|
|
+ this._localAxes.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ this._localAxes = null;
|
|
|
+
|
|
|
+ let displayOptions = this.options.displayOptions || {};
|
|
|
+
|
|
|
+ if (!displayOptions.showLocalAxes) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const targetScene = this._utilityLayer!.utilityLayerScene;
|
|
|
+ const size = displayOptions.localAxesSize || 0.075;
|
|
|
+ let lines = [];
|
|
|
+ let colors = [];
|
|
|
+ let red = new Color4(1, 0, 0, 1);
|
|
|
+ let green = new Color4(0, 1, 0, 1);
|
|
|
+ let blue = new Color4(0, 0, 1, 1);
|
|
|
+
|
|
|
+ let mwk: number[] = [];
|
|
|
+ let mik: number[] = [];
|
|
|
+ const vertsPerBone = 6;
|
|
|
+
|
|
|
+ for (let i in this.skeleton.bones) {
|
|
|
+ let bone = this.skeleton.bones[i];
|
|
|
+
|
|
|
+ if (bone._index === -1 || (!this._boneIndices.has(bone.getIndex()) && !this.options.useAllBones)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ let boneAbsoluteRestTransform = new Matrix();
|
|
|
+ let boneOrigin = new Vector3();
|
|
|
+
|
|
|
+ this.getAbsoluteRestPose(bone, boneAbsoluteRestTransform);
|
|
|
+ boneAbsoluteRestTransform.decompose(undefined, undefined, boneOrigin);
|
|
|
+
|
|
|
+ let m = bone.getBindPose().getRotationMatrix();
|
|
|
+
|
|
|
+ let boneAxisX = Vector3.TransformCoordinates(new Vector3(0 + size, 0, 0), m);
|
|
|
+ let boneAxisY = Vector3.TransformCoordinates(new Vector3(0, 0 + size, 0), m);
|
|
|
+ let boneAxisZ = Vector3.TransformCoordinates(new Vector3(0, 0, 0 + size), m);
|
|
|
+
|
|
|
+ let axisX = [boneOrigin, boneOrigin.add(boneAxisX)];
|
|
|
+ let axisY = [boneOrigin, boneOrigin.add(boneAxisY)];
|
|
|
+ let axisZ = [boneOrigin, boneOrigin.add(boneAxisZ)];
|
|
|
+
|
|
|
+ let linePoints = [axisX, axisY, axisZ];
|
|
|
+ let lineColors = [[red, red], [green, green], [blue, blue]];
|
|
|
+
|
|
|
+ lines.push(...linePoints);
|
|
|
+ colors.push(...lineColors);
|
|
|
+
|
|
|
+ for (let j = 0; j < vertsPerBone; j++) {
|
|
|
+ mwk.push(1, 0, 0, 0);
|
|
|
+ mik.push(bone.getIndex(), 0, 0, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this._localAxes = LinesBuilder.CreateLineSystem('localAxes', { lines: lines, colors: colors, updatable: true }, targetScene);
|
|
|
+ this._localAxes.setVerticesData(VertexBuffer.MatricesWeightsKind, mwk, false);
|
|
|
+ this._localAxes.setVerticesData(VertexBuffer.MatricesIndicesKind, mik, false);
|
|
|
+ this._localAxes.skeleton = this.skeleton;
|
|
|
+ this._localAxes.renderingGroupId = this.renderingGroupId;
|
|
|
+ this._localAxes.parent = this.mesh;
|
|
|
+ this._localAxes.computeBonesUsingShaders = this.options.computeBonesUsingShaders ?? true;
|
|
|
+ }
|
|
|
+
|
|
|
/** Update the viewer to sync with current skeleton state, only used for the line display. */
|
|
|
private _displayLinesUpdate(): void {
|
|
|
if (!this._utilityLayer) {
|
|
@@ -786,7 +863,13 @@ export class SkeletonViewer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /** Changes the displayMode of the skeleton viewer
|
|
|
+ /** Sets a display option of the skeleton viewer
|
|
|
+ *
|
|
|
+ * | Option | Type | Default | Description |
|
|
|
+ * | --------------- | ------- | ------- | ----------- |
|
|
|
+ * | showLocalAxes | boolean | false | Displays local axes on all bones. |
|
|
|
+ * | localAxesSize | float | 0.075 | Determines the length of each local axis. |
|
|
|
+ *
|
|
|
* @param option String of the option name
|
|
|
* @param value The numerical option value
|
|
|
*/
|