Skip to content

ModelMeshPart

Chuck Walbourn edited this page Jan 21, 2022 · 22 revisions
DirectXTK Model

This class is part of the Model hierarchy. The purpose of this class is to be container for a 'submesh' which is referenced by an instance of the ModelMesh class. A 'submesh' is a portion of a mesh that is all drawn using the same 'material' settings. A submesh is drawn in a single Direct3D 12 Draw call using a single effect.

Note that ModelMesh uses a collection of std::unique_ptr instances to ModelMeshPart since submeshes are not typically shared between mesh instances. Submeshes can easily share Direct3D 12 resources (index buffers and vertex buffers).

Header

#include <Model.h>

Initialization

ModelMeshPart instances are typically created by a Model loader along with the ModelMesh instances that contain the submeshes.

Type aliases

  • ModelMeshPart::Collection is an alias for std::vector<std::unique_ptr<ModelMeshPart>>.

  • ModelMeshPart::DrawCallback is an alias for std::function<void(_In_ ID3D12GraphicsCommandList* commandList, _In_ const ModelMeshPart& part)>.

  • ModelMeshPart::InputLayoutCollection is an alias for std::vector<D3D12_INPUT_ELEMENT_DESC>.

Data

All members of ModelMeshPart are public to facilitate writing custom model loaders and sophisticated rendering solutions. Care should be taken whenever modifying any of these elements as they have interdependencies, and can ultimately be referenced by numerous instances of Model via shared ModelMesh instances.

  • partIndex - Unique index used for creating effects (i.e. indexes std::vector<std::shared_ptr<DirectX::IEffect>> when drawing).

  • materialIndex - An index into the Model material metadata used for creating effects.

  • indexCount - Number of indices in the index buffer associated with this submesh. This is used as the first parameter to Direct3D12's DrawIndexedInstanced method.

  • startIndex - The index to start drawing with for this submesh. This facilitates sharing index buffers between multiple submeshes. This is used as the third parameter to Direct3D12's DrawIndexedInstanced method.

  • indexFormat - Format of the index buffer. For 16-bit index buffers, this is set to DXGI_FORMAT_R16_UINT. For 32-bit index buffers, this is set to DXGI_FORMAT_R32_UINT. This is used when calling Direct3D12's IASetIndexBuffer method.

  • indexBufferSize - Size of the index buffer. This is used when calling Direct3D12's IASetIndexBuffer method.

  • indexBuffer - GraphicsMemory shared smart-pointer to the index buffer associated with this submesh. This is used when calling Direct3D 12's IASetIndexBuffer method. This index buffer can be shared by multiple submeshes or even other meshes. indexBuffer.Size() should match indexBufferSize.

  • staticIndexBuffer - This is a Direct3D 12 resource object for the index buffer associated with this submesh. If set, then this should be used when calling Direct3D12's IASetIndexBuffer method instead of indexBuffer.

Either indexBuffer or staticIndexBuffer must be set. Model loaders typically load indexBuffer. You can use Model LoadStaticBuffers to create the static version.

  • vertexOffset - base vertex location which is added to each index in the index buffer before referencing the vertex buffer. This facilitates sharing of vertex buffers between multiple submeshes. This is used as the fourth parameter to Direct3D12's DrawIndexedInstanced method. vertexBuffer.Size() should match vertexBufferSize.

  • vertexStride - Stride in bytes for each vertex in the vertex buffer associated with this submesh. This is used when calling Direct3D 12's IASetVertexBuffers method.

  • vertexCount - Number of vertices in the vertex buffer associated with this submesh. This is optional metadata and can be 0 if unknown.

  • vertexBufferSize - Size of the vertex buffer. This is used when calling Direct3D12's IASetVertexBuffers method.

  • vertexBuffer - GraphicsMemory shared smart-pointer to the vertex buffer memory associated with this submesh. This is used when calling Direct3D 12's IASetVertexBuffers method. This vertex buffer can be shared by multiple submeshes or even other meshes. vertexBuffer.Size() should match vertexBufferSize.

  • staticVertexBuffer - This is a Direct3D 12 resource object for the vertex buffer associated with this submesh. If set, then this should be used when calling Direct3D12's IASetVertexBuffers method instead of vertexBuffer.

Either vertexBuffer or staticVertexBuffer must be set. Model loaders typically load vertexBuffer. You can use Model LoadStaticBuffers to create the static version.

  • primitiveType - Topology for the primitives in the submesh. It is usually set to D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST with each three indices in the index buffer forming a triangle. This is used when calling Direct3D 12's IASetPrimitiveTopology method.

Simple drawing

Use the Model::Draw function which will call ModelMesh::DrawMeshParts on all the meshes it contains, which in turn will call ModelMeshPart::Draw on each submesh part. There are also Model::DrawOpaque and Model::DrawAlpha functions will also call ModelMeshPart::Draw.

Advanced drawing

The ModelMeshPart::Draw method is used to draw each individual submesh. ModelMeshPart::Draw can be used to implement complex 'scene graph' policies (such as sorting all ModelMeshPart instance in a scene by Effects to minimize draw overhead or rough-sorting by bounding volume front-to-back for opaque parts and back-to-front for alpha blended parts), or can be used to temporarily override the effect instance being used to draw the mesh (for example when drawing shadows).

void Draw(ID3D12GraphicsCommandList* commandList) const;

You can also perform instanced drawing, although this scenario requires custom shader state to get interesting results:

void DrawInstanced(ID3D12GraphicsCommandList* commandList,
    uint32_t instanceCount,
    uint32_t startInstanceLocation = 0) const;

Here's an example of custom drawing for a Model:

for (const auto& mit : model->meshes)
{
    auto mesh = mit.get();
    assert(mesh != 0);

    for (const auto& it : mesh->opaqueMeshParts)
    {
        auto part = it->get();
        assert(part != 0);

        auto effect = modelEffects[part->partIndex].get();

        effect->Apply(commandList);
        part->Draw(commandList);
    }
}

// Need to repeat for mesh->alphaMeshParts if there is transparent geometry,
// which should be drawn after all opaque geometry and sorted back to front.

Metadata

The ModelMeshPart::vbDecl contains the input layout element descriptor needed for creating input layouts that match this submeshes vertex buffer and effect instance.

Release notes

For the July 2018 release, ModelMeshPart was updated. Existing code needs to be updated as follows:

  • Instead of using indexBuffer.Size(), use the indexBufferSize value for rendering. Custom Model loaders should be sure to set indexBufferSize.

  • Instead of using vertexBuffer.Size(), use the vertexBufferSize value for rendering. Custom Model loaders should be sure to set vertexBufferSize.

  • Custom Model loaders should continue to populate indexBuffer and vertexBuffer, but custom rendering should handle optimized meshes by checking first for staticIndexBuffer and staticVertexBuffer being non-null--typically caused by calling LoadStaticBuffers to optimize the models VBs/IBs.

For Use

  • Universal Windows Platform apps
  • Windows desktop apps
  • Windows 11
  • Windows 10
  • Xbox One
  • Xbox Series X|S

For Development

  • Visual Studio 2022
  • Visual Studio 2019 (16.11)
  • clang/LLVM v12 - v18
  • MinGW 12.2, 13.2
  • CMake 3.20

Related Projects

DirectX Tool Kit for DirectX 11

DirectXMesh

DirectXTex

DirectXMath

Tools

Test Suite

Model Viewer

Content Exporter

DxCapsViewer

See also

DirectX Landing Page

Clone this wiki locally