Needle Engine

Changes between version 3.47.6-beta and 3.47.6
Files changed (3) hide show
  1. src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  2. src/engine-components/export/usdz/extensions/Animation.ts +91 -20
  3. src/engine/codegen/register_types.ts +2 -2
src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  // Modified according to https://github.com/gkjohnson/three-mesh-bvh/issues/636#issuecomment-2209571751
5
5
  import { WorkerBase } from "three-mesh-bvh/src/workers/utils/WorkerBase.js";
6
- import generateMeshBVHWorker from "three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker";
6
+ import generateMeshBVHWorker from "three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker&inline";
7
7
 
8
8
  export class GenerateMeshBVHWorker extends WorkerBase {
9
9
 
src/engine-components/export/usdz/extensions/Animation.ts CHANGED
@@ -923,11 +923,10 @@
923
923
 
924
924
  if (debugSerialization) console.log("SERIALIZE", this.model.name, this.object.type, arr);
925
925
 
926
- const composedTransform = new Matrix4();
926
+ // const composedTransform = new Matrix4();
927
+ // writer.appendLine("matrix4d xformOp:transform.timeSamples = {");
928
+ // writer.indent++;
927
929
 
928
- writer.appendLine("matrix4d xformOp:transform.timeSamples = {");
929
- writer.indent++;
930
-
931
930
  // TransformData is a collection of clips (position, rotation and scale) for a particular node
932
931
  // We need to make sure that the same underlying animation clip ends up
933
932
  // at the same start time in the USD file, and that we're not getting overlaps to other clips.
@@ -952,18 +951,46 @@
952
951
  useGrouping: false,
953
952
  });
954
953
 
