Documentation ¶
Overview ¶
Package model3d provides a set of APIs for creating, manipulating, and storing 3D models.
model3d includes a few sub-packages:
- render3d - ray tracing, materials, etc.
- model2d - 2D graphics, smoothing, bitmaps.
- toolbox3d - modular 3D-printable components to use in larger 3D models.
In addition, model3d comes with a large collection of examples for both modeling and rendering.
Representations ¶
Models can be represented in three different ways, and model3d can convert between them seamlessly.
In particular, models can be:
- *Mesh - a triangle mesh, good for exporting to most 3D CAD tools, renderers, etc.
- Solid - a 3D boolean function defining which points are contained in the model. Ideal for composition, hand-coding, etc.
- Collider - a surface that reports collisions with rays and other geometric shapes. Ideal for ray tracing, rendering, and physics.
Generally, it is easiest to create new models by implementing the Solid interface, or by using existing solids like *Sphere or *Cylinder and combining them with JoinedSolid or SubtractedSolid.
To convert a Solid to a *Mesh, use MarchingCubes() or MarchingCubesSearch() for more precision. To convert a Solid to a Collider, use SolidCollider or simply create a Mesh and convert that to a Collider.
To convert a *Mesh to a Collider, use MeshToCollider(). To convert a *Mesh to a Solid, first convert it to a Collider and then convert that to a Solid.
To convert a Collider to a Solid, use NewColliderSolid() or NewColliderSolidHollow(). To convert a Collider to a *Mesh, the simplest approach is to convert it to a Solid and then to convert the Solid to a *Mesh.
Creating models ¶
The easiest way to create new models is by defining an object that implements the Solid interface. Once defined, a Solid can be converted to a Mesh and exported to a file (e.g. an STL file for 3D printing).
For example, here's how to implement a sphere as a Solid, taken from the actual model3d.Sphere type:
type Sphere struct { Center Coord3D Radius float64 } func (s *Sphere) Min() Coord3D { return Coord3D{ X: s.Center.X - s.Radius, Y: s.Center.Y - s.Radius, Z: s.Center.Z - s.Radius, } } func (s *Sphere) Max() Coord3D { return Coord3D{ X: s.Center.X + s.Radius, Y: s.Center.Y + s.Radius, Z: s.Center.Z + s.Radius, } } func (s *Sphere) Contains(c Coord3D) bool { return c.Dist(s.Center) <= s.Radius }
Once you have implemented a Solid, you can create a mesh and export it to a file like so:
solid := &Sphere{...} mesh := MarchingCubesSearch(solid, 0.1, 8) mesh.SaveGroupedSTL("output.stl")
In the above example, the mesh is created with an epsilon of 0.01 and 8 search steps. These parameters control the mesh resolution. See MarchingCubesSearch() for more details.
Mesh manipulation ¶
The Mesh type provides various methods to check for singularities, fix small holes, eliminate redundant triangles, etc. There are also APIs that operate on a Mesh in more complex ways, making it easier to generate meshes programmatically:
- Decimator - polygon reduction.
- MeshSmoother - smoothing for reducing sharp edges or corners.
- Subdivider - edge-based sub-division to add resolution where it is needed.
Exporting models ¶
Software for 3D printing, rendering, and modeling typically expects to import 3D models as triangle meshes. Thus, model3d provides a number of ways to import and export triangle meshes. The simplest method is Mesh.SaveGroupedSTL(), which exports and STL file to a path. For colored models, Mesh.SaveMaterialOBJ() is the method to use.
Index ¶
- Constants
- Variables
- func BoundsValid(b Bounder) bool
- func BuildMaterialOBJ(t []*Triangle, c func(t *Triangle) [3]float64) (o *fileformats.OBJFile, m *fileformats.MTLFile)
- func ColliderContains(c Collider, coord Coord3D, margin float64) bool
- func CrossSectionSolid(solid Solid, axis int, axisValue float64) model2d.Solid
- func EncodeMaterialOBJ(triangles []*Triangle, colorFunc func(t *Triangle) [3]float64) []byte
- func EncodePLY(triangles []*Triangle, colorFunc func(Coord3D) [3]uint8) []byte
- func EncodeSTL(triangles []*Triangle) []byte
- func GroupBounders(objects []Bounder)
- func GroupTriangles(faces []*Triangle)
- func InBounds(b Bounder, c Coord3D) bool
- func Triangulate(polygon []Coord2D) [][3]Coord2D
- func VertexColorsToTriangle(f func(c Coord3D) [3]float64) func(t *Triangle) [3]float64
- func WriteMaterialOBJ(w io.Writer, ts []*Triangle, colorFunc func(t *Triangle) [3]float64) error
- func WritePLY(w io.Writer, triangles []*Triangle, colorFunc func(Coord3D) [3]uint8) error
- func WriteSTL(w io.Writer, triangles []*Triangle) error
- type ARAP
- func (a *ARAP) Deform(constraints ARAPConstraints) *Mesh
- func (a *ARAP) DeformMap(constraints ARAPConstraints, initialGuess map[Coord3D]Coord3D) map[Coord3D]Coord3D
- func (a *ARAP) Laplace(constraints ARAPConstraints) map[Coord3D]Coord3D
- func (a *ARAP) MaxIterations() int
- func (a *ARAP) MinIterations() int
- func (a *ARAP) SeqDeformer() func(ARAPConstraints) *Mesh
- func (a *ARAP) SetMaxIterations(m int)
- func (a *ARAP) SetMinIterations(m int)
- func (a *ARAP) SetTolerance(t float64)
- func (a *ARAP) Tolerance() float64
- type ARAPConstraints
- type ARAPWeightingScheme
- type BVH
- type Bounder
- type Capsule
- func (c *Capsule) Contains(coord Coord3D) bool
- func (c *Capsule) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (c *Capsule) Max() Coord3D
- func (c *Capsule) Min() Coord3D
- func (c *Capsule) NormalSDF(coord Coord3D) (Coord3D, float64)
- func (c *Capsule) PointSDF(coord Coord3D) (Coord3D, float64)
- func (c *Capsule) RayCollisions(r *Ray, f func(RayCollision)) int
- func (c *Capsule) SDF(coord Coord3D) float64
- func (c *Capsule) SphereCollision(center Coord3D, r float64) bool
- type Collider
- type ColliderSolid
- type Cone
- func (c *Cone) Contains(p Coord3D) bool
- func (c *Cone) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (c *Cone) Max() Coord3D
- func (c *Cone) Min() Coord3D
- func (c *Cone) NormalSDF(coord Coord3D) (Coord3D, float64)
- func (c *Cone) PointSDF(coord Coord3D) (Coord3D, float64)
- func (c *Cone) RayCollisions(r *Ray, f func(RayCollision)) int
- func (c *Cone) SDF(coord Coord3D) float64
- func (c *Cone) SphereCollision(center Coord3D, r float64) bool
- type ConvexPolytope
- type Coord2D
- type Coord3D
- func NewCoord3DArray(a [3]float64) Coord3D
- func NewCoord3DRandBounds(min, max Coord3D) Coord3D
- func NewCoord3DRandNorm() Coord3D
- func NewCoord3DRandUniform() Coord3D
- func NewCoord3DRandUnit() Coord3D
- func Ones(a float64) Coord3D
- func X(x float64) Coord3D
- func XY(x, y float64) Coord3D
- func XYZ(x, y, z float64) Coord3D
- func XZ(x, z float64) Coord3D
- func Y(y float64) Coord3D
- func YZ(y, z float64) Coord3D
- func Z(z float64) Coord3D
- func (c Coord3D) Add(c1 Coord3D) Coord3D
- func (c Coord3D) AddScalar(s float64) Coord3D
- func (c Coord3D) Array() [3]float64
- func (c Coord3D) Coord2D() Coord2D
- func (c Coord3D) Cross(c1 Coord3D) Coord3D
- func (c Coord3D) Dist(c1 Coord3D) float64
- func (c Coord3D) Div(c1 Coord3D) Coord3D
- func (c Coord3D) Dot(c1 Coord3D) float64
- func (c Coord3D) Geo() GeoCoord
- func (c Coord3D) L1Dist(c1 Coord3D) float64
- func (c Coord3D) Max(c1 Coord3D) Coord3D
- func (c Coord3D) Mid(c1 Coord3D) Coord3D
- func (c Coord3D) Min(c1 Coord3D) Coord3D
- func (c Coord3D) Mul(c1 Coord3D) Coord3D
- func (c Coord3D) Norm() float64
- func (c Coord3D) NormSquared() float64
- func (c Coord3D) Normalize() Coord3D
- func (c Coord3D) OrthoBasis() (Coord3D, Coord3D)
- func (c Coord3D) ProjectOut(c1 Coord3D) Coord3D
- func (c Coord3D) Recip() Coord3D
- func (c Coord3D) Reflect(c1 Coord3D) Coord3D
- func (c Coord3D) Scale(s float64) Coord3D
- func (c Coord3D) SquaredDist(c1 Coord3D) float64
- func (c Coord3D) Sub(c1 Coord3D) Coord3D
- func (c Coord3D) Sum() float64
- func (c Coord3D) XY() Coord2D
- func (c Coord3D) XZ() Coord2D
- func (c Coord3D) YX() Coord2D
- func (c Coord3D) YZ() Coord2D
- func (c Coord3D) ZX() Coord2D
- func (c Coord3D) ZY() Coord2D
- type CoordMap
- func (m *CoordMap) Delete(key Coord3D)
- func (m *CoordMap) KeyRange(f func(key Coord3D) bool)
- func (m *CoordMap) Len() int
- func (m *CoordMap) Load(key Coord3D) (interface{}, bool)
- func (m *CoordMap) Range(f func(key Coord3D, value interface{}) bool)
- func (m *CoordMap) Store(key Coord3D, value interface{})
- func (m *CoordMap) Value(key Coord3D) interface{}
- func (m *CoordMap) ValueRange(f func(value interface{}) bool)
- type CoordToCoord
- func (m *CoordToCoord) Delete(key Coord3D)
- func (m *CoordToCoord) KeyRange(f func(key Coord3D) bool)
- func (m *CoordToCoord) Len() int
- func (m *CoordToCoord) Load(key Coord3D) (Coord3D, bool)
- func (m *CoordToCoord) Range(f func(key Coord3D, value Coord3D) bool)
- func (m *CoordToCoord) Store(key Coord3D, value Coord3D)
- func (m *CoordToCoord) Value(key Coord3D) Coord3D
- func (m *CoordToCoord) ValueRange(f func(value Coord3D) bool)
- type CoordToFaces
- func (m *CoordToFaces) Append(key Coord3D, x *Triangle) []*Triangle
- func (m *CoordToFaces) Delete(key Coord3D)
- func (m *CoordToFaces) KeyRange(f func(key Coord3D) bool)
- func (m *CoordToFaces) Len() int
- func (m *CoordToFaces) Load(key Coord3D) ([]*Triangle, bool)
- func (m *CoordToFaces) Range(f func(key Coord3D, value []*Triangle) bool)
- func (m *CoordToFaces) Store(key Coord3D, value []*Triangle)
- func (m *CoordToFaces) Value(key Coord3D) []*Triangle
- func (m *CoordToFaces) ValueRange(f func(value []*Triangle) bool)
- type CoordToInt
- func (m *CoordToInt) Add(key Coord3D, x int) int
- func (m *CoordToInt) Delete(key Coord3D)
- func (m *CoordToInt) KeyRange(f func(key Coord3D) bool)
- func (m *CoordToInt) Len() int
- func (m *CoordToInt) Load(key Coord3D) (int, bool)
- func (m *CoordToInt) Range(f func(key Coord3D, value int) bool)
- func (m *CoordToInt) Store(key Coord3D, value int)
- func (m *CoordToInt) Value(key Coord3D) int
- func (m *CoordToInt) ValueRange(f func(value int) bool)
- type CoordTree
- func (c *CoordTree) Contains(p Coord3D) bool
- func (c *CoordTree) Dist(p Coord3D) float64
- func (c *CoordTree) Empty() bool
- func (c *CoordTree) KNN(k int, p Coord3D) []Coord3D
- func (c *CoordTree) Leaf() bool
- func (c *CoordTree) NearestNeighbor(p Coord3D) Coord3D
- func (c *CoordTree) Slice() []Coord3D
- func (c *CoordTree) SphereCollision(p Coord3D, r float64) bool
- type Cylinder
- func (c *Cylinder) Contains(p Coord3D) bool
- func (c *Cylinder) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (c *Cylinder) Max() Coord3D
- func (c *Cylinder) Min() Coord3D
- func (c *Cylinder) NormalSDF(coord Coord3D) (Coord3D, float64)
- func (c *Cylinder) PointSDF(coord Coord3D) (Coord3D, float64)
- func (c *Cylinder) RayCollisions(r *Ray, f func(RayCollision)) int
- func (c *Cylinder) SDF(coord Coord3D) float64
- func (c *Cylinder) SphereCollision(center Coord3D, r float64) bool
- type CylinderSolid
- type Decimator
- type DistTransform
- type EdgeMap
- func (m *EdgeMap) Delete(key [2]Coord3D)
- func (m *EdgeMap) KeyRange(f func(key [2]Coord3D) bool)
- func (m *EdgeMap) Len() int
- func (m *EdgeMap) Load(key [2]Coord3D) (interface{}, bool)
- func (m *EdgeMap) Range(f func(key [2]Coord3D, value interface{}) bool)
- func (m *EdgeMap) Store(key [2]Coord3D, value interface{})
- func (m *EdgeMap) Value(key [2]Coord3D) interface{}
- func (m *EdgeMap) ValueRange(f func(value interface{}) bool)
- type EdgeToBool
- func (m *EdgeToBool) Delete(key [2]Coord3D)
- func (m *EdgeToBool) KeyRange(f func(key [2]Coord3D) bool)
- func (m *EdgeToBool) Len() int
- func (m *EdgeToBool) Load(key [2]Coord3D) (bool, bool)
- func (m *EdgeToBool) Range(f func(key [2]Coord3D, value bool) bool)
- func (m *EdgeToBool) Store(key [2]Coord3D, value bool)
- func (m *EdgeToBool) Value(key [2]Coord3D) bool
- func (m *EdgeToBool) ValueRange(f func(value bool) bool)
- type EdgeToInt
- func (m *EdgeToInt) Add(key [2]Coord3D, x int) int
- func (m *EdgeToInt) Delete(key [2]Coord3D)
- func (m *EdgeToInt) KeyRange(f func(key [2]Coord3D) bool)
- func (m *EdgeToInt) Len() int
- func (m *EdgeToInt) Load(key [2]Coord3D) (int, bool)
- func (m *EdgeToInt) Range(f func(key [2]Coord3D, value int) bool)
- func (m *EdgeToInt) Store(key [2]Coord3D, value int)
- func (m *EdgeToInt) Value(key [2]Coord3D) int
- func (m *EdgeToInt) ValueRange(f func(value int) bool)
- type FaceSDF
- type GeneralBVH
- type GeoCoord
- type IntersectedSolid
- type JoinedCollider
- type JoinedSolid
- type JoinedTransform
- type LinearConstraint
- type Matrix2
- type Matrix3
- func (m *Matrix3) Add(m1 *Matrix3) *Matrix3
- func (m *Matrix3) Det() float64
- func (m *Matrix3) Eigenvalues() [3]complex128
- func (m *Matrix3) Inverse() *Matrix3
- func (m *Matrix3) InvertInPlace()
- func (m *Matrix3) InvertInPlaceDet(det float64)
- func (m *Matrix3) Mul(m1 *Matrix3) *Matrix3
- func (m *Matrix3) MulColumn(c Coord3D) Coord3D
- func (m *Matrix3) MulColumnInv(c Coord3D, det float64) Coord3D
- func (m *Matrix3) SVD(u, s, v *Matrix3)
- func (m *Matrix3) Scale(s float64)
- func (m *Matrix3) Transpose() *Matrix3
- type Matrix3Transform
- type Mesh
- func DecimateSimple(m *Mesh, epsilon float64) *Mesh
- func LoopSubdivision(m *Mesh, iters int) *Mesh
- func MarchingCubes(s Solid, delta float64) *Mesh
- func MarchingCubesC2F(s Solid, bigDelta, smallDelta, extraSpace float64, iters int) *Mesh
- func MarchingCubesConj(s Solid, delta float64, iters int, xforms ...Transform) *Mesh
- func MarchingCubesFilter(s Solid, f func(*Rect) bool, delta float64) *Mesh
- func MarchingCubesSearch(s Solid, delta float64, iters int) *Mesh
- func MarchingCubesSearchFilter(s Solid, f func(*Rect) bool, delta float64, iters int) *Mesh
- func NewMesh() *Mesh
- func NewMeshCone(tip, base Coord3D, radius float64, numStops int) *Mesh
- func NewMeshCylinder(p1, p2 Coord3D, radius float64, numStops int) *Mesh
- func NewMeshIcosahedron() *Mesh
- func NewMeshIcosphere(center Coord3D, radius float64, n int) *Mesh
- func NewMeshPolar(radius func(g GeoCoord) float64, stops int) *Mesh
- func NewMeshRect(min, max Coord3D) *Mesh
- func NewMeshTorus(center, axis Coord3D, innerRadius, outerRadius float64, ...) *Mesh
- func NewMeshTriangles(faces []*Triangle) *Mesh
- func ProfileMesh(m2d *model2d.Mesh, minZ, maxZ float64) *Mesh
- func SubdivideEdges(m *Mesh, n int) *Mesh
- func (m *Mesh) Add(f *Triangle)
- func (m *Mesh) AddMesh(m1 *Mesh)
- func (m *Mesh) AddQuad(p1, p2, p3, p4 Coord3D) [2]*Triangle
- func (m *Mesh) Area() float64
- func (m *Mesh) Blur(rates ...float64) *Mesh
- func (m *Mesh) BlurFiltered(f func(c1, c2 Coord3D) bool, rates ...float64) *Mesh
- func (m *Mesh) Contains(f *Triangle) bool
- func (m *Mesh) Copy() *Mesh
- func (m *Mesh) DeepCopy() *Mesh
- func (m *Mesh) EliminateCoplanar(epsilon float64) *Mesh
- func (m *Mesh) EliminateEdges(f func(tmp *Mesh, segment Segment) bool) *Mesh
- func (m *Mesh) EncodeMaterialOBJ(colorFunc func(t *Triangle) [3]float64) []byte
- func (m *Mesh) EncodePLY(colorFunc func(c Coord3D) [3]uint8) []byte
- func (m *Mesh) EncodeSTL() []byte
- func (m *Mesh) Find(ps ...Coord3D) []*Triangle
- func (m *Mesh) FlattenBase(maxAngle float64) *Mesh
- func (m *Mesh) FlipDelaunay() *Mesh
- func (m *Mesh) Iterate(f func(*Triangle))
- func (m *Mesh) IterateSorted(f func(*Triangle), cmp func(f1, f2 *Triangle) bool)
- func (m *Mesh) IterateVertices(f func(c Coord3D))
- func (m *Mesh) MapCoords(f func(Coord3D) Coord3D) *Mesh
- func (m *Mesh) Max() Coord3D
- func (m *Mesh) Min() Coord3D
- func (m *Mesh) NeedsRepair() bool
- func (m *Mesh) Neighbors(f *Triangle) []*Triangle
- func (m *Mesh) Remove(f *Triangle)
- func (m *Mesh) Repair(epsilon float64) *Mesh
- func (m *Mesh) RepairNormals(epsilon float64) (*Mesh, int)
- func (m *Mesh) Rotate(axis Coord3D, angle float64) *Mesh
- func (m *Mesh) SaveGroupedSTL(path string) error
- func (m *Mesh) SaveMaterialOBJ(path string, colorFunc func(t *Triangle) [3]float64) error
- func (m *Mesh) Scale(s float64) *Mesh
- func (m *Mesh) SelfIntersections() int
- func (m *Mesh) SingularVertices() []Coord3D
- func (m *Mesh) SmoothAreas(stepSize float64, iters int) *Mesh
- func (m *Mesh) Transform(t Transform) *Mesh
- func (m *Mesh) Translate(v Coord3D) *Mesh
- func (m *Mesh) TriangleSlice() []*Triangle
- func (m *Mesh) VertexSlice() []Coord3D
- func (m *Mesh) Volume() float64
- type MeshHierarchy
- type MeshSmoother
- type MultiCollider
- type NormalSDF
- type PointSDF
- type Ray
- type RayCollision
- type Rect
- func (r *Rect) Contains(c Coord3D) bool
- func (r *Rect) Expand(delta float64) *Rect
- func (r *Rect) FirstRayCollision(ray *Ray) (RayCollision, bool)
- func (r *Rect) Max() Coord3D
- func (r *Rect) Min() Coord3D
- func (r *Rect) NormalSDF(c Coord3D) (Coord3D, float64)
- func (r *Rect) PointSDF(c Coord3D) (Coord3D, float64)
- func (r *Rect) RayCollisions(ray *Ray, f func(RayCollision)) int
- func (r *Rect) SDF(c Coord3D) float64
- func (r *Rect) SphereCollision(c Coord3D, radius float64) bool
- type RectCollider
- type RectSolid
- type SDF
- type Scale
- type Segment
- type SegmentCollider
- type Solid
- func CacheSolidBounds(s Solid) Solid
- func CheckedFuncSolid(min, max Coord3D, f func(Coord3D) bool) Solid
- func ForceSolidBounds(s Solid, min, max Coord3D) Solid
- func FuncSolid(min, max Coord3D, f func(Coord3D) bool) Solid
- func ProfileSolid(solid2d model2d.Solid, minZ, maxZ float64) Solid
- func RevolveSolid(solid model2d.Solid, axis Coord3D) Solid
- func RotateSolid(solid Solid, axis Coord3D, angle float64) Solid
- func SDFToSolid(s SDF, outset float64) Solid
- func ScaleSolid(solid Solid, s float64) Solid
- func SmoothJoin(radius float64, sdfs ...SDF) Solid
- func SmoothJoinV2(radius float64, sdfs ...NormalSDF) Solid
- func StackSolids(s ...Solid) Solid
- func TransformSolid(t Transform, s Solid) Solid
- func TranslateSolid(solid Solid, offset Coord3D) Solid
- type SolidCollider
- type Sphere
- func (s *Sphere) Contains(coord Coord3D) bool
- func (s *Sphere) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (s *Sphere) Max() Coord3D
- func (s *Sphere) Min() Coord3D
- func (s *Sphere) NormalSDF(coord Coord3D) (Coord3D, float64)
- func (s *Sphere) PointSDF(coord Coord3D) (Coord3D, float64)
- func (s *Sphere) RayCollisions(r *Ray, f func(RayCollision)) int
- func (s *Sphere) SDF(coord Coord3D) float64
- func (s *Sphere) SphereCollision(center Coord3D, r float64) bool
- type SphereSolid
- type StackedSolid
- type Subdivider
- type SubtractedSolid
- type Torus
- func (t *Torus) Contains(c Coord3D) bool
- func (t *Torus) FirstRayCollision(ray *Ray) (RayCollision, bool)
- func (t *Torus) Max() Coord3D
- func (t *Torus) Min() Coord3D
- func (t *Torus) NormalSDF(c Coord3D) (Coord3D, float64)
- func (t *Torus) PointSDF(c Coord3D) (Coord3D, float64)
- func (t *Torus) RayCollisions(ray *Ray, f func(RayCollision)) int
- func (t *Torus) SDF(c Coord3D) float64
- func (t *Torus) SphereCollision(c Coord3D, r float64) bool
- type TorusSolid
- type Transform
- type Translate
- type Triangle
- func (t *Triangle) Area() float64
- func (t *Triangle) AreaGradient() *Triangle
- func (t *Triangle) Closest(c Coord3D) Coord3D
- func (t *Triangle) Dist(c Coord3D) float64
- func (t *Triangle) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (t *Triangle) Max() Coord3D
- func (t *Triangle) Min() Coord3D
- func (t *Triangle) Normal() Coord3D
- func (t *Triangle) RayCollisions(r *Ray, f func(RayCollision)) int
- func (t *Triangle) RectCollision(rect *Rect) bool
- func (t *Triangle) SegmentCollision(s Segment) bool
- func (t *Triangle) Segments() [3]Segment
- func (t *Triangle) SharesEdge(t1 *Triangle) bool
- func (t *Triangle) SphereCollision(c Coord3D, r float64) bool
- func (t *Triangle) TriangleCollisions(t1 *Triangle) []Segment
- type TriangleCollider
- type TriangleCollision
- type VoxelSmoother
Constants ¶
const ( DefaultDecimatorMinAspectRatio = 0.1 DefaultDecimatorFeatureAngle = 0.5 )
const ( // ARAPDefaultTolerance is the default convergence // tolerance for ARAP. // It allows for early convergence stopping. ARAPDefaultTolerance = 1e-3 // ARAPMaxIterations is the default maximum number // of iterations for ARAP. ARAPMaxIterations = 5000 // ARAPMinIterations is the default minimum number // of iterations before early stopping is allowed. ARAPMinIterations = 2 )
Variables ¶
var Origin = Coord3D{}
Functions ¶
func BoundsValid ¶ added in v0.2.9
BoundsValid checks for numerical issues with the bounds.
func BuildMaterialOBJ ¶ added in v0.2.15
func BuildMaterialOBJ(t []*Triangle, c func(t *Triangle) [3]float64) (o *fileformats.OBJFile, m *fileformats.MTLFile)
BuildMaterialOBJ constructs obj and mtl files from a triangle mesh where each triangle's color is determined by a function c.
Since the obj file must reference the mtl file, it does so by the name "material.mtl". Change o.MaterialFiles if this is not desired.
func ColliderContains ¶ added in v0.2.11
ColliderContains checks if a point is within a Collider and at least margin away from the border.
If the margin is negative, points are also conatined if the point is less than -margin away from the surface.
func CrossSectionSolid ¶ added in v0.2.13
CrossSectionSolid creates a 2D cross-section of a 3D solid as a 2D solid.
The axis is 0, 1, or 2 for X, Y, or Z respectively. The axisValue is the value for the axis at which a plane is constructed.
func EncodeMaterialOBJ ¶
EncodeMaterialOBJ encodes a 3D model as a zip file containing both an OBJ and an MTL file.
The colorFunc maps faces to real-valued RGB colors.
The encoding creates a different material for every color, so the resulting file will be much smaller if a few identical colors are reused for many triangles.
func EncodePLY ¶
EncodePLY encodes a 3D model as a PLY file, including colors for every vertex.
The colorFunc maps coordinates to 24-bit RGB colors.
func EncodeSTL ¶
EncodeSTL encodes a list of triangles in the binary STL format for use in 3D printing.
func GroupBounders ¶ added in v0.2.11
func GroupBounders(objects []Bounder)
GroupBounders sorts a slice of objects into a balanced bounding box hierarchy.
The sorted slice can be recursively cut in half, and each half will be spatially separated as well as possible along some axis. To cut a slice in half, divide the length by two, round down, and use the result as the start index for the second half.
func GroupTriangles ¶
func GroupTriangles(faces []*Triangle)
GroupTriangles is like GroupBounders, but for triangles in particular.
This can be used to prepare models for being turned into a collider efficiently, or for storing meshes in an order well-suited for file compression.
The resulting hierarchy can be passed directly to GroupedTrianglesToCollider().
func Triangulate ¶
Triangulate turns any simple polygon into a set of equivalent triangles.
The polygon is passed as a series of points, in order. The first point is re-used as the ending point, so no ending should be explicitly specified.
func VertexColorsToTriangle ¶
VertexColorsToTriangle creates a per-triangle color function that averages the colors at each of the vertices.
func WriteMaterialOBJ ¶ added in v0.1.1
WriteMaterialOBJ encodes a 3D model as a zip file containing both an OBJ and an MTL file.
The colorFunc maps faces to real-valued RGB colors.
The encoding creates a different material for every color, so the resulting file will be much smaller if a few identical colors are reused for many triangles.
Types ¶
type ARAP ¶ added in v0.2.2
type ARAP struct {
// contains filtered or unexported fields
}
ARAP implements as-rigid-as-possible deformations for a pre-determined mesh.
func NewARAP ¶ added in v0.2.2
NewARAP creates an ARAP instance for the given mesh topology.
The ARAP instance will not hold a reference to m or its triangles. Rather, it copies the data as needed.
The instance uses cotangent weights, which are only guaranteed to work on meshes with smaller-than-right angles. For other weighting options, see NewARAPWeighted().
func NewARAPWeighted ¶ added in v0.2.2
func NewARAPWeighted(m *Mesh, linear, rotation ARAPWeightingScheme) *ARAP
NewARAPWeighted creates an ARAP with a specified weighting scheme.
The linear weighting scheme is used for linear solves, whereas the rotation weighting scheme is used for finding rigid transformations.
The ARAP instance will not hold a reference to m or its triangles. Rather, it copies the data as needed.
func (*ARAP) Deform ¶ added in v0.2.2
func (a *ARAP) Deform(constraints ARAPConstraints) *Mesh
Deform creates a new mesh by enforcing constraints on some points of the mesh.
func (*ARAP) DeformMap ¶ added in v0.2.2
func (a *ARAP) DeformMap(constraints ARAPConstraints, initialGuess map[Coord3D]Coord3D) map[Coord3D]Coord3D
DeformMap performs constrained mesh deformation.
The constraints argument maps coordinates from the original mesh to their new, fixed locations.
If the initialGuess is specified, it is used for the first iteration of the algorithm as a starting point for the deformation.
The result maps all old coordinates to new coordinates.
func (*ARAP) Laplace ¶ added in v0.2.2
func (a *ARAP) Laplace(constraints ARAPConstraints) map[Coord3D]Coord3D
Laplace deforms the mesh using a simple Laplacian heuristic.
This can be used to generate an initial guess for the more general Deform() method.
The result maps all old coordinates to new coordinates.
func (*ARAP) MaxIterations ¶ added in v0.2.2
MaxIterations gets the maximum allowed number of steps before optimization terminates.
func (*ARAP) MinIterations ¶ added in v0.2.2
MinIterations gets the minimum allowed number of steps before optimization terminates.
func (*ARAP) SeqDeformer ¶ added in v0.2.2
func (a *ARAP) SeqDeformer() func(ARAPConstraints) *Mesh
SeqDeformer creates a function that deforms the mesh using the previous deformed mesh as a starting point. This is useful for animations and/or user interaction.
The returned function is not safe to call from multiple Goroutines concurrently.
func (*ARAP) SetMaxIterations ¶ added in v0.2.2
SetMaxIterations sets the maximum allowed number of steps before optimization terminates.
func (*ARAP) SetMinIterations ¶ added in v0.2.2
SetMinIterations sets the minimum allowed number of steps before optimization terminates.
func (*ARAP) SetTolerance ¶ added in v0.2.2
SetTolerance changes the convergence tolerance. Lower values make the algorithm run longer but arrive at more accurate values.
See ARAPDefaultTolerance.
type ARAPConstraints ¶ added in v0.2.2
ARAPConstraints maps coordinates from an original mesh to destination coordinates on a deformed mesh.
type ARAPWeightingScheme ¶ added in v0.2.2
type ARAPWeightingScheme int
const ( // ARAPWeightingCotangent is the default weighting scheme // for ARAP from the paper. Unfortunately, it creates a // loss function that can potentially become negative. ARAPWeightingCotangent ARAPWeightingScheme = iota ARAPWeightingAbsCotangent ARAPWeightingUniform )
type BVH ¶
type BVH struct { // Leaf, if non-nil, is the sole object in this node. Leaf *Triangle // Branch, if Leaf is nil, points to two children. Branch []*BVH }
BVH represents a (possibly unbalanced) axis-aligned bounding box hierarchy of triangles.
A BVH can be used to accelerate collision detection. See BVHToCollider() for more details.
A BVH node is either a leaf (a single triangle), or a branch with two or more children.
For a more generic BVH that supports any object rather than just triangles, see GeneralBVH.
func NewBVHAreaDensity ¶
NewBVHAreaDensity is like NewGeneralBVHAreaDensity but for triangles.
type Bounder ¶
type Bounder interface { // Get the corners of a bounding box. // // A point p satisfies p >= Min and p <= Max if it is // within the bounds. Min() Coord3D Max() Coord3D }
A Bounder is an object contained in an axis-aligned bounding box.
type Capsule ¶ added in v0.3.0
A Capsule is a shape which contains all of the points within a given distance of a line segment.
func (*Capsule) FirstRayCollision ¶ added in v0.3.0
func (c *Capsule) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the capsule, if one occurs.
func (*Capsule) NormalSDF ¶ added in v0.3.0
NormalSDF gets the nearest point on the surface of the capsule and the corresponding SDF.
func (*Capsule) PointSDF ¶ added in v0.3.0
PointSDF gets the nearest point on the surface of the capsule and the corresponding SDF.
func (*Capsule) RayCollisions ¶ added in v0.3.0
func (c *Capsule) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with every ray collision.
It returns the total number of collisions.
type Collider ¶
type Collider interface { Bounder // RayCollisions enumerates the collisions with a ray. // It returns the total number of collisions. // // f may be nil, in which case this is simply used for // counting. RayCollisions(r *Ray, f func(RayCollision)) int // FirstRayCollision gets the ray collision with the // lowest scale. // // The second return value is false if no collisions // were found. FirstRayCollision(r *Ray) (collision RayCollision, collides bool) // SphereCollision checks if the collider touches a // sphere with origin c and radius r. SphereCollision(c Coord3D, r float64) bool }
A Collider is a surface which can detect intersections with linear rays and spheres.
All methods of a Collider are safe for concurrency.
func ProfileCollider ¶ added in v0.2.5
ProfileCollider turns a 2D Collider into a 3D Collider by elongating the 2D Collider along the Z axis.
func TransformCollider ¶ added in v0.2.11
func TransformCollider(t DistTransform, c Collider) Collider
TransformCollider applies t to the Collider c to produce a new, transformed Collider.
type ColliderSolid ¶
type ColliderSolid struct {
// contains filtered or unexported fields
}
A ColliderSolid is a Solid that uses a Collider to check if points are in the solid.
There are two modes for a ColliderSolid. In the first, points are inside the solid if a ray passes through the surface of the Collider an odd number of times. In the second, points are inside the solid if a sphere of a pre-determined radius touches the surface of the Collider from the point. The second modality is equivalent to creating a thick but hollow solid.
func NewColliderSolid ¶
func NewColliderSolid(c Collider) *ColliderSolid
NewColliderSolid creates a basic ColliderSolid.
func NewColliderSolidHollow ¶
func NewColliderSolidHollow(c Collider, r float64) *ColliderSolid
NewColliderSolidHollow creates a ColliderSolid that only reports containment around the edges.
func NewColliderSolidInset ¶ added in v0.2.11
func NewColliderSolidInset(c Collider, inset float64) *ColliderSolid
NewColliderSolidInset creates a ColliderSolid that only reports containment at some distance from the surface.
If inset is negative, then the solid is outset from the collider.
func (*ColliderSolid) Contains ¶
func (c *ColliderSolid) Contains(coord Coord3D) bool
Contains checks if coord is in the solid.
func (*ColliderSolid) Max ¶
func (c *ColliderSolid) Max() Coord3D
Max gets the maximum of the bounding box.
func (*ColliderSolid) Min ¶
func (c *ColliderSolid) Min() Coord3D
Min gets the minimum of the bounding box.
type Cone ¶ added in v0.2.14
A Cone is a 3D cone, eminating from a point towards the center of a base, where the base has a given radius.
func (*Cone) FirstRayCollision ¶ added in v0.3.0
func (c *Cone) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the cone, if one occurs.
func (*Cone) NormalSDF ¶ added in v0.3.0
NormalSDF is like SDF, but also returns the normal on the surface of the cone at the closest point to coord.
func (*Cone) PointSDF ¶ added in v0.3.0
PointSDF is like SDF, but also returns the closest point on the surface of the cone.
func (*Cone) RayCollisions ¶ added in v0.3.0
func (c *Cone) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with every ray collision.
It returns the total number of collisions.
type ConvexPolytope ¶
type ConvexPolytope []*LinearConstraint
A ConvexPolytope is the intersection of some linear constraints.
func NewConvexPolytopeRect ¶ added in v0.2.9
func NewConvexPolytopeRect(min, max Coord3D) ConvexPolytope
NewConvexPolytopeRect creates a rectangular convex polytope.
func (ConvexPolytope) Contains ¶
func (c ConvexPolytope) Contains(coord Coord3D) bool
Contains checks that c satisfies the constraints.
func (ConvexPolytope) Mesh ¶
func (c ConvexPolytope) Mesh() *Mesh
Mesh creates a mesh containing all of the finite faces of the polytope.
For complicated polytopes, this may take a long time to run, since it is O(n^3) in the constraints.
func (ConvexPolytope) Solid ¶
func (c ConvexPolytope) Solid() Solid
Solid creates a solid out of the polytope.
This runs in O(n^3) in the constraints, so it may be unacceptable for large polytopes.
type Coord2D ¶
func NewCoord2DPolar ¶ added in v0.2.9
NewCoord2DPolar converts polar coordinates to a Coord2D.
func NewCoord2DRandBounds ¶ added in v0.3.0
NewCoord2DRandBounds creates a random Coord2D uniformly inside the given rectangular boundary.
func NewCoord2DRandNorm ¶
func NewCoord2DRandNorm() Coord2D
NewCoord2DRandNorm creates a random Coord2D with normally distributed components.
func NewCoord2DRandUniform ¶ added in v0.2.4
func NewCoord2DRandUniform() Coord2D
NewCoord2DRandUniform creates a random Coord2D with uniformly random coordinates in [0, 1).
func NewCoord2DRandUnit ¶
func NewCoord2DRandUnit() Coord2D
NewCoord2DRandUnit creates a random Coord2D with magnitude 1.
type Coord3D ¶
A Coord3D is a coordinate in 3-D Euclidean space.
func NewCoord3DArray ¶
NewCoord3DArray creates a Coord3D from an array of x, y, and z.
func NewCoord3DRandBounds ¶ added in v0.2.8
NewCoord3DRandBounds creates a random Coord3D uniformly inside the given rectangular boundary.
func NewCoord3DRandNorm ¶
func NewCoord3DRandNorm() Coord3D
NewCoord3DRandNorm creates a random Coord3D with normally distributed components.
func NewCoord3DRandUniform ¶ added in v0.2.4
func NewCoord3DRandUniform() Coord3D
NewCoord3DRandUniform creates a random Coord3D with uniformly random coordinates in [0, 1).
func NewCoord3DRandUnit ¶
func NewCoord3DRandUnit() Coord3D
NewCoord3DRandUnit creates a random Coord3D with magnitude 1.
func (Coord3D) AddScalar ¶ added in v0.2.6
AddScalar adds s to all of the coordinates and returns the new coordinate.
func (Coord3D) Array ¶
Array creates an array with the x, y, and z. This can be useful for some vectorized code.
func (Coord3D) Coord2D ¶
Coord2D projects c onto the x,y plane and drops the Z value. It is equivalent to c.XY().
func (Coord3D) NormSquared ¶ added in v0.3.0
NormSquared computes the squared vector L2 norm.
func (Coord3D) OrthoBasis ¶
OrthoBasis creates two unit vectors which are orthogonal to c and to each other.
If c is axis-aligned, the other vectors will be as well.
func (Coord3D) ProjectOut ¶
ProjectOut projects the c1 direction out of c.
func (Coord3D) SquaredDist ¶ added in v0.2.13
SquaredDist gets the squared Euclidean distance to c1.
type CoordMap ¶ added in v0.2.14
type CoordMap struct {
// contains filtered or unexported fields
}
CoordMap implements a map-like interface for mapping Coord3D to interface{}.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func (*CoordMap) Delete ¶ added in v0.2.14
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*CoordMap) KeyRange ¶ added in v0.2.14
KeyRange is like Range, but only iterates over keys, not values.
func (*CoordMap) Load ¶ added in v0.2.14
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*CoordMap) Range ¶ added in v0.2.14
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*CoordMap) Store ¶ added in v0.2.14
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*CoordMap) ValueRange ¶ added in v0.2.14
ValueRange is like Range, but only iterates over values only.
type CoordToCoord ¶ added in v0.2.14
type CoordToCoord struct {
// contains filtered or unexported fields
}
CoordToCoord implements a map-like interface for mapping Coord3D to Coord3D.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func NewCoordToCoord ¶ added in v0.2.14
func NewCoordToCoord() *CoordToCoord
NewCoordToCoord creates an empty map.
func (*CoordToCoord) Delete ¶ added in v0.2.14
func (m *CoordToCoord) Delete(key Coord3D)
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*CoordToCoord) KeyRange ¶ added in v0.2.14
func (m *CoordToCoord) KeyRange(f func(key Coord3D) bool)
KeyRange is like Range, but only iterates over keys, not values.
func (*CoordToCoord) Len ¶ added in v0.2.14
func (m *CoordToCoord) Len() int
Len gets the number of elements in the map.
func (*CoordToCoord) Load ¶ added in v0.2.14
func (m *CoordToCoord) Load(key Coord3D) (Coord3D, bool)
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*CoordToCoord) Range ¶ added in v0.2.14
func (m *CoordToCoord) Range(f func(key Coord3D, value Coord3D) bool)
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*CoordToCoord) Store ¶ added in v0.2.14
func (m *CoordToCoord) Store(key Coord3D, value Coord3D)
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*CoordToCoord) Value ¶ added in v0.2.14
func (m *CoordToCoord) Value(key Coord3D) Coord3D
Value is like Load(), but without a second return value.
func (*CoordToCoord) ValueRange ¶ added in v0.2.14
func (m *CoordToCoord) ValueRange(f func(value Coord3D) bool)
ValueRange is like Range, but only iterates over values only.
type CoordToFaces ¶ added in v0.2.14
type CoordToFaces struct {
// contains filtered or unexported fields
}
CoordToFaces implements a map-like interface for mapping Coord3D to []*Triangle.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func NewCoordToFaces ¶ added in v0.2.14
func NewCoordToFaces() *CoordToFaces
NewCoordToFaces creates an empty map.
func (*CoordToFaces) Append ¶ added in v0.2.14
func (m *CoordToFaces) Append(key Coord3D, x *Triangle) []*Triangle
Append appends x to the value stored for the given key and returns the new value.
func (*CoordToFaces) Delete ¶ added in v0.2.14
func (m *CoordToFaces) Delete(key Coord3D)
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*CoordToFaces) KeyRange ¶ added in v0.2.14
func (m *CoordToFaces) KeyRange(f func(key Coord3D) bool)
KeyRange is like Range, but only iterates over keys, not values.
func (*CoordToFaces) Len ¶ added in v0.2.14
func (m *CoordToFaces) Len() int
Len gets the number of elements in the map.
func (*CoordToFaces) Load ¶ added in v0.2.14
func (m *CoordToFaces) Load(key Coord3D) ([]*Triangle, bool)
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*CoordToFaces) Range ¶ added in v0.2.14
func (m *CoordToFaces) Range(f func(key Coord3D, value []*Triangle) bool)
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*CoordToFaces) Store ¶ added in v0.2.14
func (m *CoordToFaces) Store(key Coord3D, value []*Triangle)
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*CoordToFaces) Value ¶ added in v0.2.14
func (m *CoordToFaces) Value(key Coord3D) []*Triangle
Value is like Load(), but without a second return value.
func (*CoordToFaces) ValueRange ¶ added in v0.2.14
func (m *CoordToFaces) ValueRange(f func(value []*Triangle) bool)
ValueRange is like Range, but only iterates over values only.
type CoordToInt ¶ added in v0.2.14
type CoordToInt struct {
// contains filtered or unexported fields
}
CoordToInt implements a map-like interface for mapping Coord3D to int.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func NewCoordToInt ¶ added in v0.2.14
func NewCoordToInt() *CoordToInt
NewCoordToInt creates an empty map.
func (*CoordToInt) Add ¶ added in v0.2.14
func (m *CoordToInt) Add(key Coord3D, x int) int
Add adds x to the value stored for the given key and returns the new value.
func (*CoordToInt) Delete ¶ added in v0.2.14
func (m *CoordToInt) Delete(key Coord3D)
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*CoordToInt) KeyRange ¶ added in v0.2.14
func (m *CoordToInt) KeyRange(f func(key Coord3D) bool)
KeyRange is like Range, but only iterates over keys, not values.
func (*CoordToInt) Len ¶ added in v0.2.14
func (m *CoordToInt) Len() int
Len gets the number of elements in the map.
func (*CoordToInt) Load ¶ added in v0.2.14
func (m *CoordToInt) Load(key Coord3D) (int, bool)
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*CoordToInt) Range ¶ added in v0.2.14
func (m *CoordToInt) Range(f func(key Coord3D, value int) bool)
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*CoordToInt) Store ¶ added in v0.2.14
func (m *CoordToInt) Store(key Coord3D, value int)
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*CoordToInt) Value ¶ added in v0.2.14
func (m *CoordToInt) Value(key Coord3D) int
Value is like Load(), but without a second return value.
func (*CoordToInt) ValueRange ¶ added in v0.2.14
func (m *CoordToInt) ValueRange(f func(value int) bool)
ValueRange is like Range, but only iterates over values only.
type CoordTree ¶ added in v0.2.13
type CoordTree struct { Coord Coord3D // SplitAxis is the dimension to split on for branches. SplitAxis int // At least one of these is non-nil for branches. LessThan *CoordTree GreaterEqual *CoordTree }
A CoordTree is a k-d tree over Coord3Ds.
A nil *CoordTree represents an empty tree.
func NewCoordTree ¶ added in v0.2.13
func (*CoordTree) Contains ¶ added in v0.2.13
Contains checks if any point in the tree is exactly equal to p.
func (*CoordTree) Dist ¶ added in v0.2.14
Dist gets the distance from a point p to its nearest neighbor in c.
func (*CoordTree) KNN ¶ added in v0.2.13
KNN gets the closest K coordinates to p in the tree. The results are sorted by ascending distance.
If there are fewer than K coordinates in the tree, then fewer than K coordinates are returned.
func (*CoordTree) Leaf ¶ added in v0.2.13
Leaf returns true if this tree contains 1 or fewer points.
func (*CoordTree) NearestNeighbor ¶ added in v0.2.13
NearestNeighbor gets the closest coordinate to p in the tree.
This will panic() if c is empty.
type Cylinder ¶
A Cylinder is a cylindrical 3D primitive.
The cylinder is defined as all the positions within a radius distance from the line segment between P1 and P2.
func (*Cylinder) FirstRayCollision ¶
func (c *Cylinder) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the cylinder, if one occurs.
func (*Cylinder) NormalSDF ¶ added in v0.3.0
NormalSDF gets the signed distance to the cylinder and the normal at the closest point on the surface.
func (*Cylinder) PointSDF ¶ added in v0.3.0
PointSDF gets the signed distance to the cylinder and the closest point on the surface.
func (*Cylinder) RayCollisions ¶
func (c *Cylinder) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with every ray collision.
It returns the total number of collisions.
type CylinderSolid ¶
type CylinderSolid = Cylinder
type Decimator ¶
type Decimator struct { // The minimum dihedral angle between two triangles // to consider an edge a "feature edge". // // If 0, DefaultDecimatorFeatureAngle is used. // // This is measured in radians. FeatureAngle float64 // The maximum distance for a vertex to be from its // average plane for it to be deleted. PlaneDistance float64 // The maximum distance for a vertex to be from the // line defining a feature edge. BoundaryDistance float64 // If true, use PlaneDistance to evaluate all vertices // rather than consulting BoundaryDistance. NoEdgePreservation bool // If true, eliminate corner vertices. EliminateCorners bool // MinimumAspectRatio is the minimum aspect ratio for // triangulation splits. // // If 0, a default of DefaultDecimatorMinAspectRatio // is used. MinimumAspectRatio float64 // FilterFunc, if specified, can be used to prevent // certain vertices from being removed. // If FilterFunc returns false for a coordinate, it // may not be removed; otherwise it may be removed. FilterFunc func(c Coord3D) bool }
Decimator implements a decimation algorithm to simplify triangle meshes.
This may only be applied to closed, manifold meshes. Thus, all edges are touching exactly two triangles, and there are no singularities or holes.
The algorithm is described in: "Decimation of Triangle Meshes" - William J. Schroeder, Jonathan A. Zarge and William E. Lorensen. https://webdocs.cs.ualberta.ca/~lin/ABProject/papers/4.pdf.
type DistTransform ¶ added in v0.2.11
type DistTransform interface { Transform // ApplyDistance computes the distance between // t.Apply(c1) and t.Apply(c2) given the distance // between c1 and c2, where c1 and c2 are arbitrary // points. ApplyDistance(d float64) float64 }
DistTransform is a Transform that changes Euclidean distances in a coordinate-independent fashion.
The inverse of a DistTransform should also be a DistTransform.
func Rotation ¶ added in v0.2.11
func Rotation(axis Coord3D, theta float64) DistTransform
Rotation creates a rotation transformation using an angle in radians around a unit vector direction.
type EdgeMap ¶ added in v0.2.14
type EdgeMap struct {
// contains filtered or unexported fields
}
EdgeMap implements a map-like interface for mapping [2]Coord3D to interface{}.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func (*EdgeMap) Delete ¶ added in v0.2.14
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*EdgeMap) KeyRange ¶ added in v0.2.14
KeyRange is like Range, but only iterates over keys, not values.
func (*EdgeMap) Load ¶ added in v0.2.14
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*EdgeMap) Range ¶ added in v0.2.14
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*EdgeMap) Store ¶ added in v0.2.14
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*EdgeMap) ValueRange ¶ added in v0.2.14
ValueRange is like Range, but only iterates over values only.
type EdgeToBool ¶ added in v0.2.14
type EdgeToBool struct {
// contains filtered or unexported fields
}
EdgeToBool implements a map-like interface for mapping [2]Coord3D to bool.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func NewEdgeToBool ¶ added in v0.2.14
func NewEdgeToBool() *EdgeToBool
NewEdgeToBool creates an empty map.
func (*EdgeToBool) Delete ¶ added in v0.2.14
func (m *EdgeToBool) Delete(key [2]Coord3D)
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*EdgeToBool) KeyRange ¶ added in v0.2.14
func (m *EdgeToBool) KeyRange(f func(key [2]Coord3D) bool)
KeyRange is like Range, but only iterates over keys, not values.
func (*EdgeToBool) Len ¶ added in v0.2.14
func (m *EdgeToBool) Len() int
Len gets the number of elements in the map.
func (*EdgeToBool) Load ¶ added in v0.2.14
func (m *EdgeToBool) Load(key [2]Coord3D) (bool, bool)
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*EdgeToBool) Range ¶ added in v0.2.14
func (m *EdgeToBool) Range(f func(key [2]Coord3D, value bool) bool)
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*EdgeToBool) Store ¶ added in v0.2.14
func (m *EdgeToBool) Store(key [2]Coord3D, value bool)
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*EdgeToBool) Value ¶ added in v0.2.14
func (m *EdgeToBool) Value(key [2]Coord3D) bool
Value is like Load(), but without a second return value.
func (*EdgeToBool) ValueRange ¶ added in v0.2.14
func (m *EdgeToBool) ValueRange(f func(value bool) bool)
ValueRange is like Range, but only iterates over values only.
type EdgeToInt ¶ added in v0.2.14
type EdgeToInt struct {
// contains filtered or unexported fields
}
EdgeToInt implements a map-like interface for mapping [2]Coord3D to int.
This can be more efficient than using a map directly, since it uses a special hash function for coordinates. The speed-up is variable, but was ~2x as of mid-2021.
func NewEdgeToInt ¶ added in v0.2.14
func NewEdgeToInt() *EdgeToInt
NewEdgeToInt creates an empty map.
func (*EdgeToInt) Add ¶ added in v0.2.14
Add adds x to the value stored for the given key and returns the new value.
func (*EdgeToInt) Delete ¶ added in v0.2.14
Delete removes the key from the map if it exists, and does nothing otherwise.
func (*EdgeToInt) KeyRange ¶ added in v0.2.14
KeyRange is like Range, but only iterates over keys, not values.
func (*EdgeToInt) Load ¶ added in v0.2.14
Load gets the value for the given key.
If no value is present, the first return argument is a zero value, and the second is false. Otherwise, the second return value is true.
func (*EdgeToInt) Range ¶ added in v0.2.14
Range iterates over the map, calling f successively for each value until it returns false, or all entries are enumerated.
It is not safe to modify the map with Store or Delete during enumeration.
func (*EdgeToInt) Store ¶ added in v0.2.14
Store assigns the value to the given key, overwriting the previous value for the key if necessary.
func (*EdgeToInt) ValueRange ¶ added in v0.2.14
ValueRange is like Range, but only iterates over values only.
type FaceSDF ¶ added in v0.2.14
type FaceSDF interface { PointSDF NormalSDF // FaceSDF gets the SDF at c and also returns the // nearest point and face to c on the surface. FaceSDF(c Coord3D) (*Triangle, Coord3D, float64) }
A FaceSDF is a PointSDF that can additionally get the triangle containing the closest point.
func GroupedTrianglesToSDF ¶
GroupedTrianglesToSDF creates a FaceSDF from a slice of triangles. If the triangles are not grouped by GroupTriangles(), the resulting PointSDF is inefficient.
type GeneralBVH ¶ added in v0.2.11
type GeneralBVH struct { // Leaf, if non-nil, is the final bounder. Leaf Bounder // Branch, if Leaf is nil, points to two children. Branch []*GeneralBVH }
GeneralBVH represents a (possibly unbalanced) axis-aligned bounding box hierarchy.
A GeneralBVH can store arbitrary Bounders. For a mesh-specific version, see BVH.
func NewGeneralBVHAreaDensity ¶ added in v0.2.11
func NewGeneralBVHAreaDensity(objects []Bounder) *GeneralBVH
NewGeneralBVHAreaDensity creates a GeneralBVH by minimizing the product of each bounding box's area with the number of objects contained in the bounding box at each branch.
This is good for efficient ray collision detection.
type GeoCoord ¶
A GeoCoord specifies a location on a sphere with a unit radius.
The latitude is an angle from -math.Pi/2 to math.pi/2 representing the North-South direction. The longitude is an angle from -math.Pi to math.Pi representing the West-East direction.
func (GeoCoord) Coord3D ¶
Coord3D converts g to Euclidean coordinates on a unit sphere centered at the origin.
type IntersectedSolid ¶
type IntersectedSolid []Solid
IntersectedSolid is a Solid containing the intersection of one or more Solids.
func (IntersectedSolid) Contains ¶
func (i IntersectedSolid) Contains(c Coord3D) bool
func (IntersectedSolid) Max ¶
func (i IntersectedSolid) Max() Coord3D
func (IntersectedSolid) Min ¶
func (i IntersectedSolid) Min() Coord3D
type JoinedCollider ¶
type JoinedCollider struct {
// contains filtered or unexported fields
}
A JoinedCollider wraps multiple other Colliders and only passes along rays and spheres that enter their combined bounding box.
func NewJoinedCollider ¶
func NewJoinedCollider(other []Collider) *JoinedCollider
NewJoinedCollider creates a JoinedCollider which combines one or more other colliders.
func (*JoinedCollider) FirstRayCollision ¶
func (j *JoinedCollider) FirstRayCollision(r *Ray) (RayCollision, bool)
func (*JoinedCollider) Max ¶
func (j *JoinedCollider) Max() Coord3D
func (*JoinedCollider) Min ¶
func (j *JoinedCollider) Min() Coord3D
func (*JoinedCollider) RayCollisions ¶
func (j *JoinedCollider) RayCollisions(r *Ray, f func(RayCollision)) int
func (*JoinedCollider) SphereCollision ¶
func (j *JoinedCollider) SphereCollision(center Coord3D, r float64) bool
type JoinedSolid ¶
type JoinedSolid []Solid
A JoinedSolid is a Solid composed of other solids.
func (JoinedSolid) Contains ¶
func (j JoinedSolid) Contains(c Coord3D) bool
func (JoinedSolid) Max ¶
func (j JoinedSolid) Max() Coord3D
func (JoinedSolid) Min ¶
func (j JoinedSolid) Min() Coord3D
func (JoinedSolid) Optimize ¶ added in v0.2.11
func (j JoinedSolid) Optimize() Solid
Optimize creates a version of the solid that is faster when joining a large number of smaller solids.
type JoinedTransform ¶
type JoinedTransform []Transform
A JoinedTransform composes transformations from left to right.
func (JoinedTransform) Apply ¶
func (j JoinedTransform) Apply(c Coord3D) Coord3D
func (JoinedTransform) ApplyBounds ¶
func (j JoinedTransform) ApplyBounds(min Coord3D, max Coord3D) (Coord3D, Coord3D)
func (JoinedTransform) ApplyDistance ¶ added in v0.2.11
func (j JoinedTransform) ApplyDistance(d float64) float64
ApplyDistance transforms a distance.
It panic()s if any transforms don't implement DistTransform.
func (JoinedTransform) Inverse ¶
func (j JoinedTransform) Inverse() Transform
type LinearConstraint ¶
A LinearConstraint defines a half-space of all points c such that c.Dot(Normal) <= Max.
func (*LinearConstraint) Contains ¶
func (l *LinearConstraint) Contains(c Coord3D) bool
Contains checks if the half-space contains c.
type Matrix3 ¶
type Matrix3 [9]float64
Matrix3 is a 3x3 matrix, stored in row-major order.
func NewMatrix3Columns ¶
NewMatrix3Columns creates a Matrix3 with the given coordinates as column entries.
func NewMatrix3Rotation ¶
NewMatrix3Rotation creates a 3D rotation matrix. Points are rotated around the given vector in a right-handed direction.
The axis is assumed to be normalized. The angle is measured in radians.
func (*Matrix3) Eigenvalues ¶ added in v0.2.2
func (m *Matrix3) Eigenvalues() [3]complex128
Eigenvalues computes the eigenvalues of the matrix.
There may be repeated eigenvalues, but for numerical reasons three are always returned.
func (*Matrix3) InvertInPlace ¶
func (m *Matrix3) InvertInPlace()
InvertInPlace moves the inverse of m into m without causing any new allocations.
func (*Matrix3) InvertInPlaceDet ¶ added in v0.2.14
InvertInPlaceDet is an optimization for InvertInPlace when the determinant has been pre-computed.
func (*Matrix3) MulColumnInv ¶ added in v0.2.14
MulColumnInv multiplies the inverse of m by the column c, given the determinant of m.
type Matrix3Transform ¶
type Matrix3Transform struct {
Matrix *Matrix3
}
Matrix3Transform is a Transform that applies a matrix to coordinates.
func (*Matrix3Transform) Apply ¶
func (m *Matrix3Transform) Apply(c Coord3D) Coord3D
func (*Matrix3Transform) ApplyBounds ¶
func (m *Matrix3Transform) ApplyBounds(min, max Coord3D) (Coord3D, Coord3D)
func (*Matrix3Transform) Inverse ¶
func (m *Matrix3Transform) Inverse() Transform
type Mesh ¶
type Mesh struct {
// contains filtered or unexported fields
}
A Mesh is a collection of triangles.
The triangles are uniquely identified as pointers, not as values. This is important for methods which reference existing triangles, such as Remove and Neighbors.
Triangles in a mesh are "connected" when they contain exactly identical points. Thus, small rounding errors can cause triangles to incorrectly be disassociated with each other.
A Mesh can be read safely from concurrent Goroutines, but modifications must not be performed concurrently with any mesh operations.
func DecimateSimple ¶
DecimateSimple decimates a mesh using a specified distance epsilon combined with default parameters.
For more fine-grained control, use Decimator.
func LoopSubdivision ¶
LoopSubdivision subdivides the mesh using the Loop subdivision rule, creating a smoother surface with more triangles.
The mesh is subdivided iters times.
The mesh must not have singular edges.
func MarchingCubes ¶
MarchingCubes turns a Solid into a surface mesh using a corrected marching cubes algorithm.
func MarchingCubesC2F ¶ added in v0.3.0
MarchingCubesC2F computes a coarse mesh for the solid, then uses that mesh to compute a fine mesh more efficiently.
The extraSpace argument, if non-zero, is extra space to consider around the coarse mesh. It can be increased in the case where the solid has fine details that are totally missed by the coarse mesh.
func MarchingCubesConj ¶ added in v0.2.9
MarchingCubesConj is like MarchingCubesSearch, but in a transformed space. In particular, it applies a series of transformations to the Solid, and then applies the inverse to the resulting mesh.
func MarchingCubesFilter ¶ added in v0.3.0
MarchingCubesFilter is like MarchingCubes, but does not scan rectangular volumes for which f returns false. This can be much more efficient than MarchingCubes if the surface is sparse and f can tell when large regions don't intersect the mesh.
Note that the filter can be conservative and possibly report collisions that do not occur. However, it should never fail to report collisions, since this could cause triangles to be missed.
func MarchingCubesSearch ¶
MarchingCubesSearch is like MarchingCubes, but applies an additional search step to move the vertices along the edges of each cube.
The tightness of the triangulation will double for every iteration.
func MarchingCubesSearchFilter ¶ added in v0.3.0
MarchingCubesSearchFilter combines MarchingCubesSearch with MarchingCubesFilter.
func NewMeshCone ¶ added in v0.2.14
NewMeshCone creates a 3D mesh representing a cone.
This is done by discretizing the base circle into numStops segments and attaching triangles to the tip.
func NewMeshCylinder ¶ added in v0.2.14
NewMeshCylinder creates a 3D mesh representing a cylinder.
This is done by discretizing the side circle into numStops segments and attaching triangles between them.
func NewMeshIcosahedron ¶ added in v0.2.14
func NewMeshIcosahedron() *Mesh
NewMeshIcosahedron creates a regular icosahedron.
The resulting icosahedron is oriented such that two points will be created at (0, -1, 0) and (0, 1, 0), and exactly two other points will have an x value of zero.
func NewMeshIcosphere ¶ added in v0.2.14
NewMeshIcosphere approximates a sphere using a geodesic polyhedron, which is more symmetrical than the spheres created with NewMeshPolar().
The resulting model has 20*n^2 triangles.
func NewMeshPolar ¶
NewMeshPolar creates a mesh with a 3D polar function.
If radius is nil, a radius of 1 is used.
func NewMeshRect ¶
NewMeshRect creates a new mesh around the rectangular bounds.
func NewMeshTorus ¶ added in v0.2.14
func NewMeshTorus(center, axis Coord3D, innerRadius, outerRadius float64, innerStops, outerStops int) *Mesh
NewMeshTorus creates a 3D mesh representing a torus.
This is done by discretizing the local ring into innerStops segments, and the larger ring into outerStops segments.
The innerRadius must be smaller than the outerRadius, since doing otherwise would cause self-intersections.
func NewMeshTriangles ¶
NewMeshTriangles creates a mesh with the given collection of triangles.
func ProfileMesh ¶ added in v0.2.11
ProfileMesh creates a 3D mesh from a 2D mesh by using the 2D mesh as a face surface and extending it along the Z axis.
The 2D mesh must be manifold, closed, and oriented.
func SubdivideEdges ¶ added in v0.2.14
SubdivideEdges sub-divides each edge into n sub-edges and fills each original triangle with n^2 coplanar triangles.
func (*Mesh) AddQuad ¶ added in v0.2.9
AddQuad adds a quadrilateral to the mesh.
For correct normals, the vertices should be in counter- clockwise order as seen from the outside of the mesh.
func (*Mesh) Blur ¶
Blur creates a new mesh by moving every vertex closer to its connected vertices.
The rate argument specifies how much the vertex should be moved, 0 being no movement and 1 being the most. If multiple rates are passed, then multiple iterations of the algorithm are performed in succession. If a rate of -1 is passed, then all of neighbors are averaged together with each point, and the resulting average is used.
func (*Mesh) BlurFiltered ¶
BlurFiltered is like Blur, but vertices are only considered neighbors if f returns true for their initial coordinates.
Once vertices are considered neighbors, they will be treated as such for every blur iteration, even if the coordinates change in such a way that f would no longer consider them neighbors.
If f is nil, then this is equivalent to Blur().
func (*Mesh) Copy ¶ added in v0.2.23
Copy returns a shallow copy of m, where all of the triangles are the same exact pointers.
func (*Mesh) DeepCopy ¶ added in v0.2.23
DeepCopy returns a deep copy of m, where all of the triangles are copied individually.
func (*Mesh) EliminateCoplanar ¶
EliminateCoplanar eliminates vertices inside whose neighboring triangles are all co-planar.
The epsilon argument controls how close two normals must be for the triangles to be considered coplanar. A good value for very precise results is 1e-8.
func (*Mesh) EliminateEdges ¶
EliminateEdges creates a new mesh by iteratively removing edges according to the function f.
The f function takes the current new mesh and a line segment, and returns true if the segment should be removed.
func (*Mesh) EncodeMaterialOBJ ¶
EncodeMaterialOBJ encodes the mesh as a zip file with per-triangle material.
func (*Mesh) Find ¶
Find gets all the triangles that contain all of the passed points.
For example, to find all triangles containing a line from from p1 to p2, you could do m.Find(p1, p2).
func (*Mesh) FlattenBase ¶
FlattenBase flattens out the bases of objects for printing on an FDM 3D printer. It is intended to be used for meshes based on flat-based solids, where the base's edges got rounded by smoothing.
The maxAngle argument specifies the maximum angle (in radians) to flatten. If left at zero, 45 degrees is used since this is the recommended angle on many FDM 3D printers.
In some meshes, this may cause triangles to overlap on the base of the mesh. Thus, it is only intended to be used when the base is clearly defined, and all of the triangles touching it are not above any other triangles (along the Z-axis).
func (*Mesh) FlipDelaunay ¶ added in v0.2.2
FlipDelaunay "flips" edges in triangle pairs until the mesh is Delaunay.
This can be used to prepare a mesh for cotangent weights, either for smoothing, deformation, or some other mesh operation.
func (*Mesh) Iterate ¶
Iterate calls f for every triangle in m in an arbitrary order.
If f adds or removes triangles, they will not be visited.
func (*Mesh) IterateSorted ¶
IterateSorted is like Iterate, but it first sorts all the triangles according to a less than function, cmp.
func (*Mesh) IterateVertices ¶ added in v0.1.1
IterateVertices calls f for every vertex in m in an arbitrary order.
If f adds or removes vertices, they will not be visited.
func (*Mesh) MapCoords ¶
MapCoords creates a new mesh by transforming all of the coordinates according to the function f.
func (*Mesh) NeedsRepair ¶
NeedsRepair checks if every edge touches exactly two triangles. If not, NeedsRepair returns true.
func (*Mesh) Neighbors ¶
Neighbors gets all the triangles with a side touching a given triangle f.
The triangle f itself is not included in the results.
The triangle f needn't be in the mesh. However, if it is not in the mesh, but an equivalent triangle is, then said equivalent triangle will be in the results.
func (*Mesh) Remove ¶
Remove removes the triangle f from the mesh.
It looks at f as a pointer, so the pointer must be exactly the same as one passed to Add.
func (*Mesh) Repair ¶
Repair finds vertices that are close together and combines them into one.
The epsilon argument controls how close points have to be. In particular, it sets the approximate maximum distance across all dimensions.
func (*Mesh) RepairNormals ¶
RepairNormals flips normals when they point within the solid defined by the mesh, as determined by the even-odd rule.
The repaired mesh is returned, along with the number of modified triangles.
The check is performed by adding the normal, scaled by epsilon, to the center of the triangle, and then counting the number of ray collisions from this point in the direction of the normal.
func (*Mesh) Rotate ¶ added in v0.2.15
Rotate returns a mesh with all coordinates rotated by a given angle (in radians) around a given unit axis.
func (*Mesh) SaveGroupedSTL ¶
SaveGroupedSTL writes the mesh to an STL file with the triangles grouped in such a way that the file can be compressed efficiently.
func (*Mesh) SaveMaterialOBJ ¶ added in v0.2.13
SaveMaterialOBJ saves the mesh to a zip file with a per-triangle material.
func (*Mesh) SelfIntersections ¶
SelfIntersections counts the number of times the mesh intersects itself. In an ideal mesh, this would be 0.
func (*Mesh) SingularVertices ¶
SingularVertices gets the points at which the mesh is squeezed to zero volume. In other words, it gets the points where two pieces of volume are barely touching by a single point.
func (*Mesh) SmoothAreas ¶
SmoothAreas uses gradient descent to iteratively smooth out the surface by moving every vertex in the direction that minimizes the area of its adjacent triangles.
The stepSize argument specifies how much the vertices are moved at each iteration. Good values depend on the mesh, but a good start is on the order of 0.1.
The iters argument specifies how many gradient steps are taken.
This algorithm can produce very smooth objects, but it is much less efficient than Blur(). Consider Blur() when perfect smoothness is not required.
This method is a simpler version of the MeshSmoother object, which provides a more controlled smoothing API.
func (*Mesh) Translate ¶ added in v0.2.13
Translate returns a mesh with all coordinates added to a given vector.
func (*Mesh) TriangleSlice ¶
TriangleSlice gets a snapshot of all the triangles currently in the mesh. The resulting slice is a copy, and will not change as the mesh is updated.
func (*Mesh) VertexSlice ¶ added in v0.1.1
VertexSlice gets a snapshot of all the vertices currently in the mesh.
The result is a copy and is in no way connected to the mesh in memory.
type MeshHierarchy ¶ added in v0.2.13
type MeshHierarchy struct { // Mesh is the root shape of this (sub-)hierarchy. Mesh *Mesh // MeshSolid is a solid indicating which points are // contained in the mesh. MeshSolid Solid Children []*MeshHierarchy }
A MeshHierarchy is a tree structure where each node is a closed, simple surface, and children are contained inside their parents.
Only manifold meshes with no self-intersections can be converted into a MeshHierarchy.
func MeshToHierarchy ¶ added in v0.2.13
func MeshToHierarchy(m *Mesh) []*MeshHierarchy
MeshToHierarchy creates a MeshHierarchy for each exterior mesh contained in m.
The mesh m must be manifold and have no self-intersections.
func (*MeshHierarchy) Contains ¶ added in v0.2.13
func (m *MeshHierarchy) Contains(c Coord3D) bool
Contains checks if c is inside the hierarchy using the even-odd rule.
func (*MeshHierarchy) FullMesh ¶ added in v0.2.13
func (m *MeshHierarchy) FullMesh() *Mesh
FullMesh re-combines the root mesh with all of its children.
func (*MeshHierarchy) MapCoords ¶ added in v0.2.13
func (m *MeshHierarchy) MapCoords(f func(Coord3D) Coord3D) *MeshHierarchy
MapCoords creates a new MeshHierarchy by applying f to every coordinate in every mesh.
func (*MeshHierarchy) Max ¶ added in v0.2.13
func (m *MeshHierarchy) Max() Coord3D
Max gets the maximum point of the outer mesh's bounding box.
func (*MeshHierarchy) Min ¶ added in v0.2.13
func (m *MeshHierarchy) Min() Coord3D
Min gets the minimum point of the outer mesh's bounding box.
type MeshSmoother ¶
type MeshSmoother struct { // StepSize controls how fast the mesh is updated. // A good value will depend on the mesh, but a good // default is 0.1. StepSize float64 // Iterations controls the number of gradient steps // to take in order to smooth a mesh. // More values result in smoother meshes but take // more time. Iterations int // ConstraintDistance is the minimum distance after // which the origin constraint will take effect. // This allows points to move freely a little bit // without being constrained at all, which is good // for sharp meshes created from voxel grids. // // If this is 0, then points will always be pulled // towards their origin by a factor of // ConstraintWeight. ConstraintDistance float64 // ConstraintWeight is the weight of the distance // constraint term, ||x-x0||^2. // If this is 0, no constraint is applied. ConstraintWeight float64 // ConstraintFunc, if specified, is a totally custom // gradient term that constrains points to their // original positions. // // The return value of the function is added to the // gradient at every step. // // This is independent of ConstraintDistance and // ConstraintWeight, which can be used simultaneously. ConstraintFunc func(origin, newCoord Coord3D) Coord3D // HardConstraintFunc, if non-nil, is a function that // returns true for all of the initial points that // should not be modified at all. HardConstraintFunc func(origin Coord3D) bool }
A MeshSmoother uses gradient descent to smooth out the surface of a mesh by minimizing surface area.
The smoother can be constrained to discourage vertices from moving far from their origins, making the surface locally smooth without greatly modifying the volume.
func (*MeshSmoother) Smooth ¶
func (m *MeshSmoother) Smooth(mesh *Mesh) *Mesh
Smooth applies gradient descent to smooth the mesh.
type MultiCollider ¶ added in v0.2.6
type MultiCollider interface { TriangleCollider SegmentCollider RectCollider }
func BVHToCollider ¶
func BVHToCollider(b *BVH) MultiCollider
BVHToCollider converts a BVH into a MultiCollider in a hierarchical way.
func GroupedTrianglesToCollider ¶
func GroupedTrianglesToCollider(tris []*Triangle) MultiCollider
GroupedTrianglesToCollider converts a mesh of triangles into a MultiCollider.
The triangles should be sorted by GroupTriangles. Otherwise, the resulting Collider may not be efficient.
func MeshToCollider ¶
func MeshToCollider(m *Mesh) MultiCollider
MeshToCollider creates an efficient MultiCollider out of a mesh.
type NormalSDF ¶ added in v0.3.0
type NormalSDF interface { SDF // NormalSDF gets the SDF at c and also returns the // normal at the nearest point to c on the surface. NormalSDF(c Coord3D) (Coord3D, float64) }
A NormalSDF is an SDF that can additionally get the tangent normal for the nearest point on a surface.
type PointSDF ¶ added in v0.2.3
type PointSDF interface { SDF // PointSDF gets the SDF at c and also returns the // nearest point to c on the surface. PointSDF(c Coord3D) (Coord3D, float64) }
A PointSDF is an SDF that can additionally get the nearest point on a surface.
func FuncPointSDF ¶ added in v0.2.13
FuncPointSDF creates a PointSDF from a function.
If the bounds are invalid, FuncPointSDF() will panic(). In particular, max must be no less than min, and all floating-point values must be finite numbers.
type Ray ¶
A Ray is a line originating at a point and extending infinitely in some (positive) direction.
type RayCollision ¶
type RayCollision struct { // The amount of the ray direction to add to the ray // origin to hit the point in question. // // The scale should be non-negative. Scale float64 // The normal pointing outward from the surface at the // point of collision. Normal Coord3D // Extra contains additional, implementation-specific // information about the collision. // // For an example, see TriangleCollision. Extra interface{} }
RayCollision is a point where a ray intersects a surface.
type Rect ¶
A Rect is a 3D primitive that fills an axis-aligned rectangular space.
func BoundsRect ¶ added in v0.2.13
BoundsRect creates a Rect from a Bounder's bounds.
func (*Rect) Expand ¶ added in v0.3.0
Expand returns a new Rect that is delta units further along in every direction, making it a total of 2*delta units longer along each axis.
func (*Rect) FirstRayCollision ¶
func (r *Rect) FirstRayCollision(ray *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the rectangular surface.
func (*Rect) NormalSDF ¶ added in v0.3.0
NormalSDF gets the nearest point on the surface of the rect and the corresponding SDF.
func (*Rect) PointSDF ¶ added in v0.3.0
PointSDF gets the nearest point on the surface of the rect and the corresponding SDF.
func (*Rect) RayCollisions ¶
func (r *Rect) RayCollisions(ray *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with each ray collision with the rectangular surface. It returns the number of collisions.
type RectCollider ¶ added in v0.2.6
type RectCollider interface { // RectCollision returns true if any part of the // surface is inside the rect. RectCollision(r *Rect) bool }
A RectCollider is a surface which can detect if a 3D axis-aligned rectangular volume collides with the surface.
type SDF ¶
An SDF is a signed distance function.
An SDF returns 0 on the boundary of some surface, positive values inside the surface, and negative values outside the surface. The magnitude is the distance to the surface.
All methods of an SDF are safe for concurrency.
func ColliderToSDF ¶
ColliderToSDF generates an SDF that uses bisection search to approximate the SDF for any Collider.
The iterations argument controls the precision. If set to 0, a default of 32 is used.
func FuncSDF ¶ added in v0.2.13
FuncSDF creates an SDF from a function.
If the bounds are invalid, FuncSDF() will panic(). In particular, max must be no less than min, and all floating-point values must be finite numbers.
func ProfileSDF ¶ added in v0.2.5
ProfileSDF turns a 2D SDF into a 3D SDF by elongating the 2D SDF along the Z axis.
func TransformSDF ¶ added in v0.2.11
func TransformSDF(t DistTransform, s SDF) SDF
TransformSDF applies t to the SDF s to produce a new, transformed SDF.
type Scale ¶ added in v0.2.11
type Scale struct {
Scale float64
}
Scale is a transform that scales an object.
func (*Scale) ApplyBounds ¶ added in v0.2.11
func (*Scale) ApplyDistance ¶ added in v0.2.11
type Segment ¶
type Segment [2]Coord3D
A Segment is a line segment in a canonical ordering, such that segments can be compared via the == operator even if they were created with their points in the opposite order.
func NewSegment ¶
NewSegment creates a segment with the canonical ordering.
func (*Segment) ClosestL1 ¶ added in v0.2.13
ClosestL1 gets the point on the segment closest to c as measured in L1 distance.
func (*Segment) L1Dist ¶ added in v0.2.13
L1Dist gets the minimum L1 distance from c to a point on the line segment.
func (Segment) Other ¶ added in v0.2.11
Other gets a point in t that is not in s, provided that t is not degenerate.
func (Segment) RectCollision ¶ added in v0.2.6
RectCollision checks if the segment intersects a Rect.
type SegmentCollider ¶ added in v0.2.6
type SegmentCollider interface { // SegmentCollision returns true if the segment // collides with the surface. SegmentCollision(s Segment) bool }
A SegmentCollider is a surface which can detect if a line segment collides with the surface.
type Solid ¶
type Solid interface { // Contains must always return false outside of the // boundaries of the solid. Bounder Contains(p Coord3D) bool }
A Solid is a boolean function where a value of true indicates that a point is part of the solid, and false indicates that it is not.
All methods of a Solid are safe for concurrency.
func CacheSolidBounds ¶
CacheSolidBounds creates a Solid that has a cached version of the solid's boundary coordinates.
The solid also explicitly checks that points are inside the boundary before passing them off to s.
func CheckedFuncSolid ¶ added in v0.2.11
CheckedFuncSolid is like FuncSolid, but it does an automatic bounds check before calling f.
func ForceSolidBounds ¶ added in v0.2.7
ForceSolidBounds creates a new solid that reports the exact bounds given by min and max.
Points outside of these bounds will be removed from s, but otherwise s is preserved.
func FuncSolid ¶ added in v0.2.11
FuncSolid creates a Solid from a function.
If the bounds are invalid, FuncSolid() will panic(). In particular, max must be no less than min, and all floating-point values must be finite numbers.
func ProfileSolid ¶ added in v0.2.5
ProfileSolid turns a 2D solid into a 3D solid by elongating the 2D solid along the Z axis.
func RevolveSolid ¶ added in v0.2.13
RevolveSolid rotates a 2D solid around an axis to create a 3D solid. The y-axis of the 2D solid is extended along the axis of revolution, while the x-axis is used as a radius.
The 2D solid should either be symmetrical around the axis, or be empty on one side of the axis. Either way, the union of both reflections of the 2D solid is used.
func RotateSolid ¶ added in v0.2.15
RotateSolid creates a new Solid by rotating a Solid by a given angle (in radians) around a given (unit) axis.
func SDFToSolid ¶ added in v0.3.0
SDFToSolid creates a Solid which is true inside the SDF.
If the outset argument is non-zero, it is the extra distance outside the SDF that is considered inside the solid. It can also be negative to inset the solid.
func ScaleSolid ¶ added in v0.2.11
ScaleSolid creates a new Solid that scales incoming coordinates c by 1/s. Thus, the new solid is s times larger.
func SmoothJoin ¶ added in v0.2.2
SmoothJoin joins the SDFs into a union Solid and smooths the intersections using a given smoothing radius.
If the radius is 0, it is equivalent to turning the SDFs directly into solids and then joining them.
func SmoothJoinV2 ¶ added in v0.3.0
SmoothJoinV2 is like SmoothJoin, but uses surface normals to improve results for SDFs that intersect at obtuse angles.
func StackSolids ¶ added in v0.1.1
StackSolids joins solids together and moves each solid after the first so that the lowest Z value of its bounding box collides with the highest Z value of the previous solid's bounding box. In other words, the solids are stacked on top of each other along the Z axis.
func TransformSolid ¶
TransformSolid applies t to the solid s to produce a new, transformed solid.
func TranslateSolid ¶ added in v0.2.13
TranslateSolid creates a new Solid by translating a Solid by a given offset.
type SolidCollider ¶
type SolidCollider struct { Solid Solid // Epsilon is a distance considered "small" in the // context of the solid. // It is used to walk along rays to find // intersections. Epsilon float64 // BisectCount, if non-zero, specifies the number of // bisections to use to narrow down collisions. // If it is zero, a reasonable default is used. BisectCount int // NormalSamples, if non-zero, specifies how many // samples to use to approximate normals. // If not specified, a default is used. NormalSamples int // NormalBisectEpsilon, if non-zero, specifies a small // distance to use in a bisection-based method to // compute approximate normals. // // If set, this should typically be smaller than // Epsilon, since smaller values don't affect runtime // but do improve accuracy (up to a point). // // If this is 0, bisection is not used to approximate // normals, but rather a more noisy but less brittle // algorithm. NormalBisectEpsilon float64 }
A SolidCollider approximates the behavior of a Collider based on nothing but a Solid.
func (*SolidCollider) FirstRayCollision ¶
func (s *SolidCollider) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision approximately finds the first time the ray collides with the solid.
The result may be inaccurate for parts of the solid smaller than epsilon.
func (*SolidCollider) Max ¶
func (s *SolidCollider) Max() Coord3D
Max gets the maximum boundary of the Solid.
func (*SolidCollider) Min ¶
func (s *SolidCollider) Min() Coord3D
Min gets the minimum boundary of the Solid.
func (*SolidCollider) RayCollisions ¶
func (s *SolidCollider) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions counts the approximate number of times the ray collides with the solid's border.
The result may be inaccurate for parts of the solid smaller than epsilon.
func (*SolidCollider) SphereCollision ¶
func (s *SolidCollider) SphereCollision(c Coord3D, r float64) bool
SphereCollision checks if the solid touches a sphere with origin c and radius r.
The result may be inaccurate for parts of the solid smaller than epsilon.
This grows slower with r as O(r^3).
type Sphere ¶
A Sphere is a spherical 3D primitive.
func (*Sphere) FirstRayCollision ¶
func (s *Sphere) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the sphere, if one occurs.
func (*Sphere) NormalSDF ¶ added in v0.3.0
NormalSDF gets the signed distance function at coord and also returns the normal at the nearest point to it on the sphere.
func (*Sphere) PointSDF ¶ added in v0.2.3
PointSDF gets the signed distance function at coord and also returns the nearest point to it on the sphere.
func (*Sphere) RayCollisions ¶
func (s *Sphere) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with every ray collision.
It returns the total number of collisions.
type SphereSolid ¶
type SphereSolid = Sphere
type StackedSolid ¶
type StackedSolid []Solid
A StackedSolid is like a JoinedSolid, but the solids after the first are moved so that the lowest Z value of their bounding box collides with the highest Z value of the previous solid. In other words, the solids are stacked on top of each other along the Z axis.
This API is deprecated in favor of the StackSolids() function.
func (StackedSolid) Contains ¶
func (s StackedSolid) Contains(c Coord3D) bool
func (StackedSolid) Max ¶
func (s StackedSolid) Max() Coord3D
func (StackedSolid) Min ¶
func (s StackedSolid) Min() Coord3D
type Subdivider ¶
type Subdivider struct {
// contains filtered or unexported fields
}
A Subdivider is used for sub-dividing triangles in a mesh to add levels of detail where it is needed in a model.
To achieve this, it tracks line segments that are to be split, and then replaces triangles in the mesh such that the given lines are split and the midpoint is replaced with a more accurate value.
func (*Subdivider) Add ¶
func (s *Subdivider) Add(p1, p2 Coord3D)
Add adds a line segment that needs to be split.
func (*Subdivider) AddFiltered ¶
func (s *Subdivider) AddFiltered(m *Mesh, f func(p1, p2 Coord3D) bool)
AddFiltered adds line segments for which f returns true.
func (*Subdivider) Subdivide ¶
func (s *Subdivider) Subdivide(mesh *Mesh, midpointFunc func(p1, p2 Coord3D) Coord3D)
Subdivide modifies the mesh by replacing triangles whose sides are affected by subdivision.
The midpointFunc computes a 3D coordinate that should replace the midpoint of a given line segment from the original mesh.
type SubtractedSolid ¶
SubtractedSolid is a Solid consisting of all the points in Positive which are not in Negative.
func (*SubtractedSolid) Contains ¶
func (s *SubtractedSolid) Contains(c Coord3D) bool
func (*SubtractedSolid) Max ¶
func (s *SubtractedSolid) Max() Coord3D
func (*SubtractedSolid) Min ¶
func (s *SubtractedSolid) Min() Coord3D
type Torus ¶
A Torus is a 3D primitive that represents a torus.
The torus is defined by revolving a sphere of radius InnerRadius around the point Center and around the axis Axis, at a distance of OuterRadius from Center.
The Torus is only valid if the inner radius is lower than the outer radius. Otherwise, invalid ray collisions and SDF values may be reported.
func (*Torus) FirstRayCollision ¶ added in v0.3.0
func (t *Torus) FirstRayCollision(ray *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the surface of the torus.
func (*Torus) NormalSDF ¶ added in v0.3.0
NormalSDF is like SDF, but also returns the normal on the surface of the torus at the closest point to c.
func (*Torus) PointSDF ¶ added in v0.3.0
PointSDF is like SDF, but also returns the closest point on the surface of the torus.
func (*Torus) RayCollisions ¶ added in v0.3.0
func (t *Torus) RayCollisions(ray *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with each ray collision with the surface of the torus. It returns the number of collisions.
type TorusSolid ¶
type TorusSolid = Torus
type Transform ¶
type Transform interface { // Apply applies the transformation to c. Apply(c Coord3D) Coord3D // ApplyBounds gets a new bounding rectangle that is // guaranteed to bound the old bounding rectangle when // it is transformed. ApplyBounds(min, max Coord3D) (Coord3D, Coord3D) // Inverse gets an inverse transformation. // // The inverse may not perfectly invert bounds // transformations, since some information may be lost // during such a transformation. Inverse() Transform }
Transform is an invertible coordinate transformation.
type Translate ¶
type Translate struct {
Offset Coord3D
}
Translate is a Transform that adds an offset to coordinates.
func (*Translate) ApplyBounds ¶
func (*Translate) ApplyDistance ¶ added in v0.2.11
type Triangle ¶
type Triangle [3]Coord3D
A Triangle is a triangle in 3D Euclidean space.
func ReadOFF ¶
ReadOFF decodes a file in the object file format. See http://segeval.cs.princeton.edu/public/off_format.html.
func TriangulateFace ¶
TriangulateFace turns any simple polygon face into a set of triangles.
If the points are not coplanar, the result is approximated.
func (*Triangle) AreaGradient ¶
AreaGradient computes the gradient of the triangle's area with respect to every coordinate.
func (*Triangle) FirstRayCollision ¶
func (t *Triangle) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the ray collision if there is one.
The Extra field is a *TriangleCollision.
func (*Triangle) Normal ¶
Normal computes a normal vector for the triangle using the right-hand rule.
func (*Triangle) RayCollisions ¶
func (t *Triangle) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with a collision (if applicable) and returns the collisions count (0 or 1).
The Extra field is a *TriangleCollision.
func (*Triangle) RectCollision ¶ added in v0.2.6
RectCollision checks if any part of the triangle is inside the rect.
func (*Triangle) SegmentCollision ¶ added in v0.2.6
SegmentCollision checks if the segment collides with the triangle.
func (*Triangle) SharesEdge ¶
SharesEdge checks if p shares exactly one edge with p1.
func (*Triangle) SphereCollision ¶
SphereCollision checks if any part of the triangle is within the sphere.
func (*Triangle) TriangleCollisions ¶
TriangleCollisions finds the segment where t intersects t1. If no segment exists, an empty slice is returned.
If t and t1 are (nearly) co-planar, no collisions are reported, since small numerical differences can have a major impact.
type TriangleCollider ¶
type TriangleCollider interface { Collider // TriangleCollisions gets all of the segments on the // surface which intersect the triangle t. TriangleCollisions(t *Triangle) []Segment }
A TriangleCollider is like a Collider, but it can also check if and where a triangle intersects the surface.
This is intended to be used for piecewise-linear surfaces where triangle-surface intersections can be parameterized as line segments.
All methods of a TriangleCollider are safe for concurrency.
type TriangleCollision ¶
type TriangleCollision struct { // The triangle that reported the collision. Triangle *Triangle // Barycentric coordinates in the triangle, // corresponding to the corners. Barycentric [3]float64 }
TriangleCollision is triangle-specific collision information.
type VoxelSmoother ¶
type VoxelSmoother struct { StepSize float64 Iterations int // MaxDistance is the maximum L_infinity distance a // vertex must move. MaxDistance float64 }
VoxelSmoother uses hard-constraints on top of gradient descent to minimize the surface area of a mesh while keeping vertices within a square region of space.
This is based on the surface nets algorithm.
Also see MeshSmoother, which is similar but more general-purpose.
func (*VoxelSmoother) Smooth ¶
func (v *VoxelSmoother) Smooth(mesh *Mesh) *Mesh
Smooth applies gradient descent to smooth the mesh.
Source Files ¶
- bounder.go
- bvh.go
- collisions.go
- coord_tree.go
- coords.go
- decimate.go
- deformation.go
- doc.go
- export.go
- fast_maps.go
- import.go
- matrix.go
- mc.go
- measurements.go
- mesh.go
- mesh_hierarchy.go
- mesh_ops.go
- polytope.go
- primitives.go
- ptr_mesh.go
- sdf.go
- shapes.go
- smooth.go
- solid.go
- subdivision.go
- transform.go
- triangulate.go