Kanzi 4.1.0
kanzi::Mesh::CreateInfo Struct Reference

Use Mesh::CreateInfo to describe and create meshes. More...

#include <kanzi/core.ui/graphics3d/mesh_create_info.hpp>

Classes

struct  Adjustment
 Describes a single adjustment made by adjustForDeviceCapabilities(). More...
 
struct  AdjustmentKey
 Named keys for Adjustment parameter maps. More...
 
struct  Cluster
 Parameters for Mesh::Cluster creation. More...
 
struct  MorphData
 Morph data associated with deforming this mesh. More...
 

Public Types

enum class  AdjustmentType { VertexFormatFallback , MorphFormatFallback }
 Identifies the type of adjustment performed by adjustForDeviceCapabilities(). More...
 
typedef vector< PropertyEntryPropertyContainer
 
typedef pair< AbstractPropertyType, VariantPropertyEntry
 
enum class  Status {
  Valid , VertexCountZero , VertexDataSizeMismatch , InstanceBufferWithoutInstances ,
  InstanceDataSizeMismatch , IndexBufferWithoutIndices , IndexDataSizeMismatch , ClusterExceedsIndexBounds ,
  ClusterPrimitiveTypeInvalid , IndexOffsetNotAligned , VertexFormatAttributeOutOfBounds , MorphVertexCountZero ,
  MorphVertexFormatEmpty , MorphVertexDataSizeMismatch , InstanceAttributeWithoutInstanceSize , BufferSizeOverflow ,
  ClusterCountZero , MorphVertexCountMismatch , MaxVertexAttributesExceeded , MaxVertexAttributeStrideExceeded ,
  MaxVertexAttributeOffsetExceeded , VertexFormatNotSupported
}
 Status tells if mesh creation parameters can be used to create a mesh. More...
 

Public Member Functions

 CreateInfo ()=default
 Default constructor.
 

Public Attributes

Box boundingBox
 The bounding box for the mesh in the local coordinates of the mesh.
 
vector< Mesh::CreateInfo::Clusterclusters
 Clusters.
 
gfx::AccessFlag cpuAccessFlag
 The Access Flags for the buffers created to support the mesh.
 
gfx::BufferHandleGuard indexBufferHandle
 Kanzi graphics handle to the index buffer.
 
size_t indexCount
 Number of indices in the mesh.
 
vector< byte > indexData
 Index data.
 
IndexBufferType indexType
 The data type of the index buffer: UInt16 or UInt32.
 
gfx::BufferHandleGuard instanceBufferHandle
 Native handle to the instance buffer.
 
size_t instanceCount
 Number of instances in the mesh.
 
vector< byte > instanceData
 Instance buffer data.
 
vector< Matrix4x4instanceTransforms
 Instance transforms.
 
GPUResource::MemoryType memoryType
 Memory type for the mesh data.
 
optional< Mesh::CreateInfo::MorphDatamorphData
 Morph data.
 
PropertyContainer properties
 Properties to copy to the mesh.
 
Skeleton skeleton
 Mesh skeleton for bone animations.
 
size_t vertexCount
 Number of vertices in the mesh.
 
MeshVertexFormat vertexFormat
 Mesh vertex attributes.
 

Detailed Description

Use Mesh::CreateInfo to describe and create meshes.

Vertex and index listings define meshes. Indices refer to vertices which define the faces of a mesh.

To define a mesh, you need:

  • Vertex format definition. This definition describes the components that define a vertex. This includes information about the vertex position, texture coordinates, normal, and tangent.
  • List of vertices. Each vertex contains components that the format definition describes.
  • List of indices. Indices describe polygons by referring to each vertex by index. When triangles describe a polygon, three indices describe a triangle. You can use several index listings, each of which uses a material.

When you render a large number of copies of the same mesh, performing a draw call for each copy consumes GPU time and decreases application performance. Instancing makes it possible to draw multiple copies of a mesh with different attributes, such as position, size, and color, with a single render call. For an example of how to render multiple instances of a cube mesh at different locations and with different colors, see Creating a mesh with instancing.

To enable the Kanzi Studio Preview to visualize the bounding volume of a mesh, set the bounding box for that mesh.

Examples

Creating a mesh

To create a cube mesh:

