Former-commit-id: 64c9625b85553dcdb32306c9e03d69dc3d913ef3
This commit is contained in:
Ben
2022-02-27 23:52:18 +00:00
parent a4b38a6d61
commit 6fca2d6f9e
11 changed files with 4880 additions and 7172 deletions

View File

@@ -0,0 +1,28 @@
#version 300 es
precision highp float;
uniform SceneUniforms {
mat4 viewProj;
vec4 eyePosition;
vec4 lightPosition;
} uScene;
uniform sampler2D tex;
in vec3 vPosition;
in vec3 vNormal;
out vec4 fragColor;
void main() {
vec3 color = vNormal;
vec3 normal = normalize(vNormal);
vec3 eyeVec = normalize(uScene.eyePosition.xyz - vPosition);
vec3 incidentVec = normalize(vPosition - uScene.lightPosition.xyz);
vec3 lightVec = -incidentVec;
float diffuse = max(dot(lightVec, normal), 0.0);
float highlight = pow(max(dot(eyeVec, reflect(incidentVec, normal)), 0.0), 100.0);
float ambient = 0.1;
fragColor = vec4(color * (diffuse + highlight + ambient), 1.0);
}

View File

@@ -0,0 +1,24 @@
#version 300 es
layout(std140, column_major) uniform;
layout(location=0) in vec4 position;
layout(location=1) in vec4 normal;
uniform SceneUniforms {
mat4 viewProj;
vec4 eyePosition;
vec4 lightPosition;
} uScene;
uniform mat4 uModel;
out vec3 vPosition;
out vec3 vNormal;
void main() {
vec4 worldPosition = uModel * position;
vPosition = worldPosition.xyz;
vNormal = (uModel * normal).xyz;
gl_Position = uScene.viewProj * worldPosition;
}

View File

