150 lines
3.3 KiB
Go
150 lines
3.3 KiB
Go
|
|
package mesh
|
||
|
|
|
||
|
|
import (
|
||
|
|
"zworld/engine/object"
|
||
|
|
"zworld/engine/renderapi/material"
|
||
|
|
"zworld/engine/renderapi/texture"
|
||
|
|
"zworld/engine/renderapi/vertex"
|
||
|
|
"zworld/plugins/math/shape"
|
||
|
|
"zworld/plugins/math/vec3"
|
||
|
|
)
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
object.Register[*Static](Deserialize)
|
||
|
|
}
|
||
|
|
|
||
|
|
type Mesh interface {
|
||
|
|
object.Component
|
||
|
|
|
||
|
|
Primitive() vertex.Primitive
|
||
|
|
CastShadows() bool
|
||
|
|
Material() *material.Def
|
||
|
|
MaterialID() material.ID
|
||
|
|
|
||
|
|
Texture(texture.Slot) texture.Ref
|
||
|
|
|
||
|
|
// Bounding sphere used for view frustum culling
|
||
|
|
BoundingSphere() shape.Sphere
|
||
|
|
|
||
|
|
// returns the VertexData property
|
||
|
|
// this is kinda ugly - but other components might need to subscribe to changes ?
|
||
|
|
Mesh() *object.Property[vertex.Mesh]
|
||
|
|
}
|
||
|
|
|
||
|
|
// mesh base
|
||
|
|
type Static struct {
|
||
|
|
object.Component
|
||
|
|
|
||
|
|
primitive vertex.Primitive
|
||
|
|
shadows bool
|
||
|
|
mat *material.Def
|
||
|
|
matId material.ID
|
||
|
|
|
||
|
|
textures map[texture.Slot]texture.Ref
|
||
|
|
|
||
|
|
// bounding radius
|
||
|
|
center vec3.T
|
||
|
|
radius float32
|
||
|
|
|
||
|
|
VertexData object.Property[vertex.Mesh]
|
||
|
|
}
|
||
|
|
|
||
|
|
// New creates a new mesh component
|
||
|
|
func New(mat *material.Def) *Static {
|
||
|
|
return NewPrimitiveMesh(vertex.Triangles, mat)
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewLines creates a new line mesh component
|
||
|
|
func NewLines() *Static {
|
||
|
|
return NewPrimitiveMesh(vertex.Lines, nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewPrimitiveMesh creates a new mesh composed of a given GL primitive
|
||
|
|
func NewPrimitiveMesh(primitive vertex.Primitive, mat *material.Def) *Static {
|
||
|
|
m := object.NewComponent(&Static{
|
||
|
|
mat: mat,
|
||
|
|
matId: material.Hash(mat),
|
||
|
|
textures: make(map[texture.Slot]texture.Ref),
|
||
|
|
primitive: primitive,
|
||
|
|
shadows: true,
|
||
|
|
|
||
|
|
VertexData: object.NewProperty[vertex.Mesh](nil),
|
||
|
|
})
|
||
|
|
m.VertexData.OnChange.Subscribe(func(data vertex.Mesh) {
|
||
|
|
// refresh bounding sphere
|
||
|
|
min := data.Min()
|
||
|
|
max := data.Max()
|
||
|
|
m.center = max.Sub(min).Scaled(0.5)
|
||
|
|
m.radius = m.center.Length()
|
||
|
|
})
|
||
|
|
return m
|
||
|
|
}
|
||
|
|
|
||
|
|
//func (m *Static) Name() string {
|
||
|
|
//return "Mesh"
|
||
|
|
//}
|
||
|
|
|
||
|
|
func (m *Static) Primitive() vertex.Primitive { return m.primitive }
|
||
|
|
func (m *Static) Mesh() *object.Property[vertex.Mesh] { return &m.VertexData }
|
||
|
|
|
||
|
|
func (m *Static) Texture(slot texture.Slot) texture.Ref {
|
||
|
|
return m.textures[slot]
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) SetTexture(slot texture.Slot, ref texture.Ref) {
|
||
|
|
m.textures[slot] = ref
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) CastShadows() bool {
|
||
|
|
return m.primitive == vertex.Triangles && m.shadows && !m.mat.Transparent
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) SetShadows(shadows bool) {
|
||
|
|
m.shadows = shadows
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) Material() *material.Def {
|
||
|
|
return m.mat
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) MaterialID() material.ID {
|
||
|
|
return m.matId
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) BoundingSphere() shape.Sphere {
|
||
|
|
return shape.Sphere{
|
||
|
|
Center: m.Transform().WorldPosition().Add(m.center),
|
||
|
|
Radius: m.radius,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type MeshState struct {
|
||
|
|
object.ComponentState
|
||
|
|
Primitive vertex.Primitive
|
||
|
|
Material material.Def
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) State() MeshState {
|
||
|
|
return MeshState{
|
||
|
|
// send help
|
||
|
|
ComponentState: object.NewComponentState(m.Component),
|
||
|
|
Primitive: m.primitive,
|
||
|
|
Material: *m.Material(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *Static) Serialize(enc object.Encoder) error {
|
||
|
|
return enc.Encode(m.State())
|
||
|
|
}
|
||
|
|
|
||
|
|
func Deserialize(dec object.Decoder) (object.Component, error) {
|
||
|
|
var state MeshState
|
||
|
|
if err := dec.Decode(&state); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
obj := NewPrimitiveMesh(state.Primitive, &state.Material)
|
||
|
|
obj.Component = state.ComponentState.New()
|
||
|
|
return obj, nil
|
||
|
|
}
|