From 744fd75192258ce7d1a66be0b0647ad92f9e4320 Mon Sep 17 00:00:00 2001 From: Brooks Palin Date: Fri, 29 Dec 2023 11:33:17 -0700 Subject: [PATCH] Stablized bvh representation --- package-lock.json | 538 ++++++++++++++++++++++++++++++++++++++- studio-bvh/src/joint.rs | 94 +++++-- studio/src/bvh/loader.rs | 76 +++--- studio/src/bvh/mod.rs | 127 ++++++++- studio/src/debug.rs | 26 +- studio/src/scene.rs | 70 ++--- 6 files changed, 820 insertions(+), 111 deletions(-) diff --git a/package-lock.json b/package-lock.json index b8d9010..8a80778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2684,6 +2684,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", @@ -2691,9 +2702,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -4304,6 +4315,28 @@ "@types/chai": "*" } }, + "node_modules/@types/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", @@ -4526,6 +4559,181 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -4597,6 +4805,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", @@ -5276,6 +5494,16 @@ "fsevents": "~2.3.2" } }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -5378,6 +5606,13 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5905,6 +6140,20 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -5958,6 +6207,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true, + "peer": true + }, "node_modules/esbuild": { "version": "0.17.19", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", @@ -6013,6 +6269,30 @@ "node": ">=0.8.0" } }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -6038,6 +6318,19 @@ "node": ">=0.10" } }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -6068,6 +6361,16 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6424,6 +6727,13 @@ "node": ">= 6" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -7293,6 +7603,37 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -7455,6 +7796,16 @@ "@types/trusted-types": "^2.0.2" } }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/loader-utils": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", @@ -7637,6 +7988,13 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "dev": true }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7788,6 +8146,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -8520,6 +8885,16 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -8928,6 +9303,16 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -9291,6 +9676,16 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -9307,6 +9702,71 @@ "node": ">=6" } }, + "node_modules/terser": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -10039,6 +10499,20 @@ "node": ">=14" } }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -10057,6 +10531,64 @@ "node": ">=12" } }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", diff --git a/studio-bvh/src/joint.rs b/studio-bvh/src/joint.rs index b0612de..bb960e2 100644 --- a/studio-bvh/src/joint.rs +++ b/studio-bvh/src/joint.rs @@ -8,7 +8,7 @@ use std::{ ffi::{CStr, CString}, fmt, mem, ops::{Deref, DerefMut}, - str, + str, collections::VecDeque, net, }; /// A 3-element point representing the location of a joint offset or @@ -397,12 +397,16 @@ impl fmt::Debug for JointPrivateData { } } +pub(crate) enum JointIterType { + All(usize), + Sequence(VecDeque) +} + /// An iterator over the `Joint`s of a `Bvh` skeleton. pub struct Joints<'a> { pub(crate) joints: &'a [JointData], // pub(crate) motion_values: &'a [f32], - pub(crate) current_joint: usize, - pub(crate) from_child: Option, + pub(crate) iter_type: JointIterType, } impl fmt::Debug for Joints<'_> { @@ -418,8 +422,15 @@ impl<'a> Joints<'a> { Joints { joints, // clips, - current_joint: 0, - from_child: None, + iter_type: JointIterType::All(0), + } + } + + pub(crate) const fn iter_from(joints: &'a [JointData], start : usize) -> Self { + Joints { + joints, + // clips, + iter_type: JointIterType::All(start), } } @@ -431,24 +442,25 @@ impl<'a> Joints<'a> { /// need to iterate through to the end sites of all children, you will /// need to continually call `iter_children` on each `Joint` in the iterator. pub(crate) fn iter_children(joint: &Joint<'a>) -> Self { - let first_child = joint + let first_child : VecDeque = joint .joints .iter() - .find(|jd| { + .filter(|jd| { if let Some(p) = jd.private_data() { p.parent_index == joint.index } else { false } }) - .map(JointData::index) - .unwrap(); + .map(|value| value.index()) + .collect(); + // .map(JointData::index) + // .unwrap(); Joints { joints: joint.joints, // clips: joint.clips, - current_joint: joint.data().index(), - from_child: Some(first_child), + iter_type: JointIterType::Sequence(first_child), } } @@ -472,22 +484,58 @@ impl<'a> Joints<'a> { impl<'a> Iterator for Joints<'a> { type Item = Joint<'a>; fn next(&mut self) -> Option { - if self.current_joint >= self.joints.len() { - return None; + match &mut self.iter_type { + JointIterType::All(mut current) => { + if current >= self.joints.len() { + return None; + } + + let joint = Some(Joint { + index: current, + joints: self.joints, + }); + + current += 1; + joint + }, + JointIterType::Sequence(ref mut joints) => { + let Some(next) = joints.pop_front() + else { return None }; + + if next >= self.joints.len() { + return None; + } + + Some(Joint { + index: next, + joints: self.joints, + }) + }, } - let joint = Some(Joint { - index: self.current_joint, - joints: self.joints, - }); - if self.from_child.is_none() { - self.current_joint += 1; - } else { - unimplemented!() - } + // if self.current_joint >= self.joints.len() { + // return None; + // } - joint + // let joint = Some(Joint { + // index: self.current_joint, + // joints: self.joints, + // }); + + // // if let Some(from_child) = self.from_child { + + // // } else { + // // self.current_joint += 1; + // // } + + // // if self.from_child.is_none() { + // self.current_joint += 1; + // // } else { + // // return None + // // } + + // joint } } diff --git a/studio/src/bvh/loader.rs b/studio/src/bvh/loader.rs index 4df8c49..9b22d4a 100644 --- a/studio/src/bvh/loader.rs +++ b/studio/src/bvh/loader.rs @@ -6,7 +6,7 @@ use bevy::{ use super::{ error::{Anyhow, Error}, - Bvh, BvhJoint, + Bvh, }; #[derive(Default)] @@ -26,22 +26,24 @@ impl AssetLoader for BvhLoader { Box::pin(async move { let mut buf = vec![]; reader.read_to_end(&mut buf).await.anyhow()?; + let bvh = studio_bvh::from_bytes(&buf).anyhow()?; // FIXME: This is algorithmically terrible - let bvh = studio_bvh::from_bytes(&buf).anyhow()?; - let all_joints = bvh.joints().map(|j| j.data().clone()).collect::>(); - let joints = bvh - .joints() - .filter_map(|joint| { - if joint.is_root() { - Some(joint.data().clone().into_bvh_joint(&all_joints)) - } else { - None - } - }) - .collect(); + // let all_joints = bvh.joints().map(|j| j.data().clone()).collect::>(); + // let joints = bvh + // .joints() + // .filter_map(|joint| { + // if joint.is_root() { + // Some(joint.data().clone().into_bvh_joint(&all_joints)) + // } else { + // None + // } + // }) + // .collect(); - Ok(Bvh { joints }) + // bvh.frame_cursor(). + + Ok(Bvh(bvh)) }) } @@ -50,27 +52,27 @@ impl AssetLoader for BvhLoader { } } -trait IntoBvhJoint: Sized { - fn into_bvh_joint(self, data: &[Self]) -> BvhJoint; -} +// trait IntoBvhJoint: Sized { +// fn into_bvh_joint(self, data: &[Self]) -> BvhJoint; +// } -impl IntoBvhJoint for studio_bvh::JointData { - fn into_bvh_joint(self, data: &[Self]) -> BvhJoint { - BvhJoint { - name: String::from_utf8_lossy(self.name()).into(), - transform: Transform::from_translation((*self.offset()).into()), - children: data - .iter() - .filter_map(|joint| { - joint.parent_index().and_then(|idx| { - if idx == self.index() { - Some(joint.clone().into_bvh_joint(data)) - } else { - None - } - }) - }) - .collect(), - } - } -} +// impl IntoBvhJoint for studio_bvh::JointData { +// fn into_bvh_joint(self, data: &[Self]) -> BvhJoint { +// BvhJoint { +// name: String::from_utf8_lossy(self.name()).into(), +// transform: Transform::from_translation((*self.offset()).into()), +// children: data +// .iter() +// .filter_map(|joint| { +// joint.parent_index().and_then(|idx| { +// if idx == self.index() { +// Some(joint.clone().into_bvh_joint(data)) +// } else { +// None +// } +// }) +// }) +// .collect(), +// } +// } +// } diff --git a/studio/src/bvh/mod.rs b/studio/src/bvh/mod.rs index 7753a97..a4a68db 100644 --- a/studio/src/bvh/mod.rs +++ b/studio/src/bvh/mod.rs @@ -1,4 +1,5 @@ -use bevy::prelude::*; +use bevy::{prelude::*, ecs::system::{Command, EntityCommands}, asset::AsyncReadExt}; +use studio_bvh::joint; mod error; mod loader; @@ -10,21 +11,123 @@ pub struct BvhPlugin; impl Plugin for BvhPlugin { fn build(&self, app: &mut App) { app.init_asset::() - .init_asset::() .register_asset_loader(BvhLoader); } } -#[derive(Asset, TypePath, Debug)] -pub struct Bvh { - pub joints: Vec, +//============================================================================== +// Bvh Asset +//============================================================================== + +#[derive(Clone, Debug, Default, Asset, TypePath)] +pub struct Bvh(studio_bvh::Bvh); + +//============================================================================== +// Bvh Anim Component +//============================================================================== + +#[derive(Component, Debug)] +pub struct BvhAnim { + pub bvh : Handle, + pub frame : usize, } -#[derive(Asset, TypePath, Debug, Clone)] -pub struct BvhJoint { - pub name: String, - /// Local transform - pub transform: Transform, - /// Direct children of this joint - pub children: Vec, +//============================================================================== +// Bvh Anim Component +//============================================================================== + +#[derive(Debug, Component)] +pub struct BvhJoint; + +//============================================================================== +// Commands Plugin +//============================================================================== + +pub trait CommandsSpawnBvhExt { + fn spawn_bvh(&mut self, asset : &Handle) -> Entity; + + fn spawn_bvh_with_transform(&mut self, asset : &Handle, transform : Transform) -> Entity; } + +impl <'w, 's> CommandsSpawnBvhExt for Commands<'w, 's> { + fn spawn_bvh(&mut self, asset : &Handle) -> Entity { + let entity = self.spawn_empty().id(); + self.add(SpawnBvhCommand(entity, 1.0, asset.clone())); + + self.entity(entity).insert(BvhAnim { + bvh : asset.clone(), + frame : 0, + }); + entity + } + + fn spawn_bvh_with_transform(&mut self, asset : &Handle, transform : Transform) -> Entity { + let entity = self.spawn_empty().id(); + self.add(SpawnBvhCommand(entity, 1.0, asset.clone())); + + self.entity(entity).insert(( + BvhAnim { + bvh : asset.clone(), + frame : 0, + }, + transform + )); + entity + } +} + +pub struct SpawnBvhCommand(Entity, f32, Handle); + +impl Command for SpawnBvhCommand { + fn apply(self, world: &mut World) { + let bvh = { + let Some(bvh) = world.get_resource::>().unwrap().get(self.2) + else { panic!("Could not create the BVH entity because the bvh file has not been loaded yet") }; + + bvh.clone() + }; + + let Some(root) = bvh.0.root_joint() + else { panic!("Could not create the BVH entity because the bvh file has no root joint") }; + + spawn_bvh_recursive(world, &self.0, root); + } +} + +//============================================================================== +// Utility Functions +//============================================================================== + +// fn spawn_bvh(commands : &mut Commands, asset : Handle, assets : &Res>) -> Option { +// let Some(root) = bvh.0.root_joint() +// else { return None; }; + +// let tree = spawn_bvh_recursive(commands, &bvh.0, root); + +// // commands.entity(tree).insert(BvhAnim { +// // bvh : bvh.id(), +// // frame : 0, +// // } + +// // Some() +// } + +fn spawn_bvh_recursive(world : &mut World, entity : &Entity, joint : studio_bvh::Joint) { + let offset = joint.data().offset(); + let transform = Transform::from_xyz(offset[0], offset[1], offset[2]); + + // Save the name of the joint + let name = String::from_utf8_lossy(joint.data().name()).to_string(); + + world.entity_mut(*entity).insert(( + SpatialBundle::from_transform(transform), + BvhJoint, + Name::new(name) + )); + + for child in joint.children() { + let mut child_entity = world.spawn_empty().id(); + spawn_bvh_recursive(world, &child_entity, child); + world.entity_mut(*entity).push_children(&[child_entity]); + }; +} \ No newline at end of file diff --git a/studio/src/debug.rs b/studio/src/debug.rs index d89541c..8d8a64c 100644 --- a/studio/src/debug.rs +++ b/studio/src/debug.rs @@ -2,13 +2,14 @@ use std::fmt; use bevy::{prelude::*, window::PrimaryWindow}; use bevy_inspector_egui::quick::WorldInspectorPlugin; -use bevy_mod_picking::debug::DebugPickingMode; +use bevy_mod_picking::debug::{DebugPickingMode, self}; +use bevy_rapier3d::na::Quaternion; use crate::{ camera_controller::{CameraController, CameraMotionSystem}, input::{Action, InputAction, Lifecycle}, scene::SkeletalJoint, - MainCamera, + MainCamera, bvh::BvhJoint, }; #[derive(Resource, Deref, DerefMut)] @@ -36,6 +37,7 @@ impl Plugin for DebugPlugin { .add_systems( Update, ( + debug_bvh_model, toggle_debug_mode, update_debug_picking_mode.run_if(resource_changed::()), update_gizmo_line_thickness, @@ -47,6 +49,26 @@ impl Plugin for DebugPlugin { } } +fn debug_bvh_model( + mut gizmos: Gizmos, + bvh_joints : Query<(&GlobalTransform, Option<&Children>), With>, + debug_mode : Res, +) { + if debug_mode.0 { + for (transform, children) in bvh_joints.iter() { + gizmos.sphere(transform.translation(), Quat::IDENTITY, 0.01, Color::TEAL); + + if let Some(children) = children { + for child in children.iter() { + if let Ok((child_transform, _)) = bvh_joints.get(child.clone()) { + gizmos.line(transform.translation(), child_transform.translation(), Color::RED); + } + } + } + } + } +} + fn toggle_debug_mode(mut input: EventReader, mut r_debug: ResMut) { if input .read() diff --git a/studio/src/scene.rs b/studio/src/scene.rs index 8c25223..8b8b2e9 100644 --- a/studio/src/scene.rs +++ b/studio/src/scene.rs @@ -17,7 +17,7 @@ use bevy::{ use wasm_bindgen::prelude::wasm_bindgen; use crate::{ - bvh::{Bvh, BvhJoint}, + bvh::{Bvh, BvhJoint, CommandsSpawnBvhExt}, camera_controller::{CameraController, CameraControllerBundle}, debug::DebugPoint, math::{Combinable, Extrema}, @@ -155,52 +155,54 @@ fn initialize(mut cmd: Commands, r_assets: Res) { // TODO fn spawn_test_bvh( - mut cmd: Commands, + mut commands: Commands, mut er_bvh_events: EventReader>, r_bvh: Res, - ra_bvh: Res>, ) { for event in er_bvh_events.read() { if matches!(event, AssetEvent::LoadedWithDependencies { .. }) { - let bvh = ra_bvh.get(&**r_bvh).unwrap(); - for joint in bvh.joints.iter() { - let scale = Vec3::splat(0.01); - let offset = vec3(0., 0.849, -0.024); + commands.spawn_bvh_with_transform(&r_bvh.0, Transform::from_scale(Vec3::splat(0.01)).with_translation(Vec3::new(0., 0.849, -0.024))); - let mut parent = cmd.spawn(( - Name::new("BVH Skeleton"), - SpatialBundle::from_transform(Transform { - rotation: default(), - translation: offset, - scale, - }), - )); - let parent_ent = parent.id(); + info!("SPAWNED BVH") + // let bvh = ra_bvh.get(&**r_bvh).unwrap(); + // for joint in bvh.joints.iter() { + // let scale = Vec3::splat(0.01); + // let offset = vec3(0., 0.849, -0.024); - spawn_joint(parent.commands(), joint, Some(parent_ent)); - } + // let mut parent = cmd.spawn(( + // Name::new("BVH Skeleton"), + // SpatialBundle::from_transform(Transform { + // rotation: default(), + // translation: offset, + // scale, + // }), + // )); + // let parent_ent = parent.id(); + + // spawn_joint(parent.commands(), joint, Some(parent_ent)); + // } } } } -// TODO -fn spawn_joint(cmd: &mut Commands, joint: &BvhJoint, parent: Option) { - let mut spawned = cmd.spawn(( - Name::new(joint.name.clone()), - SpatialBundle::from_transform(joint.transform), - SceneElement, - SkeletalJoint(Color::CYAN), - )); - let spawned_ent = spawned.id(); +// // TODO +// fn spawn_joint(cmd: &mut Commands, joint: &BvhJoint, parent: Option) { +// let mut spawned = cmd.spawn(( +// Name::new(joint.name.clone()), +// SpatialBundle::from_transform(joint.transform), +// SceneElement, +// SkeletalJoint(Color::CYAN), +// )); +// let spawned_ent = spawned.id(); - if let Some(parent) = parent { - spawned.set_parent(parent); - } +// if let Some(parent) = parent { +// spawned.set_parent(parent); +// } - for child in joint.children.iter() { - spawn_joint(spawned.commands(), child, Some(spawned_ent)); - } -} +// for child in joint.children.iter() { +// spawn_joint(spawned.commands(), child, Some(spawned_ent)); +// } +// } fn init_scene_loading( mut cmd: Commands,