/
sphere.go
63 lines (56 loc) · 2.06 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
package mesh
import (
"image/color"
"math"
"github.com/go-gl/mathgl/mgl32"
"github.com/goxjs/gl"
"github.com/omustardo/gome/util/glutil"
)
// maxDetail determines how many times to recursively subdivide an icosahedron
func initializeSpheres(maxDetail int) {
if spheres == nil {
spheres = make(map[int]Mesh)
}
faces := icosahedronFaces()
// Make more spheres of increasing detail by subdividing the icosahedron faces,
for i := 0; i <= maxDetail; i++ {
// Only create the mesh if it hasn't been done yet.
if _, ok := spheres[i]; !ok {
vertices := make([]mgl32.Vec3, 0, 20*3*int(math.Pow(float64(i), 4)))
for _, f := range faces {
vertices = append(vertices, f[0], f[1], f[2])
}
vertexVBO := glutil.LoadBufferVec3(vertices)
//texCoords := circleTexCoords(numCircleSegments)
//texCoordsVBO := glutil.LoadBufferVec2(texCoords)
// Use vertexVBO as the normalVBO to smooth out polygon edges.
spheres[i] = NewMesh(vertexVBO, gl.Buffer{}, vertexVBO, gl.TRIANGLES, len(vertices), nil, gl.Texture{}, gl.Buffer{})
}
// Divide each face into four faces and continue.
newFaces := make([][3]mgl32.Vec3, 0, 4*len(faces))
for _, f := range faces {
// for each face, divide it into four triangles
for _, face := range subdivideTriangle(f) {
// and then push them outward so they are on the surface of the sphere
for vert := range face {
face[vert] = face[vert].Normalize()
}
newFaces = append(newFaces, face)
}
}
faces = newFaces
}
}
// NewSphere returns a sphere mesh. The higher the detail, the more triangles that make up the mesh.
// Making this number too large will very quickly make you run out of memory.
// Detail 0 is an icosahedron with 20 triangular faces. Each detail level has (detail ^ 4) * 3 * 20 vertices,
// so by detail 5 it's up to 37500 faces. Recommended value for a decently smooth sphere is 4.
func NewSphere(detail int, col *color.NRGBA, texture gl.Texture) Mesh {
if _, ok := spheres[detail]; !ok {
initializeSpheres(detail)
}
s := spheres[detail]
s.Color = col
s.SetTexture(texture)
return s
}