@@ -0,0 +1,134 @@
export default class Box {
constructor(gl, options) {
this.gl = gl;
this.options = options;
this.vao = gl.createVertexArray();
gl.bindVertexArray(this.vao);
}
get vertexCount() {
return this.verticies;
}
bind() {
this.gl.bindVertexArray(this.vao);
}
create(options) {
const { positions, normals } = this.boxVerticies(options);
this.verticies = positions.length / 3;
this.gl.bindVertexArray(this.vao);
const positionBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
this.gl.vertexAttribPointer(0, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(0);
const normalBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, normalBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, normals, this.gl.STATIC_DRAW);
this.gl.vertexAttribPointer(2, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(1);
}
// TODO: Use indicies ffs
boxVerticies(options) {
options = options || {};
const dimensions = options.dimensions || [1, 1, 1];
const position = options.position || [-dimensions[0] / 2, -dimensions[1] / 2, -dimensions[2] / 2];
const x = position[0];
const y = position[1];
const z = position[2];
const width = dimensions[0];
const height = dimensions[1];
const depth = dimensions[2];
const fbl = { x, y, z: z + depth };
const fbr = { x: x + width, y, z: z + depth };
const ftl = { x, y: y + height, z: z + depth };
const ftr = { x: x + width, y: y + height, z: z + depth };
const bbl = { x, y, z };
const bbr = { x: x + width, y, z };
const btl = { x, y: y + height, z };
const btr = { x: x + width, y: y + height, z };
const positions = new Float32Array([
// front
fbl.x, fbl.y, fbl.z,
fbr.x, fbr.y, fbr.z,
ftl.x, ftl.y, ftl.z,
ftl.x, ftl.y, ftl.z,
fbr.x, fbr.y, fbr.z,
ftr.x, ftr.y, ftr.z,
// right
fbr.x, fbr.y, fbr.z,
bbr.x, bbr.y, bbr.z,
ftr.x, ftr.y, ftr.z,
ftr.x, ftr.y, ftr.z,
bbr.x, bbr.y, bbr.z,
btr.x, btr.y, btr.z,
// back
fbr.x, bbr.y, bbr.z,
bbl.x, bbl.y, bbl.z,
btr.x, btr.y, btr.z,
btr.x, btr.y, btr.z,
bbl.x, bbl.y, bbl.z,
btl.x, btl.y, btl.z,
// left
bbl.x, bbl.y, bbl.z,
fbl.x, fbl.y, fbl.z,
btl.x, btl.y, btl.z,
btl.x, btl.y, btl.z,
fbl.x, fbl.y, fbl.z,
ftl.x, ftl.y, ftl.z,
// top
ftl.x, ftl.y, ftl.z,
ftr.x, ftr.y, ftr.z,
btl.x, btl.y, btl.z,
btl.x, btl.y, btl.z,
ftr.x, ftr.y, ftr.z,
btr.x, btr.y, btr.z,
// bottom
bbl.x, bbl.y, bbl.z,
bbr.x, bbr.y, bbr.z,
fbl.x, fbl.y, fbl.z,
fbl.x, fbl.y, fbl.z,
bbr.x, bbr.y, bbr.z,
fbr.x, fbr.y, fbr.z,
]);
const normals = new Float32Array(positions.length);
let ni;
for (let i = 0, count = positions.length / 3; i < count; i++) {
ni = i * 3;
normals[ni] = parseInt(i / 6, 10) === 1
? 1
: parseInt(i / 6, 10) === 3 ? -1 : 0;
normals[ni + 1] = parseInt(i / 6, 10) === 4
? 1
: parseInt(i / 6, 10) === 5 ? -1 : 0;
normals[ni + 2] = parseInt(i / 6, 10) === 0
? 1
: parseInt(i / 6, 10) === 2 ? -1 : 0;
}
return {
positions,
normals,
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
import * as glm from './glm.mjs';
import Shader from './shader.mjs';
import Box from './box.mjs';
let BasicVsource, BasicFSource;
export async function RendererPreInit() {
BasicFSource = await fetch('./brick-renderer/basic.fs').then(r => r.text());
BasicVsource = await fetch('./brick-renderer/basic.vs').then(r => r.text());
}
class BaseRenderer {
constructor(canvas) {
this.canvas = canvas;
this.gl = canvas.getContext('webgl2');
this.gl.viewport(0, 0, canvas.width, canvas.height);
this.gl.clearColor(0.84313, 0.76078, 1.0, 1.0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.gl.enable(this.gl.DEPTH_TEST);
this.shader = new Shader(this.gl, BasicVsource, BasicFSource);
this.shader.link();
}
}
export class BrickRenderer extends BaseRenderer {
constructor(canvas, options) {
super(canvas);
const sceneUniformLocation = this.shader.getUniformBlock('SceneUniforms');
const modelMatrixLocation = this.shader.getUniform('uModel');
this.shader.attatch();
const boxObj = new Box(this.gl, { dimensions: [0.5, 0.6, 0.5] });
const projMatrix = glm.mat4.create();
glm.mat4.perspective(projMatrix, Math.PI / 2, this.gl.drawingBufferWidth / this.gl.drawingBufferHeight, 0.1, 10.0);
const viewMatrix = glm.mat4.create();
const eyePosition = glm.vec3.fromValues(1, 1, 1);
glm.mat4.lookAt(viewMatrix, eyePosition, glm.vec3.fromValues(0, 0, 0), glm.vec3.fromValues(0, 1, 0));
const viewProjMatrix = glm.mat4.create();
glm.mat4.multiply(viewProjMatrix, projMatrix, viewMatrix);
const lightPosition = glm.vec3.fromValues(1, 1, 0.5);
const modelMatrix = glm.mat4.create();
const rotateXMatrix = glm.mat4.create();
const rotateYMatrix = glm.mat4.create();
const sceneUniformData = new Float32Array(24);
sceneUniformData.set(viewProjMatrix);
sceneUniformData.set(eyePosition, 16);
sceneUniformData.set(lightPosition, 20);
const sceneUniformBuffer = this.gl.createBuffer();
this.gl.bindBufferBase(this.gl.UNIFORM_BUFFER, 0, sceneUniformBuffer);
this.gl.bufferData(this.gl.UNIFORM_BUFFER, sceneUniformData, this.gl.STATIC_DRAW);
let angleX = 0;
let angleY = 0;
function draw() {
angleX += 0.01;
angleY += 0.015;
glm.mat4.fromXRotation(rotateXMatrix, angleX);
glm.mat4.fromYRotation(rotateYMatrix, angleY);
glm.mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
this.gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.gl.drawArrays(this.gl.TRIANGLES, 0, boxObj.vertexCount);
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
}
}

View File

@@ -0,0 +1,127 @@
export default class Shader {
constructor(gl, vSource, fSource) {
this.gl = gl;
this.vSource = vSource;
this.fSource = fSource;
this.uniformBlockNum = 0;
this.shaderProgram = 123;
this.vShader = this.gl.createShader(this.gl.VERTEX_SHADER);
this.gl.shaderSource(this.vShader, this.vSource);
this.gl.compileShader(this.vShader);
if (!this.gl.getShaderParameter(this.vShader, this.gl.COMPILE_STATUS)) {
console.error(this.gl.getShaderInfoLog(this.vShader));
}
this.fShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
this.gl.shaderSource(this.fShader, this.fSource);
this.gl.compileShader(this.fShader);
if (!this.gl.getShaderParameter(this.fShader, this.gl.COMPILE_STATUS)) {
console.error(this.gl.getShaderInfoLog(this.fShader));
}
}
get vertexShader() {
return this.vShader;
}
get fragmentShader() {
return this.fShader;
}
get program() {
return this.shaderProgram;
}
getUniformBlock(name) {
const location = this.gl.getUniformBlockIndex(this.shaderProgram, name);
this.gl.uniformBlockBinding(this.shaderProgram, location, this.uniformBlockNum);
this.uniformBlockNum++;
return location;
}
getUniform(name) {
return this.gl.getUniformLocation(this.shaderProgram, name);
}
attribLocation(location, name) {
this.gl.bindAttribLocation(this.shaderProgram, location, name);
}
setUniform(uniform, value) {
switch (uniform.type) {
case this.gl.FLOAT:
this.gl.uniform1f(uniform, value);
break;
case this.gl.FLOAT_VEC2:
this.gl.uniform2f(uniform, value[0], value[1]);
break;
case this.gl.FLOAT_VEC3:
this.gl.uniform3f(uniform, value[0], value[1], value[2]);
break;
case this.gl.FLOAT_VEC4:
this.gl.uniform4f(uniform, value[0], value[1], value[2], value[3]);
break;
case this.gl.INT:
this.gl.uniform1i(uniform, value);
break;
case this.gl.INT_VEC2:
this.gl.uniform2i(uniform, value[0], value[1]);
break;
case this.gl.INT_VEC3:
this.gl.uniform3i(uniform, value[0], value[1], value[2]);
break;
case this.gl.INT_VEC4:
this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]);
break;
case this.gl.BOOL:
this.gl.uniform1i(uniform, value);
break;
case this.gl.BOOL_VEC2:
this.gl.uniform2i(uniform, value[0], value[1]);
break;
case this.gl.BOOL_VEC3:
this.gl.uniform3i(uniform, value[0], value[1], value[2]);
break;
case this.gl.BOOL_VEC4:
this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]);
break;
case this.gl.FLOAT_MAT2:
this.gl.uniformMatrix2fv(uniform, false, value);
break;
case this.gl.FLOAT_MAT3:
this.gl.uniformMatrix3fv(uniform, false, value);
break;
case this.gl.FLOAT_MAT4:
this.gl.uniformMatrix4fv(uniform, false, value);
break;
case this.gl.SAMPLER_2D:
this.gl.uniform1i(uniform, value);
break;
case this.gl.SAMPLER_CUBE:
this.gl.uniform1i(uniform, value);
break;
default:
console.error(`Unsupported uniform type ${uniform.type}`);
}
}
link() {
this.shaderProgram = this.gl.createProgram();
this.gl.attachShader(this.shaderProgram, this.vShader);
this.gl.attachShader(this.shaderProgram, this.fShader);
this.gl.linkProgram(this.shaderProgram);
if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
console.error(this.gl.getProgramParameter(this.shaderProgram));
}
}
attatch() {
this.gl.useProgram(this.shaderProgram);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -10,10 +10,11 @@
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans&display=swap" rel="stylesheet">
<script src="components/components.js"></script>
<script src="gl-matrix.js"></script>
<script src="utils.js"></script>
<script src="https://cdn.jsdelivr.net/npm/glm-js@0.0.6-c/build/glm-js.min.js"></script>
<script src="index.js"></script>
<script type="module" src="brick-renderer/glm.mjs"></script>
<script type="module" src="brick-renderer/shader.mjs"></script>
<script type="module" src="brick-renderer/index.mjs"></script>
<script type="module" src="index.mjs"></script>
</head>
<body>
<loading-component></loading-component>
@@ -33,66 +34,6 @@
</content-margin>
<canvas id="webglviewer" width="640" height="480"></canvas>
<script type="x-shader/vs" id="vertex-draw">
#version 300 es
layout(std140, column_major) uniform;
layout(location=0) in vec4 position;
layout(location=1) in vec2 uv;
layout(location=2) in vec4 normal;
uniform SceneUniforms {
mat4 viewProj;
vec4 eyePosition;
vec4 lightPosition;
} uScene;
uniform mat4 uModel;
out vec3 vPosition;
out vec2 vUV;
out vec3 vNormal;
void main() {
vec4 worldPosition = uModel * position;
vPosition = worldPosition.xyz;
vUV = uv;
vNormal = (uModel * normal).xyz;
gl_Position = uScene.viewProj * worldPosition;
}
</script>
<script type="x-shader/vf" id="fragment-draw">
#version 300 es
precision highp float;
layout(std140, column_major) uniform;
uniform SceneUniforms {
mat4 viewProj;
vec4 eyePosition;
vec4 lightPosition;
} uScene;
uniform sampler2D tex;
in vec3 vPosition;
in vec2 vUV;
in vec3 vNormal;
out vec4 fragColor;
void main() {
vec3 color = vec3(vUV, 1.0);
vec3 normal = normalize(vNormal);
vec3 eyeVec = normalize(uScene.eyePosition.xyz - vPosition);
vec3 incidentVec = normalize(vPosition - uScene.lightPosition.xyz);
vec3 lightVec = -incidentVec;
float diffuse = max(dot(lightVec, normal), 0.0);
float highlight = pow(max(dot(eyeVec, reflect(incidentVec, normal)), 0.0), 100.0);
float ambient = 0.1;
fragColor = vec4(color * (diffuse + highlight + ambient), 1.0);
}
</script>
</limited-margin>
</body>

View File

@@ -1,125 +0,0 @@
function main() {
const canvas = document.querySelector('#webglviewer');
const gl = canvas.getContext('webgl2');
// Only continue if WebGL is available and working
if (gl === null) {
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// Set clear color to black, fully opaque
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear the color buffer with specified clear color
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
const vsSource = document.getElementById('vertex-draw').text.trim();
const fsSource = document.getElementById('fragment-draw').text.trim();
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(vertexShader));
}
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(fragmentShader));
}
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
}
const sceneUniformsLocation = gl.getUniformBlockIndex(program, 'SceneUniforms');
gl.uniformBlockBinding(program, sceneUniformsLocation, 0);
const modelMatrixLocation = gl.getUniformLocation(program, 'uModel');
gl.useProgram(program);
const box = utils.createBox({dimensions: [.5, .6, .5]});
const numVertices = box.positions.length / 3;
const cubeArray = gl.createVertexArray();
gl.bindVertexArray(cubeArray);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, box.positions, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);
const uvBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, box.uvs, gl.STATIC_DRAW);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(1);
const normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, box.normals, gl.STATIC_DRAW);
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(2);
const projMatrix = mat4.create();
mat4.perspective(projMatrix, Math.PI / 2, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 10.0);
const viewMatrix = mat4.create();
const eyePosition = vec3.fromValues(1, 1, 1);
mat4.lookAt(viewMatrix, eyePosition, vec3.fromValues(0, 0, 0), vec3.fromValues(0, 1, 0));
const viewProjMatrix = mat4.create();
mat4.multiply(viewProjMatrix, projMatrix, viewMatrix);
const lightPosition = vec3.fromValues(1, 1, 0.5);
const modelMatrix = mat4.create();
const rotateXMatrix = mat4.create();
const rotateYMatrix = mat4.create();
const sceneUniformData = new Float32Array(24);
sceneUniformData.set(viewProjMatrix);
sceneUniformData.set(eyePosition, 16);
sceneUniformData.set(lightPosition, 20);
const sceneUniformBuffer = gl.createBuffer();
gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, sceneUniformBuffer);
gl.bufferData(gl.UNIFORM_BUFFER, sceneUniformData, gl.STATIC_DRAW);
let angleX = 0;
let angleY = 0;
function draw() {
angleX += 0.01;
angleY += 0.015;
mat4.fromXRotation(rotateXMatrix, angleX);
mat4.fromYRotation(rotateYMatrix, angleY);
mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, numVertices);
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
}
window.onload = main;

