box-geometry
Version:
cube geometry mesh generator for gl-vao
169 lines (132 loc) • 4.46 kB
JavaScript
'use strict'
var createVAO = require('gl-vao')
var createBuffer = require('gl-buffer')
var toarray = require('toarray')
var glm = require('gl-matrix')
var mat4 = glm.mat4
var vec3 = glm.vec3
var applyTransformToVertices = function(vertices, matrix, w) {
for (var i = 0; i < vertices.length / 4; i += 1) {
var vertex = vertices.subarray(i * 4, (i + 1) * 4)
if (w !== undefined)
vertex[3] = w // pass body part index in w coordinate for avatar.vert
vec3.transformMat4(vertex, vertex, matrix)
}
}
var identity = mat4.create()
// TODO: split out into an independent non-avatar module, as this is
// mostly generic except for 1) use of w coord for index, 2) uv divisors
var generateBoxesMesh = function(gl, info, opts) {
info = toarray(info)
opts = opts || {}
opts.uDiv = opts.uDiv || 1
opts.vDiv = opts.vDiv || 1
opts.setWindex = opts.setWindex !== undefined ? opts.setWindex : false
// Cube coordinates, see https://developer.mozilla.org/en-US/docs/Web/WebGL/Creating_3D_objects_using_WebGL
var cube = new Float32Array([
// Back face
-0.5, -0.5, 0.5, 1.0,
0.5, -0.5, 0.5, 1.0,
0.5, 0.5, 0.5, 1.0,
-0.5, 0.5, 0.5, 1.0,
// Front face
-0.5, -0.5, -0.5, 1.0,
-0.5, 0.5, -0.5, 1.0,
0.5, 0.5, -0.5, 1.0,
0.5, -0.5, -0.5, 1.0,
// Top face
-0.5, 0.5, -0.5, 1.0,
-0.5, 0.5, 0.5, 1.0,
0.5, 0.5, 0.5, 1.0,
0.5, 0.5, -0.5, 1.0,
// Bottom face
-0.5, -0.5, -0.5, 1.0,
0.5, -0.5, -0.5, 1.0,
0.5, -0.5, 0.5, 1.0,
-0.5, -0.5, 0.5, 1.0,
// Left face
0.5, -0.5, -0.5, 1.0,
0.5, 0.5, -0.5, 1.0,
0.5, 0.5, 0.5, 1.0,
0.5, -0.5, 0.5, 1.0,
// Right face
-0.5, -0.5, -0.5, 1.0,
-0.5, -0.5, 0.5, 1.0,
-0.5, 0.5, 0.5, 1.0,
-0.5, 0.5, -0.5, 1.0
])
var cubeCount = info.length
// add vetices for each cube
var verticesArray = new Float32Array(cube.length * cubeCount)
for (var i = 0; i < cubeCount; i += 1) {
var thisCube = new Float32Array(cube.length)
thisCube.set(cube)
applyTransformToVertices(thisCube, info[i].matrix || identity, opts.setWindex ? i : undefined)
verticesArray.set(thisCube, cube.length * i)
}
var vertices = createBuffer(gl, verticesArray)
var cubeVertexIndices = new Uint16Array([
0, 1, 2, 0, 2, 3, // back
4, 5, 6, 4, 6, 7, // front
8, 9, 10, 8, 10, 11, // top
12, 13, 14, 12, 14, 15, // bottom
16, 17, 18, 16, 18, 19, // left
20, 21, 22, 20, 22, 23 // right
])
// repeat vertex indices for each cube, offset by cube vertex count
var indexArray = new Uint16Array(cubeVertexIndices.length * cubeCount)
for (var i = 0; i < cubeCount; i += 1) {
for (var j = 0; j < cubeVertexIndices.length; j += 1) {
indexArray[i * cubeVertexIndices.length + j] = cubeVertexIndices[j] + (cube.length / 4) * i
}
}
var index = createBuffer(gl
, indexArray
, gl.ELEMENT_ARRAY_BUFFER
)
// set UV coordinates for textures
var uvArray = new Float32Array(2 * 4 * 6 * cubeCount)
var setCubeFaceUV = function(face,x,y,w,h,r) {
w = w || 8
h = h || 8
r = r || 0
var i = face * 8
uvArray[i + (0 + r) % 4 * 2 + 0] = x / opts.uDiv
uvArray[i + (0 + r) % 4 * 2 + 1] = (y + h) / opts.vDiv
uvArray[i + (1 + r) % 4 * 2 + 0] = x / opts.uDiv
uvArray[i + (1 + r) % 4 * 2 + 1] = y / opts.vDiv
uvArray[i + (2 + r) % 4 * 2 + 0] = (x + w) / opts.uDiv
uvArray[i + (2 + r) % 4 * 2 + 1] = y / opts.vDiv
uvArray[i + (3 + r) % 4 * 2 + 0] = (x + w) / opts.uDiv
uvArray[i + (3 + r) % 4 * 2 + 1] = (y + h) / opts.vDiv
}
for (var i = 0; i < cubeCount; i += 1) {
var uvs = info[i].uv
if (uvs) {
for (var face = 0; face < 6; face += 1) {
var x = uvs[5*face + 0]
var y = uvs[5*face + 1]
var w = uvs[5*face + 2]
var h = uvs[5*face + 3]
var r = uvs[5*face + 4]
setCubeFaceUV(6*i + face, x, y, w, h, r)
}
}
}
var uv = createBuffer(gl, uvArray)
// Create a VAO from the vertices and uv buffers, indexed by the
// index buffer.
var mesh = createVAO(gl, [
{
buffer: vertices
, size: 4
},
{
buffer: uv
, size: 2
}
], index)
mesh.length = indexArray.length
return mesh
}
module.exports = generateBoxesMesh