mesh-tool: mesht - create/inspect/edit OBJ+STL with ASCII multi-view rendering
- OBJ read/write (multi-object, ngon fan-triangulation, negative indices), STL binary+ascii with auto-detect and vertex welding - info: bbox/size/area/volume + watertightness via edge manifold stats - view: z-buffered orthographic ASCII renders (front/side/top/iso/back) - transform: center/mirror/scale/rotate/translate/fit, per-object filter, winding auto-flip on negative determinant - create: box/sphere/cylinder/cone/plane/torus; merge; convert - go tests: primitive volumes vs analytic values, roundtrips, topology Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmdG9GqfSWCzts7AkDwRDh
This commit is contained in:
122
mesh-tool/mesh/vec.go
Normal file
122
mesh-tool/mesh/vec.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package mesh
|
||||
|
||||
import "math"
|
||||
|
||||
// Vec3 is a point or direction in 3D space.
|
||||
type Vec3 struct{ X, Y, Z float64 }
|
||||
|
||||
func (a Vec3) Add(b Vec3) Vec3 { return Vec3{a.X + b.X, a.Y + b.Y, a.Z + b.Z} }
|
||||
func (a Vec3) Sub(b Vec3) Vec3 { return Vec3{a.X - b.X, a.Y - b.Y, a.Z - b.Z} }
|
||||
func (a Vec3) Mul(s float64) Vec3 { return Vec3{a.X * s, a.Y * s, a.Z * s} }
|
||||
func (a Vec3) Dot(b Vec3) float64 { return a.X*b.X + a.Y*b.Y + a.Z*b.Z }
|
||||
func (a Vec3) Len() float64 { return math.Sqrt(a.Dot(a)) }
|
||||
func (a Vec3) Cross(b Vec3) Vec3 {
|
||||
return Vec3{
|
||||
a.Y*b.Z - a.Z*b.Y,
|
||||
a.Z*b.X - a.X*b.Z,
|
||||
a.X*b.Y - a.Y*b.X,
|
||||
}
|
||||
}
|
||||
|
||||
// Norm returns the unit vector, or the zero vector for zero-length input.
|
||||
func (a Vec3) Norm() Vec3 {
|
||||
l := a.Len()
|
||||
if l == 0 {
|
||||
return Vec3{}
|
||||
}
|
||||
return a.Mul(1 / l)
|
||||
}
|
||||
|
||||
// Min/Max return the component-wise minimum/maximum.
|
||||
func (a Vec3) Min(b Vec3) Vec3 {
|
||||
return Vec3{math.Min(a.X, b.X), math.Min(a.Y, b.Y), math.Min(a.Z, b.Z)}
|
||||
}
|
||||
func (a Vec3) Max(b Vec3) Vec3 {
|
||||
return Vec3{math.Max(a.X, b.X), math.Max(a.Y, b.Y), math.Max(a.Z, b.Z)}
|
||||
}
|
||||
|
||||
// Mat4 is a row-major 4x4 transform matrix.
|
||||
type Mat4 [16]float64
|
||||
|
||||
func Identity() Mat4 {
|
||||
return Mat4{
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Mul returns m * n (n is applied first when transforming points).
|
||||
func (m Mat4) Mul(n Mat4) Mat4 {
|
||||
var r Mat4
|
||||
for row := 0; row < 4; row++ {
|
||||
for col := 0; col < 4; col++ {
|
||||
sum := 0.0
|
||||
for k := 0; k < 4; k++ {
|
||||
sum += m[row*4+k] * n[k*4+col]
|
||||
}
|
||||
r[row*4+col] = sum
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Apply transforms a point (w = 1).
|
||||
func (m Mat4) Apply(v Vec3) Vec3 {
|
||||
return Vec3{
|
||||
m[0]*v.X + m[1]*v.Y + m[2]*v.Z + m[3],
|
||||
m[4]*v.X + m[5]*v.Y + m[6]*v.Z + m[7],
|
||||
m[8]*v.X + m[9]*v.Y + m[10]*v.Z + m[11],
|
||||
}
|
||||
}
|
||||
|
||||
// Det3 is the determinant of the upper-left 3x3. Negative means the
|
||||
// transform mirrors space, which flips triangle winding.
|
||||
func (m Mat4) Det3() float64 {
|
||||
return m[0]*(m[5]*m[10]-m[6]*m[9]) -
|
||||
m[1]*(m[4]*m[10]-m[6]*m[8]) +
|
||||
m[2]*(m[4]*m[9]-m[5]*m[8])
|
||||
}
|
||||
|
||||
func Translate(t Vec3) Mat4 {
|
||||
m := Identity()
|
||||
m[3], m[7], m[11] = t.X, t.Y, t.Z
|
||||
return m
|
||||
}
|
||||
|
||||
func ScaleXYZ(s Vec3) Mat4 {
|
||||
m := Identity()
|
||||
m[0], m[5], m[10] = s.X, s.Y, s.Z
|
||||
return m
|
||||
}
|
||||
|
||||
func RotateX(deg float64) Mat4 {
|
||||
s, c := math.Sincos(deg * math.Pi / 180)
|
||||
return Mat4{
|
||||
1, 0, 0, 0,
|
||||
0, c, -s, 0,
|
||||
0, s, c, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
}
|
||||
|
||||
func RotateY(deg float64) Mat4 {
|
||||
s, c := math.Sincos(deg * math.Pi / 180)
|
||||
return Mat4{
|
||||
c, 0, s, 0,
|
||||
0, 1, 0, 0,
|
||||
-s, 0, c, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
}
|
||||
|
||||
func RotateZ(deg float64) Mat4 {
|
||||
s, c := math.Sincos(deg * math.Pi / 180)
|
||||
return Mat4{
|
||||
c, -s, 0, 0,
|
||||
s, c, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user