* Parse skeleton/skin data
(json: GLTFJson, buffers: ArrayBuffer[])
| 898 | * Parse skeleton/skin data |
| 899 | */ |
| 900 | private parseSkeleton(json: GLTFJson, buffers: ArrayBuffer[]): ISkeletonData | undefined { |
| 901 | if (!json.skins || json.skins.length === 0) return undefined; |
| 902 | |
| 903 | // Use first skin |
| 904 | const skin = json.skins[0]; |
| 905 | const joints: ISkeletonJoint[] = []; |
| 906 | |
| 907 | // Load inverse bind matrices |
| 908 | let inverseBindMatrices: Float32Array | null = null; |
| 909 | if (skin.inverseBindMatrices !== undefined) { |
| 910 | const ibmData = this.getAccessorData(json, buffers, skin.inverseBindMatrices); |
| 911 | inverseBindMatrices = new Float32Array(ibmData.data.buffer, (ibmData.data as Float32Array).byteOffset, ibmData.count * 16); |
| 912 | } |
| 913 | |
| 914 | // Build joint hierarchy |
| 915 | const jointIndexMap = new Map<number, number>(); |
| 916 | for (let i = 0; i < skin.joints.length; i++) { |
| 917 | jointIndexMap.set(skin.joints[i], i); |
| 918 | } |
| 919 | |
| 920 | for (let i = 0; i < skin.joints.length; i++) { |
| 921 | const nodeIndex = skin.joints[i]; |
| 922 | const node = json.nodes![nodeIndex]; |
| 923 | |
| 924 | // Find parent |
| 925 | let parentIndex = -1; |
| 926 | for (const [idx, jointIdx] of jointIndexMap) { |
| 927 | if (jointIdx !== i) { |
| 928 | const parentNode = json.nodes![idx]; |
| 929 | if (parentNode.children?.includes(nodeIndex)) { |
| 930 | parentIndex = jointIdx; |
| 931 | break; |
| 932 | } |
| 933 | } |
| 934 | } |
| 935 | |
| 936 | const ibm = new Float32Array(16); |
| 937 | if (inverseBindMatrices) { |
| 938 | for (let j = 0; j < 16; j++) { |
| 939 | ibm[j] = inverseBindMatrices[i * 16 + j]; |
| 940 | } |
| 941 | } else { |
| 942 | // Identity matrix |
| 943 | ibm[0] = ibm[5] = ibm[10] = ibm[15] = 1; |
| 944 | } |
| 945 | |
| 946 | joints.push({ |
| 947 | name: node.name || `Joint_${i}`, |
| 948 | nodeIndex, |
| 949 | parentIndex, |
| 950 | inverseBindMatrix: ibm |
| 951 | }); |
| 952 | } |
| 953 | |
| 954 | // Find root joint |
| 955 | let rootJointIndex = 0; |
| 956 | for (let i = 0; i < joints.length; i++) { |
| 957 | if (joints[i].parentIndex === -1) { |
no test coverage detected