From 890ef427b3ef52f7d70f00fac0a051ec0e49a884 Mon Sep 17 00:00:00 2001 From: Alex Nichol Date: Sat, 6 Jan 2024 15:22:44 -0500 Subject: [PATCH] start mimicking GL.iNet --- examples/parody/gl_inet/body.go | 69 +++++++++++++++++++++++++++++ examples/parody/gl_inet/ethernet.go | 60 +++++++++++++++++++++++++ examples/parody/gl_inet/fanhole.go | 54 ++++++++++++++++++++++ examples/parody/gl_inet/main.go | 64 ++++++++++++++++++++++++++ 4 files changed, 247 insertions(+) create mode 100644 examples/parody/gl_inet/body.go create mode 100644 examples/parody/gl_inet/ethernet.go create mode 100644 examples/parody/gl_inet/fanhole.go create mode 100644 examples/parody/gl_inet/main.go diff --git a/examples/parody/gl_inet/body.go b/examples/parody/gl_inet/body.go new file mode 100644 index 0000000..1166ce7 --- /dev/null +++ b/examples/parody/gl_inet/body.go @@ -0,0 +1,69 @@ +package main + +import ( + "math" + + "github.com/unixpickle/model3d/model2d" + "github.com/unixpickle/model3d/model3d" +) + +const ( + BodyCornerRadius = 0.15 + BodySideLength = 2.2 + BodyRadius = 5.0 + BodyPowerHoleRadius = 0.03 + BodyPowerHoleWidth = 0.15 +) + +func InetBody() model3d.Solid { + sphere := model3d.Sphere{ + Center: model3d.Z(-BodyRadius + 1.0), + Radius: BodyRadius, + } + baseRect := model2d.NewRect( + model2d.Ones(-BodySideLength/2+BodyCornerRadius), + model2d.Ones(BodySideLength/2-BodyCornerRadius), + ) + holes := model3d.JoinedSolid{ + &model3d.Cylinder{ + P1: model3d.XYZ(-0.25, 0.9, 0.8), + P2: model3d.XYZ(-0.25, 1.0, 1.0), + Radius: 0.02, + }, + &model3d.Cylinder{ + P1: model3d.XYZ(0.0, 0.9, 0.8), + P2: model3d.XYZ(0.0, 1.0, 1.0), + Radius: 0.02, + }, + &model3d.Cylinder{ + P1: model3d.XYZ(0.25, 0.9, 0.8), + P2: model3d.XYZ(0.25, 1.0, 1.0), + Radius: 0.02, + }, + } + powerHole2d := model2d.NewColliderSolidInset( + model2d.NewRect( + model2d.XY(0.8-BodyPowerHoleRadius-BodyPowerHoleWidth, 0.15+BodyPowerHoleRadius), + model2d.XY(0.8-BodyPowerHoleRadius, 0.15+BodyPowerHoleRadius+1e-5), + ), + -BodyPowerHoleRadius, + ) + powerHole := model3d.RotateSolid( + model3d.ProfileSolid(powerHole2d, BodySideLength/2-0.2, BodySideLength/2+0.05), + model3d.X(1), + math.Pi/2, + ) + return model3d.CheckedFuncSolid( + model3d.XYZ(-BodySideLength/2, -BodySideLength/2, 0), + model3d.XYZ(BodySideLength/2, BodySideLength/2, 1.0), + func(c model3d.Coord3D) bool { + if !sphere.Contains(c) { + return false + } + if holes.Contains(c) || powerHole.Contains(c) { + return false + } + return baseRect.SDF(c.XY()) > -BodyCornerRadius + }, + ) +} diff --git a/examples/parody/gl_inet/ethernet.go b/examples/parody/gl_inet/ethernet.go new file mode 100644 index 0000000..d19d055 --- /dev/null +++ b/examples/parody/gl_inet/ethernet.go @@ -0,0 +1,60 @@ +package main + +import ( + "github.com/unixpickle/model3d/model2d" + "github.com/unixpickle/model3d/model3d" +) + +func EthernetJackSolid() model3d.Solid { + profile := model2d.NewColliderSolid( + model2d.MeshToCollider( + model2d.CurveMesh(model2d.JoinedCurve{ + &model2d.BezierCurve{ + model2d.XY(0.15, 0.15), + model2d.XY(0.85, 0.15), + }, + &model2d.BezierCurve{ + model2d.XY(0.85, 0.15), + model2d.XY(0.85, 0.7), + }, + &model2d.BezierCurve{ + model2d.XY(0.85, 0.7), + model2d.XY(0.65, 0.7), + }, + &model2d.BezierCurve{ + model2d.XY(0.65, 0.7), + model2d.XY(0.65, 0.85), + }, + &model2d.BezierCurve{ + model2d.XY(0.65, 0.85), + model2d.XY(0.35, 0.85), + }, + &model2d.BezierCurve{ + model2d.XY(0.35, 0.85), + model2d.XY(0.35, 0.7), + }, + &model2d.BezierCurve{ + model2d.XY(0.35, 0.7), + model2d.XY(0.15, 0.7), + }, + &model2d.BezierCurve{ + model2d.XY(0.1, 0.7), + model2d.XY(0.1, 0.1), + }, + }, 300).MapCoords(model2d.XY(1.0, -1.0).Mul).Translate(model2d.Y(1.0)), + ), + ) + return model3d.CheckedFuncSolid( + model3d.XYZ(-0.9, -BodySideLength/2+0.02, 0.1), + model3d.XYZ(0.3, -BodySideLength/2+0.3, 0.6), + func(c model3d.Coord3D) bool { + x := (c.X + 0.9) / (0.9 + 0.3) + if x > 0.5 { + x -= 0.5 + } + x *= 2.0 + y := (c.Z - 0.1) / 0.5 + return !profile.Contains(model2d.XY(x, y)) + }, + ) +} diff --git a/examples/parody/gl_inet/fanhole.go b/examples/parody/gl_inet/fanhole.go new file mode 100644 index 0000000..a725fc1 --- /dev/null +++ b/examples/parody/gl_inet/fanhole.go @@ -0,0 +1,54 @@ +package main + +import ( + "math" + + "github.com/unixpickle/model3d/model2d" + "github.com/unixpickle/model3d/model3d" +) + +func FanHole() model3d.Solid { + oneHole := model3d.CheckedFuncSolid( + model3d.XYZ(0.9, 0.7, 0.5), + model3d.XYZ(BodySideLength/2+0.01, 0.9, 0.7), + func(c model3d.Coord3D) bool { + x := (c.Y - 0.8) / 0.1 + y := (c.Z - 0.6) / 0.1 + xy := model2d.XY(x, y) + if xy.Norm() > 1.0 { + return false + } + if c.X < BodySideLength/2-0.03 { + r := xy.Norm() + theta := math.Atan2(y, x) + r + if theta < 0 { + theta += math.Pi * 2 + } + for i := 0; i < 3; i++ { + if thetaDiff(theta, float64(i)*math.Pi*2/3+0.1) < 0.3/math.Max(0.03, r) { + return false + } + } + } + return true + }, + ) + transformed := model3d.TransformSolid( + &model3d.Matrix3Transform{ + Matrix: &model3d.Matrix3{-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}, + }, + oneHole, + ) + return model3d.JoinedSolid{oneHole, transformed} +} + +func thetaDiff(t1, t2 float64) float64 { + diff := t2 - t1 + for diff < 0 { + diff += math.Pi * 2 + } + for diff > math.Pi*2 { + diff -= math.Pi * 2 + } + return diff +} diff --git a/examples/parody/gl_inet/main.go b/examples/parody/gl_inet/main.go new file mode 100644 index 0000000..740a026 --- /dev/null +++ b/examples/parody/gl_inet/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "log" + + "github.com/unixpickle/model3d/model3d" + "github.com/unixpickle/model3d/render3d" + "github.com/unixpickle/model3d/toolbox3d" +) + +func main() { + body := InetBody() + + jack := EthernetJackSolid() + min, max := jack.Min(), jack.Max() + min = min.AddScalar(0.01) + max = max.AddScalar(-0.01) + min.Y -= 0.1 + jackHole := model3d.NewRect(min, max) + min.Y = max.Y - 0.1 + jackEnd := model3d.NewRect(min, max) + + usbPort := model3d.NewRect( + model3d.XYZ(BodySideLength/2-0.3, -0.8, 0.2), + model3d.XYZ(BodySideLength/2+0.1, -0.65, 0.7), + ) + usbInner := model3d.NewRect( + model3d.XYZ(BodySideLength/2-0.3, -0.8, 0.2), + model3d.XYZ(BodySideLength/2-0.05, -0.75, 0.7), + ) + + fanHole := FanHole() + + body = model3d.JoinedSolid{ + &model3d.SubtractedSolid{ + Positive: body, + Negative: model3d.JoinedSolid{ + jackHole, + usbPort, + fanHole, + }, + }, + usbInner, + } + + joined := model3d.JoinedSolid{ + body, + jack, + jackEnd, + } + + log.Println("Creating mesh...") + mesh, interior := model3d.DualContourInterior(joined, 0.01, true, false) + mesh.SaveGroupedSTL("out.stl") + colorFunc := toolbox3d.JoinedSolidCoordColorFunc( + interior, + body, render3d.NewColorRGB(224.0/255, 209.0/255, 0), + jackEnd, render3d.NewColor(0.5), + usbInner, render3d.NewColor(0.5), + jack, render3d.NewColor(0.9), + ) + log.Println("Rendering...") + render3d.SaveRandomGrid("rendering.png", mesh, 3, 3, 300, colorFunc.RenderColor) +}