Render3D. Mesh

Mesh - Triangles with positions, normals, uvs and colors, uploaded once and drawn by matrix

  • Build with addStrip, addQuad, combine or the shape builders, then render each frame
  • Its back faces are skipped unless doubleSided is set, which the open builders like buildGrid do for you
  • Two forms: a triangle strip, what the builders make, or an indexed list of triangles over their own vertices, what addTriangles and the model loaders make; upload sends the GPU an indexed list either way, see getTriangles, so a strip's joins between its pieces cost nothing to draw, and toIndexed turns a strip mesh into the list form
  • The GPU buffer is created lazily on first render and dropped by dispose, or freed once the mesh is garbage collected, so dispose is only needed to free it right away, like for a mesh rebuilt often

Constructor

new Mesh()

Create an empty mesh

Example
const mesh = buildLathe([[0, -1], [1, 0], [0, 1]], 4); // octahedron
mesh.render(buildMatrix(vec3(0, 1, 0)), undefined, RED);

Members

bounds :Object|undefined

Type:
  • Object | undefined
Properties
TypeDescription
Object | undefined

Bounding box, for picking, measured with the radius

buffer :WebGLBuffer|undefined

Type:
  • WebGLBuffer | undefined
Properties
TypeDescription
WebGLBuffer | undefined

GPU vertex buffer, created by upload

bufferCount

Properties
TypeDescription
number

Indices in the GPU index buffer, three per triangle

colors :Array.<Color>

Type:
  • Array.<Color>
Properties
TypeDescription
Array.<Color>

Vertex colors

dirty

Properties
TypeDescription
boolean

The mesh changed and needs uploading again, set it yourself if you edit the arrays

doubleSided

Properties
TypeDescription
boolean

Draw both sides, each lit as the side that is seen; off skips the faces pointing away, which is faster and right for closed shapes, the open builders like buildGrid and buildRibbon turn it on

dynamicDraw

Properties
TypeDescription
boolean

The values change often but the shape never does, for a water surface or a cloth: set once, the mesh keeps its GPU layout and a dirty upload only rewrites the vertices into the buffer it has; the strip must keep the same points in the same order, a new point count asserts; the layout is decided by the first upload, so strip entries equal then stay one vertex and triangles with no area then stay dropped, set vertexKeys or give it distinct values at the start, not a flat grid of one color or points all in one place

indexBuffer :WebGLBuffer|undefined

Type:
  • WebGLBuffer | undefined
Properties
TypeDescription
WebGLBuffer | undefined

GPU index buffer, the triangles, created by upload

indices :Array.<number>|undefined

Type:
  • Array.<number> | undefined
Properties
TypeDescription
Array.<number> | undefined

The mesh as an indexed triangle list instead of a strip: the arrays hold each vertex once and this says how they join, three vertex numbers per triangle, counter clockwise seen from the front like a strip's first triangle; addTriangles and the loaders fill it, toIndexed turns a strip mesh into this form

instanceData :Float32Array|undefined

Type:
  • Float32Array | undefined

instanced :boolean|undefined

Type:
  • boolean | undefined
Properties
TypeDescription
boolean | undefined

Draw every use of this mesh in the opaque stage as one instanced call, undefined follows render3D.instancing

normals :Array.<Vector3>

Type:
  • Array.<Vector3>
Properties
TypeDescription
Array.<Vector3>

Vertex normals

points :Array.<Vector3>

Type:
  • Array.<Vector3>
Properties
TypeDescription
Array.<Vector3>

Vertex positions, in strip order or one per vertex of an indexed mesh

radius

Properties
TypeDescription
number

Bounding sphere radius around the origin, for culling and picking, computed by upload

uvs :Array.<Vector2>

Type:
  • Array.<Vector2>
Properties
TypeDescription
Array.<Vector2>

Vertex texture coords, 0-1 across the tile

vertexCount

Number of vertices in the mesh

vertexKeys :Int32Array|undefined

Type:
  • Int32Array | undefined
Properties
TypeDescription
Int32Array | undefined