955
- for (let i = 0; i < arr.length; i++) {
956
- const transformData = arr[i];
957
- if (!transformData) continue;
958
- const startTime = startTimes[i];
959
- {
960
- const timesArray = transformData.getSortedTimesArray();
961
-
954
+
955
+ const xFormOrder: Array<"xformOp:translate" | "xformOp:orient" | "xformOp:scale"> = [];
956
+
957
+ function writeAnimationTimesamples(arr: TransformData[], type: "position" | "rotation" | "scale") {
958
+
959
+ const hasAnimationData = arr.some(x => x && {
960
+ position: x.pos,
961
+ rotation: x.rot,
962
+ scale: x.scale
963
+ }[type]);
964
+ if (!hasAnimationData) {
965
+ return;
966
+ }
967
+
968
+ switch (type) {
969
+ case "position":
970
+ xFormOrder.push("xformOp:translate");
971
+ writer.beginBlock(`double3 xformOp:translate.timeSamples = {`, '');
972
+ break;
973
+ case "rotation":
974
+ xFormOrder.push("xformOp:orient");
975
+ writer.beginBlock(`quatf xformOp:orient.timeSamples = {`, '');
976
+ break;
977
+ case "scale":
978
+ xFormOrder.push("xformOp:scale");
979
+ writer.beginBlock(`double3 xformOp:scale.timeSamples = {`, '');
980
+ break;
981
+ }
982
+
983
+ for (let i = 0; i < arr.length; i++) {
984
+ const transformData = arr[i];
985
+ if (!transformData) continue;
986
+ const startTime = startTimes[i];
987
+ const timesArray = transformData.getSortedTimesArray(type === "position", type === "rotation", type === "scale");
988
+
962
989
  if (!timesArray || timesArray.length === 0) {
963
990
  console.error("got an animated object but no time values?", object, transformData);
964
991
  continue;
965
992
  }
966
-
993
+
967
994
  // if (debug) // writing out the clip name and duration is useful even when not debugging
968
995
  {
969
996
  const clipName = transformData.clip?.name ?? "rest";
@@ -972,16 +999,60 @@
972
999
  writer.appendLine("# " + clipName + ": start=" + formatter.format(startTime * transformData.frameRate) + ", length=" + formatter.format(duration * transformData.frameRate) + ", frames=" + transformData.getFrames());
973
1000
  }
974
1001
 
975
- for (const { time, translation, rotation, scale } of transformData.getValues(timesArray)) {
976
- composedTransform.compose(translation, rotation, scale);
977
-
978
- const timeStr = formatter.format((startTime + time) * transformData.frameRate);
979
- const line = `${timeStr}: ${buildMatrix(composedTransform)},`;
980
- writer.appendLine(line);
1002
+ if (type === "position" && transformData.pos) {
1003
+ for (const { time, translation } of transformData.getValues(timesArray, true, false, false)) {
1004
+ const timeStr = formatter.format((startTime + time) * transformData.frameRate);
1005
+ const line = `${timeStr}: (${fn(translation.x)}, ${fn(translation.y)}, ${fn(translation.z)}),`;
1006
+ writer.appendLine(line);
1007
+ }
981
1008
  }
1009
+ if (type === "rotation" && transformData.rot) {
1010
+ for (const { time, rotation } of transformData.getValues(timesArray, false, true, false)) {
1011
+ const timeStr = formatter.format((startTime + time) * transformData.frameRate);
1012
+ const line = `${timeStr}: (${fn(rotation.w)}, ${fn(rotation.x)}, ${fn(rotation.y)}, ${fn(rotation.z)}),`;
1013
+ writer.appendLine(line);
1014
+ }
1015
+ }
1016
+ if (type === "scale" && transformData.scale) {
1017
+ for (const { time, scale } of transformData.getValues(timesArray, false, false, true)) {
1018
+ const timeStr = formatter.format((startTime + time) * transformData.frameRate);
1019
+ const line = `${timeStr}: (${fn(scale.x)}, ${fn(scale.y)}, ${fn(scale.z)}),`;
1020
+ writer.appendLine(line);
1021
+ }
1022
+ }
982
1023
  }
1024
+ writer.closeBlock();
983
1025
  }
984
- writer.indent--;
985
- writer.appendLine("}");
1026
+ writeAnimationTimesamples(arr, "position");
1027
+ writeAnimationTimesamples(arr, "rotation");
1028
+ writeAnimationTimesamples(arr, "scale");
1029
+
1030
+ if (xFormOrder.length > 0) {
1031
+ const xformUnique = [...new Set(xFormOrder)];
1032
+ writer.appendLine(`uniform token[] xformOpOrder = [${xformUnique.map(x => `"${x}"`).join(', ')}]`);
1033
+ }
1034
+
1035
+ // for (let i = 0; i < arr.length; i++) {
1036
+ // const transformData = arr[i];
1037
+ // if (!transformData) continue;
1038
+ // const startTime = startTimes[i];
1039
+ // const timesArray = transformData.getSortedTimesArray();
1040
+
1041
+ // if (!timesArray || timesArray.length === 0) {
1042
+ // console.error("got an animated object but no time values?", object, transformData);
1043
+ // continue;
1044
+ // }
1045
+ // for (const { time, translation, rotation, scale } of transformData.getValues(timesArray)) {
1046
+ // composedTransform.compose(translation, rotation, scale);
1047
+
1048
+
1049
+ // const timeStr = formatter.format((startTime + time) * transformData.frameRate);
1050
+ // const line = `${timeStr}: ${buildMatrix(composedTransform)},`;
1051
+ // writer.appendLine(line);
1052
+ // }
1053
+ // }
1054
+
1055
+ // writer.indent--;
1056
+ // writer.appendLine("}");
986
1057
  }
987
1058
  }
src/engine/codegen/register_types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable */
2
2
  import { TypeStore } from "./../engine_typestore.js"
3
-
3
+
4
4
  // Import types
5
5
  import { __Ignore } from "../../engine-components/codegen/components.js";
6
6
  import { ActionBuilder } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js";
@@ -220,7 +220,7 @@
220
220
  import { XRFlag } from "../../engine-components/webxr/XRFlag.js";
221
221
  import { XRRig } from "../../engine-components/webxr/WebXRRig.js";
222
222
  import { XRState } from "../../engine-components/webxr/XRFlag.js";
223
-
223
+
224
224
  // Register types
225
225
  TypeStore.add("__Ignore", __Ignore);
226
226
  TypeStore.add("ActionBuilder", ActionBuilder);