From 27824a0de1a519f55e037a2169fa00887503cbaa Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 24 Jan 2026 17:31:01 -0600 Subject: [PATCH] collada: render animated/skinned cube --- collada/mesh.py | 103 ++++++++++++++++++++- include/collada.hpp | 2 +- models/skinned_cube/cube.DAE | 124 +++++++++++++++++++++++++ models/skinned_cube/skinned_cube.DAE | 12 +-- models/skinned_cube/skinned_cube.max | Bin 208896 -> 208896 bytes src/collada.cpp | 132 +++++++++++++++++++++++++-- src/effect/collada.fx | 14 ++- src/main.cpp | 16 ++-- 8 files changed, 375 insertions(+), 28 deletions(-) create mode 100755 models/skinned_cube/cube.DAE diff --git a/collada/mesh.py b/collada/mesh.py index a8ad141..0c64029 100644 --- a/collada/mesh.py +++ b/collada/mesh.py @@ -46,6 +46,7 @@ def mesh_vertex_buffer(collada, mesh): source.technique_common.accessor.stride for input, source in chain.from_iterable(by_offset.values()) ) + vertex_table = [] index_table = {} next_output_index = 0 index_buffer = [] @@ -55,7 +56,6 @@ def mesh_vertex_buffer(collada, mesh): for vertex_ix in range(triangles.count * 3): index_table_key = tuple(triangles.p[vertex_ix * p_stride + offset] for offset in used_offsets) - print(index_table_key) if index_table_key in index_table: index_buffer.append(index_table[index_table_key]) continue @@ -67,15 +67,15 @@ def mesh_vertex_buffer(collada, mesh): # emit vertex attributes for new output index in vertex buffer for offset in used_offsets: p_index = triangles.p[vertex_ix * p_stride + offset] + if offset == vertex_input.offset: + vertex_table.append(p_index) for input, source in by_offset[offset]: - print(input.semantic, end=" ") source_stride = source.technique_common.accessor.stride source_index = p_index * source_stride array_slice = source.array_element.floats[source_index:source_index+source_stride] - print(array_slice, end=" ") vertex_buffer.extend(array_slice) - print() + """ print("{") for i in range(triangles.count): print(", ".join(str(index_buffer[i * 3 + j]) for j in range(3)), end=",\n") @@ -85,6 +85,95 @@ def mesh_vertex_buffer(collada, mesh): print(", ".join(str(vertex_buffer[i * vertex_buffer_stride + j]) for j in range(vertex_buffer_stride)), end=",\n") print("}") + """ + # vertex table: + # list indices: (output/direct3d) vertex indices + # list values: (input/collada) vertex indices + return vertex_table + +def filter_tiny(fs, epsilon=0.00001): + return [f if abs(f) > epsilon else 0 for f in fs] + +def matrix_transpose(fs): + return ( + fs[0], fs[4], fs[8], fs[12], + fs[1], fs[5], fs[9], fs[13], + fs[2], fs[6], fs[10], fs[14], + fs[3], fs[7], fs[11], fs[15], + ) + +def matrix_print(fs): + for i, f in enumerate(fs): + print(f"{f:5.01f}f", end=", ") + if i % 4 == 3: + print() + +def skin_vertex_buffer(collada, skin, vertex_table): + inverse_bind_matrix_input, = find_semantics(skin.joints.inputs, "INV_BIND_MATRIX") + inverse_bind_matrix_source = collada.lookup(inverse_bind_matrix_input.source, types.SourceCore) + stride = inverse_bind_matrix_source.technique_common.accessor.stride + count = inverse_bind_matrix_source.technique_common.accessor.count + array = inverse_bind_matrix_source.array_element + assert type(inverse_bind_matrix_source.array_element) == types.FloatArray + assert stride == 16 + assert array.count == count * stride + + # enable to improve inverse bind matrix human-readability + #floats = filter_tiny(array.floats) + + inverse_bind_matrices = [] + print("static const float inverse_bind_matrices[] = {") + for i in range(count): + offset = stride * i + matrix = matrix_transpose(floats[offset:offset+stride]) + matrix_print(matrix) + if i + 1 < count: + print() + print("};") + + ###################################################################### + # vertex weights + ###################################################################### + max_offset = max(i.offset for i in skin.vertex_weights.inputs) + weights_input, = find_semantics(skin.vertex_weights.inputs, "WEIGHT") + weights_source = collada.lookup(weights_input.source, types.SourceCore) + joints_input, = find_semantics(skin.vertex_weights.inputs, "JOINT") + joints_source = collada.lookup(joints_input.source, types.SourceCore) + assert weights_source.technique_common.accessor.stride == 1 + assert joints_source.technique_common.accessor.stride == 1 + + vertex_weights = defaultdict(int) + + v_stride = max_offset + 1 + v_offset = 0 + vertex_influences = [] + for vcount in skin.vertex_weights.vcount: + influences = [] + for vi in range(vcount): + joint_index = skin.vertex_weights.v[v_offset + joints_input.offset] + weight_index = skin.vertex_weights.v[v_offset + weights_input.offset] + pprint(weights_source) + weight = weights_source.array_element.floats[weight_index] + influences.append((joint_index, weight)) + v_offset += v_stride + vertex_influences.append(influences) + + vertex_buffer = [] + for vertex_index in vertex_table: + influences = vertex_influences[vertex_index] + def emit(column): + for i in range(4): + if i >= len(influences): + vertex_buffer.append(0) + else: + vertex_buffer.append(influences[i][column]) + emit(0) # emit joint int4 + emit(1) # emit weight float4 + + for i, v in enumerate(vertex_buffer): + print(v, end=", ") + if i % 8 == 7: + print() if __name__ == "__main__": import sys @@ -92,4 +181,8 @@ if __name__ == "__main__": mesh = collada.library_geometries[0].geometries[0].geometric_element assert type(mesh) is types.Mesh - mesh_vertex_buffer(collada, mesh) + vertex_table = mesh_vertex_buffer(collada, mesh) + + skin = collada.library_controllers[0].controllers[0].control_element + assert type(skin) is types.Skin + skin_vertex_buffer(collada, skin, vertex_table) diff --git a/include/collada.hpp b/include/collada.hpp index 54f50b4..375990c 100644 --- a/include/collada.hpp +++ b/include/collada.hpp @@ -6,7 +6,7 @@ namespace collada { HRESULT LoadEffect(); HRESULT LoadMesh(); - void Render(); + void Render(float t); } #endif diff --git a/models/skinned_cube/cube.DAE b/models/skinned_cube/cube.DAE new file mode 100755 index 0000000..ee61974 --- /dev/null +++ b/models/skinned_cube/cube.DAE @@ -0,0 +1,124 @@ + + + + + + + + -0.5 -0.5 -0.5 + 0.5 -0.5 -0.5 + -0.5 0.5 -0.5 + 0.5 0.5 -0.5 + -0.5 -0.5 0.5 + 0.5 -0.5 0.5 + -0.5 0.5 0.5 + 0.5 0.5 0.5 + + + + + + + + + + + + 0 0 -1 + 0 0 -1 + 0 0 -1 + 0 0 -1 + 0 0 1 + 0 0 1 + 0 0 1 + 0 0 1 + 0 -1 0 + 0 -1 0 + 0 -1 0 + 0 -1 0 + 1 0 0 + 1 0 0 + 1 0 0 + 1 0 0 + 0 1 0 + 0 1 0 + 0 1 0 + 0 1 0 + -1 0 0 + -1 0 0 + -1 0 0 + -1 0 0 + + + + + + + + + + + + 0 0 0 + 1 0 0 + 0 1 0 + 1 1 0 + 0 0 0 + 1 0 0 + 0 1 0 + 1 1 0 + 0 0 0 + 1 0 0 + 0 1 0 + 1 1 0 + + + + + + + + + + + + + + + + +

