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)
							 | 
						||
| 
								 | 
							
								}
							 |