Old hobby attempt at a 3D voxel engine in Go/OpenGL.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

model.go 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package main
  2. import (
  3. "github.com/go-gl/gl/v2.1/gl"
  4. )
  5. type Texture struct {
  6. binding uint32
  7. minU float32
  8. maxU float32
  9. minV float32
  10. maxV float32
  11. }
  12. type Vertex struct {
  13. coord Vec3
  14. texcoord Vec2
  15. color Vec3
  16. }
  17. type Quad struct {
  18. v [4]Vertex
  19. normal Vec3
  20. }
  21. type Model struct {
  22. faceQuads [6][]Quad
  23. quads []Quad
  24. dlist uint32
  25. hasDlist bool
  26. }
  27. func getQuadDirection(q *Quad) Direction {
  28. m := []int{2, 3, 0, 1, 4, 5}
  29. var d Direction
  30. var occ int
  31. for i := 0; i < 3; i++ {
  32. j := q.v[0].coord[i]
  33. if (j == 0 || j == 1) && j == q.v[1].coord[i] && q.v[1].coord[i] == q.v[2].coord[i] && q.v[2].coord[i] == q.v[3].coord[i] {
  34. occ++
  35. d = Direction(m[i * 2 + int(j)])
  36. }
  37. }
  38. if occ == 1 {
  39. return d
  40. } else {
  41. return UNKNOWN
  42. }
  43. }
  44. func (m *Model) freeDlist() {
  45. if m.hasDlist {
  46. gl.DeleteBuffers(1, &m.dlist)
  47. m.hasDlist = false
  48. }
  49. }
  50. func (m *Model) AddQuad(q Quad) {
  51. m.freeDlist()
  52. d := getQuadDirection(&q)
  53. if d == UNKNOWN {
  54. m.quads = append(m.quads, q)
  55. } else {
  56. m.faceQuads[int(d)] = append(m.faceQuads[int(d)], q)
  57. }
  58. }
  59. func (q *Quad) render() {
  60. gl.Normal3f(q.normal[0], q.normal[1], q.normal[2])
  61. for i := 0; i < 4; i++ {
  62. gl.Vertex3f(q.v[i].coord[0], q.v[i].coord[1], q.v[i].coord[2])
  63. gl.TexCoord2f(q.v[i].texcoord[0], q.v[i].texcoord[1])
  64. gl.Color3f(q.v[i].color[0], q.v[i].color[1], q.v[i].color[2])
  65. }
  66. }
  67. func (m *Model) Render() {
  68. if m.hasDlist {
  69. gl.CallList(m.dlist)
  70. } else {
  71. gl.NewList(m.dlist, gl.COMPILE_AND_EXECUTE)
  72. gl.Begin(gl.QUADS)
  73. for i := 0; i < 6; i++ {
  74. for _, quad := range m.faceQuads[i] {
  75. quad.render()
  76. }
  77. }
  78. for _, quad := range m.quads {
  79. quad.render()
  80. }
  81. gl.End()
  82. gl.EndList()
  83. }
  84. }
  85. func NewFullCubeModel(ta [6]Texture) Model {
  86. return NewCubeModel(ta, Vec3{0, 0, 0}, Vec3{1, 1, 1})
  87. }
  88. func NewCubeModel(ta [6]Texture, min Vec3, max Vec3) Model {
  89. m := Model{}
  90. q := Quad{}
  91. c := Vec3{max[0], max[1], max[2]}
  92. t := ta[5]
  93. q.normal = Vec3{0, 0, 1}
  94. q.v = [4]Vertex{
  95. Vertex{coord: Vec3{min[0], max[1], max[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  96. Vertex{coord: Vec3{max[0], max[1], max[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  97. Vertex{coord: Vec3{max[0], min[1], max[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  98. Vertex{coord: Vec3{min[0], min[1], max[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  99. }
  100. m.AddQuad(q)
  101. t = ta[4]
  102. q.normal = Vec3{0, 0, -1}
  103. q.v = [4]Vertex{
  104. Vertex{coord: Vec3{min[0], max[1], min[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  105. Vertex{coord: Vec3{max[0], max[1], min[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  106. Vertex{coord: Vec3{max[0], min[1], min[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  107. Vertex{coord: Vec3{min[0], min[1], min[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  108. }
  109. m.AddQuad(q)
  110. t = ta[1]
  111. q.normal = Vec3{0, 0, 1}
  112. q.v = [4]Vertex{
  113. Vertex{coord: Vec3{min[0], max[1], min[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  114. Vertex{coord: Vec3{max[0], max[1], min[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  115. Vertex{coord: Vec3{max[0], max[1], max[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  116. Vertex{coord: Vec3{min[0], max[1], max[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  117. }
  118. m.AddQuad(q)
  119. t = ta[0]
  120. q.normal = Vec3{0, 0, -1}
  121. q.v = [4]Vertex{
  122. Vertex{coord: Vec3{min[0], min[1], min[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  123. Vertex{coord: Vec3{max[0], min[1], min[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  124. Vertex{coord: Vec3{max[0], min[1], max[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  125. Vertex{coord: Vec3{min[0], min[1], max[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  126. }
  127. m.AddQuad(q)
  128. t = ta[3]
  129. q.normal = Vec3{1, 0, 0}
  130. q.v = [4]Vertex{
  131. Vertex{coord: Vec3{max[0], max[1], min[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  132. Vertex{coord: Vec3{max[0], max[1], max[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  133. Vertex{coord: Vec3{max[0], min[1], max[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  134. Vertex{coord: Vec3{max[0], min[1], min[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  135. }
  136. m.AddQuad(q)
  137. t = ta[2]
  138. q.normal = Vec3{-1, 0, 0}
  139. q.v = [4]Vertex{
  140. Vertex{coord: Vec3{min[0], max[1], min[2]}, texcoord: Vec2{t.minU, t.minV}, color: c},
  141. Vertex{coord: Vec3{min[0], max[1], max[2]}, texcoord: Vec2{t.maxU, t.minV}, color: c},
  142. Vertex{coord: Vec3{min[0], min[1], max[2]}, texcoord: Vec2{t.maxU, t.maxV}, color: c},
  143. Vertex{coord: Vec3{min[0], min[1], min[2]}, texcoord: Vec2{t.minU, t.maxV}, color: c},
  144. }
  145. m.AddQuad(q)
  146. return m
  147. }