Skip to content

Commit

Permalink
cherry, straw, fix internals
Browse files Browse the repository at this point in the history
  • Loading branch information
unixpickle committed Aug 27, 2023
1 parent 1531830 commit 74f9270
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 8 deletions.
75 changes: 75 additions & 0 deletions examples/usable/milkshake_ringholder/cherry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"github.com/unixpickle/model3d/model2d"
"github.com/unixpickle/model3d/model3d"
"github.com/unixpickle/model3d/render3d"
"github.com/unixpickle/model3d/toolbox3d"
)

const (
CherryRadius = 0.25
CherryStemLength = 0.15
CherryStemRadius = 0.05
)

func CherrySolid() (model3d.Solid, toolbox3d.CoordColorFunc) {
curve := model2d.SmoothBezier(
model2d.XY(0, -CherryRadius),
model2d.XY(-CherryRadius*0.7, -CherryRadius),
model2d.XY(-CherryRadius, -CherryRadius*0.3),
model2d.XY(-CherryRadius, 0),
// Point 1
model2d.XY(-CherryRadius*0.9, CherryRadius*0.5),
model2d.XY(-CherryRadius*0.6, CherryRadius*0.7),
// Point 2
model2d.XY(-CherryRadius*0.4, CherryRadius*0.9),
model2d.XY(-CherryRadius*0.1, CherryRadius*0.8),
// Point 3
model2d.XY(-CherryRadius*0.1, CherryRadius*0.7),
model2d.XY(0, CherryRadius*0.7),
)
profile := model2d.CurveMesh(curve, 100)
profile.AddMesh(profile.MapCoords(model2d.XY(-1, 1).Mul))
solid2d := model2d.NewColliderSolid(model2d.MeshToCollider(profile))
center := CreamHeight + CupHeight
solid := model3d.CheckedFuncSolid(
model3d.XYZ(-CherryRadius, -CherryRadius, center-CherryRadius),
model3d.XYZ(CherryRadius, CherryRadius, center+CherryRadius+0.2),
func(c model3d.Coord3D) bool {
x := c.XY().Norm()
y := c.Z - center
return solid2d.Contains(model2d.XY(x, y))
},
)

stemCurve := model2d.BezierCurve{
model2d.XY(0.0, center+CherryRadius-0.03),
model2d.XY(0.0, center+CherryRadius+CherryStemLength/2),
model2d.XY(CherryStemLength*0.4, center+CherryRadius+CherryStemLength),
}
var segments []model3d.Segment
eps := 0.01
for t := 0.0; t < 1.0-eps; t += eps {
p1 := stemCurve.Eval(t)
p2 := stemCurve.Eval(t + eps)
segments = append(
segments,
model3d.NewSegment(
model3d.YZ(p1.X, p1.Y),
model3d.YZ(p2.X, p2.Y),
),
)
}
stem := toolbox3d.LineJoin(CherryStemRadius, segments...)

colorFn := func(c model3d.Coord3D) render3d.Color {
if stem.Contains(c) {
return render3d.NewColorRGB(0.2, 0.0, 0.0)
} else {
return render3d.NewColorRGB(1.0, 0.0, 0.0)
}
}

return model3d.JoinedSolid{solid, stem}, colorFn
}
47 changes: 41 additions & 6 deletions examples/usable/milkshake_ringholder/cream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,38 @@ import (
)

const (
CreamRadius = 0.15
CreamHeight = 0.8
CreamZOffset = 0.05
CreamRadius = 0.15
CreamHeight = 0.8
CreamZOffset = 0.05
CreamRadiusOffset = 0.05
)

func CreamSolid() (model3d.Solid, toolbox3d.CoordColorFunc) {
mesh := CreamMesh()
return model3d.NewColliderSolid(model3d.MeshToCollider(mesh)),
collider := model3d.MeshToCollider(mesh)
direction := model3d.NewCoord3DRandUnit()
solid := model3d.CheckedFuncSolid(
collider.Min(),
collider.Max(),
func(c model3d.Coord3D) bool {
var numInterior, numExterior int
ray := model3d.Ray{Origin: c, Direction: direction}
collider.RayCollisions(&ray, func(rc model3d.RayCollision) {
if rc.Normal.Dot(direction) < 0 {
numExterior++
} else {
numInterior++
}
})
return numInterior > numExterior
},
)
interior := &model3d.Cone{
Tip: model3d.Z(solid.Max().Z),
Base: model3d.Z(CupHeight - CreamZOffset),
Radius: CupTopRadius - CreamRadius,
}
return model3d.JoinedSolid{solid, interior},
toolbox3d.ConstantCoordColorFunc(render3d.NewColor(1.0))
}

