106 lines
2.6 KiB
Go
106 lines
2.6 KiB
Go
package cylinder
|
|
|
|
import (
|
|
"zworld/engine/object"
|
|
"zworld/engine/object/mesh"
|
|
"zworld/engine/renderapi/color"
|
|
"zworld/engine/renderapi/material"
|
|
"zworld/engine/renderapi/vertex"
|
|
"zworld/plugins/math"
|
|
"zworld/plugins/math/vec3"
|
|
)
|
|
|
|
type Cylinder struct {
|
|
object.Object
|
|
Mesh *Mesh
|
|
}
|
|
|
|
func NewObject(args Args) *Cylinder {
|
|
return object.New("Cylinder", &Cylinder{
|
|
Mesh: New(args),
|
|
})
|
|
}
|
|
|
|
// A Cylinder is a forward rendered colored cyllinder mesh
|
|
type Mesh struct {
|
|
*mesh.Static
|
|
Args
|
|
}
|
|
|
|
type Args struct {
|
|
Mat *material.Def
|
|
Radius float32
|
|
Height float32
|
|
Segments int
|
|
Color color.T
|
|
}
|
|
|
|
func New(args Args) *Mesh {
|
|
if args.Mat == nil {
|
|
args.Mat = material.ColoredForward()
|
|
}
|
|
cyllinder := object.NewComponent(&Mesh{
|
|
Static: mesh.New(args.Mat),
|
|
Args: args,
|
|
})
|
|
// this should not run on the main thread
|
|
cyllinder.generate()
|
|
return cyllinder
|
|
}
|
|
|
|
func (c *Mesh) generate() {
|
|
// vertex order: clockwise
|
|
|
|
data := make([]vertex.C, 2*2*3*c.Segments)
|
|
hh := c.Height / 2
|
|
sangle := 2 * math.Pi / float32(c.Segments)
|
|
color := c.Color.Vec4()
|
|
|
|
// top
|
|
top := vec3.New(0, hh, 0)
|
|
bottom := vec3.New(0, -hh, 0)
|
|
for i := 0; i < c.Segments; i++ {
|
|
o := 12 * i // segment vertex offset
|
|
|
|
right := sangle * (float32(i) + 0.5)
|
|
left := sangle * (float32(i) + 1.5)
|
|
topRight := vec3.New(math.Cos(right), 0, -math.Sin(right)).Scaled(c.Radius)
|
|
topRight.Y = hh
|
|
topLeft := vec3.New(math.Cos(left), 0, -math.Sin(left)).Scaled(c.Radius)
|
|
topLeft.Y = hh
|
|
bottomRight := vec3.New(math.Cos(right), 0, -math.Sin(right)).Scaled(c.Radius)
|
|
bottomRight.Y = -hh
|
|
bottomLeft := vec3.New(math.Cos(left), 0, -math.Sin(left)).Scaled(c.Radius)
|
|
bottomLeft.Y = -hh
|
|
|
|
// top face
|
|
data[o+0] = vertex.C{P: topLeft, N: vec3.Up, C: color}
|
|
data[o+1] = vertex.C{P: top, N: vec3.Up, C: color}
|
|
data[o+2] = vertex.C{P: topRight, N: vec3.Up, C: color}
|
|
|
|
// bottom face
|
|
data[o+3] = vertex.C{P: bottomRight, N: vec3.Down, C: color}
|
|
data[o+4] = vertex.C{P: bottom, N: vec3.Down, C: color}
|
|
data[o+5] = vertex.C{P: bottomLeft, N: vec3.Down, C: color}
|
|
|
|
// calculate segment normal
|
|
nv1 := topRight.Sub(bottomLeft)
|
|
nv2 := bottomRight.Sub(bottomLeft)
|
|
n := vec3.Cross(nv1, nv2)
|
|
|
|
// side face 1
|
|
data[o+6] = vertex.C{P: topRight, N: n, C: color}
|
|
data[o+7] = vertex.C{P: bottomLeft, N: n, C: color}
|
|
data[o+8] = vertex.C{P: topLeft, N: n, C: color}
|
|
|
|
// side face 2
|
|
data[o+9] = vertex.C{P: bottomRight, N: n, C: color}
|
|
data[o+10] = vertex.C{P: bottomLeft, N: n, C: color}
|
|
data[o+11] = vertex.C{P: topRight, N: n, C: color}
|
|
}
|
|
|
|
key := object.Key("cylinder", c)
|
|
mesh := vertex.NewTriangles(key, data, []uint16{})
|
|
c.VertexData.Set(mesh)
|
|
}
|