zworld/plugins/geometry/sphere/sphere.go

116 lines
3.2 KiB
Go
Raw Permalink Normal View History

2024-01-14 22:56:06 +08:00
package sphere
import (
"zworld/engine/object"
"zworld/engine/object/mesh"
"zworld/engine/renderapi/material"
"zworld/engine/renderapi/texture"
"zworld/engine/renderapi/vertex"
"zworld/plugins/math/vec2"
"zworld/plugins/math/vec3"
)
type Mesh struct {
*mesh.Static
Subdivisions object.Property[int]
data vertex.MutableMesh[vertex.T, uint16]
}
func New(mat *material.Def) *Mesh {
m := object.NewComponent(&Mesh{
Static: mesh.New(mat),
Subdivisions: object.NewProperty(3),
})
m.SetTexture(texture.Diffuse, texture.Checker)
m.data = vertex.NewTriangles[vertex.T, uint16](object.Key("sphere", m), nil, nil)
m.Subdivisions.OnChange.Subscribe(func(int) { m.refresh() })
m.refresh()
return m
}
func (m *Mesh) refresh() {
tris := icosphere(m.Subdivisions.Get())
vertices := []vertex.T{}
for _, tri := range tris {
vertices = append(vertices, vertex.T{
P: tri.A,
N: tri.A,
T: vec2.New(0, 0),
})
vertices = append(vertices, vertex.T{
P: tri.B,
N: tri.B,
T: vec2.New(0, 0),
})
vertices = append(vertices, vertex.T{
P: tri.C,
N: tri.C,
T: vec2.New(0, 0),
})
}
m.data.Update(vertices, nil)
m.VertexData.Set(m.data)
}
func icosphere(subdivisions int) []vertex.Triangle {
const X = float32(0.525731112119133606)
const Z = float32(0.850650808352039932)
vertices := []vec3.T{
vec3.New(-X, 0, Z),
vec3.New(X, 0, Z),
vec3.New(-X, 0, -Z),
vec3.New(X, 0, -Z),
vec3.New(0, Z, X),
vec3.New(0, Z, -X),
vec3.New(0, -Z, X),
vec3.New(0, -Z, -X),
vec3.New(Z, X, 0),
vec3.New(-Z, X, 0),
vec3.New(Z, -X, 0),
vec3.New(-Z, -X, 0),
}
faces := []vertex.Triangle{
{A: vertices[1], B: vertices[4], C: vertices[0]},
{A: vertices[4], B: vertices[9], C: vertices[0]},
{A: vertices[4], B: vertices[5], C: vertices[9]},
{A: vertices[8], B: vertices[5], C: vertices[4]},
{A: vertices[1], B: vertices[8], C: vertices[4]},
{A: vertices[1], B: vertices[10], C: vertices[8]},
{A: vertices[10], B: vertices[3], C: vertices[8]},
{A: vertices[8], B: vertices[3], C: vertices[5]},
{A: vertices[3], B: vertices[2], C: vertices[5]},
{A: vertices[3], B: vertices[7], C: vertices[2]},
{A: vertices[3], B: vertices[10], C: vertices[7]},
{A: vertices[10], B: vertices[6], C: vertices[7]},
{A: vertices[6], B: vertices[11], C: vertices[7]},
{A: vertices[6], B: vertices[0], C: vertices[11]},
{A: vertices[6], B: vertices[1], C: vertices[0]},
{A: vertices[10], B: vertices[1], C: vertices[6]},
{A: vertices[11], B: vertices[0], C: vertices[9]},
{A: vertices[2], B: vertices[11], C: vertices[9]},
{A: vertices[5], B: vertices[2], C: vertices[9]},
{A: vertices[11], B: vertices[2], C: vertices[7]},
}
for r := subdivisions; r > 0; r-- {
result := make([]vertex.Triangle, 0, 4*len(faces))
for _, tri := range faces {
v1 := vec3.Mid(tri.A, tri.B).Normalized()
v2 := vec3.Mid(tri.B, tri.C).Normalized()
v3 := vec3.Mid(tri.C, tri.A).Normalized()
result = append(result, vertex.Triangle{A: tri.A, B: v1, C: v3})
result = append(result, vertex.Triangle{A: tri.B, B: v2, C: v1})
result = append(result, vertex.Triangle{A: tri.C, B: v3, C: v2})
result = append(result, vertex.Triangle{A: v1, B: v2, C: v3})
}
faces = result
}
return faces
}