Which strip entries are one vertex, set by a builder that knows, one whole number per entry with equal numbers meaning the same vertex; upload skips its search for them, then drops the keys, since an edit after that may tell the entries apart; adding geometry or recomputing normals drops them too

vertexLayout :Object|undefined

Type:
  • Object | undefined

Methods

addQuad(a, b, c, d, coloropt, uvsopt) → {Mesh}

Add a flat quad from four corners in loop order, counter clockwise seen from the front, a is the top left of the texture

Parameters:
NameTypeAttributesDescription
aVector3
bVector3
cVector3
dVector3
colorColor | Array.<Color><optional>

One for all or one per corner

uvsArray.<Vector2><optional>

One per corner, default across the tile

Returns:
Type: 
Mesh

addStrip(points, normalsopt, uvsopt, colorsopt) → {Mesh}

Add a triangle strip, joined to the previous one by invisible flat triangles so one mesh holds many strips

  • Strip order: the first three points make a triangle, then each point makes another with the two before it
  • List the first three points counter clockwise as seen from the front, or the face points away and may vanish when back faces are culled
Parameters:
NameTypeAttributesDescription
pointsArray.<Vector3>

Strip order

normalsVector3 | Array.<Vector3><optional>

One for all or one per point, default up

uvsVector2 | Array.<Vector2><optional>

One for all or one per point, default zero

colorsColor | Array.<Color><optional>

One for all or one per point, default white

Returns:
Type: 
Mesh

addTriangles(points, indices, normalsopt, uvsopt, colorsopt) → {Mesh}

Add triangles over their own vertices, the indexed form a model file comes in

  • The mesh becomes indexed: a strip mesh is turned into triangles first, and strips added later join as triangles
  • List each triangle counter clockwise as seen from the front, like a strip's first triangle
Parameters:
NameTypeAttributesDescription
pointsArray.<Vector3>

Each vertex once

indicesArray.<number>

Three vertex numbers per triangle, into points

normalsVector3 | Array.<Vector3><optional>

One for all or one per point, default up

uvsVector2 | Array.<Vector2><optional>

One for all or one per point, default zero

colorsColor | Array.<Color><optional>

One for all or one per point, default white

Returns:
Type: 
Mesh

center() → {Mesh}

Move the mesh so the center of its bounds is on the origin

Returns:
Type: 
Mesh

combine(mesh, matrixopt, coloropt) → {Mesh}

Append another mesh transformed by a matrix, for building one shape out of several

Parameters:
NameTypeAttributesDescription
meshMesh
matrixMatrix4 | Vector3<optional>

Transform, or just a position to move it to

colorColor<optional>

Multiplies the appended vertex colors

Returns:
Type: 
Mesh

computeNormals(smoothopt) → {Mesh}

Derive normals from the triangles, of the strip or of the index list

Parameters:
NameTypeAttributesDefaultDescription
smoothboolean<optional>
false

Round the lighting across faces instead of giving each face a hard edge; flat normals on an indexed mesh give every corner its own vertex

Returns:
Type: 
Mesh

computeRadius() → {number}

Measure the bounding sphere around the origin into radius, called by upload

Returns:
Type: 
number

dispose()

Delete the GPU buffer now, the CPU arrays stay so the mesh can be rendered again

  • Optional, the buffer is freed anyway once the mesh is garbage collected, this frees it right away

fit(sizeopt) → {Mesh}

Scale the mesh evenly so its largest extent is a size, for loaded models of unknown units

Parameters:
NameTypeAttributesDefaultDescription
sizenumber<optional>
1
Returns:
Type: 
Mesh

flipNormals() → {Mesh}

Turn the mesh inside out so it is lit and drawn from within, for rooms and domes

Returns:
Type: 
Mesh

getBounds() → {Object}

Measure the axis aligned box around the vertices

Returns:
Type: 
Object

getTriangles() → {Object}

The mesh as an indexed triangle list, what upload sends to the GPU: the strip's real triangles over its distinct vertices, the joins between its pieces dropped and every triangle facing the way it did in the strip

  • Vertices are compared to a millionth, so two at one place with the same normal, uv and color are one
Returns:
  • vertices are strip indices, one per distinct vertex; indices are the triangles, three per triangle, into vertices
Type: 
Object