// Define a CreateInfo structure and set it to not keep the data after uploading it to the GPU.
Mesh::CreateInfo createInfo;
createInfo.memoryType = GPUResource::GpuOnly;
// Describe the format for each vertex. In this example, every vertex has a position in 3D space,
// texture coordinates pointing to 2D texture space, and normal and tangent data in 3D space.
// Add a three-component position to the vertex format description.
// Use the standard Kanzi name kzPosition.
MeshVertexAttribute position("kzPosition", VertexAttribute::SemanticPosition, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(position);
// Add a two-component texture coordinate to the vertex format description.
// Texture coordinates enable you to use textures on a mesh.
// Use the standard Kanzi name kzTextureCoordinate0.
MeshVertexAttribute textureCoordinate("kzTextureCoordinate0", VertexAttribute::SemanticTextureCoordinate, 0, gfx::Format::RG32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(textureCoordinate);
// Add three-component normals to the vertex format description.
// Normals enable you to use lighting on a mesh.
// Use the standard Kanzi name kzNormal.
MeshVertexAttribute normal("kzNormal", VertexAttribute::SemanticNormal, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(normal);
// Add three-component tangents to the vertex format description.
// Tangents enable you to use normal maps on a mesh.
// Use the standard Kanzi name kzTangent.
MeshVertexAttribute tangent("kzTangent", VertexAttribute::SemanticTangent, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(tangent);
// Now that you added all components to the vertex format description, update the offsets,
// strides, and vertex size.
createInfo.vertexFormat.updateSizesAndOffsets();
// Create a cluster. Two triangles define a face. Since a cube has six faces, you must create
// 36 indices (2 * 3 * 6 = 36). In this example, the entire mesh uses a single material, which
// is why you need only one cluster.
createInfo.indexCount = 36;
createInfo.indexType = IndexBufferTypeUInt16;
Mesh::CreateInfo::Cluster cluster(GraphicsPrimitiveTypeTriangles, 36, material, materialUrl);
createInfo.clusters.push_back(cluster);
createInfo.indexData.resize(createInfo.indexCount * sizeof(uint16_t));
// Create the vertices. Four vertices define one face of a cube. Since a cube has six faces,
// you must create 24 vertices (4 * 6 = 24). Here you create vertex faces with normals that
// point to the same direction. This makes the faces of a cube appear flat. You cannot reuse
// vertex positions because the normals for each face are separate.
{
createInfo.vertexCount = 24;
// Define the positions of the cube corners.
// This example first defines the back face, then the front face.
const Vector3 cornerPositions[] = {
Vector3(1.0f, 1.0f, 1.0f),
Vector3(-1.0f, 1.0f, 1.0f),
Vector3(-1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, -1.0f),
Vector3(1.0f, 1.0f, -1.0f),
Vector3(-1.0f, 1.0f, -1.0f),
Vector3(-1.0f, -1.0f, -1.0f)
};
// Define texture UV coordinates for all faces.
const Vector2 UVs[] = {
Vector2(1.0f, 1.0f),
Vector2(0.0f, 1.0f),
Vector2(0.0f, 0.0f),
Vector2(1.0f, 0.0f)
};
// Define vertex indices for all faces.
const unsigned int faceIndices[][4] = {
// Front.
{ 0, 1, 2, 3 },
// Right.
{ 5, 0, 3, 4 },
// Back.
{ 6, 5, 4, 7 },
// Left.
{ 1, 6, 7, 2 },
// Top.
{ 5, 6, 1, 0 },
// Bottom.
{ 3, 2, 7, 4 }
};
// Define normals for each face.
const Vector3 faceNormals[] = {
Vector3(0.0f, 0.0f, 1.0f),
Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, -1.0f),
Vector3(-1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, -1.0f, 0.0f)
};
// Define tangents for each face.
const Vector3 faceTangent[] = {
Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, -1.0f),
Vector3(-1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f),
Vector3(1.0f, 0.0f, 0.0f),
Vector3(1.0f, 0.0f, 0.0f)
};
uint16_t vertexIndex = 0;
// To generate the vertex data, loop the data arrays that you defined above.
for (unsigned int face = 0; face < 6; ++face)
{
// Add two triangles.
uint16_t* indexData = reinterpret_cast<uint16_t*>(&createInfo.indexData[0]);
unsigned int faceBaseIndex = face * 6;
// The first three vertices of a face define the first triangle...
indexData[faceBaseIndex + 0] = vertexIndex + 0;
indexData[faceBaseIndex + 1] = vertexIndex + 1;
indexData[faceBaseIndex + 2] = vertexIndex + 2;
// ...and the second triangle uses the two last vertices of the face with the first vertex.
// These two triangles create a quad.
indexData[faceBaseIndex + 3] = vertexIndex + 2;
indexData[faceBaseIndex + 4] = vertexIndex + 3;
indexData[faceBaseIndex + 5] = vertexIndex + 0;
// Write vertices for the face.
for (unsigned int faceCorner = 0; faceCorner < 4; ++faceCorner, ++vertexIndex)
{
unsigned int boxCorner = faceIndices[face][faceCorner];
// Write the correct vertex for this corner of each face.
writeVertexAttribute(createInfo, vertexIndex, 0, cornerPositions[boxCorner]);
// UVs for each face are the same.
writeVertexAttribute(createInfo, vertexIndex, 1, UVs[faceCorner]);
// Normal is constant throughout the face.
writeVertexAttribute(createInfo, vertexIndex, 2, faceNormals[face]);
// Tangent is constant throughout the face.
writeVertexAttribute(createInfo, vertexIndex, 3, faceTangent[face]);
}
}
}
// Create a Box and set it as the bounding volume of the mesh.
// Position the box in the center of the mesh. Set the dimensions of the box along each axis
// to 2.0f, that is, from point (-1, -1, -1) to point (1, 1, 1) in the local coordinate space
// of the mesh.
createInfo.boundingBox = Box::fromCenterAndSize(Vector3(0.0f, 0.0f, 0.0f), Vector3(2.0f, 2.0f, 2.0f));
// Create a mesh from the data that you defined in the CreateInfo.
MeshSharedPtr mesh = Mesh::create(domain, createInfo, "box");

Creating a mesh from native handles

To create a mesh from native handles:

// Define a CreateInfo structure.
Mesh::CreateInfo createInfo;
// Describe the format for each vertex. In this example, every vertex has a position in 3D space,
// texture coordinates pointing to 2D texture space, and normal and tangent data in 3D space.
// Add a three-component position to the vertex format description.
// Use the standard Kanzi name kzPosition.
MeshVertexAttribute position("kzPosition", VertexAttribute::SemanticPosition, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(position);
// Add a two-component texture coordinate to the vertex format description.
// Texture coordinates enable you to use textures on a mesh.
// Use the standard Kanzi name kzTextureCoordinate0.
MeshVertexAttribute textureCoordinate("kzTextureCoordinate0", VertexAttribute::SemanticTextureCoordinate, 0, gfx::Format::RG32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(textureCoordinate);
// Add three-component normals to the vertex format description.
// Normals enable you to use lighting on a mesh.
// Use the standard Kanzi name kzNormal.
MeshVertexAttribute normal("kzNormal", VertexAttribute::SemanticNormal, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(normal);
// Add three-component tangents to the vertex format description.
// Tangents enable you to use normal maps on a mesh.
// Use the standard Kanzi name kzTangent.
MeshVertexAttribute tangent("kzTangent", VertexAttribute::SemanticTangent, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(tangent);
// Now that you added all components to the vertex format description, update the offsets,
// strides, and vertex size.
createInfo.vertexFormat.updateSizesAndOffsets();
// Create the vertices. Four vertices define one face of a cube. Since cube has six faces,
// you must create 24 vertices (4 * 6 = 24). Here you create vertex faces with normals that
// point to the same direction. This makes the faces of a cube appear flat. You cannot reuse
// vertex positions because the normals for each face are separate.
{
createInfo.vertexCount = 24;
// Define the positions of the cube corners.
// This example first defines the back face, then the front face.
const Vector3 cornerPositions[] = {
Vector3(1.0f, 1.0f, 1.0f),
Vector3(-1.0f, 1.0f, 1.0f),
Vector3(-1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, -1.0f),
Vector3(1.0f, 1.0f, -1.0f),
Vector3(-1.0f, 1.0f, -1.0f),
Vector3(-1.0f, -1.0f, -1.0f)
};
// Define texture UV coordinates for all faces.
const Vector2 UVs[] = {
Vector2(1.0f, 1.0f),
Vector2(0.0f, 1.0f),
Vector2(0.0f, 0.0f),
Vector2(1.0f, 0.0f)
};
// Define vertex indices for all faces.
const unsigned int faceIndices[][4] = {
// Front.
{ 0, 1, 2, 3 },
// Right.
{ 5, 0, 3, 4 },
// Back.
{ 6, 5, 4, 7 },
// Left.
{ 1, 6, 7, 2 },
// Top.
{ 5, 6, 1, 0 },
// Bottom.
{ 3,
2,
7,
4 }
};
// Define normals for all faces.
const Vector3 faceNormals[] = {
Vector3(0.0f, 0.0f, 1.0f),
Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, -1.0f),
Vector3(-1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, -1.0f, 0.0f)
};
// Define tangents for all faces.
const Vector3 faceTangent[] = {
Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, -1.0f),
Vector3(-1.0f, 0.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f),
Vector3(1.0f, 0.0f, 0.0f),
Vector3(1.0f, 0.0f, 0.0f)
};
uint16_t vertexIndex = 0;
vector<uint16_t> indexBuffer;
indexBuffer.resize(36);
// To generate the vertex data, loop the data arrays that you defined above.
// Mesh::CreateInfo stores source bytes per attribute in attributes[i].initialData;
// the writeVertexAttribute helper sizes each attribute's buffer on demand.
for (unsigned int face = 0; face < 6; ++face)
{
// Add two triangles.
uint16_t* indexData = indexBuffer.data();
unsigned int faceBaseIndex = face * 6;
// The first three vertices of a face define the first triangle...
indexData[faceBaseIndex + 0] = vertexIndex + 0;
indexData[faceBaseIndex + 1] = vertexIndex + 1;
indexData[faceBaseIndex + 2] = vertexIndex + 2;
// ...and the second triangle uses the two last vertices of the face with the first vertex.
// These two triangles create a quad.
indexData[faceBaseIndex + 3] = vertexIndex + 2;
indexData[faceBaseIndex + 4] = vertexIndex + 3;
indexData[faceBaseIndex + 5] = vertexIndex + 0;
// Write per-corner values for all four attributes.
for (unsigned int faceCorner = 0; faceCorner < 4; ++faceCorner, ++vertexIndex)
{
unsigned int boxCorner = faceIndices[face][faceCorner];
writeVertexAttribute(createInfo, vertexIndex, 0u, cornerPositions[boxCorner]);
writeVertexAttribute(createInfo, vertexIndex, 1u, UVs[faceCorner]);
writeVertexAttribute(createInfo, vertexIndex, 2u, faceNormals[face]);
writeVertexAttribute(createInfo, vertexIndex, 3u, faceTangent[face]);
}
}
// Create Kanzi graphics index buffer.
gfx::BufferCreateInfo indexBufferCreateInfo;
indexBufferCreateInfo.name = "Custom Index Buffer";
indexBufferCreateInfo.usageFlag = gfx::BufferUsageFlag::IndexBuffer;
indexBufferCreateInfo.size = static_cast<uint32_t>(indexBuffer.size() * sizeof(uint16_t));
indexBufferCreateInfo.initialData = as_bytes(toSpan(indexBuffer));
auto indexBufferHandle = gfx::create(indexBufferCreateInfo);
createInfo.indexBufferHandle = indexBufferHandle;
createInfo.indexType = IndexBufferTypeUInt16;
createInfo.indexCount = indexBuffer.size();
// Create a cluster. Two triangles define a face. Since a cube has six faces, you must create
// 36 indices (2 * 3 * 6 = 36). In this example, the entire mesh uses a single material, which
// is why you need only one cluster.
Mesh::CreateInfo::Cluster cluster(GraphicsPrimitiveTypeTriangles, indexBuffer.size(), material, materialUrl);
createInfo.clusters.push_back(cluster);
}
// Create a Box and set it as the bounding volume of the mesh.
// Position the box in the center of the mesh. Set the dimensions of the box along each axis
// to 2.0f, that is, from point (-1, -1, -1) to point (1, 1, 1) in the local coordinate space
// of the mesh.
createInfo.boundingBox = Box::fromCenterAndSize(Vector3(0.0f, 0.0f, 0.0f), Vector3(2.0f, 2.0f, 2.0f));
// Create a mesh from the data that you defined in the CreateInfo.
MeshSharedPtr mesh = Mesh::create(domain, createInfo, "box");

Creating a mesh with instancing

To create a mesh with instancing:

// Create a custom shader to use instanced attributes.
const char* vertexSource =
"#version 310 es\n"
"in vec3 kzPosition;\n"
"in vec3 InstancePosition;\n"
"in vec4 InstanceColor;\n"
"uniform highp mat4 kzProjectionCameraWorldMatrix;\n"
"out vec4 outColor;\n"
"void main() {\n"
"precision mediump float;\n"
"vec3 position = kzPosition + InstancePosition;\n"
"gl_Position = kzProjectionCameraWorldMatrix * vec4(position, 1.0);\n"
"outColor = InstanceColor;\n"
"}\n";
const char* fragmentSource =
"#version 310 es\n"
"in vec4 outColor;\n"
"layout(location = 0) out vec4 fragColor;\n"
"void main() {\n"
"precision lowp float;\n"
"fragColor = outColor;\n"
"}\n";
ShaderProgram::CreateInfo shaderCreateInfo;
{
auto compiler = kanzi::makeShaderCompiler();
gfx::ShaderFormat shaderFormat = gfx::ShaderFormat::Glsl43;
for (auto&& format : { gfx::ShaderFormat::VulkanSpirv13, gfx::ShaderFormat::GlslES30, gfx::ShaderFormat::Glsl33 })
{
if (gfx::isShaderFormatSupported(format))
{
shaderFormat = format;
break;
}
}
array<ShaderCompiler::ShaderSource, 2> sources;
sources[0].stage = gfx::ShaderStage::Vertex;
sources[0].source = vertexSource;
sources[1].stage = gfx::ShaderStage::Fragment;
sources[1].source = fragmentSource;
constexpr auto options = ShaderCompiler::OptionFlags::Default;
auto shaderResult = compiler->compile(sources, options, asSpan(shaderFormat), "");
shaderCreateInfo.addSourceShader(ShaderTypeVertex, toSpan(shaderResult.shaders[shaderFormat][gfx::ShaderStage::Vertex].blob));
shaderCreateInfo.addSourceShader(ShaderTypeFragment, toSpan(shaderResult.shaders[shaderFormat][gfx::ShaderStage::Fragment].blob));
if (shaderResult.info)
{
shaderCreateInfo.reflectionInfo = kanzi::move(shaderResult.info.value());
}
}
static const ShaderVertexAttribute kzPosition = ShaderVertexAttribute("kzPosition", VertexAttribute::SemanticPosition,
0, GraphicsElementTypeFLOAT, 0, 3, 0, 0);
static const ShaderVertexAttribute InstancePosition = ShaderVertexAttribute("InstancePosition", VertexAttribute::SemanticPosition,
1, GraphicsElementTypeFLOAT, 0, 3, 1, 0);
static const ShaderVertexAttribute InstanceColor = ShaderVertexAttribute("InstanceColor", VertexAttribute::SemanticColor,
0, GraphicsElementTypeFLOAT, 0, 4, 2, 0);
shaderCreateInfo.vertexFormat.push_back(kzPosition);
shaderCreateInfo.vertexFormat.push_back(InstancePosition);
shaderCreateInfo.vertexFormat.push_back(InstanceColor);
shaderCreateInfo.addFixedUniform("kzProjectionCameraWorldMatrix");
auto shader = ShaderProgram::create(domain, shaderCreateInfo, "CustomShader");
auto material = Material::create(domain, "CustomMaterial", shader);
// Define a CreateInfo structure and set it to not keep the data after uploading it to the GPU.
Mesh::CreateInfo createInfo;
createInfo.memoryType = GPUResource::GpuOnly;
// Describe the format for each vertex. In this example, every vertex has a position in 3D space,
// and every instance has a position in 3D space and a color.
// Add a three-component position to the vertex format description.
// Use the standard Kanzi name kzPosition.
MeshVertexAttribute position("kzPosition", VertexAttribute::SemanticPosition, 0, gfx::Format::RGB32_Float, ~0u);
createInfo.vertexFormat.attributes.push_back(position);
// Add instance position.
MeshVertexAttribute instancePosition("InstancePosition", VertexAttribute::SemanticPosition, 1, gfx::Format::RGB32_Float, 0);
instancePosition.divisor = 1;
createInfo.vertexFormat.attributes.push_back(instancePosition);
// Add instance color.
MeshVertexAttribute instanceColor("InstanceColor", VertexAttribute::SemanticColor, 0, gfx::Format::RGBA8_UNorm, 3 * sizeof(float));
instanceColor.divisor = 1;
createInfo.vertexFormat.attributes.push_back(instanceColor);
// Now that you added all components to the vertex format description, update the offsets,
// strides, and sizes.
createInfo.vertexFormat.updateSizesAndOffsets();
// Initialize index data.
createInfo.indexType = IndexBufferTypeUInt16;
createInfo.indexCount = 36;
createInfo.indexData.resize(createInfo.indexCount * sizeof(uint16_t));
// Create a cluster. Two triangles define a face. Since a cube has six faces, you must create
// 36 indices (2 * 3 * 6 = 36). In this example, the entire mesh uses a single material, which
// is why you need only one cluster.
Mesh::CreateInfo::Cluster cluster(GraphicsPrimitiveTypeTriangles, 36, material, "");
createInfo.clusters.push_back(cluster);
// Create the vertices. In this example, faces share vertices, so you need only eight vertices.
{
createInfo.vertexCount = 8;
// Define the positions of the cube corners.
// This example first defines the back face, then the front face.
const Vector3 cornerPositions[] = {
Vector3(1.0f, 1.0f, 1.0f),
Vector3(-1.0f, 1.0f, 1.0f),
Vector3(-1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, 1.0f),
Vector3(1.0f, -1.0f, -1.0f),
Vector3(1.0f, 1.0f, -1.0f),
Vector3(-1.0f, 1.0f, -1.0f),
Vector3(-1.0f, -1.0f, -1.0f)
};
// Define vertex indices for all faces.
const uint16_t faceIndices[][4] = {
// Front.
{ 0, 1, 2, 3 },
// Right.
{ 5, 0, 3, 4 },
// Back.
{ 6, 5, 4, 7 },
// Left.
{ 1, 6, 7, 2 },
// Top.
{ 5, 6, 1, 0 },
// Bottom.
{ 3, 2, 7, 4 }
};
// To generate the vertex data, loop the data arrays that you defined above.
for (unsigned int face = 0; face < 6; ++face)
{
// Add two triangles.
uint16_t* indexData = reinterpret_cast<uint16_t*>(&createInfo.indexData[0]);
unsigned int faceBaseIndex = face * 6;
// The first three vertices of a face define the first triangle...
indexData[faceBaseIndex + 0] = faceIndices[face][0];
indexData[faceBaseIndex + 1] = faceIndices[face][1];
indexData[faceBaseIndex + 2] = faceIndices[face][2];
// ...and the second triangle uses the two last vertices of the face with the first vertex.
// These two triangles create a quad.
indexData[faceBaseIndex + 3] = faceIndices[face][2];
indexData[faceBaseIndex + 4] = faceIndices[face][3];
indexData[faceBaseIndex + 5] = faceIndices[face][0];
}
// Write vertices.
for (unsigned int vertexIndex = 0; vertexIndex < 8; ++vertexIndex)
{
// Write the correct vertex for this corner of each face.
writeVertexAttribute(createInfo, vertexIndex, 0, cornerPositions[vertexIndex]);
}
}
// Create the instance data: float position vector with three components and packed
// 32-bit color per instance.
{
// Create four instances of the cube.
createInfo.instanceCount = 4;
createInfo.instanceData.resize(createInfo.instanceCount * createInfo.vertexFormat.instanceSize);
// Define the positions.
const Vector3 instancePositions[] = {
Vector3(-1.0f, -1.0f, 0.0f),
Vector3(-1.0f, 1.0f, 0.0f),
Vector3(1.0f, 1.0f, 0.0f),
Vector3(1.0f, -1.0f, 0.0f)
};
// Define the colors: white, red, green, blue.
const uint32_t instanceColors[] = {
0xffffffff,
0xffff0000,
0xff00ff00,
0xff0000ff
};
byte* instanceBuffer = createInfo.instanceData.data();
for (unsigned instance = 0; instance < createInfo.instanceCount; ++instance)
{
// Copy the positions and colors to the instance data buffer.
auto pos = reinterpret_cast<float*>(instanceBuffer + instance * createInfo.vertexFormat.instanceSize);
*pos++ = instancePositions[instance].getX();
*pos++ = instancePositions[instance].getY();
*pos++ = instancePositions[instance].getZ();
auto color = reinterpret_cast<uint32_t*>(pos);
*color = instanceColors[instance];
}
}
// Create a Box and set it as the bounding volume of the mesh.
// Position the box in the center of the mesh. Set the dimensions of the box along each axis
// to 4.0f, that is, from point (-2, -2, -1) to point (2, 2, 1) in the local coordinate space
// of the mesh. This includes all the instances.
createInfo.boundingBox = Box::fromCenterAndSize(Vector3(0.0f, 0.0f, 0.0f), Vector3(4.0f, 4.0f, 2.0f));
// Create a mesh from the data that you defined in the CreateInfo.
MeshSharedPtr mesh = Mesh::create(domain, createInfo, "instancedBox");
See also
Mesh
Since
Kanzi 4.0.0 removed the instanceSize and vertexSize fields.

Member Typedef Documentation

◆ PropertyEntry

◆ PropertyContainer

Member Enumeration Documentation

◆ Status

Status tells if mesh creation parameters can be used to create a mesh.

Enumerator
Valid 

CreateInfo is valid and can be used to create a Mesh.

VertexCountZero 

vertexCount is zero.

VertexDataSizeMismatch 

For at least one vertex attribute, initialData size exceeds vertexCount * gfx::getPixelStride(attribute.format).

InstanceBufferWithoutInstances 

instanceBufferHandle is valid but instanceCount is zero.

InstanceDataSizeMismatch 

instanceData size exceeds instanceCount * vertexFormat.instanceSize.

IndexBufferWithoutIndices 

indexBufferHandle is valid but indexCount is zero.

IndexDataSizeMismatch 

indexData size exceeds indexCount * index type stride.

ClusterExceedsIndexBounds 

A cluster's indexCount + indexOffset exceeds the total indexCount.

ClusterPrimitiveTypeInvalid 

A cluster has an invalid primitiveType (e.g., GraphicsPrimitiveTypeInvalid).

IndexOffsetNotAligned 

A cluster's indexOffset is not aligned to the index type stride.

VertexFormatAttributeOutOfBounds 

A vertex attribute's offset + byte size exceeds vertexFormat.vertexSize.

MorphVertexCountZero 

morphData is present but morphData.vertexCount is zero.

MorphVertexFormatEmpty 

morphData is present but morphData.vertexFormat.attributes is empty.

MorphVertexDataSizeMismatch 

morphData vertex data size exceeds morphData.vertexCount * morphData.vertexFormat.vertexSize.

InstanceAttributeWithoutInstanceSize 

A vertex attribute has a non-zero divisor but vertexFormat.instanceSize is zero.

BufferSizeOverflow 

A buffer size calculation (count * size) overflows or exceeds uint32_t max.

ClusterCountZero 

clusters is empty.

MorphVertexCountMismatch 

Vertex-buffer-path morph data: morphData.vertexCount does not equal createInfo.vertexCount.

MaxVertexAttributesExceeded 

Number of non-instance vertex attributes exceeds device maximum.

MaxVertexAttributeStrideExceeded 

Vertex stride exceeds device maximum.

MaxVertexAttributeOffsetExceeded 

A vertex attribute's offset exceeds device maximum.

VertexFormatNotSupported 

A vertex attribute's format is not supported for VertexAttribute usage.

◆ AdjustmentType

Identifies the type of adjustment performed by adjustForDeviceCapabilities().

Since
Kanzi 4.1.0
Enumerator
VertexFormatFallback 

A vertex attribute format was replaced with a supported fallback.

MorphFormatFallback 

A morph vertex attribute format was replaced with a supported fallback.

Applies to vertex-buffer-based morph rendering only; data-texture-based morph storage is sampled and not subject to vertex-attribute format constraints, so its layout (dataTexture* offsets) is left untouched.

Constructor & Destructor Documentation

◆ CreateInfo()

kanzi::Mesh::CreateInfo::CreateInfo ( )
explicitdefault

Default constructor.

Member Data Documentation

◆ memoryType

GPUResource::MemoryType kanzi::Mesh::CreateInfo::memoryType

Memory type for the mesh data.

If Gpu is not included, mesh data will not be deployed when created. If Ram is not included, mesh will not contain buffer data after it has been deployed. Default value is GpuOnly.

See also
MemoryType

◆ clusters

vector<Mesh::CreateInfo::Cluster> kanzi::Mesh::CreateInfo::clusters

Clusters.

◆ morphData

optional<Mesh::CreateInfo::MorphData> kanzi::Mesh::CreateInfo::morphData

Morph data.

◆ boundingBox

Box kanzi::Mesh::CreateInfo::boundingBox

The bounding box for the mesh in the local coordinates of the mesh.

When you do not set the size of a node with the Node::WidthProperty, Node::HeightProperty, and Node::DepthProperty properties, layout control nodes use the bounding box to determine the size of the node.

The Kanzi Studio Preview uses the bounding box to visualize the bounding volume of the mesh.

◆ skeleton

Skeleton kanzi::Mesh::CreateInfo::skeleton

Mesh skeleton for bone animations.

◆ vertexFormat

MeshVertexFormat kanzi::Mesh::CreateInfo::vertexFormat

Mesh vertex attributes.

Since
Kanzi 4.0.0 changed the type to MeshVertexFormat.

◆ vertexCount

size_t kanzi::Mesh::CreateInfo::vertexCount

Number of vertices in the mesh.

Since
Kanzi 3.9.7 changed type to unsigned int.
Kanzi 4.0.0 changed the type to size_t.

◆ instanceCount

size_t kanzi::Mesh::CreateInfo::instanceCount

Number of instances in the mesh.

Since
Kanzi 3.9.6
Kanzi 3.9.7 changed type to unsigned int.
Kanzi 4.1 changed type to size_t.

◆ instanceData

vector<byte> kanzi::Mesh::CreateInfo::instanceData

Instance buffer data.

The size of instanceData must not exceed instanceCount * vertexFormat.instanceSize.

Since
Kanzi 3.9.6

◆ instanceBufferHandle

gfx::BufferHandleGuard kanzi::Mesh::CreateInfo::instanceBufferHandle

Native handle to the instance buffer.

Since
Kanzi 3.9.6
Kanzi 4.0.0 changed the type to BufferHandleGuard.

◆ instanceTransforms

vector<Matrix4x4> kanzi::Mesh::CreateInfo::instanceTransforms

Instance transforms.

Instance transforms. Must be in sync with raw instance data.

Since
Kanzi 4.1.0
Attention
This feature is experimental and is likely to change in future releases.

◆ indexCount

size_t kanzi::Mesh::CreateInfo::indexCount

Number of indices in the mesh.

If indexCount is 0, no index buffer is created. If indexBufferHandle is valid, indexCount * kanzi::getIndexTypeStride(indexType) must be less than or equal the size of the indexBufferHandle.

Since
Kanzi 4.0.0

◆ indexData

vector<byte> kanzi::Mesh::CreateInfo::indexData

Index data.

The size of indexData must not exceed indexCount * kanzi::getIndexTypeStride(indexType).

◆ indexBufferHandle

gfx::BufferHandleGuard kanzi::Mesh::CreateInfo::indexBufferHandle

Kanzi graphics handle to the index buffer.

Since
Kanzi 3.9.6
Kanzi 4.0.0 changed the type to BufferHandleGuard.

◆ indexType

IndexBufferType kanzi::Mesh::CreateInfo::indexType

The data type of the index buffer: UInt16 or UInt32.

◆ cpuAccessFlag

gfx::AccessFlag kanzi::Mesh::CreateInfo::cpuAccessFlag

The Access Flags for the buffers created to support the mesh.

Since
Kanzi 4.1.0

◆ properties

PropertyContainer kanzi::Mesh::CreateInfo::properties

Properties to copy to the mesh.

Currently they are not used.


The documentation for this struct was generated from the following file: