box.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package geometry
  5. import (
  6. "github.com/g3n/engine/gls"
  7. "github.com/g3n/engine/math32"
  8. )
  9. // Box represents a box or cube geometry.
  10. type Box struct {
  11. Geometry
  12. Width float64
  13. Height float64
  14. Depth float64
  15. WidthSegments int
  16. HeightSegments int
  17. DepthSegments int
  18. }
  19. // NewBox creates and returns a pointer to a new Box geometry object.
  20. // The geometry is defined by its width, height, depth and the number of
  21. // segments of each dimension (minimum = 1).
  22. func NewBox(width, height, depth float64, widthSegments, heightSegments, depthSegments int) *Box {
  23. box := new(Box)
  24. box.Geometry.Init()
  25. box.Width = width
  26. box.Height = height
  27. box.Depth = depth
  28. box.WidthSegments = widthSegments
  29. box.HeightSegments = heightSegments
  30. box.DepthSegments = depthSegments
  31. // Create buffers
  32. positions := math32.NewArrayF32(0, 16)
  33. normals := math32.NewArrayF32(0, 16)
  34. uvs := math32.NewArrayF32(0, 16)
  35. indices := math32.NewArrayU32(0, 16)
  36. wHalf := width / 2
  37. vHalf := height / 2
  38. dHalf := depth / 2
  39. // Internal function to build each box plane
  40. buildPlane := func(u, v string, udir, vdir int, width, height, depth float64, materialIndex uint) {
  41. gridX := widthSegments
  42. gridY := heightSegments
  43. wHalf := width / 2
  44. hHalf := height / 2
  45. offset := positions.Len() / 3
  46. var w string
  47. if (u == "x" && v == "y") || (u == "y" && v == "x") {
  48. w = "z"
  49. } else if (u == "x" && v == "z") || (u == "z" && v == "x") {
  50. w = "y"
  51. gridY = depthSegments
  52. } else if (u == "z" && v == "y") || (u == "y" && v == "z") {
  53. w = "x"
  54. gridX = depthSegments
  55. }
  56. gridX1 := gridX + 1
  57. gridY1 := gridY + 1
  58. segmentWidth := width / float64(gridX)
  59. segmentHeight := height / float64(gridY)
  60. var normal math32.Vector3
  61. if depth > 0 {
  62. normal.SetByName(w, 1)
  63. } else {
  64. normal.SetByName(w, -1)
  65. }
  66. // Generates the plane vertices, normals and uv coordinates.
  67. for iy := 0; iy < gridY1; iy++ {
  68. for ix := 0; ix < gridX1; ix++ {
  69. var vector math32.Vector3
  70. vector.SetByName(u, float32((float64(ix)*segmentWidth-wHalf)*float64(udir)))
  71. vector.SetByName(v, float32((float64(iy)*segmentHeight-hHalf)*float64(vdir)))
  72. vector.SetByName(w, float32(depth))
  73. positions.AppendVector3(&vector)
  74. normals.AppendVector3(&normal)
  75. uvs.Append(float32(float64(ix)/float64(gridX)), float32(float64(1)-(float64(iy)/float64(gridY))))
  76. }
  77. }
  78. gstart := indices.Size()
  79. matIndex := materialIndex
  80. // Generates the indices for the vertices, normals and uvs
  81. for iy := 0; iy < gridY; iy++ {
  82. for ix := 0; ix < gridX; ix++ {
  83. a := ix + gridX1*iy
  84. b := ix + gridX1*(iy+1)
  85. c := (ix + 1) + gridX1*(iy+1)
  86. d := (ix + 1) + gridX1*iy
  87. indices.Append(uint32(a+offset), uint32(b+offset), uint32(d+offset), uint32(b+offset), uint32(c+offset), uint32(d+offset))
  88. }
  89. }
  90. gcount := indices.Size() - gstart
  91. box.AddGroup(gstart, gcount, int(matIndex))
  92. }
  93. buildPlane("z", "y", -1, -1, depth, height, wHalf, 0) // px
  94. buildPlane("z", "y", 1, -1, depth, height, -wHalf, 1) // nx
  95. buildPlane("x", "z", 1, 1, width, depth, vHalf, 2) // py
  96. buildPlane("x", "z", 1, -1, width, depth, -vHalf, 3) // ny
  97. buildPlane("x", "y", 1, -1, width, height, dHalf, 4) // pz
  98. buildPlane("x", "y", -1, -1, width, height, -dHalf, 5) // nz
  99. box.SetIndices(indices)
  100. box.AddVBO(gls.NewVBO().AddAttrib("VertexPosition", 3).SetBuffer(positions))
  101. box.AddVBO(gls.NewVBO().AddAttrib("VertexNormal", 3).SetBuffer(normals))
  102. box.AddVBO(gls.NewVBO().AddAttrib("VertexTexcoord", 2).SetBuffer(uvs))
  103. return box
  104. }