src/buffer/tubemesh-buffer.js
- /**
- * @file Tube Mesh Buffer
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- * @private
- */
-
- import { Vector3 } from '../../lib/three.es6.js'
-
- import { defaults, getUintArray } from '../utils.js'
- import { serialArray } from '../math/array-utils.js'
- import MeshBuffer from './mesh-buffer.js'
-
- var vTangent = new Vector3()
- var vMeshNormal = new Vector3()
-
- /**
- * Tube mesh buffer. Draws a tube.
- */
- class TubeMeshBuffer extends MeshBuffer {
- /**
- * @param {Object} data - attribute object
- * @param {Float32Array} data.position - positions
- * @param {Float32Array} data.normal - normals
- * @param {Float32Array} data.binormal - binormals
- * @param {Float32Array} data.tangent - tangents
- * @param {Float32Array} data.color - colors
- * @param {Float32Array} data.size - sizes
- * @param {Picker} data.picking - picking ids
- * @param {BufferParameters} params - parameter object
- */
- constructor (data, params) {
- var d = data || {}
- var p = params || {}
-
- var radialSegments = defaults(p.radialSegments, 4)
- var capped = defaults(p.capped, false)
-
- var capVertices = capped ? radialSegments : 0
- var capTriangles = capped ? radialSegments - 2 : 0
-
- var n = d.position.length / 3
- var n1 = n - 1
- var x = n * radialSegments * 3 + 2 * capVertices * 3
- var xi = n1 * 2 * radialSegments * 3 + 2 * capTriangles * 3
-
- var meshPosition = new Float32Array(x)
- var meshColor = new Float32Array(x)
- var meshNormal = new Float32Array(x)
- var meshIndex = getUintArray(xi, x / 3)
-
- super({
- position: meshPosition,
- color: meshColor,
- index: meshIndex,
- normal: meshNormal,
- picking: d.picking
- }, p)
-
- //
-
- this.aspectRatio = defaults(p.aspectRatio, 1.0)
- this.radialSegments = radialSegments
- this.capped = capped
-
- this.capVertices = capVertices
- this.capTriangles = capTriangles
- this.size2 = n
-
- d.primitiveId = serialArray(n)
- this.setAttributes(d)
-
- this.meshIndex = meshIndex
- this.makeIndex()
- }
-
- setAttributes (data) {
- var aspectRatio = this.aspectRatio
-
- var n = this.size2
- var n1 = n - 1
- var radialSegments = this.radialSegments
-
- var attributes = this.geometry.attributes
-
- var position, normal, binormal, tangent, color, size, primitiveId
- var meshPosition, meshColor, meshNormal, meshPrimitiveId
-
- if (data.position) {
- position = data.position
- normal = data.normal
- binormal = data.binormal
- tangent = data.tangent
- size = data.size
-
- meshPosition = attributes.position.array
- meshNormal = attributes.normal.array
-
- attributes.position.needsUpdate = true
- attributes.normal.needsUpdate = true
- }
-
- if (data.color) {
- color = data.color
- meshColor = attributes.color.array
- attributes.color.needsUpdate = true
- }
-
- if (data.primitiveId) {
- primitiveId = data.primitiveId
- meshPrimitiveId = attributes.primitiveId.array
- attributes.primitiveId.needsUpdate = true
- }
-
- var i, j, k, l, s, t
- var v, cx, cy
- var cx1, cy1, cx2, cy2
- var radius
-
- var normX, normY, normZ
- var biX, biY, biZ
- var posX, posY, posZ
-
- var cxArr = []
- var cyArr = []
- var cx1Arr = []
- var cy1Arr = []
- var cx2Arr = []
- var cy2Arr = []
-
- if (position) {
- for (j = 0; j < radialSegments; ++j) {
- v = (j / radialSegments) * 2 * Math.PI
-
- cxArr[ j ] = aspectRatio * Math.cos(v)
- cyArr[ j ] = Math.sin(v)
-
- cx1Arr[ j ] = aspectRatio * Math.cos(v - 0.01)
- cy1Arr[ j ] = Math.sin(v - 0.01)
- cx2Arr[ j ] = aspectRatio * Math.cos(v + 0.01)
- cy2Arr[ j ] = Math.sin(v + 0.01)
- }
- }
-
- for (i = 0; i < n; ++i) {
- k = i * 3
- l = k * radialSegments
-
- if (position) {
- vTangent.set(
- tangent[ k ], tangent[ k + 1 ], tangent[ k + 2 ]
- )
-
- normX = normal[ k ]
- normY = normal[ k + 1 ]
- normZ = normal[ k + 2 ]
-
- biX = binormal[ k ]
- biY = binormal[ k + 1 ]
- biZ = binormal[ k + 2 ]
-
- posX = position[ k ]
- posY = position[ k + 1 ]
- posZ = position[ k + 2 ]
-
- radius = size[ i ]
- }
-
- for (j = 0; j < radialSegments; ++j) {
- s = l + j * 3
-
- if (position) {
- cx = -radius * cxArr[ j ] // TODO: Hack: Negating it so it faces outside.
- cy = radius * cyArr[ j ]
-
- cx1 = -radius * cx1Arr[ j ]
- cy1 = radius * cy1Arr[ j ]
- cx2 = -radius * cx2Arr[ j ]
- cy2 = radius * cy2Arr[ j ]
-
- meshPosition[ s ] = posX + cx * normX + cy * biX
- meshPosition[ s + 1 ] = posY + cx * normY + cy * biY
- meshPosition[ s + 2 ] = posZ + cx * normZ + cy * biZ
-
- // TODO half of these are symmetric
- vMeshNormal.set(
- // ellipse tangent approximated as vector from/to adjacent points
- (cx2 * normX + cy2 * biX) -
- (cx1 * normX + cy1 * biX),
- (cx2 * normY + cy2 * biY) -
- (cx1 * normY + cy1 * biY),
- (cx2 * normZ + cy2 * biZ) -
- (cx1 * normZ + cy1 * biZ)
- ).cross(vTangent)
-
- meshNormal[ s ] = vMeshNormal.x
- meshNormal[ s + 1 ] = vMeshNormal.y
- meshNormal[ s + 2 ] = vMeshNormal.z
- }
-
- if (color) {
- meshColor[ s ] = color[ k ]
- meshColor[ s + 1 ] = color[ k + 1 ]
- meshColor[ s + 2 ] = color[ k + 2 ]
- }
-
- if (primitiveId) {
- meshPrimitiveId[ i * radialSegments + j ] = primitiveId[ i ]
- }
- }
- }
-
- // front cap
-
- k = 0
- l = n * 3 * radialSegments
-
- for (j = 0; j < radialSegments; ++j) {
- s = k + j * 3
- t = l + j * 3
-
- if (position) {
- meshPosition[ t ] = meshPosition[ s ]
- meshPosition[ t + 1 ] = meshPosition[ s + 1 ]
- meshPosition[ t + 2 ] = meshPosition[ s + 2 ]
-
- meshNormal[ t ] = tangent[ k ]
- meshNormal[ t + 1 ] = tangent[ k + 1 ]
- meshNormal[ t + 2 ] = tangent[ k + 2 ]
- }
-
- if (color) {
- meshColor[ t ] = meshColor[ s ]
- meshColor[ t + 1 ] = meshColor[ s + 1 ]
- meshColor[ t + 2 ] = meshColor[ s + 2 ]
- }
-
- if (primitiveId) {
- meshPrimitiveId[ n * radialSegments + j ] = meshPrimitiveId[ 0 + j ]
- }
- }
-
- // back cap
-
- k = (n - 1) * 3 * radialSegments
- l = (n + 1) * 3 * radialSegments
-
- for (j = 0; j < radialSegments; ++j) {
- s = k + j * 3
- t = l + j * 3
-
- if (position) {
- meshPosition[ t ] = meshPosition[ s ]
- meshPosition[ t + 1 ] = meshPosition[ s + 1 ]
- meshPosition[ t + 2 ] = meshPosition[ s + 2 ]
-
- meshNormal[ t ] = tangent[ n1 * 3 ]
- meshNormal[ t + 1 ] = tangent[ n1 * 3 + 1 ]
- meshNormal[ t + 2 ] = tangent[ n1 * 3 + 2 ]
- }
-
- if (color) {
- meshColor[ t ] = meshColor[ s ]
- meshColor[ t + 1 ] = meshColor[ s + 1 ]
- meshColor[ t + 2 ] = meshColor[ s + 2 ]
- }
-
- if (primitiveId) {
- meshPrimitiveId[ (n + 1) * radialSegments + j ] = meshPrimitiveId[ (n - 1) * radialSegments + j ]
- }
- }
- }
-
- makeIndex () {
- var meshIndex = this.meshIndex
-
- var n = this.size2
- var n1 = n - 1
- var capTriangles = this.capTriangles
- var radialSegments = this.radialSegments
- var radialSegments1 = this.radialSegments + 1
-
- var i, k, irs, irs1, l, j
-
- for (i = 0; i < n1; ++i) {
- k = i * radialSegments * 3 * 2
-
- irs = i * radialSegments
- irs1 = (i + 1) * radialSegments
-
- for (j = 0; j < radialSegments; ++j) {
- l = k + j * 3 * 2
-
- // meshIndex[ l + 0 ] = irs + ( ( j + 0 ) % radialSegments );
- meshIndex[ l ] = irs + j
- meshIndex[ l + 1 ] = irs + ((j + 1) % radialSegments)
- // meshIndex[ l + 2 ] = irs1 + ( ( j + 0 ) % radialSegments );
- meshIndex[ l + 2 ] = irs1 + j
-
- // meshIndex[ l + 3 ] = irs1 + ( ( j + 0 ) % radialSegments );
- meshIndex[ l + 3 ] = irs1 + j
- meshIndex[ l + 4 ] = irs + ((j + 1) % radialSegments)
- meshIndex[ l + 5 ] = irs1 + ((j + 1) % radialSegments)
- }
- }
-
- // capping
-
- var strip = [ 0 ]
-
- for (j = 1; j < radialSegments1 / 2; ++j) {
- strip.push(j)
- if (radialSegments - j !== j) {
- strip.push(radialSegments - j)
- }
- }
-
- // front cap
-
- l = n1 * radialSegments * 3 * 2
- k = n * radialSegments
-
- for (j = 0; j < strip.length - 2; ++j) {
- if (j % 2 === 0) {
- meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]
- meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
- meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]
- } else {
- meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]
- meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
- meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]
- }
- }
-
- // back cap
-
- l = n1 * radialSegments * 3 * 2 + 3 * capTriangles
- k = n * radialSegments + radialSegments
-
- for (j = 0; j < strip.length - 2; ++j) {
- if (j % 2 === 0) {
- meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]
- meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
- meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]
- } else {
- meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]
- meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]
- meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]
- }
- }
- }
- }
-
- export default TubeMeshBuffer