Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving matrix multiplication to the CPU. Adding glMatrix dependency. #315

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
Open
93 changes: 4 additions & 89 deletions core/Transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

'use strict';

var glMatrix = require('gl-matrix');
var mat44 = glMatrix.mat4;

var QUAT = [0, 0, 0, 1];
var ONES = [1, 1, 1];

Expand Down Expand Up @@ -450,7 +453,7 @@ Transform.prototype.calculateWorldMatrix = function calculateWorldMatrix () {
while (nearestBreakPoint && !nearestBreakPoint.isBreakPoint())
nearestBreakPoint = nearestBreakPoint.parent;

if (nearestBreakPoint) return multiply(this.global, nearestBreakPoint.getWorldTransform(), this.local);
if (nearestBreakPoint) return mat44.multiply(this.global, nearestBreakPoint.getWorldTransform(), this.local);
else {
for (var i = 0; i < 16 ; i++) this.global[i] = this.local[i];
return false;
Expand Down Expand Up @@ -680,92 +683,4 @@ function fromNodeWithParent (node, transform) {
return changed;
}

/**
* private method to multiply two transforms.
*
* @method
*
* @param {Array} out The array to write the result to
* @param {Array} a the left hand transform
* @param {Array} b the right hand transform
*
* @return {undefined} undefined
*/
function multiply (out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[4], a11 = a[5], a12 = a[6],
a20 = a[8], a21 = a[9], a22 = a[10],
a30 = a[12], a31 = a[13], a32 = a[14];

var changed = false;
var res;

// Cache only the current line of the second matrix
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];

res = b0*a00 + b1*a10 + b2*a20 + b3*a30;
changed = changed ? changed : out[0] === res;
out[0] = res;

res = b0*a01 + b1*a11 + b2*a21 + b3*a31;
changed = changed ? changed : out[1] === res;
out[1] = res;

res = b0*a02 + b1*a12 + b2*a22 + b3*a32;
changed = changed ? changed : out[2] === res;
out[2] = res;

out[3] = 0;

b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];

res = b0*a00 + b1*a10 + b2*a20 + b3*a30;
changed = changed ? changed : out[4] === res;
out[4] = res;

res = b0*a01 + b1*a11 + b2*a21 + b3*a31;
changed = changed ? changed : out[5] === res;
out[5] = res;

res = b0*a02 + b1*a12 + b2*a22 + b3*a32;
changed = changed ? changed : out[6] === res;
out[6] = res;

out[7] = 0;

b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];

res = b0*a00 + b1*a10 + b2*a20 + b3*a30;
changed = changed ? changed : out[8] === res;
out[8] = res;

res = b0*a01 + b1*a11 + b2*a21 + b3*a31;
changed = changed ? changed : out[9] === res;
out[9] = res;

res = b0*a02 + b1*a12 + b2*a22 + b3*a32;
changed = changed ? changed : out[10] === res;
out[10] = res;

out[11] = 0;

b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];

res = b0*a00 + b1*a10 + b2*a20 + b3*a30;
changed = changed ? changed : out[12] === res;
out[12] = res;

res = b0*a01 + b1*a11 + b2*a21 + b3*a31;
changed = changed ? changed : out[13] === res;
out[13] = res;

res = b0*a02 + b1*a12 + b2*a22 + b3*a32;
changed = changed ? changed : out[14] === res;
out[14] = res;

out[15] = 1;

return changed;
}

