LittleJS 1.30.0

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

Create an empty mesh

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

Members

Methods

Members

bounds : Object|undefinedrender3dMesh.js:313

Bounding box, for picking, measured with the radius

buffer : WebGLBuffer|undefinedrender3dMesh.js:266

GPU vertex buffer, created by upload

bufferCount : numberrender3dMesh.js:271

Indices in the GPU index buffer, three per triangle

colors : Array<Color>render3dMesh.js:263

Vertex colors

dirty : booleanrender3dMesh.js:274

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

doubleSided : booleanrender3dMesh.js:281

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 : booleanrender3dMesh.js:287

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|undefinedrender3dMesh.js:269

GPU index buffer, the triangles, created by upload

indices : Array<number>|undefinedrender3dMesh.js:293

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

instanced : boolean|undefinedrender3dMesh.js:278

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

instanceData : Float32Array|undefinedrender3dMesh.js:308

Vertex normals

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

radius : numberrender3dMesh.js:310

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

Vertex texture coords, 0-1 across the tile

vertexCount : numberrender3dMesh.js:327

Number of vertices in the mesh

vertexData : Float32Array|undefinedrender3dMesh.js:318

The vertices in the GPU layout, given to setVertexData, read only; a mesh given them has no points

vertexIndices : Uint32Array|Uint16Array|undefinedrender3dMesh.js:321

The triangles given to setVertexData, read only

vertexKeys : Int32Array|undefinedrender3dMesh.js:299

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|undefinedrender3dMesh.js:302

Methods

addQuad(a, b, c, d, color, uvs) → Meshrender3dMesh.js:460

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

a Vector3
b Vector3
c Vector3
d Vector3
color Color|Array<Color> optional

One for all or one per corner

uvs Array<Vector2> optional

One per corner, default across the tile

addStrip(points, normals, uvs, colors) → Meshrender3dMesh.js:383

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
points Array<Vector3>

Strip order

normals Vector3|Array<Vector3> optional

One for all or one per point, default up

uvs Vector2|Array<Vector2> optional

One for all or one per point, default zero

colors Color|Array<Color> optional

One for all or one per point, default white

addTriangles(points, indices, normals, uvs, colors) → Meshrender3dMesh.js:413

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
points Array<Vector3>

Each vertex once

indices Array<number>

Three vertex numbers per triangle, into points

normals Vector3|Array<Vector3> optional

One for all or one per point, default up

uvs Vector2|Array<Vector2> optional

One for all or one per point, default zero

colors Color|Array<Color> optional

One for all or one per point, default white

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

combine(mesh, matrix, color) → Meshrender3dMesh.js:471

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

mesh Mesh
matrix Matrix4|Vector3 optional

Transform, or just a position to move it to

color Color optional

Multiplies the appended vertex colors

computeNormals(smooth) → Meshrender3dMesh.js:677

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

smooth boolean optional, default 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, and a strip that folds, where neighbors share vertices that can hold only one normal, is made indexed first

computeRadius() → numberrender3dMesh.js:662

Measure the bounding sphere around the origin into radius; upload measures it as it packs, and calls this only with no WebGL

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

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

size number optional, default 1
flipNormals() → Meshrender3dMesh.js:601

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

getBounds() → Objectrender3dMesh.js:625

Measure the axis aligned box around the vertices

getTriangles() → Objectrender3dMesh.js:813

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
intersect(mesh, matrix) → Meshrender3dMesh.js:565

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

mesh Mesh

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

matrix Matrix4|Vector3 optional

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

mirror(axis) → Meshrender3dMesh.js:514

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
axis Vector3 optional

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

render(matrix, tileInfo, color)render3dMesh.js:890

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

matrix Matrix4|Vector3 optional

Object transform, or just a position to draw it at

tileInfo TileInfo|TextureInfo optional

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

color Color optional

Tint

scaleUVs(scale) → Meshrender3dMesh.js:570

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

scale Vector2|number

Repeats across and up, a number for both

setColor(color) → Meshrender3dMesh.js:613

Set every vertex color

color Color
setVertexData(vertexData, indices, vertexCount) → Meshrender3dMesh.js:343

Make the mesh from vertices already in the GPU layout, for a big mesh a game generates, like terrain: they go to the GPU as they are, with no points made and packed again

  • Each vertex is RENDER3D_VERTEX_FLOATS floats, written by meshWriteVertex: its place, its normal, its uv and its color as RGBA bytes through a Uint32Array view of the same buffer
  • The triangles are listed counter clockwise seen from the front, as addTriangles takes them
  • The arrays are kept, not copied, and never changed, so a lost context uploads them again; call this again after changing them
  • The mesh's points, normals, uvs, colors and indices are emptied, and what edits or reads those, like transform, combine and computeNormals, does not take a mesh made this way; it draws, casts shadows, is instanced and is picked like any other
vertexData Float32Array

At least vertexCount * RENDER3D_VERTEX_FLOATS floats

indices Uint32Array|Uint16Array

Three vertex numbers per triangle

vertexCount number optional

The vertices in use, all the data holds by default

spin(count, axis) → Meshrender3dMesh.js:527

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

count number

Copies, spaced evenly around the whole turn

axis Vector3 optional

Up by default

subtract(mesh, matrix) → Meshrender3dMesh.js:559

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
mesh Mesh

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

matrix Matrix4|Vector3 optional

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

const wall = buildBox(vec3(4, 3, .5)).subtract(buildBox(vec3(1, 2, 1)), vec3(0, -.5, 0)); // a doorway
toIndexed() → Meshrender3dMesh.js:437

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
transform(matrix) → Meshrender3dMesh.js:583

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

matrix Matrix4|Vector3

Transform, or just an offset to move by

union(mesh, matrix) → Meshrender3dMesh.js:541

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

mesh Mesh

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

matrix Matrix4|Vector3 optional

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

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