# Mesh
Mesh Mesh
is used to store and manage vertices and index data. Generally speaking, it will be parsed and stored directly when the model is imported into the tool, so no special care is required. But sometimes developers will have their own needs to build Mesh, let's take a look at its construction method.
# Create
constructor(
vertexLayout: VertexLayout, vBuffer: ArrayBufferView,
iBuffer: ArrayBufferView, indexType: EIndexType = EIndexType.UINT16
);
It can be seen that to construct a Mesh
several parameters need to be provided, they are:
# VertexLayout
The first is VertexLayout
, used to describe the vertex layout, for example:
const myLayout = new engine.VertexLayout({
attributes: [
{
name: "a_position",
format: engine.EVertexFormat.FLOAT2,
offset: 0,
usage: engine.EVertexLayoutUsage.POSITION,
},
{
name: "a_texCoord",
offset: 8,
format: engine.EVertexFormat.FLOAT2,
usage: engine.EVertexLayoutUsage.UV0,
},
{
name: "a_color",
format: engine.EVertexFormat.UBYTE4,
offset: 16,
usage: engine.EVertexLayoutUsage.COLOR,
}
],
stride: 20
});
A custom VertexLayout
is defined here, which has two parameters:
- Attributes: describes the structure of the vertex, that is, how the GPU will understand the incoming vertex data, such as the first element, which indicates that the vertex attribute is named
a_position
in the shader, and the format isFLOAT2
, at the vertex The offset in the buffer is 0 and is used asPOSITION
. - stride: describes the number of bytes of bandwidth occupied by each vertex.
# Buffer and Type
The last three parameters are vertex data, index data and index format. The vertex data according to the layout structure stores the vertex data of the entire Mesh, and the index data is stored** The index of the primitive to the vertex**, and the index format determines the storage format of the index data, which can be UINT16
or UINT32
, if it is UINT16
, the vertex index value in the index data** must not be More than 65535**.
# Setting parameters
After creating a new Mesh, the developer also needs to set some parameters to make it work correctly, mainly SubMesh and surrounding balls.
# SubMesh
With the data and layout, Mesh also needs to provide some information to let the renderer know how to use the data. We provide an abstraction called SubMesh
to divide the Mesh into several parts:
// Add a SubMesh, whose index data length is `length` vertices, and the first index offset is `offset`
mesh.addSubMesh(length, offset);
// Modify the SubMesh information at the position of `subMeshIndex`
mesh.modifySubMesh(subMeshIndex, length, offset);
The main reason for this segmentation is that even the same Mesh may have different materials to handle different parts. For details, see the following chapters.
# Surround the ball
For each Mesh, in the culling phase of the camera, a bounding ball is needed to determine whether it is within the visible range. Developers can set the bounding ball through the following scheme:
// `center` is the offset of the center of the sphere relative to the origin of the model, `radius` is the radius of the sphere
mesh.setBoundBall(center, radius);
# update data
In some cases, developers also need to dynamically update vertex or index data, such as particle systems. We also provide some solutions to fulfill this need:
// Starting with the byte offset `offset`, update the entire `buffer` to the vertex data.
mesh.uploadVertexBuffer(offset, buffer);
// Starting from the byte offset `offset`, update the entire `buffer` to the index data.
mesh.uploadIndexBuffer(offset, buffer);
Note that this update operation can only be used after Mesh has been submitted to the GPU!