116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
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
 | 
						|
}
 |