box.go 3.6 KB

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