quads
quads copied to clipboard
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
SimplicialComplex -
positionIndex
Number -
target
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
SimplicialComplex -
cell
Cell
Returns Cell cloned cell
computeCellCenter
Computes the center of a single cell.
Parameters
-
mesh
SimplicialComplex -
cell
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
Object -
mesh
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
SimplicialComplex -
drawMode
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
SimplicialComplex -
cell
Cell -
insetT
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
SimplicialComplex -
cell
Cell -
insetT
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
SimplicialComplex -
cell
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
SimplicialComplex -
positionIndexA
Number -
positionIndexB
Number -
previousCell
Cell? Optional will not be matched against
Returns Cell
getCellNormal
Compute a cell's normal regardless of it's neighboring cells.
Parameters
-
mesh
SimplicialComplex -
cell
Cell -
target
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
SimplicialComplex -
cell
Cell -
target
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
SimplicialComplex -
cell
Cell -
type
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cells
Cell -
axis
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
cell
Cell -
t
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
SimplicialComplex -
subdivisions
Number -
positions
Array<Position>?= mesh.positions -
cells
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
SimplicialComplex -
cell
Cell
Returns SimplicialComplex
Three
splitVertical
Split a cell horizontally.
b---bc---c
| | |
| | |
a---ad---d
Parameters
-
$0
Object quad -
targetCell
Array -
t
Number Specifies where the split should be. Ranged from0
to1
-
_ref
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
Array -
targetCell
Array -
t
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
Object -
positionIndex
Number -
target
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
Object -
cell
Array -
t
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
Object -
positionIndexA
Number -
positionIndexB
Number -
previousCell
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
Object -
cell
Array -
t
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
Object -
cell
Array -
type
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