diff --git a/include/collada_scene.hpp b/include/collada_scene.hpp index 63a0ccd..7bfdf35 100644 --- a/include/collada_scene.hpp +++ b/include/collada_scene.hpp @@ -26,14 +26,12 @@ namespace collada_scene { }; struct scene_state { - const UINT m_numBuffers = 1; // FIXME - const UINT m_strides[1] = {3 * 3 * 4}; // FIXME - const UINT m_offsets[1] = {0}; // FIXME - - ID3D10Buffer * m_pVertexBuffers[1] = {}; // FIXME + ID3D10Buffer * m_pVertexBuffers[2] = { NULL, NULL }; ID3D10Buffer * m_pIndexBuffer = NULL; ID3D10InputLayout ** m_pVertexLayouts = NULL; + ID3D10InputLayout ** m_pSkinnedVertexLayouts = NULL; + UINT * m_iVertexLayoutStrides = NULL; node_instance * m_nodeInstances = NULL; @@ -70,16 +68,22 @@ namespace collada_scene { int const instance_materials_count); void render_instance_geometries(collada::instance_geometry const * const instance_geometries, int const instance_geometries_count); + void render_skin(collada::skin const& skin, + collada::instance_material const * const instance_materials, + int const instance_materials_count); void render_instance_controllers(collada::instance_controller const * const instance_controllers, int const instance_controllers_count); - void set_material(collada::effect const& effect); + void set_instance_material(collada::instance_material const& instance_material); void set_color_or_texture(collada::color_or_texture const& color_or_texture, ID3D10EffectVectorVariable * pVectorVariable, ID3D10EffectShaderResourceVariable * pShaderResourceVariable); }; HRESULT LoadEffect(); - HRESULT LoadLayout(collada::inputs const& inputs, ID3D10InputLayout ** ppVertexLayout); + HRESULT LoadLayout(collada::inputs const& inputs, + ID3D10InputLayout ** ppVertexLayout, + ID3D10InputLayout ** ppSkinnedVertexLayout, + UINT * iVertexLayoutStride); HRESULT LoadVertexBuffer(LPCWSTR name, ID3D10Buffer ** ppVertexBuffer); HRESULT LoadIndexBuffer(LPCWSTR name, ID3D10Buffer ** ppIndexBuffer); } diff --git a/src/collada_scene.cpp b/src/collada_scene.cpp index 9bd88a2..29378a9 100644 --- a/src/collada_scene.cpp +++ b/src/collada_scene.cpp @@ -49,18 +49,20 @@ namespace collada_scene { case input_format::FLOAT2: return DXGI_FORMAT_R32G32_FLOAT; case input_format::FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT; case input_format::FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case input_format::INT4: return DXGI_FORMAT_R32G32B32A32_SINT; default: assert(false); } } - static inline int format_size(input_format format) + static inline UINT format_size(input_format format) { switch (format) { case input_format::FLOAT1: return 1 * 4; case input_format::FLOAT2: return 2 * 4; case input_format::FLOAT3: return 3 * 4; case input_format::FLOAT4: return 4 * 4; + case input_format::INT4: return 4 * 4; default: assert(false); } @@ -71,9 +73,14 @@ namespace collada_scene { HRESULT hr; m_pVertexLayouts = New(m_descriptor->inputs_list_count); + m_pSkinnedVertexLayouts = New(m_descriptor->inputs_list_count); + m_iVertexLayoutStrides = New(m_descriptor->inputs_list_count); for (int i = 0; i < m_descriptor->inputs_list_count; i++) { - hr = LoadLayout(m_descriptor->inputs_list[i], &m_pVertexLayouts[i]); + hr = LoadLayout(m_descriptor->inputs_list[i], + &m_pVertexLayouts[i], + &m_pSkinnedVertexLayouts[i], + &m_iVertexLayoutStrides[i]); if (FAILED(hr)) return hr; } @@ -203,6 +210,10 @@ namespace collada_scene { if (FAILED(hr)) return E_FAIL; + hr = LoadVertexBuffer(L"RES_MODELS_CURVE_INTERPOLATION_VJW", &m_pVertexBuffers[1]); + if (FAILED(hr)) + return E_FAIL; + hr = LoadIndexBuffer(L"RES_MODELS_CURVE_INTERPOLATION_IDX", &m_pIndexBuffer); if (FAILED(hr)) return E_FAIL; @@ -217,14 +228,34 @@ namespace collada_scene { return S_OK; } - HRESULT LoadLayout(inputs const& inputs, ID3D10InputLayout ** ppVertexLayout) + input_element const input_elements_blendindices_0_4_blendweight_0_4[] = { + { + .semantic = "BLENDINDICES", + .semantic_index = 0, + .format = input_format::INT4, + }, + { + .semantic = "BLENDWEIGHT", + .semantic_index = 0, + .format = input_format::FLOAT4, + }, + }; + + inputs const skin_inputs = { + .elements = input_elements_blendindices_0_4_blendweight_0_4, + .elements_count = 2, + }; + + HRESULT LoadLayout(inputs const& inputs, + ID3D10InputLayout ** ppVertexLayout, + ID3D10InputLayout ** ppSkinnedVertexLayout, + UINT * iVertexLayoutStride) { HRESULT hr; - D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count]; + D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count + 2]; - assert(inputs.elements_count == 3); - int byte_offset = 0; + UINT byte_offset = 0; for (int i = 0; i < inputs.elements_count; i++) { layout[i].SemanticName = inputs.elements[i].semantic; layout[i].SemanticIndex = inputs.elements[i].semantic_index; @@ -236,6 +267,7 @@ namespace collada_scene { byte_offset += format_size(inputs.elements[i].format); } + *iVertexLayoutStride = byte_offset; D3D10_PASS_DESC passDesc; g_pTechniqueBlinn->GetPassByIndex(0)->GetDesc(&passDesc); @@ -249,6 +281,33 @@ namespace collada_scene { return hr; } + ////////////////////////////////////////////////////////////////////// + // skinned layout + ////////////////////////////////////////////////////////////////////// + + UINT skin_byte_offset = 0; + for (int i = 0; i < skin_inputs.elements_count; i++) { + int ix = inputs.elements_count + i; + layout[ix].SemanticName = skin_inputs.elements[i].semantic; + layout[ix].SemanticIndex = skin_inputs.elements[i].semantic_index; + layout[ix].Format = dxgi_format(skin_inputs.elements[i].format); + layout[ix].InputSlot = 0; + layout[ix].AlignedByteOffset = skin_byte_offset; + layout[ix].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA; + layout[ix].InstanceDataStepRate = 0; + + skin_byte_offset += format_size(skin_inputs.elements[i].format); + } + + hr = g_pd3dDevice->CreateInputLayout(layout, inputs.elements_count + skin_inputs.elements_count, + passDesc.pIAInputSignature, + passDesc.IAInputSignatureSize, + ppSkinnedVertexLayout); + if (FAILED(hr)) { + print("CreateInputLayout\n"); + return hr; + } + return S_OK; } @@ -392,8 +451,9 @@ namespace collada_scene { } } - void scene_state::set_material(effect const& effect) + void scene_state::set_instance_material(instance_material const& instance_material) { + effect const& effect = *instance_material.material->effect; switch (effect.type) { case effect_type::BLINN: set_color_or_texture(effect.blinn.emission, g_pEmissionVariable, g_pTexEmissionVariable); @@ -420,6 +480,14 @@ namespace collada_scene { default: break; } + + int texture_channels[4] = { + instance_material.emission.input_set, + instance_material.ambient.input_set, + instance_material.diffuse.input_set, + instance_material.specular.input_set, + }; + g_pTextureChannelVariable->SetIntVector(texture_channels); } void scene_state::render_geometry(geometry const& geometry, @@ -427,10 +495,6 @@ namespace collada_scene { int const instance_materials_count) { mesh const& mesh = geometry.mesh; - - UINT strides[1] = { 3 * 3 * 4 }; - UINT offsets[1] = { (UINT)mesh.vertex_buffer_offset }; - g_pd3dDevice->IASetVertexBuffers(0, m_numBuffers, m_pVertexBuffers, strides, offsets); g_pd3dDevice->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, mesh.index_buffer_offset); D3D10_TECHNIQUE_DESC techDesc; @@ -439,17 +503,43 @@ namespace collada_scene { for (int j = 0; j < instance_materials_count; j++) { instance_material const& instance_material = instance_materials[j]; triangles const& triangles = mesh.triangles[instance_material.element_index]; - set_material(*instance_material.material->effect); - int texture_channels[4] = { - instance_material.emission.input_set, - instance_material.ambient.input_set, - instance_material.diffuse.input_set, - instance_material.specular.input_set, - }; - g_pTextureChannelVariable->SetIntVector(texture_channels); + + set_instance_material(instance_material); + + UINT numBuffers = 1; + UINT offsets[1] = { (UINT)mesh.vertex_buffer_offset }; + UINT strides[1] = { m_iVertexLayoutStrides[triangles.inputs_index] }; + g_pd3dDevice->IASetVertexBuffers(0, numBuffers, m_pVertexBuffers, strides, offsets); + g_pd3dDevice->IASetInputLayout(m_pVertexLayouts[triangles.inputs_index]); + + g_pTechniqueBlinn->GetPassByIndex(0)->Apply(0); + g_pd3dDevice->DrawIndexed(triangles.count * 3, triangles.index_offset, 0); + } + } + + void scene_state::render_skin(skin const& skin, + instance_material const * const instance_materials, + int const instance_materials_count) + { + mesh const& mesh = skin.geometry->mesh; + g_pd3dDevice->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, mesh.index_buffer_offset); + + D3D10_TECHNIQUE_DESC techDesc; + g_pTechniqueBlinn->GetDesc(&techDesc); + + for (int j = 0; j < instance_materials_count; j++) { + instance_material const& instance_material = instance_materials[j]; + triangles const& triangles = mesh.triangles[instance_material.element_index]; + + set_instance_material(instance_material); + + UINT numBuffers = 2; + UINT offsets[2] = { (UINT)mesh.vertex_buffer_offset, (UINT)skin.vertex_buffer_offset }; + UINT strides[2] = { m_iVertexLayoutStrides[triangles.inputs_index], 2 * 4 * 4 }; + g_pd3dDevice->IASetVertexBuffers(0, numBuffers, m_pVertexBuffers, strides, offsets); + g_pd3dDevice->IASetInputLayout(m_pSkinnedVertexLayouts[triangles.inputs_index]); g_pTechniqueBlinn->GetPassByIndex(0)->Apply(0); - g_pd3dDevice->IASetInputLayout(m_pVertexLayouts[triangles.inputs_index]); g_pd3dDevice->DrawIndexed(triangles.count * 3, triangles.index_offset, 0); } } @@ -459,9 +549,7 @@ namespace collada_scene { { for (int i = 0; i < instance_geometries_count; i++) { instance_geometry const &instance_geometry = instance_geometries[i]; - geometry const& geometry = *instance_geometry.geometry; - - render_geometry(geometry, + render_geometry(*instance_geometry.geometry, instance_geometry.instance_materials, instance_geometry.instance_materials_count); } @@ -472,11 +560,9 @@ namespace collada_scene { { for (int i = 0; i < instance_controllers_count; i++) { instance_controller const &instance_controller = instance_controllers[i]; - geometry const& geometry = *instance_controller.controller->skin.geometry; - - render_geometry(geometry, - instance_controller.instance_materials, - instance_controller.instance_materials_count); + render_skin(instance_controller.controller->skin, + instance_controller.instance_materials, + instance_controller.instance_materials_count); } }