quads v1.2.0
quads
- Geometry Tools
This package is a collection of quad geometry creation and manipulation tools. They can be used agnostic to any given library as they only operate on simple arrays and objects. Please note that this package is an early release, and the APIs may stabilize over time. More rigorous testing is also in the works.
Types
SimplicialComplex
This is a complicated math word that means an object with { positions, cells }
. The
word mesh
is used for convenience in this module, and normals
are included with
this object.
// A single quad oriented facing up.
const mesh = {
positions: [[-1, 0, -1], [-1, 0, 1], [1, 0, 1], [1, 0, -1]],
normals: [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]],
cells: [[0, 1, 2, 3]]
}
Additional attributes may be added for one's own applications. For example:
mesh.colors = mesh.positions.map(p => [0, p.y, 0])
Type: Object
Properties
Position
An array of 3 values representing a position x, y, z.
Type: Array
Cell
In a simplicial complex, a cell is an array of of indices that refer to a position or
some other attribute like normals. Quads have 4 indices, and this module uses the
convention of [a, b, c, d]
with clockwise winding order.
b-------c
| |
| |
a-------d
Type: Array
Normal
An array of 3 values, x, y, z representing a surface normal. A valid normal has a length of 1. Normals are used for lighting calculation, and for knowing which way a surface is oriented in space. Many operation rely on valid normals.
Type: Array
API
averageNormalForPosition
Computes the average normal for a position given the connected cells.
Parameters
mesh
SimplicialComplexpositionIndex
Numbertarget
Array? = []normalCache
Map? A Map can be provided to cache intermediate normal computations.positionIndexToCells
Map? A Map where positionIndex is mapped to its cell, used primarily internally.
Returns Normal target
clone
Clones a cell. Returns the new cell.
Parameters
mesh
SimplicialComplexcell
Cell
Returns Cell cloned cell
computeCellCenter
Computes the center of a single cell.
Parameters
mesh
SimplicialComplexcell
Cell
Returns Position center
computeCenterPositions
Computes all of the centers of all the cells.
Parameters
mesh
SimplicialComplex
Returns Array<Position> centers
computeNormals
Updates all of the normals for all the positions using #averageNormalForPosition. If a normal doesn't exist, then it is created.
Parameters
mesh
SimplicialComplex
Returns SimplicialComplex
createBox
Creates a quad box of the given dimensions. This box will render as a
smoothed out box, as the normals are averaged. This is typically used for a
starting place for subdividing or extrusion operations. If the
optionalMesh
object is passed, then the box will be created inside of
that simplicial complex, otherwise a new mesh simplicial complex will be
generated.
Parameters
Returns SimplicialComplex
createBoxDisjoint
Creates a quad box of the given dimensions, but with non-joined positions. This box renders as a flat shaded box. If the optionalMesh object is passed, then the box will be created inside of that simplicial complex, otherwise a new mesh simplicial complex will be generated.
Parameters
Returns SimplicialComplex
createQuad
Create a quad with options. If the optionalMesh object is passed, then the quad will be created inside of that simplicial complex, otherwise a new mesh simplicial complex will be generated. Both the mesh simplicial complex and the created cell are returned in an object.
Parameters
options
Objectmesh
SimplicialComplex?= {}
Examples
Usage:
const {mesh, cell} = createQuad({ positions: [[-1, 0, -1], [-1, 0, 1], [1, 0, 1], [1, 0, -1]] })
const {mesh, cell} = createQuad({ w: 1, h: 1 })
const {mesh, cell} = createQuad()
Returns Object {mesh, cell}
elementsFromQuads
Returns an elements array using the given ArrayType
, which can be used by WebGL.
Parameters
mesh
SimplicialComplexdrawMode
String?= 'triangles'ArrayType
typeof?= Uint16Array
Returns Array Elements using the given ArrayType
, which can be used by WebGL.
extrude
Given a target cell, first inset it, then move it along the cell's normal outwards by a given distance.
Parameters
mesh
SimplicialComplexcell
CellinsetT
Number Value ranged from0
to1
, defaults to0
extrude
Number Distance to extrude, defaults to0
extrudeDisjoint
Given a target cell, first inset it, then move it along the cell's normal outwards by a given distance, but all new geometry generated will not share positions.
Parameters
mesh
SimplicialComplexcell
CellinsetT
Number = 0, ranged from0
(the edge) to1
(the center).extrude
Number = 0, the distance to extrude out.
flip
Flip a cell's normal to point the other way. Returns the cell.
Parameters
mesh
SimplicialComplexcell
Cell
Returns Cell The cell
getCellFromEdge
Find a cell given two position indices. Optionally provide a previousCell
that will not be matched against. Returns the first cell that matches.
Parameters
mesh
SimplicialComplexpositionIndexA
NumberpositionIndexB
NumberpreviousCell
Cell? Optional will not be matched against
Returns Cell
getCellNormal
Compute a cell's normal regardless of it's neighboring cells.
Parameters
mesh
SimplicialComplexcell
Celltarget
Normal? = []
Returns Normal The target normal.
getCellsFromPositionIndex
Given a position index, find any cells that include it.
Parameters
Returns Array<Cell> The target cells.
getCenter
Computes the center of a cell.
Parameters
mesh
SimplicialComplexcell
Celltarget
Position?= []
Returns Position center
getLoop
Gets a loop of cells. Given a single cell, start walking in both directions to select a loop. .
Parameters
mesh
SimplicialComplexcell
Celltype
String can either be"cells"
,"positions"
, or"normals"
.opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns Array an array according to the type
.
getNewGeometry
Get all newly created geometry of the given type from whatever arbitrary operations were done on the mesh. This assumes new geometry was created and not destroyed.
Parameters
Examples
Usage:
const extrudedCells = quad.getNewGeometry(mesh, "cells", () => {
quad.extrude(mesh, tipCell, 0.5, 3)
});
Returns Array
inset
Inset a cell some value between 0
(its edges) and 1
(its center).
b----------c
|\ q1 /|
| \ / |
| f----g |
|q0| tC |q2| tc = targetCell
| e----h |
| / \ |
|/ q3 \|
a----------d
Parameters
mesh
SimplicialComplexcell
Cellt
Number Specifies where the split should be. Ranged from0
to1
, defaults to0
.
Returns Array<Cell> cells [q0, q1, q2, q3, targetCell]
insetDisjoint
Inset a cell some value between 0
(its edges) and 1
(its center), but
keep the new cells disjoint so they do not share any positions.
bT----------cT
bL \ qT / cR
|\ \ / /|
| \ fT----gT / |
| fL fM----gM gR |
|qL| | tC | |qR| tC = targetCell
| eL eM----hM hR |
| / eB----hB \ |
|/ / \ \|
aL / qB \ dR
aB----------dB
Parameters
mesh
SimplicialComplexcell
Cellt
Number? value between 0 - 1 (optional, default0
)
Returns Array<Cell> cells [qL, qT, qR, qB, targetCell]
.
insetLoop
Given a cell, walk a loop and inset the loop, where 0 is the inset being on the edge, and 1 the inset being in the enter. Setting opposite to true will make the cell walk the loop in the opposite direction, e.g. up/down rather than left/right.
*----*----*----*----*----*----*----*----*----*
| | | | | | | | | |
| | |<---|----|----|----|--->| | |
| | | | |cell| | | | |
| | |<---|----|----|----|--->| | |
| | | | | | | | | |
*----*----*----*----*----*----*----*----*----*
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns SimplicialComplex
mergePositions
Combine all positions together and recompute the normals.
Parameters
mesh
SimplicialComplex
Returns SimplicialComplex
mirror
Clone all existing geometry, and mirror it about the given axis.
Parameters
mesh
SimplicialComplexcells
Cellaxis
Number is either0
,1
, or2
, which represents thex
,y
, andz
axis respectively.
splitHorizontal
Split a cell horizontally.
b--------c
| |
ab------cd
| |
a--------d
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
targetCell
splitHorizontalDisjoint
Split a cell horizontally into two new disconnected cells.
b--------c
| |
ab1----cd1
ab2----cd2
| target |
a--------d
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
targetCell
splitLoop
Given a cell, walk along the mesh in both directions and split the cell.
*--------*--------*--------*--------*--------*--------*--------*
| | | | | | | |
* *<-------*--------*--cell--*--------*------->* *
| | | | | | | |
*--------*--------*--------*--------*--------*--------*--------*
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns SimplicialComplex
splitVertical
Split a cell horizontally.
b---bc---c
| | |
| | |
a---ad---d
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
, defaults to0.5
.targetCell
splitVerticalDisjoint
Split a cell horizontally into two new disconnected cells.
b---bc1 bc2---c
| | | |
| | | |
a---ad1 ad2---d
Parameters
mesh
SimplicialComplexcell
Cellt
Number?= 0.5 Specifies where the split should be. Ranged from0
to1
, defaults to0.5
.targetCell
subdivide
Use catmull clark subdivision to smooth out the geometry. All normals will be recomputed. Under the hood this is a convenience function for the module gl-catmull-clark.
Parameters
mesh
SimplicialComplexsubdivisions
Numberpositions
Array<Position>?= mesh.positionscells
Cell?= mesh.cells
Returns SimplicialComplex
updateNormals
Updates all of the normals for all the positions using #averageNormalForPosition. If a normal doesn't exist, then it is created.
Parameters
mesh
SimplicialComplexcell
Cell
Returns SimplicialComplex
Three
splitVertical
Split a cell horizontally.
b---bc---c
| | |
| | |
a---ad---d
Parameters
splitVerticalDisjoint
Split a cell horizontally into two new disconnected cells.
b---bc1 bc2---c
| | | |
| | | |
a---ad1 ad2---d
Parameters
splitHorizontal
Split a cell horizontally.
b--------c
| |
ab------cd
| |
a--------d
Parameters
$0.positions
Array$0.cells
ArraytargetCell
Arrayt
Number Specifies where the split should be. Ranged from0
to1
_ref2
splitHorizontalDisjoint
Split a cell horizontally into two new disconnected cells.
b--------c
| |
ab1----cd1
ab2----cd2
| target |
a--------d
Parameters
inset
Inset a cell some value between 0
(its edges) and 1
(its center).
b----------c
|\ q1 /|
| \ / |
| f----g |
|q0| tQ |q2|
| e----h |
| / \ |
|/ q3 \|
a----------d
Parameters
Returns Array cells [q0, q1, q2, q3, tC]
where tC
is the targetCell
.
extrude
Given a target cell, first inset it, then move it along the cell's normal outwards by a given distance.
Parameters
averageNormalForPosition
Computes the average normal for a position given the connected cells.
Parameters
mesh
ObjectpositionIndex
Numbertarget
Array? = []normalCache
Map? = new Map() can be provided to cache intermediate normal computations.positionIndexToCells
Number
Returns any the targetNormal
insetDisjoint
Inset a cell some value between 0
(its edges) and 1
(its center), but
keep the new cells disjoint so they do not share any positions.
bT----------cT
bL \ qT / cR
|\ \ / /|
| \ fT----gT / |
| fL fM----gM gR |
|qL| | tC | |qR| tC = targetCell
| eL eM----hM hR |
| / eB----hB \ |
|/ / \ \|
aL / qB \ dR
aB----------dB
Parameters
Returns Array cells [q0, q1, q2, q3, tC]
where tC
is the targetCell
.
extrudeDisjoint
Given a target cell, first inset it, then move it along the cell's normal outwards by a given distance, but all new geometry generated will not share positions.
Parameters
getCenter
Computes the center of a cell
Parameters
Returns Array the targetPosition
clone
Clones a cell. Returns the new cell.
Parameters
Returns Array a new cell
updateNormals
Updates all of the normals for all the positions using #averageNormalForPosition. If a normal doesn't exist, then it is created.
Parameters
Returns Object mesh
getCellNormal
Compute a cell's normal regardless of it's neighboring cells.
Parameters
Returns Array The target normal.
getCellsFromPositionIndex
Given a position index, find any cells that include it.
Parameters
Returns Array The target cells.
flip
Flip a cell's normal to point the other way. Returns the cell.
Parameters
Returns Array The cell
createQuad
Create a quad with options. If the optionalMesh object is passed, then the quad will be created inside of that simplicial complex, otherwise a new mesh simplicial complex will be generated. Both the mesh simplicial complex and the created cell are returned in an object.
Parameters
Examples
Usage:
const {mesh, cell} = createQuad({ positions: [[-1, 0, -1], [-1, 0, 1], [1, 0, 1], [1, 0, -1]] })
const {mesh, cell} = createQuad({ w: 1, h: 1 })
const {mesh, cell} = createQuad()
Returns Object {mesh, cell}
createBoxDisjoint
Creates a quad box of the given dimensions, but with non-joined positions. This box renders as a flat shaded box. If the optionalMesh object is passed, then the box will be created inside of that simplicial complex, otherwise a new mesh simplicial complex will be generated.
Parameters
Returns Object a simplicial complex
createBox
Creates a quad box of the given dimensions. This box will render as a
smoothed out box, as the normals are averaged. This is typically used for a
starting place for subdividing or extrusion operations. If the
optionalMesh
object is passed, then the box will be created inside of
that simplicial complex, otherwise a new mesh simplicial complex will be
generated.
Parameters
Returns Object a simplicial complex
mergePositions
Combine all positions together and recompute the normals.
Parameters
mesh
Object
Returns Object mesh
elementsFromQuads
Returns an elements array using the given ArrayType
, which can be used by WebGL.
Parameters
Returns Array Elements using the given ArrayType
, which can be used by WebGL.
computeNormals
Updates all of the normals for all the positions using #averageNormalForPosition. If a normal doesn't exist, then it is created.
Parameters
mesh
Object
Returns Object The mesh
splitLoop
Given a cell, walk along the mesh in both directions and split the cell.
*--------*--------*--------*--------*--------*--------*--------*
| | | | | | | |
* *<-------*--------*--cell--*--------*------->* *
| | | | | | | |
*--------*--------*--------*--------*--------*--------*--------*
Parameters
mesh
Objectcell
Arrayt
Number Specifies where the split should be. Ranged from0
to1
opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns Object mesh
getCellFromEdge
Find a cell given two position indices. Optionally provide a previousCell
that will not be matched against. Returns the first cell that matches.
Parameters
mesh
ObjectpositionIndexA
NumberpositionIndexB
NumberpreviousCell
Array? Optional will not be matched against
Returns Array Elements using the given ArrayType
, which can be used by WebGL.
getNewGeometry
Get all newly created geometry of the given type from whatever arbitrary operations were done on the mesh. This assumes new geometry was created and not destroyed.
Parameters
Examples
Usage:
const extrudedCells = quad.getNewGeometry(mesh, "cells", () => {
quad.extrude(mesh, tipCell, 0.5, 3)
});
Returns Array
subdivide
Use catmull clark subdivision to smooth out the geometry. All normals will be recomputed. Under the hood this is a convenience function for the module gl-catmull-clark.
Parameters
Returns Object mesh
computeCenterPositions
Computes all of the centers of all the cells.
Parameters
mesh
Object
Returns any A new array
computeCellCenter
Computes the center of a single cell.
Parameters
Returns any A new array
insetLoop
Given a cell, walk a loop and inset the loop, where 0 is the inset being on the edge, and 1 the inset being in the enter. Setting opposite to true will make the cell walk the loop in the opposite direction, e.g. up/down rather than left/right.
*----*----*----*----*----*----*----*----*----*
| | | | | | | | | |
| | |<---|----|----|----|--->| | |
| | | | |cell| | | | |
| | |<---|----|----|----|--->| | |
| | | | | | | | | |
*----*----*----*----*----*----*----*----*----*
Parameters
mesh
Objectcell
Arrayt
Number Specifies where the split should be. Ranged from0
to1
opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns Object mesh
getLoop
Gets a loop of cells. Given a single cell, start walking in both directions to select a loop. .
Parameters
mesh
Objectcell
Arraytype
String can either be"cells"
,"positions"
, or"normals"
.opposite
Boolean will walk in the opposite direction, e.g. up and down, versus left and right
Returns Array an array according to the type
.
mirror
Clone all existing geometry, and mirror it about the given axis.
Parameters