UNPKG

fury-js

Version:

WebGL Game Engine

141 lines (124 loc) 4.52 kB
const r = require('./renderer'); const Bounds = require('./bounds'); const vec3 = require('./maths').vec3; const Utils = require('./utils'); module.exports = (function(){ let exports = {}; let calculateMinPoint = exports.calculateMinPoint = function(out, positions) { let i, l, v1 = Number.MAX_VALUE, v2 = Number.MAX_VALUE, v3 = Number.MAX_VALUE; for (i = 0, l = positions.length; i < l; i += 3) { v1 = Math.min(v1, positions[i]); v2 = Math.min(v2, positions[i+1]); v3 = Math.min(v3, positions[i+2]); } out[0] = v1, out[1] = v2, out[2] = v3; }; let calculateMaxPoint = exports.calculateMaxPoint = function(out, positions) { let i, l, v1 = Number.MIN_VALUE, v2 = Number.MIN_VALUE, v3 = Number.MIN_VALUE; for (i = 0, l = positions.length; i < l; i += 3) { v1 = Math.max(v1, positions[i]); v2 = Math.max(v2, positions[i+1]); v3 = Math.max(v3, positions[i+2]); } out[0] = v1, out[1] = v2, out[2] = v3; }; // Returns the furthest vertex from the local origin // Note this is not the same as the furthest from the mid-point of the vertices positions // This is necessray for the boundingRadius to remain accurate under rotation let calculateBoundingRadius = function(positions) { var sqrResult = 0; for (let i = 0, l = positions.length; i< l; i += 3) { let sqrDistance = positions[i] * positions[i] + positions[i + 1] * positions[i + 1] + positions[i + 2] * positions[i + 2]; if (sqrDistance > sqrResult) { sqrResult = sqrDistance; } } return Math.sqrt(sqrResult); }; let createBuffer = function(data, size, indexed) { if (data.length > 65535) { console.warn("buffer contains more than 16-bit max number of points, rendering may be truncated"); } if (data.buffer) { if (!indexed) { return r.createArrayBuffer(data, size); } else { return r.createElementArrayBuffer(data, size); } } else { return r.createBuffer(data, size, indexed); } }; let calculateBounds = exports.calculateBounds = function(mesh, positions) { mesh.boundingRadius = calculateBoundingRadius(positions); calculateMinPoint(mesh.bounds.min, positions); calculateMaxPoint(mesh.bounds.max, positions); mesh.bounds.recalculateExtents(); }; // TODO: Method to calculate normals from vertex information + winding info exports.create = function(config) { let mesh = {}; mesh.bounds = Bounds.create({ min: vec3.create(), max: vec3.create() }); mesh.boundingRadius = 0; update(mesh, config, true); return mesh; }; let update = exports.update = function(mesh, config, firstBuild) { if (config) { if (config.renderMode !== undefined) { mesh.renderMode = config.renderMode; } else if (mesh.renderMode === undefined) { mesh.renderMode = r.RenderMode.Triangles; } let { positions, uvs, normals, indices, customAttributes } = config; if (positions) { calculateBounds(mesh, positions); mesh.vertexBuffer = createBuffer(positions, 3); } if (uvs) { mesh.textureBuffer = createBuffer(uvs, 2); } if (normals) { mesh.normalBuffer = createBuffer(normals, 3); } if (indices) { mesh.indexed = true; mesh.indexBuffer = createBuffer(indices, 1, true); } else { mesh.indexed = false; } if (customAttributes && customAttributes.length) { for (let i = 0, l = customAttributes.length; i < l; i++) { let { name, source, size } = customAttributes[i]; if (!firstBuild || !mesh[name]) { let data = config[source]; if (data.buffer) { mesh[name] = r.createArrayBuffer(data, size); } else { mesh[name] = r.createBuffer(data, size); } } else { console.error("Duplicate definition of '" + name + "' in mesh configuration " + JSON.stringify(customAttributes)); } } } } }; exports.combineConfig = function(meshes) { let result = { positions: [], normals: [], uvs: [], indices: [] }; for (let i = 0, l = meshes.length; i < l; i++) { let mesh = meshes[i]; let indexOffset = result.positions.length / 3; Utils.arrayCombine(result.positions, mesh.positions); Utils.arrayCombine(result.normals, mesh.normals); Utils.arrayCombine(result.uvs, mesh.uvs); for (let index = 0, n = mesh.indices.length; index < n; index++) { result.indices.push(mesh.indices[index] + indexOffset); } } return result; }; return exports; })();