module.exports = Transform;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"uglify-js": "^2.4.17"
},
"dependencies": {
"gl-matrix": "^2.3.1",
"glslify": "^2.0.0"
},
"browserify": {
Expand Down
99 changes: 99 additions & 0 deletions webgl-geometries/GeometryHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

var Vec3 = require('../math/Vec3');
var Vec2 = require('../math/Vec2');
var glMatrix = require('gl-matrix');
var vec3 = glMatrix.vec3;

var outputs = [
new Vec3(),
Expand Down Expand Up @@ -563,4 +565,101 @@ GeometryHelper.addBackfaceTriangles = function addBackfaceTriangles(vertices, in
}
};

// http://www.terathon.com/code/tangent.html

GeometryHelper.computeTangents = function computeTangents(vertices, indices, normals, textureCoords, out) {
var nFaces = indices.length / 3;
var nVerts = vertices.length / 3;
var tdir = vec3.create();
var sdir = vec3.create();
var tan1 = [],
tan2 = [];
var out = out || [];

for (var i = 0; i < nVerts; i++) {
tan1[i] = vec3.create();
tan2[i] = vec3.create();
}

for (var i = 0; i < nFaces; i++)
{
var i1 = indices[i * 3];
var i2 = indices[i * 3 + 1];
var i3 = indices[i * 3 + 2];

var v1 = vertices.slice(i1 * 3, i1 * 3 + 3);
var v2 = vertices.slice(i2 * 3, i2 * 3 + 3);
var v3 = vertices.slice(i3 * 3, i3 * 3 + 3);

var w1 = textureCoords.slice(i1 * 2, i1 * 2 + 2);
var w2 = textureCoords.slice(i2 * 2, i2 * 2 + 2);
var w3 = textureCoords.slice(i3 * 2, i3 * 2 + 2);

var x1 = v2[0] - v1[0];
var x2 = v3[0] - v1[0];
var y1 = v2[1] - v1[1];
var y2 = v3[1] - v1[1];
var z1 = v2[2] - v1[2];
var z2 = v3[2] - v1[2];

var s1 = w2[0] - w1[0];
var s2 = w3[0] - w1[0];
var t1 = w2[1] - w1[1];
var t2 = w3[1] - w1[1];

var r = 1.0 / (s1 * t2 - s2 * t1);

vec3.set(sdir,
(t2 * x1 - t1 * x2) * r,
(t2 * y1 - t1 * y2) * r,
(t2 * z1 - t1 * z2) * r
);

vec3.set(tdir,
(s1 * x2 - s2 * x1) * r,
(s1 * y2 - s2 * y1) * r,
(s1 * z2 - s2 * z1) * r
);

vec3.add(tan1[i1], tan1[i1], sdir);
vec3.add(tan1[i2], tan1[i2], sdir);
vec3.add(tan1[i3], tan1[i3], sdir);

vec3.add(tan2[i1], tan2[i1], tdir);
vec3.add(tan2[i2], tan2[i2], tdir);
vec3.add(tan2[i3], tan2[i3], tdir);

}

var normal = vec3.create();
var t = vec3.create();

for (i = 0; i < nVerts; i++)
{
vec3.set(normal,
normals[i * 3],
normals[i * 3 + 1],
normals[i * 3 + 2]
);

vec3.set(t,
tan1[i][0],
tan1[i][1],
tan1[i][2]
);

// Gram-Schmidt orthogonalize

vec3.scale(normal, normal, vec3.dot(normal, t));
vec3.subtract(t, t, normal);
vec3.normalize(t, t);

out[i * 3] = t[0];
out[i * 3 + 1] = t[1];
out[i * 3 + 2] = t[2];
}

return out;
}

module.exports = GeometryHelper;
24 changes: 18 additions & 6 deletions webgl-geometries/primitives/Box.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
'use strict';

var Geometry = require('../Geometry');
var GeometryHelper = require('../GeometryHelper');

function pickOctant(i) {
return [(i & 1) * 2 - 1, (i & 2) - 1, (i & 4) / 2 - 1];
Expand Down Expand Up @@ -54,6 +55,8 @@ var boxData = [
function BoxGeometry(options) {
options = options || {};

var buffers = [];

var vertices = [];
var textureCoords = [];
var normals = [];
Expand All @@ -77,16 +80,25 @@ function BoxGeometry(options) {
}
indices.push(v, v + 1, v + 2);
indices.push(v + 2, v + 1, v + 3);
}

buffers.push(
{ name: 'a_pos', data: vertices },
{ name: 'a_texCoord', data: textureCoords, size: 2 },
{ name: 'a_normals', data: normals },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gonna have to be a_normal after @FarhadG's big ol change

{ name: 'indices', data: indices, size: 1 }
);

if (options.tangents) {
buffers.push({
name: 'a_tangent',
data: GeometryHelper.computeTangents(vertices, indices, normals, textureCoords),
size: 3
});
}

return new Geometry({
buffers: [
{ name: 'a_pos', data: vertices },
{ name: 'a_texCoord', data: textureCoords, size: 2 },
{ name: 'a_normals', data: normals },
{ name: 'indices', data: indices, size: 1 }
]
buffers: buffers
});
}

Expand Down
25 changes: 19 additions & 6 deletions webgl-geometries/primitives/Sphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,26 @@ function ParametricSphere (options) {
true
);

var vertices = buffers.vertices,
indices = buffers.indices,
textureCoords = GeometryHelper.getSpheroidUV(buffers.vertices),
normals = GeometryHelper.getSpheroidNormals(buffers.vertices);

var buffers = [
{ name: 'a_pos', data: buffers.vertices },
{ name: 'a_texCoord', data: textureCoords, size: 2 },
{ name: 'a_normals', data: normals },
{ name: 'indices', data: buffers.indices, size: 1 }
];

buffers.push({
name: 'a_tangent',
data: GeometryHelper.computeTangents(vertices, indices, normals, textureCoords),
size: 3
});

return new Geometry({
buffers: [
{ name: 'a_pos', data: buffers.vertices },
{ name: 'a_texCoord', data: GeometryHelper.getSpheroidUV(buffers.vertices), size: 2 },
{ name: 'a_normals', data: GeometryHelper.getSpheroidNormals(buffers.vertices) },
{ name: 'indices', data: buffers.indices, size: 1 }
]
buffers: buffers
});
}

Expand Down
13 changes: 8 additions & 5 deletions webgl-renderers/Program.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ var TYPES = {
2: 'vec2 ',
3: 'vec3 ',
4: 'vec4 ',
9: 'mat3 ',
16: 'mat4 '
};

var inputTypes = {
u_baseColor: 'vec4',
u_normals: 'vert',
u_normals: 'vec3',
u_glossiness: 'vec4',
u_positionOffset: 'vert'
};
Expand All @@ -65,9 +66,9 @@ var masks = {
*/
var uniforms = keyValueToArrays({
u_perspective: identityMatrix,
u_view: identityMatrix,
u_mvMatrix: identityMatrix,
u_resolution: [0, 0, 0],
u_transform: identityMatrix,
u_normalMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0],
u_size: [1, 1, 1],
u_time: 0,
u_opacity: 1,
Expand All @@ -89,7 +90,8 @@ var uniforms = keyValueToArrays({
var attributes = keyValueToArrays({
a_pos: [0, 0, 0],
a_texCoord: [0, 0],
a_normals: [0, 0, 0]
a_normals: [0, 0, 0],
a_tangent: [0, 0, 0]
});

/**
Expand All @@ -99,7 +101,8 @@ var varyings = keyValueToArrays({
v_textureCoordinate: [0, 0],
v_normal: [0, 0, 0],
v_position: [0, 0, 0],
v_eyeVector: [0, 0, 0]
v_eyeVector: [0, 0, 0],
v_tangent: [0, 0, 0]
});

/**
Expand Down
Loading