-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
sphere.go
72 lines (61 loc) · 1.5 KB
/
sphere.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package normals
import (
"image/color"
"image/draw"
"math"
"github.com/EliCDavis/vector/vector2"
"github.com/EliCDavis/vector/vector3"
)
type Sphere struct {
Center vector2.Float64
Radius float64
Direction Direction
}
func (s Sphere) Draw(src draw.Image) {
center3 := vector3.New(s.Center.X(), 0, s.Center.Y())
corner := vector2.Fill(s.Radius)
bottom := s.Center.Sub(corner)
top := s.Center.Add(corner)
circleYMultiplier := 1.
if s.Direction == Subtractive {
circleYMultiplier = -1
}
// a = center.X()
// b := 0
// c := center.Y()
// Equation of a Sphere
// (x - a)^2 + (y - b)^2 + (z - c)^2 = r^2
// (y - b)^2 = r^2 - (x - a)^2 - (z - c)^2
// y - b = math.sqrt(r^2 - (x - a)^2 - (z - c)^2)
// y = math.sqrt(r^2 - (x - a)^2 - (z - c)^2) + b
// y = math.sqrt(r^2 - (x - a)^2 - (z - c)^2)
rr := s.Radius * s.Radius
a := s.Center.X()
c := s.Center.Y()
for x := bottom.X(); x < top.X(); x++ {
xA := x - a
xAxA := xA * xA
for y := bottom.Y(); y < top.Y(); y++ {
pix := vector2.New(x, y)
dist := pix.Distance(s.Center)
if dist > s.Radius {
continue
}
zC := y - c
circleY := math.Sqrt(rr-xAxA-(zC*zC)) * circleYMultiplier
pixNormal := vector3.New(x, circleY, y).
Sub(center3).
Normalized().
MultByVector(vector3.Fill(circleYMultiplier)).
Scale(127).
Clamp(-127, 127)
c := color.RGBA{
R: byte(128 + pixNormal.X()),
G: byte(128 - pixNormal.Z()),
B: byte(128 + pixNormal.Y()),
A: 255,
}
src.Set(int(x), int(y), c)
}
}
}