Expand Down Expand Up @@ -52,14 +76,25 @@ func CreamMesh() *model3d.Mesh {
rotation := c.Z / length * 25
x1, x2 = x1.Scale(math.Cos(rotation)).Add(x2.Scale(math.Sin(rotation))),
x1.Scale(-math.Sin(rotation)).Add(x2.Scale(math.Cos(rotation)))
return centerCoord.Add(x1.Scale(c.Y)).Add(x2.Scale(c.X))

// Taper off at the end
t := c.Z / length
taper := 1.0
if t > 0.85 {
taper = (1.0 - t) / (1 - 0.85)
}

return centerCoord.Add(x1.Scale(c.Y * taper)).Add(x2.Scale(c.X * taper))
})
}

func creamCurve(t float64) model3d.Coord3D {
theta := t * 30
// We want the start to naturally "tuck into" the spiral.
radius := (CupTopRadius - CreamRadius) * (1 - math.Abs(t*1.1-0.1))
radius := math.Min(
CupTopRadius-CreamRadius-CreamRadiusOffset,
(CupTopRadius-CreamRadius)*(1-math.Abs(t*1.1-0.1)),
)
return model3d.XYZ(
math.Cos(theta)*radius,
math.Sin(theta)*radius,
Expand Down
2 changes: 1 addition & 1 deletion examples/usable/milkshake_ringholder/cup.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
CupHeight = 3
CupRimHeight = 0.4
CupRimThickness = 0.1
CupContentsDepth = 0.1
CupContentsDepth = 0.05
)

func CupSolid() (model3d.Solid, toolbox3d.CoordColorFunc) {
Expand Down
8 changes: 7 additions & 1 deletion examples/usable/milkshake_ringholder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ import (
func main() {
cup, cupColor := CupSolid()
cream, creamColor := CreamSolid()
joined := model3d.JoinedSolid{cup, cream}
straw, strawColor := StrawSolid()
cherry, cherryColor := CherrySolid()
joined := model3d.JoinedSolid{cup, cream, straw, cherry}

mesh, interior := model3d.MarchingCubesInterior(joined, 0.02, 8)
mesh = model3d.MeshToHierarchy(mesh)[0].Mesh
colorFunc := toolbox3d.JoinedSolidCoordColorFunc(
interior,
cup, cupColor,
cream, creamColor,
straw, strawColor,
cherry, cherryColor,
)

render3d.SaveRandomGrid("rendering.png", mesh, 3, 3, 300, colorFunc.RenderColor)
mesh.SaveMaterialOBJ("milkshake.zip", colorFunc.TriangleColor)
}
69 changes: 69 additions & 0 deletions examples/usable/milkshake_ringholder/straw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"math"

"github.com/unixpickle/model3d/model3d"
"github.com/unixpickle/model3d/render3d"
"github.com/unixpickle/model3d/toolbox3d"
)

const (
StrawHeight = 1.5
StrawRadius = 0.1
StrawInset = 0.02
StrawTwistRate = 5.0
)

func StrawSolid() (model3d.Solid, toolbox3d.CoordColorFunc) {
s1, c1 := SingleStrawSolid()
xf1 := model3d.JoinedTransform{
model3d.Rotation(model3d.Y(1), 0.5),
&model3d.Translate{Offset: model3d.XZ(-1.1, 0.1)},
}
s2 := model3d.TransformSolid(xf1, s1)
c2 := c1.Transform(xf1)
xf2 := model3d.JoinedTransform{
model3d.Rotation(model3d.XY(-0.2, 1).Normalize(), -0.2),
&model3d.Translate{Offset: model3d.XZ(0.3, 0.0)},
}
s3 := model3d.TransformSolid(xf2, s1)
c3 := c1.Transform(xf2)
return model3d.JoinedSolid{s2, s3}, toolbox3d.JoinedSolidCoordColorFunc(nil, s2, c2, s3, c3)
}

func SingleStrawSolid() (model3d.Solid, toolbox3d.CoordColorFunc) {
outerSolid := &model3d.Cylinder{
P1: model3d.Z(CupHeight * 0.9),
P2: model3d.Z(CupHeight + StrawHeight),
Radius: StrawRadius,
}
solid := &model3d.SubtractedSolid{
Positive: outerSolid,
Negative: &model3d.Cylinder{
P1: model3d.Z(CupHeight + StrawHeight - 0.05),
P2: model3d.Z(CupHeight + StrawHeight),
Radius: StrawRadius - StrawInset,
},
}
colorFn := func(c model3d.Coord3D) render3d.Color {
if c.XY().Norm() <= StrawRadius-StrawInset {
return render3d.NewColor(0.8)
}
theta := math.Atan2(c.X, c.Y)
twist := c.Z * StrawTwistRate
theta += twist
for theta < 0 {
theta += math.Pi * 2
}
for theta > math.Pi*2 {
theta -= math.Pi * 2
}
if theta < math.Pi/4 || (theta > math.Pi && theta < math.Pi+math.Pi/4) {
return render3d.NewColorRGB(1.0, 0.0, 0.0)
} else {
return render3d.NewColor(0.8)
}
}
return solid, colorFn
}

0 comments on commit 74f9270

Please sign in to comment.