+ 0 0 9 2 1 11 3 2 10 + 3 2 10 1 3 8 0 0 9 + + 4 4 8 5 5 9 7 6 11 + 7 6 11 6 7 10 4 4 8 + + 0 8 4 1 9 5 5 10 7 + 5 10 7 4 11 6 0 8 4 + + 1 12 0 3 13 1 7 14 3 + 7 14 3 5 15 2 1 12 0 + + 3 16 4 2 17 5 6 18 7 + 6 18 7 7 19 6 3 16 4 + + 2 20 0 0 21 1 4 22 3 + 4 22 3 6 23 2 2 20 0 +

+
+
+
+
+ + + + + + + + + + + +
diff --git a/models/skinned_cube/skinned_cube.DAE b/models/skinned_cube/skinned_cube.DAE index 825b3c8..542a014 100755 --- a/models/skinned_cube/skinned_cube.DAE +++ b/models/skinned_cube/skinned_cube.DAE @@ -6,8 +6,8 @@ OpenCOLLADA for 3ds Max; Version: 1.6; Revision: 68 file:///C:/cygwin/home/bilbo/d3d10/models/skinned_cube/skinned_cube.max - 2026-01-23T23:56:13 - 2026-01-23T23:56:13 + 2026-01-24T13:01:29 + 2026-01-24T13:01:29 Z_UP @@ -126,9 +126,9 @@ - 1 0 0 0 0 0 0 0 0 0.2 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.2 + 1 0.2 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.2 - + @@ -140,8 +140,8 @@ - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 0 0 1 2 0 0 1 3 0 0 1 4 0 0 1 0 0 5 1 0 0 6 1 0 0 7 1 0 0 8 1 9 0 10 1 11 0 12 1 13 0 14 1 15 0 16 1 17 0 18 1 19 0 20 1 21 0 22 1 23 0 24 1 25 0 26 1 27 0 28 1 29 0 30 1 31 0 32 1 33 0 34 1 35 0 36 1 37 0 38 1 39 0 40 + 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 2 1 3 0 4 1 5 0 6 1 7 0 8 1 9 0 10 1 11 0 12 1 13 0 14 1 15 0 16 1 17 0 18 1 19 0 20 1 21 0 22 1 23 0 24 1 25 0 26 1 27 0 28 1 29 0 30 1 31 0 32 diff --git a/models/skinned_cube/skinned_cube.max b/models/skinned_cube/skinned_cube.max index fd21ecbbaacd296c592c3da1be69405f9f193468..ab2ecc484a2a36897a368679aac6ef81cd2372b4 100755 GIT binary patch delta 4688 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 delta 4592 zcmeHJdr*|u75~otV9T3jVP#?C%E}53Be(>mBV$~o6E$Ugq+?2KC6a=Swm3{32mz$5 zk643(F&}s%@+v~(V`4BGKa)C?#@3l8O4P(OR%5Vn`pAf6CK(%T#_c)Z?!7FSY5wR; z|H$;4J-hdw^E>Zz@3-EODDOzrKt)PSiSG;Non6;JRTRaWsMV$1hg({$vyuH%(e63x zAXKZK-WcjaX_a<&dOiG5t4`g@7P+*0sdZ4SRlBx9=ka^4DUl)feLkO-V6M=-?x--@ z%s?fr)$GzvxjUT1C_=`QNUM;3g!E&i)kq|}fBd3(XUuE)-vw=HLHKcRfj9bO3d;vm zLdvbT!OQnJAZ2UX3O#KFr2dp0%;&K~;M6PLgg%I5O3Fe-IhenA-7~uVG+bnS3ZnF;5r_xq;$1hu zmfVFUQj{T_sr(ov371SU;WsE<{K5^$hV6X$tzeiEfSDw0Gs@B0(!U^VJE|Ji6vb~X zT%i_`wMLQ$yq!OH?h(H{QkpsTwffOg-#u!$`RZ%Un3WL2&32yk348=$delug6&gzU zBK^e27w6t<0lo8PdpDUi*-w6S+=4=ah%+*L#c z&T|gGn#8i><|t;ADnL=vGnY?IW~tT>5qJgZ&q&vhK0>;#KatFOLiKznyT$aMxL6z0 zA)Wcc+GeQ{x+77Y2~dXjz|y^LR-Tri3bSX#9apxc^ub7hN0=_ zkOpxS-IK!>hR?PCb=88MdB+B)e!AWhn_B02sI>i&^4}K@66D0%N{{d9*B79D{lw9p zAtj>yt*fz*c{b{=&u4Fh0n;lVWxY{sAL#KvU~Qludx9;GIBsU|!QK*<4W0bq64qr} z@!TlBRQLxaYFvQ`6>`TPn29@HWSQjCCma;2{oVUX$*%VG^^vJK>8L>6w{IWG zT-@Ep!qx8XZUTf!zZ(Y_AkRZdzR5eW_9h+KJRb?oXhj7(={u4q*N@Ruz z%Bs#fafXmiSr?PKVaHB_kLUNSE$Q^T!QTDrK!l?rRctTTn`6BlwgpG@2NeQk{8T8o zMA}8_lJ)}>hOAAgQ5zfDsHv%$WGP_gZ^Dez=+FB{n1}jfl;0y{{xRe@hV#`OJ9dzd zn?mMRpK5LQCokG&TvNnyh@O{=3Vklr92V?oa7eRHo+TAGcR%may-bBukgA zP8VU^5TGJidSfJGMdu};m^-%P%no$3bPF~;*ma;3K~T&j(=w@D51`beM~_li8J35B zd+9&fE3zZf50DH0wzRaAEZDv&qEg{2hYl90$Y3+oK;?1?qoZhimK_%CR&ZoEP^9b- z&{-hr=MV=gL%1?PMszCXM+@0Jx9Esf9UB`XQK2{saxS*1YrR`ZbVs;wTCs$|(cl^n z6=BjXSczcK@bIvX{1_QuMaHDk`Oy!~b>I?_bL|q7;8L$&zfR8FYV_M9w28nyguiN zQgwvUva+Xwo|2N14I4Jp*4APWuN>^}Xxrnh zGy1lE+*DvFnk=0!?Va=?r}YB)ndMgGetTechniqueByName("Render"); // variables + g_pJointVariable = g_pEffect->GetVariableByName("mJoint")->AsMatrix(); + g_pWorldVariable = g_pEffect->GetVariableByName("World")->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->AsMatrix(); @@ -163,6 +239,8 @@ namespace collada { {"POSITION" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0}, + {"BLENDINDICES", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, + {"BLENDWEIGHT" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D10_INPUT_PER_VERTEX_DATA, 0}, }; UINT numElements = (sizeof (layout)) / (sizeof (layout[0])); @@ -194,7 +272,19 @@ namespace collada { bd.CPUAccessFlags = 0; bd.MiscFlags = 0; initData.pSysMem = vertex_buffer; - hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffer); + hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBufferPNT); + if (FAILED(hr)) { + print("CreateBuffer: D3D10_BIND_VERTEX_BUFFER\n"); + return hr; + } + + bd.Usage = D3D10_USAGE_IMMUTABLE; + bd.ByteWidth = (sizeof (joints_weights)); + bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; + bd.CPUAccessFlags = 0; + bd.MiscFlags = 0; + initData.pSysMem = joints_weights; + hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBufferJW); if (FAILED(hr)) { print("CreateBuffer: D3D10_BIND_VERTEX_BUFFER\n"); return hr; @@ -215,20 +305,48 @@ namespace collada { return S_OK; } - void Render() + void Render(float t) { - XMMATRIX World = XMMatrixScaling(0.1, 0.1, 0.1); + XMMATRIX World = XMMatrixScaling(1, 1, 1); + + // XMMATRIX XM_CALLCONV XMMatrixRotationNormal(FXMVECTOR NormalAxis, float Angle) noexcept; + //XMConvertToRadians + XMVECTOR axis = XMVectorSet(0, 1, 0, 0); + XMVECTOR axisZ = XMVectorSet(0, 0, 1, 0); + XMMATRIX joint0 + = XMMatrixRotationNormal(axis, XMConvertToRadians(-90)) + ; + XMMATRIX joint1 + = XMMatrixRotationNormal(axisZ, sin(t)) + * XMMatrixTranslation(10, 0, 0) + * joint0 + ; + + XMMATRIX joint0ibm = XMLoadFloat4x4((XMFLOAT4X4*)&inverse_bind_matrices[0 * 16]); + XMMATRIX joint1ibm = XMLoadFloat4x4((XMFLOAT4X4*)&inverse_bind_matrices[1 * 16]); + XMMATRIX mJoints[2] = { + joint0ibm * joint0, + joint1ibm * joint1, + }; + + g_pJointVariable->SetMatrixArray((float *)mJoints, 0, 2); g_pWorldVariable->SetMatrix((float *)&World); g_pViewVariable->SetMatrix((float *)&g_View); g_pProjectionVariable->SetMatrix((float *)&g_Projection); UINT stride[] = { - 3 * 3 * 4, + 3 * 3 * 4, // position normal texture + 4 * 2 * 4, // joint weight }; - UINT offset[] = { 0 }; + UINT offset[] = { 0, 0 }; + ID3D10Buffer * vertex_buffers[] = { + g_pVertexBufferPNT, + g_pVertexBufferJW, + }; + g_pd3dDevice->IASetInputLayout(g_pVertexLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVertexBuffer, stride, offset); + g_pd3dDevice->IASetVertexBuffers(0, 2, vertex_buffers, stride, offset); g_pd3dDevice->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); diff --git a/src/effect/collada.fx b/src/effect/collada.fx index f88529e..97ed0fb 100644 --- a/src/effect/collada.fx +++ b/src/effect/collada.fx @@ -2,11 +2,15 @@ matrix World; matrix View; matrix Projection; +matrix mJoint[2]; + struct VS_INPUT { float4 Pos : POSITION; float3 Normal : NORMAL; float2 Tex : TEXCOORD0; + float4 Joint : BLENDINDICES0; + float4 Weight : BLENDWEIGHT0; }; struct PS_INPUT @@ -20,7 +24,15 @@ PS_INPUT VS(VS_INPUT input) { PS_INPUT output; - output.Pos = mul(input.Pos, World); + matrix mSkin + = input.Weight.x * mJoint[int(input.Joint.x)] + + input.Weight.y * mJoint[int(input.Joint.y)] + + input.Weight.z * mJoint[int(input.Joint.z)] + + input.Weight.w * mJoint[int(input.Joint.w)] + ; + + output.Pos = mul(input.Pos, mSkin); + output.Pos = mul(output.Pos, World); output.Pos = mul(output.Pos, View); output.Pos = mul(output.Pos, Projection); diff --git a/src/main.cpp b/src/main.cpp index 27844c4..f0f8d45 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,8 +126,8 @@ XMFLOAT4 g_vLightColors[2] = { // -XMVECTOR g_Eye = XMVectorSet(0.0f, 0.0f, -2.0f, 1.0f); -XMVECTOR g_At = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); +XMVECTOR g_Eye = XMVectorSet(0.0f, -30.0f, 15.0f, 1.0f); +XMVECTOR g_At = XMVectorSet(0.0f, 0.0f, 15.0f, 1.0f); // forward declarations @@ -1710,15 +1710,15 @@ void Update(float t, float dt) // view XMMATRIX mRotateView - = XMMatrixRotationY(deadzone(g_Joystate.thumbLX) * 3.0f * dt) - * XMMatrixRotationX(deadzone(g_Joystate.thumbLY) * 3.0f * dt); + = XMMatrixRotationX(deadzone(g_Joystate.thumbLY) * 3.0f * dt) + * XMMatrixRotationZ(deadzone(g_Joystate.thumbLX) * 3.0f * dt); XMMATRIX mTranslateView = XMMatrixTranslation(deadzone(g_Joystate.thumbRX) * 3.0f * dt, - 0.0f, - deadzone(g_Joystate.thumbRY) * 3.0f * dt); + deadzone(g_Joystate.thumbRY) * 3.0f * dt, + 0.0f); g_Eye = XMVector4Transform(g_Eye, mTranslateView * mRotateView); - XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); + XMVECTOR Up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); g_View = XMMatrixLookAtLH(g_Eye, g_At, Up); @@ -1827,7 +1827,7 @@ void Render(float t, float dt) RenderFont(dt); - collada::Render(); + collada::Render(t); // present g_pSwapChain->Present(0, 0);