tube.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. // TODO: UVs, Caps
  5. package geometry
  6. import (
  7. "math"
  8. "github.com/g3n/engine/gls"
  9. "github.com/g3n/engine/math32"
  10. )
  11. func CalculateNormals(indices math32.ArrayU32, positions, normals math32.ArrayF32) math32.ArrayF32 {
  12. var x1x2, y1y2, z1z2, x3x2, y3y2, z3z2, x, y, z, l float32
  13. var x1, y1, z1, x2, y2, z2, x3, y3, z3 int // position indexes
  14. for i := 0; i < len(indices)/3; i++ {
  15. x1 = int(indices[i*3] * uint32(3))
  16. y1 = x1 + 1
  17. z1 = x1 + 2
  18. x2 = int(indices[i*3+1] * uint32(3))
  19. y2 = x2 + 1
  20. z2 = x2 + 2
  21. x3 = int(indices[i*3+2] * uint32(3))
  22. y3 = x3 + 1
  23. z3 = x3 + 2
  24. x1x2 = positions[x1] - positions[x2]
  25. y1y2 = positions[y1] - positions[y2]
  26. z1z2 = positions[z1] - positions[z2]
  27. x3x2 = positions[x3] - positions[x2]
  28. y3y2 = positions[y3] - positions[y2]
  29. z3z2 = positions[z3] - positions[z2]
  30. x = y1y2*z3z2 - z1z2*y3y2
  31. y = z1z2*x3x2 - x1x2*z3z2
  32. z = x1x2*y3y2 - y1y2*x3x2
  33. l = float32(math.Sqrt(float64(x)*float64(x) + float64(y)*float64(y) + float64(z)*float64(z)))
  34. if l == 0 {
  35. l = 1.0
  36. }
  37. normals[x1] += x / l
  38. normals[y1] += y / l
  39. normals[z1] += z / l
  40. normals[x2] += x / l
  41. normals[y2] += y / l
  42. normals[z2] += z / l
  43. normals[x3] += x / l
  44. normals[y3] += y / l
  45. normals[z3] += z / l
  46. }
  47. for i := 0; i < len(normals)/3; i++ {
  48. x = normals[i*3]
  49. y = normals[i*3+1]
  50. z = normals[i*3+2]
  51. l = float32(math.Sqrt(float64(x)*float64(x) + float64(y)*float64(y) + float64(z)*float64(z)))
  52. if l == 0 {
  53. l = 1.0
  54. }
  55. normals[i*3] = x / l
  56. normals[i*3+1] = y / l
  57. normals[i*3+2] = z / l
  58. }
  59. return normals
  60. }
  61. func NewRibbon(paths [][]math32.Vector3, close bool) *Geometry {
  62. /*
  63. if len(paths) < 3 {
  64. close = false
  65. }
  66. */
  67. c := NewGeometry()
  68. var ls, is []int // path lengths, path indexes
  69. positions := math32.NewArrayF32(0, 0)
  70. indices := math32.NewArrayU32(0, 0)
  71. i := 0
  72. for p := 0; p < len(paths); p++ {
  73. path := paths[p]
  74. l := len(path)
  75. ls = append(ls, l)
  76. is = append(is, i)
  77. for j := 0; j < l; j++ {
  78. positions.AppendVector3(&path[j])
  79. }
  80. i += l
  81. }
  82. l1 := ls[0] - 1 // path1 length
  83. l2 := ls[1] - 1 // path2 length
  84. min := l2
  85. if l1 < l2 {
  86. min = l1
  87. }
  88. p := 0
  89. i = 0
  90. for i <= min && p < len(ls)-1 {
  91. t := is[p+1] - is[p]
  92. indices.Append(uint32(i), uint32(i+t), uint32(i+1))
  93. indices.Append(uint32(i+t+1), uint32(i+1), uint32(i+t))
  94. i++
  95. if i == min {
  96. if close {
  97. indices.Append(uint32(i), uint32(i+t), uint32(is[p]))
  98. indices.Append(uint32(is[p]+t), uint32(is[p]), uint32(i+t))
  99. }
  100. p++
  101. if p == len(ls)-1 {
  102. break
  103. }
  104. l1 = ls[p] - 1
  105. l2 = ls[p+1] - 1
  106. i = is[p]
  107. if l1 < l2 {
  108. min = l1 + i
  109. } else {
  110. min = l2 + i
  111. }
  112. }
  113. }
  114. normals := math32.NewArrayF32(positions.Size(), positions.Size())
  115. normals = CalculateNormals(indices, positions, normals)
  116. c.SetIndices(indices)
  117. c.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition))
  118. c.AddVBO(gls.NewVBO(normals).AddAttrib(gls.VertexNormal))
  119. return c
  120. }
  121. func NewTube(path []math32.Vector3, radius float32, radialSegments int, close bool) *Geometry {
  122. l := len(path)
  123. var tangents, normals, binormals []math32.Vector3
  124. tangents = make([]math32.Vector3, l)
  125. normals = make([]math32.Vector3, l)
  126. binormals = make([]math32.Vector3, l)
  127. tangents[0] = *path[1].Clone().Sub(&path[0])
  128. tangents[0].Normalize()
  129. tangents[l-1] = *path[l-1].Clone().Sub(&path[l-2])
  130. tangents[l-1].Normalize()
  131. var tmpVertex *math32.Vector3
  132. if tangents[0].X != 1 {
  133. tmpVertex = math32.NewVector3(1, 0, 0)
  134. } else if tangents[0].Y != 1 {
  135. tmpVertex = math32.NewVector3(0, 1, 0)
  136. } else if tangents[0].Z != 1 {
  137. tmpVertex = math32.NewVector3(0, 0, 1)
  138. }
  139. normals[0] = *tangents[0].Clone().Cross(tmpVertex)
  140. normals[0].Normalize()
  141. binormals[0] = *tangents[0].Clone().Cross(&normals[0])
  142. binormals[0].Normalize()
  143. for i := 1; i < l; i++ {
  144. prev := *path[i].Clone().Sub(&path[i-1])
  145. if i < l-1 {
  146. cur := *path[i+1].Clone().Sub(&path[i])
  147. tangents[i] = *prev.Clone().Add(&cur)
  148. tangents[i].Normalize()
  149. }
  150. normals[i] = *binormals[i-1].Clone().Cross(&tangents[i])
  151. normals[i].Normalize()
  152. binormals[i] = *tangents[i].Clone().Cross(&normals[i])
  153. binormals[i].Normalize()
  154. }
  155. pi2 := math.Pi * 2
  156. step := pi2 / float64(radialSegments)
  157. var radialPaths [][]math32.Vector3
  158. for i := 0; i < l; i++ {
  159. var radialPath []math32.Vector3
  160. var ang float32
  161. for ang = 0.0; ang < float32(pi2); ang += float32(step) {
  162. matrix := math32.NewMatrix4()
  163. matrix.MakeRotationAxis(&tangents[i], ang)
  164. x := normals[i].X
  165. y := normals[i].Y
  166. z := normals[i].Z
  167. rw := 1 / (x*matrix[3] + y*matrix[7] + z*matrix[11] + matrix[15])
  168. newX := (x*matrix[0] + y*matrix[4] + z*matrix[8] + matrix[12]) * rw
  169. newY := (x*matrix[1] + y*matrix[5] + z*matrix[9] + matrix[13]) * rw
  170. newZ := (x*matrix[2] + y*matrix[6] + z*matrix[10] + matrix[14]) * rw
  171. rotated := math32.NewVector3(newX, newY, newZ).MultiplyScalar(radius).Add(&path[i])
  172. radialPath = append(radialPath, *rotated)
  173. }
  174. radialPaths = append(radialPaths, radialPath)
  175. }
  176. return NewRibbon(radialPaths, close)
  177. }