NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/buffer/tubemesh-buffer.js

  1. /**
  2. * @file Tube Mesh Buffer
  3. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  4. * @private
  5. */
  6.  
  7. import { Vector3 } from '../../lib/three.es6.js'
  8.  
  9. import { defaults, getUintArray } from '../utils.js'
  10. import { serialArray } from '../math/array-utils.js'
  11. import MeshBuffer from './mesh-buffer.js'
  12.  
  13. var vTangent = new Vector3()
  14. var vMeshNormal = new Vector3()
  15.  
  16. /**
  17. * Tube mesh buffer. Draws a tube.
  18. */
  19. class TubeMeshBuffer extends MeshBuffer {
  20. /**
  21. * @param {Object} data - attribute object
  22. * @param {Float32Array} data.position - positions
  23. * @param {Float32Array} data.normal - normals
  24. * @param {Float32Array} data.binormal - binormals
  25. * @param {Float32Array} data.tangent - tangents
  26. * @param {Float32Array} data.color - colors
  27. * @param {Float32Array} data.size - sizes
  28. * @param {Picker} data.picking - picking ids
  29. * @param {BufferParameters} params - parameter object
  30. */
  31. constructor (data, params) {
  32. var d = data || {}
  33. var p = params || {}
  34.  
  35. var radialSegments = defaults(p.radialSegments, 4)
  36. var capped = defaults(p.capped, false)
  37.  
  38. var capVertices = capped ? radialSegments : 0
  39. var capTriangles = capped ? radialSegments - 2 : 0
  40.  
  41. var n = d.position.length / 3
  42. var n1 = n - 1
  43. var x = n * radialSegments * 3 + 2 * capVertices * 3
  44. var xi = n1 * 2 * radialSegments * 3 + 2 * capTriangles * 3
  45.  
  46. var meshPosition = new Float32Array(x)
  47. var meshColor = new Float32Array(x)
  48. var meshNormal = new Float32Array(x)
  49. var meshIndex = getUintArray(xi, x / 3)
  50.  
  51. super({
  52. position: meshPosition,
  53. color: meshColor,
  54. index: meshIndex,
  55. normal: meshNormal,
  56. picking: d.picking
  57. }, p)
  58.  
  59. //
  60.  
  61. this.aspectRatio = defaults(p.aspectRatio, 1.0)
  62. this.radialSegments = radialSegments
  63. this.capped = capped
  64.  
  65. this.capVertices = capVertices
  66. this.capTriangles = capTriangles
  67. this.size2 = n
  68.  
  69. d.primitiveId = serialArray(n)
  70. this.setAttributes(d)
  71.  
  72. this.meshIndex = meshIndex
  73. this.makeIndex()
  74. }
  75.  
  76. setAttributes (data) {
  77. var aspectRatio = this.aspectRatio
  78.  
  79. var n = this.size2
  80. var n1 = n - 1
  81. var radialSegments = this.radialSegments
  82.  
  83. var attributes = this.geometry.attributes
  84.  
  85. var position, normal, binormal, tangent, color, size, primitiveId
  86. var meshPosition, meshColor, meshNormal, meshPrimitiveId
  87.  
  88. if (data.position) {
  89. position = data.position
  90. normal = data.normal
  91. binormal = data.binormal
  92. tangent = data.tangent
  93. size = data.size
  94.  
  95. meshPosition = attributes.position.array
  96. meshNormal = attributes.normal.array
  97.  
  98. attributes.position.needsUpdate = true
  99. attributes.normal.needsUpdate = true
  100. }
  101.  
  102. if (data.color) {
  103. color = data.color
  104. meshColor = attributes.color.array
  105. attributes.color.needsUpdate = true
  106. }
  107.  
  108. if (data.primitiveId) {
  109. primitiveId = data.primitiveId
  110. meshPrimitiveId = attributes.primitiveId.array
  111. attributes.primitiveId.needsUpdate = true
  112. }
  113.  
  114. var i, j, k, l, s, t
  115. var v, cx, cy
  116. var cx1, cy1, cx2, cy2
  117. var radius
  118.  
  119. var normX, normY, normZ
  120. var biX, biY, biZ
  121. var posX, posY, posZ
  122.  
  123. var cxArr = []
  124. var cyArr = []
  125. var cx1Arr = []
  126. var cy1Arr = []
  127. var cx2Arr = []
  128. var cy2Arr = []
  129.  
  130. if (position) {
  131. for (j = 0; j < radialSegments; ++j) {
  132. v = (j / radialSegments) * 2 * Math.PI
  133.  
  134. cxArr[ j ] = aspectRatio * Math.cos(v)
  135. cyArr[ j ] = Math.sin(v)
  136.  
  137. cx1Arr[ j ] = aspectRatio * Math.cos(v - 0.01)
  138. cy1Arr[ j ] = Math.sin(v - 0.01)
  139. cx2Arr[ j ] = aspectRatio * Math.cos(v + 0.01)
  140. cy2Arr[ j ] = Math.sin(v + 0.01)
  141. }
  142. }
  143.  
  144. for (i = 0; i < n; ++i) {
  145. k = i * 3
  146. l = k * radialSegments
  147.  
  148. if (position) {
  149. vTangent.set(
  150. tangent[ k ], tangent[ k + 1 ], tangent[ k + 2 ]
  151. )
  152.  
  153. normX = normal[ k ]
  154. normY = normal[ k + 1 ]
  155. normZ = normal[ k + 2 ]
  156.  
  157. biX = binormal[ k ]
  158. biY = binormal[ k + 1 ]
  159. biZ = binormal[ k + 2 ]
  160.  
  161. posX = position[ k ]
  162. posY = position[ k + 1 ]
  163. posZ = position[ k + 2 ]
  164.  
  165. radius = size[ i ]
  166. }
  167.  
  168. for (j = 0; j < radialSegments; ++j) {
  169. s = l + j * 3
  170.  
  171. if (position) {
  172. cx = -radius * cxArr[ j ] // TODO: Hack: Negating it so it faces outside.
  173. cy = radius * cyArr[ j ]
  174.  
  175. cx1 = -radius * cx1Arr[ j ]
  176. cy1 = radius * cy1Arr[ j ]
  177. cx2 = -radius * cx2Arr[ j ]
  178. cy2 = radius * cy2Arr[ j ]
  179.  
  180. meshPosition[ s ] = posX + cx * normX + cy * biX
  181. meshPosition[ s + 1 ] = posY + cx * normY + cy * biY
  182. meshPosition[ s + 2 ] = posZ + cx * normZ + cy * biZ
  183.  
  184. // TODO half of these are symmetric
  185. vMeshNormal.set(
  186. // ellipse tangent approximated as vector from/to adjacent points
  187. (cx2 * normX + cy2 * biX) -
  188. (cx1 * normX + cy1 * biX),
  189. (cx2 * normY + cy2 * biY) -
  190. (cx1 * normY + cy1 * biY),
  191. (cx2 * normZ + cy2 * biZ) -
  192. (cx1 * normZ + cy1 * biZ)
  193. ).cross(vTangent)
  194.  
  195. meshNormal[ s ] = vMeshNormal.x
  196. meshNormal[ s + 1 ] = vMeshNormal.y
  197. meshNormal[ s + 2 ] = vMeshNormal.z
  198. }
  199.  
  200. if (color) {
  201. meshColor[ s ] = color[ k ]
  202. meshColor[ s + 1 ] = color[ k + 1 ]
  203. meshColor[ s + 2 ] = color[ k + 2 ]
  204. }
  205.  
  206. if (primitiveId) {
  207. meshPrimitiveId[ i * radialSegments + j ] = primitiveId[ i ]
  208. }
  209. }
  210. }
  211.  
  212. // front cap
  213.  
  214. k = 0
  215. l = n * 3 * radialSegments
  216.  
  217. for (j = 0; j < radialSegments; ++j) {
  218. s = k + j * 3
  219. t = l + j * 3
  220.  
  221. if (position) {
  222. meshPosition[ t ] = meshPosition[ s ]
  223. meshPosition[ t + 1 ] = meshPosition[ s + 1 ]
  224. meshPosition[ t + 2 ] = meshPosition[ s + 2 ]
  225.  
  226. meshNormal[ t ] = tangent[ k ]
  227. meshNormal[ t + 1 ] = tangent[ k + 1 ]
  228. meshNormal[ t + 2 ] = tangent[ k + 2 ]
  229. }
  230.  
  231. if (color) {
  232. meshColor[ t ] = meshColor[ s ]
  233. meshColor[ t + 1 ] = meshColor[ s + 1 ]
  234. meshColor[ t + 2 ] = meshColor[ s + 2 ]
  235. }
  236.  
  237. if (primitiveId) {
  238. meshPrimitiveId[ n * radialSegments + j ] = meshPrimitiveId[ 0 + j ]
  239. }
  240. }
  241.  
  242. // back cap
  243.  
  244. k = (n - 1) * 3 * radialSegments
  245. l = (n + 1) * 3 * radialSegments
  246.  
  247. for (j = 0; j < radialSegments; ++j) {
  248. s = k + j * 3
  249. t = l + j * 3
  250.  
  251. if (position) {
  252. meshPosition[ t ] = meshPosition[ s ]
  253. meshPosition[ t + 1 ] = meshPosition[ s + 1 ]
  254. meshPosition[ t + 2 ] = meshPosition[ s + 2 ]
  255.  
  256. meshNormal[ t ] = tangent[ n1 * 3 ]
  257. meshNormal[ t + 1 ] = tangent[ n1 * 3 + 1 ]
  258. meshNormal[ t + 2 ] = tangent[ n1 * 3 + 2 ]
  259. }
  260.  
  261. if (color) {
  262. meshColor[ t ] = meshColor[ s ]
  263. meshColor[ t + 1 ] = meshColor[ s + 1 ]
  264. meshColor[ t + 2 ] = meshColor[ s + 2 ]
  265. }
  266.  
  267. if (primitiveId) {
  268. meshPrimitiveId[ (n + 1) * radialSegments + j ] = meshPrimitiveId[ (n - 1) * radialSegments + j ]
  269. }
  270. }
  271. }
  272.  
  273. makeIndex () {
  274. var meshIndex = this.meshIndex
  275.  
  276. var n = this.size2
  277. var n1 = n - 1
  278. var capTriangles = this.capTriangles
  279. var radialSegments = this.radialSegments
  280. var radialSegments1 = this.radialSegments + 1
  281.  
  282. var i, k, irs, irs1, l, j
  283.  
  284. for (i = 0; i < n1; ++i) {
  285. k = i * radialSegments * 3 * 2
  286.  
  287. irs = i * radialSegments
  288. irs1 = (i + 1) * radialSegments
  289.  
  290. for (j = 0; j < radialSegments; ++j) {
  291. l = k + j * 3 * 2
  292.  
  293. // meshIndex[ l + 0 ] = irs + ( ( j + 0 ) % radialSegments );
  294. meshIndex[ l ] = irs + j
  295. meshIndex[ l + 1 ] = irs + ((j + 1) % radialSegments)
  296. // meshIndex[ l + 2 ] = irs1 + ( ( j + 0 ) % radialSegments );
  297. meshIndex[ l + 2 ] = irs1 + j
  298.  
  299. // meshIndex[ l + 3 ] = irs1 + ( ( j + 0 ) % radialSegments );
  300. meshIndex[ l + 3 ] = irs1 + j
  301. meshIndex[ l + 4 ] = irs + ((j + 1) % radialSegments)
  302. meshIndex[ l + 5 ] = irs1 + ((j + 1) % radialSegments)
  303. }
  304. }
  305.  
  306. // capping
  307.  
  308. var strip = [ 0 ]
  309.  
  310. for (j = 1; j < radialSegments1 / 2; ++j) {
  311. strip.push(j)
  312. if (radialSegments - j !== j) {
  313. strip.push(radialSegments - j)
  314. }
  315. }
  316.  
  317. // front cap
  318.  
  319. l = n1 * radialSegments * 3 * 2
  320. k = n * radialSegments
  321.  
  322. for (j = 0; j < strip.length - 2; ++j) {
  323. if (j % 2 === 0) {
  324. meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]
  325. meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
  326. meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]
  327. } else {
  328. meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]
  329. meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
  330. meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]
  331. }
  332. }
  333.  
  334. // back cap
  335.  
  336. l = n1 * radialSegments * 3 * 2 + 3 * capTriangles
  337. k = n * radialSegments + radialSegments
  338.  
  339. for (j = 0; j < strip.length - 2; ++j) {
  340. if (j % 2 === 0) {
  341. meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]
  342. meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
  343. meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]
  344. } else {
  345. meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]
  346. meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
  347. meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]
  348. }
  349. }
  350. }
  351. }
  352.  
  353. export default TubeMeshBuffer