intersect(mesh, matrixopt) → {Mesh}

Returns a new mesh of only what is in both this mesh and the other, see subtract

Parameters:
NameTypeAttributesDescription
meshMesh

Closed, as the builders make them apart from the open ones like buildGrid

matrixMatrix4 | Vector3<optional>

Places the other mesh, or just a position to move it to

Returns:
Type: 
Mesh

mirror(axisopt) → {Mesh}

Returns a new mesh: this one and its mirror image across the plane through the origin facing axis

  • For modeling half a shape against that plane, a part that crosses it overlaps its image
Parameters:
NameTypeAttributesDescription
axisVector3<optional>

Faces the mirror plane, vec3(1,0,0) mirrors across x

Returns:
Type: 
Mesh

render(matrixopt, tileInfoopt, coloropt)

Draw the mesh with the current draw state, batched with its other uses in the opaque stage

Parameters:
NameTypeAttributesDescription
matrixMatrix4 | Vector3<optional>

Object transform, or just a position to draw it at

tileInfoTileInfo | TextureInfo<optional>

Texture, mesh uvs map across the tile or the whole texture

colorColor<optional>

Tint

scaleUVs(scale) → {Mesh}

Scale every uv, so a whole texture repeats across the mesh when its TextureInfo wraps

Parameters:
NameTypeDescription
scaleVector2 | number

Repeats across and up, a number for both

Returns:
Type: 
Mesh

setColor(color) → {Mesh}

Set every vertex color

Parameters:
NameTypeDescription
colorColor
Returns:
Type: 
Mesh

spin(count, axisopt) → {Mesh}

Returns a new mesh of count copies of this one, each turned further around an axis through the origin

Parameters:
NameTypeAttributesDescription
countnumber

Copies, spaced evenly around the whole turn

axisVector3<optional>

Up by default

Returns:
Type: 
Mesh

subtract(mesh, matrixopt) → {Mesh}

Returns a new mesh of this one with the other cut out of it, CSG with BSP trees

  • Both must be closed, every edge shared by two triangles, as the builders make them apart from the open ones like buildGrid and buildRibbon; the result is closed and indexed, and neither mesh changes
  • The faces a cut makes come from the other mesh's surface, turned to face out, with its normals, uvs and colors, so a smooth cylinder drills a round hole
  • Parts that overlap must be joined with union to be one solid, not with combine, mirror or spin, which leave them overlapping, and CSG then gives a wrong shape
  • Cuts split the triangles near them, so the result has more: a few thousand triangles take tens to a few hundred milliseconds, so build shapes this way at load time, not every frame; joining several cutters with union and cutting once is quicker than cutting with each in turn
  • Details closer than about 1e-4 are made one, so build a very small part larger and scale it after
Parameters:
NameTypeAttributesDescription
meshMesh

Closed, as the builders make them apart from the open ones like buildGrid

matrixMatrix4 | Vector3<optional>

Places the other mesh, or just a position to move it to

Returns:
Type: 
Mesh
Example
const wall = buildBox(vec3(4, 3, .5)).subtract(buildBox(vec3(1, 2, 1)), vec3(0, -.5, 0)); // a doorway

toIndexed() → {Mesh}

Turn a strip mesh into the indexed form, each distinct vertex once and the real triangles over them, in place

  • An indexed mesh is left as it is; the builders make strips and a loader makes this, and either draws the same
Returns:
Type: 
Mesh

transform(matrix) → {Mesh}

Move, turn or scale every vertex in place, normals follow along

Parameters:
NameTypeDescription
matrixMatrix4 | Vector3

Transform, or just an offset to move by

Returns:
Type: 
Mesh

union(mesh, matrixopt) → {Mesh}

Returns a new mesh of everything in this mesh or the other, see subtract

Parameters:
NameTypeAttributesDescription
meshMesh

Closed, as the builders make them apart from the open ones like buildGrid

matrixMatrix4 | Vector3<optional>

Places the other mesh, or just a position to move it to

Returns:
Type: 
Mesh

upload() → {Mesh}

Pack the vertices and create the GPU buffer, called automatically by render

Returns:
Type: 
Mesh