10
client/public/index.mjs Normal file
View File

@@ -0,0 +1,10 @@
import { RendererPreInit, BrickRenderer } from './brick-renderer/index.mjs';
async function main() {
await RendererPreInit();
const canvas = document.querySelector('#webglviewer');
const Renderer = new BrickRenderer(canvas);
}
window.onload = main;

View File

@@ -1,374 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT)
//
// Copyright (c) 2017 Tarek Sherif
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////////////////////////////////////////////
(function() {
var translateMat = mat4.create();
var rotateXMat = mat4.create();
var rotateYMat = mat4.create();
var rotateZMat = mat4.create();
var scaleMat = mat4.create();
var zeros = [0, 0, 0];
var ones = [1, 1, 1];
window.utils = {
xformMatrix: function xformMatrix(xform, translate, rotate, scale) {
translate = translate || zeros;
rotate = rotate || zeros;
scale = scale || ones;
mat4.fromTranslation(translateMat, translate);
mat4.fromXRotation(rotateXMat, rotate[0]);
mat4.fromYRotation(rotateYMat, rotate[1]);
mat4.fromZRotation(rotateZMat, rotate[2]);
mat4.fromScaling(scaleMat, scale);
mat4.multiply(xform, rotateXMat, scaleMat);
mat4.multiply(xform, rotateYMat, xform);
mat4.multiply(xform, rotateZMat, xform);
mat4.multiply(xform, translateMat, xform);
},
loadCubemapImages: function loadCubeMapImages(urls, ok) {
var numImages = 6;
var negX = new Image();
var posX = new Image();
var negY = new Image();
var posY = new Image();
var negZ = new Image();
var posZ = new Image();
function onload() {
if (--numImages === 0) {
ok(negX, posX, negY, posY, negZ, posZ);
}
}
negX.onload = onload;
posX.onload = onload;
negY.onload = onload;
posY.onload = onload;
negZ.onload = onload;
posZ.onload = onload;
negX.src = urls.negX;
posX.src = urls.posX;
negY.src = urls.negY;
posY.src = urls.posY;
negZ.src = urls.negZ;
posZ.src = urls.posZ;
},
createBox: function createBox(options) {
options = options || {};
var dimensions = options.dimensions || [1, 1, 1];
var position = options.position || [-dimensions[0] / 2, -dimensions[1] / 2, -dimensions[2] / 2];
var x = position[0];
var y = position[1];
var z = position[2];
var width = dimensions[0];
var height = dimensions[1];
var depth = dimensions[2];
var fbl = {x: x, y: y, z: z + depth};
var fbr = {x: x + width, y: y, z: z + depth};
var ftl = {x: x, y: y + height, z: z + depth};
var ftr = {x: x + width, y: y + height, z: z + depth};
var bbl = {x: x, y: y, z: z };
var bbr = {x: x + width, y: y, z: z };
var btl = {x: x, y: y + height, z: z };
var btr = {x: x + width, y: y + height, z: z };
var positions = new Float32Array([
//front
fbl.x, fbl.y, fbl.z,
fbr.x, fbr.y, fbr.z,
ftl.x, ftl.y, ftl.z,
ftl.x, ftl.y, ftl.z,
fbr.x, fbr.y, fbr.z,
ftr.x, ftr.y, ftr.z,
//right
fbr.x, fbr.y, fbr.z,
bbr.x, bbr.y, bbr.z,
ftr.x, ftr.y, ftr.z,
ftr.x, ftr.y, ftr.z,
bbr.x, bbr.y, bbr.z,
btr.x, btr.y, btr.z,
//back
fbr.x, bbr.y, bbr.z,
bbl.x, bbl.y, bbl.z,
btr.x, btr.y, btr.z,
btr.x, btr.y, btr.z,
bbl.x, bbl.y, bbl.z,
btl.x, btl.y, btl.z,
//left
bbl.x, bbl.y, bbl.z,
fbl.x, fbl.y, fbl.z,
btl.x, btl.y, btl.z,
btl.x, btl.y, btl.z,
fbl.x, fbl.y, fbl.z,
ftl.x, ftl.y, ftl.z,
//top
ftl.x, ftl.y, ftl.z,
ftr.x, ftr.y, ftr.z,
btl.x, btl.y, btl.z,
btl.x, btl.y, btl.z,
ftr.x, ftr.y, ftr.z,
btr.x, btr.y, btr.z,
//bottom
bbl.x, bbl.y, bbl.z,
bbr.x, bbr.y, bbr.z,
fbl.x, fbl.y, fbl.z,
fbl.x, fbl.y, fbl.z,
bbr.x, bbr.y, bbr.z,
fbr.x, fbr.y, fbr.z,
]);
var uvs = new Float32Array([
//front
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
//right
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
//back
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
//left
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
//top
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
//bottom
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1
]);
var normals = new Float32Array(positions.length);
var i, count;
var ni;
for (i = 0, count = positions.length / 3; i < count; i++) {
ni = i * 3;
normals[ni] = parseInt(i / 6, 10) === 1 ? 1 :
parseInt(i / 6, 10) === 3 ? -1 : 0;
normals[ni+1] = parseInt(i / 6, 10) === 4 ? 1 :
parseInt(i / 6, 10) === 5 ? -1 : 0;
normals[ni+2] = parseInt(i / 6, 10) === 0 ? 1 :
parseInt(i / 6, 10) === 2 ? -1 : 0;
}
return {
positions: positions,
normals: normals,
uvs: uvs
};
},
createSphere: function createSphere(options) {
options = options || {};
var long_bands = options.long_bands || 32;
var lat_bands = options.lat_bands || 32;
var radius = options.radius || 1;
var lat_step = Math.PI / lat_bands;
var long_step = 2 * Math.PI / long_bands;
var num_positions = long_bands * lat_bands * 4;
var num_indices = long_bands * lat_bands * 6;
var lat_angle, long_angle;
var positions = new Float32Array(num_positions * 3);
var normals = new Float32Array(num_positions * 3);
var uvs = new Float32Array(num_positions * 2);
var indices = new Uint16Array(num_indices);
var x1, x2, x3, x4,
y1, y2,
z1, z2, z3, z4,
u1, u2,
v1, v2;
var i, j;
var k = 0, l = 0;
var vi, ti;
for (i = 0; i < lat_bands; i++) {
lat_angle = i * lat_step;
y1 = Math.cos(lat_angle);
y2 = Math.cos(lat_angle + lat_step);
for (j = 0; j < long_bands; j++) {
long_angle = j * long_step;
x1 = Math.sin(lat_angle) * Math.cos(long_angle);
x2 = Math.sin(lat_angle) * Math.cos(long_angle + long_step);
x3 = Math.sin(lat_angle + lat_step) * Math.cos(long_angle);
x4 = Math.sin(lat_angle + lat_step) * Math.cos(long_angle + long_step);
z1 = Math.sin(lat_angle) * Math.sin(long_angle);
z2 = Math.sin(lat_angle) * Math.sin(long_angle + long_step);
z3 = Math.sin(lat_angle + lat_step) * Math.sin(long_angle);
z4 = Math.sin(lat_angle + lat_step) * Math.sin(long_angle + long_step);
u1 = 1 - j / long_bands;
u2 = 1 - (j + 1) / long_bands;
v1 = 1 - i / lat_bands;
v2 = 1 - (i + 1) / lat_bands;
vi = k * 3;
ti = k * 2;
positions[vi] = x1 * radius;
positions[vi+1] = y1 * radius;
positions[vi+2] = z1 * radius; //v0
positions[vi+3] = x2 * radius;
positions[vi+4] = y1 * radius;
positions[vi+5] = z2 * radius; //v1
positions[vi+6] = x3 * radius;
positions[vi+7] = y2 * radius;
positions[vi+8] = z3 * radius; // v2
positions[vi+9] = x4 * radius;
positions[vi+10] = y2 * radius;
positions[vi+11] = z4 * radius; // v3
normals[vi] = x1;
normals[vi+1] = y1;
normals[vi+2] = z1;
normals[vi+3] = x2;
normals[vi+4] = y1;
normals[vi+5] = z2;
normals[vi+6] = x3;
normals[vi+7] = y2;
normals[vi+8] = z3;
normals[vi+9] = x4;
normals[vi+10] = y2;
normals[vi+11] = z4;
uvs[ti] = u1;
uvs[ti+1] = v1;
uvs[ti+2] = u2;
uvs[ti+3] = v1;
uvs[ti+4] = u1;
uvs[ti+5] = v2;
uvs[ti+6] = u2;
uvs[ti+7] = v2;
indices[l ] = k;
indices[l + 1] = k + 1;
indices[l + 2] = k + 2;
indices[l + 3] = k + 2;
indices[l + 4] = k + 1;
indices[l + 5] = k + 3;
k += 4;
l += 6;
}
}
return {
positions: positions,
normals: normals,
uvs: uvs,
indices: indices
};
},
computeBoundingBox: function (position, options) {
options = options || {};
var geo = options.geo || false;
var res = {
min: vec3.create(),
max: vec3.create()
};
vec3.set(res.min, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
vec3.set(res.max, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
for ( var i = 0, len = position.length; i < len; i+=3 ) {
res.min[0] = Math.min(position[i], res.min[0]);
res.max[0] = Math.max(position[i], res.max[0]);
res.min[1] = Math.min(position[i], res.min[1]);
res.max[1] = Math.max(position[i], res.max[1]);
res.min[2] = Math.min(position[i], res.min[2]);
res.max[2] = Math.max(position[i], res.max[2]);
}
if (geo) {
var size = vec3.create();
vec3.subtract(size, res.max, res.min);
res.geo = utils.createBox({
position: res.min,
width: size[0],
height: size[1],
depth: size[2]
});
}
return res;
}
}
})();