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.EncodeMaterialOBJ() is the method to use.
Index ¶
- Constants
- 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 GroupTriangles(tris []*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 Collider
- type ColliderSolid
- type ConvexPolytope
- type Coord2D
- type Coord3D
- func NewCoord3DArray(a [3]float64) 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) 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) Normalize() Coord3D
- func (c Coord3D) OrthoBasis() (Coord3D, Coord3D)
- func (c Coord3D) ProjectOut(c1 Coord3D) Coord3D
- func (c Coord3D) Reflect(c1 Coord3D) Coord3D
- func (c Coord3D) Scale(s float64) Coord3D
- 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 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) 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 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) Mul(m1 *Matrix3) *Matrix3
- func (m *Matrix3) MulColumn(c Coord3D) 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 MarchingCubesSearch(s Solid, delta float64, iters int) *Mesh
- func NewMesh() *Mesh
- func NewMeshPolar(radius func(g GeoCoord) float64, stops int) *Mesh
- func NewMeshRect(min, max Coord3D) *Mesh
- func NewMeshTriangles(ts []*Triangle) *Mesh
- func (m *Mesh) Add(t *Triangle)
- func (m *Mesh) AddMesh(m1 *Mesh)
- func (m *Mesh) Blur(rates ...float64) *Mesh
- func (m *Mesh) BlurFiltered(f func(c1, c2 Coord3D) bool, rates ...float64) *Mesh
- func (m *Mesh) Contains(t *Triangle) bool
- 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(t *Triangle))
- func (m *Mesh) IterateSorted(f func(t *Triangle), cmp func(t1, t2 *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(t *Triangle) []*Triangle
- func (m *Mesh) Remove(t *Triangle)
- func (m *Mesh) Repair(epsilon float64) *Mesh
- func (m *Mesh) RepairNormals(epsilon float64) (*Mesh, int)
- func (m *Mesh) SaveGroupedSTL(path string) 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) TriangleSlice() []*Triangle
- func (m *Mesh) VertexSlice() []Coord3D
- type MeshSmoother
- type MultiCollider
- type PointSDF
- type Ray
- type RayCollision
- type Rect
- func (r *Rect) Contains(c Coord3D) bool
- func (r *Rect) FirstRayCollision(ray *Ray) (RayCollision, bool)
- func (r *Rect) Max() Coord3D
- func (r *Rect) Min() Coord3D
- 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 Segment
- type SegmentCollider
- type Solid
- type SolidCollider
- type Sphere
- func (s *Sphere) Contains(c Coord3D) bool
- func (s *Sphere) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (s *Sphere) Max() Coord3D
- func (s *Sphere) Min() Coord3D
- func (s *Sphere) PointSDF(c Coord3D) (Coord3D, float64)
- func (s *Sphere) RayCollisions(r *Ray, f func(RayCollision)) int
- func (s *Sphere) SDF(c Coord3D) float64
- func (s *Sphere) SphereCollision(c Coord3D, r float64) bool
- type SphereSolid
- type StackedSolid
- type Subdivider
- type SubtractedSolid
- type Torus
- 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 ¶
This section is empty.
Functions ¶
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 GroupTriangles ¶
func GroupTriangles(tris []*Triangle)
GroupTriangles sorts the triangle slice into a balanced bounding volume hierarchy. In particular, the sorted slice can be recursively cut in half, and each half will be spatially separated as well as possible along some axis.
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 InBounds ¶
InBounds returns true if c is contained within the bounding rectangular volume of b.
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 final triangle. Leaf *Triangle // Branch, if Leaf is nil, points to two children. Branch []*BVH }
BVH represents a (possibly unbalanced) axis-aligned bounding volume 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 triangle), or a branch with two or more children.
func NewBVHAreaDensity ¶
NewBVHAreaDensity creates a BVH by minimizing the product of each bounding box's area with the number of triangles contained in the bounding box at each branch.
This is good for efficient ray collision detection.
type Bounder ¶
type Bounder interface { // Get the corners of a bounding rectangular volume. // // A point p satisfies: p >= Min and p <= Max if it is // within the bounds. Min() Coord3D Max() Coord3D }
A Bounder is a shape contained within a rectangular volume of space.
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.
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(collider Collider) *ColliderSolid
NewColliderSolid creates a ColliderSolid.
func NewColliderSolidHollow ¶
func NewColliderSolidHollow(collider Collider, r float64) *ColliderSolid
NewColliderSolidHollow creates a ColliderSolid which includes all points within r distance from the surface of the Collider.
The radius r must be greater than zero.
func (*ColliderSolid) Contains ¶
func (c *ColliderSolid) Contains(p Coord3D) bool
func (*ColliderSolid) Max ¶
func (c *ColliderSolid) Max() Coord3D
func (*ColliderSolid) Min ¶
func (c *ColliderSolid) Min() Coord3D
type ConvexPolytope ¶
type ConvexPolytope []*LinearConstraint
A ConvexPolytope is the intersection of some linear constraints.
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 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 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) OrthoBasis ¶
OrthoBasis creates two unit vectors which are orthogonal to c and to each other.
func (Coord3D) ProjectOut ¶
ProjectOut projects the c1 direction out of c.
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) 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 }
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 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
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) 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.
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 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 NewMeshPolar ¶
NewMeshPolar creates a mesh with a 3D polar function.
func NewMeshRect ¶
NewMeshRect creates a new mesh around the rectangular bounds.
func NewMeshTriangles ¶
NewMeshTriangles creates a mesh with the given collection of triangles.
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) 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 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 t.
The triangle t itself is not included in the results.
The triangle t 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 t from the mesh.
It looks at t as a pointer, so the pointer must be exactly the same as a triangle 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) 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) 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) 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 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 }
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 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 GroupedTrianglesToSDF ¶
GroupedTrianglesToSDF creates a PointSDF from a slice of triangles. If the triangles are not grouped by GroupTriangles(), the resulting PointSDF is inefficient.
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 volume.
func (*Rect) FirstRayCollision ¶
func (r *Rect) FirstRayCollision(ray *Ray) (RayCollision, bool)
FirstRayCollision gets the first ray collision with the rectangular surface.
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.
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) 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 in 3D 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 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 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 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.
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) PointSDF ¶ added in v0.2.3
PointSDF gets the signed distance function at c and also returns the nearest point to c 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.
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 ¶
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.