Skip to content

Instantly share code, notes, and snippets.

@cjcliffe
Forked from Maciek416/CubicVR.js
Created April 20, 2010 06:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjcliffe/372115 to your computer and use it in GitHub Desktop.
Save cjcliffe/372115 to your computer and use it in GitHub Desktop.
/*
Javascript port of CubicVR 3D engine for WebGL
by Charles J. Cliffe
http://www.cubicvr.org/
May be used under the terms of LGPL v3.0 or greater.
*/
var CubicVR = null;
var CubicVR_GLCore = new Object();
var CubicVR_Materials = Array();
var CubicVR_Material_ref = Array();
var CubicVR_Textures = Array();
var CubicVR_Texture_ref = Array();
var CubicVR_Images = Array();
var CubicVR_ShaderPool = new Array();
var CubicVR_CoreShader_vs = null;
var CubicVR_CoreShader_fs = null;
var M_PI = 3.1415926535897932384626433832795028841968;
var M_TWO_PI = 2.0*M_PI;
/* Transform Controller */
cubicvr_transform = function(init_mat)
{
this.m_stack = new Array();
this.m_cache = new Array();
this.c_stack = 0;
this.valid = 0;
this.result = null;
if (typeof(init_mat)!='undefined')
{
this.m_stack[0] = init_mat;
}
else
{
this.setIdentity();
}
}
CubicVR_GLCore.init = function(gl_in,vs_in,fs_in)
{
CubicVR_GLCore.gl = gl_in;
CubicVR_GLCore.CoreShader_vs = cubicvr_getScriptContents(vs_in);
CubicVR_GLCore.CoreShader_fs = cubicvr_getScriptContents(fs_in);
gl.enable( gl.CULL_FACE );
gl.cullFace( gl.BACK );
gl.frontFace( gl.CCW );
}
cubicvr_transform.prototype.setIdentity = function()
{
this.m_stack[this.c_stack] = this.getIdentity();
if (this.valid == this.c_stack && this.c_stack) this.valid--;
}
cubicvr_transform.prototype.getIdentity = function()
{
return [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 ];
}
cubicvr_transform.prototype.invalidate = function()
{
this.valid = 0;
this.result = null;
}
cubicvr_transform.prototype.getResult = function()
{
if (!this.c_stack) return this.m_stack[0];
if (this.valid != this.c_stack)
{
if (this.valid > this.c_stack)
{
while (this.valid > this.c_stack+1)
{
this.valid--;
this.m_cache.pop();
}
}
else
{
for (var i = this.valid; i <= this.c_stack; i++)
{
this.m_cache[i] = (i==0)?this.m_stack[0]:this.multiply4_4by4_4(this.m_cache[i-1],this.m_stack[i]);
this.valid++;
}
}
this.result = this.m_cache[this.valid-1];
}
return this.result;
}
cubicvr_transform.prototype.pushMatrix = function(m)
{
this.c_stack++;
this.m_stack.push(m?m:this.getIdentity());
}
cubicvr_transform.prototype.popMatrix = function()
{
if (this.c_stack==0) return;
this.c_stack--;
return this.m_stack.pop();
}
cubicvr_transform.prototype.multiply4_4by4_4 = function(m1, m2)
{
var mOut = new Array();
mOut[0] = m2[0]* m1[0]+m2[4]* m1[1]+ m2[8]*m1[2]+ m2[12]*m1[3];
mOut[1] = m2[1]* m1[0]+m2[5]* m1[1]+ m2[9]*m1[2]+ m2[13]*m1[3];
mOut[2] = m2[2]* m1[0]+m2[6]* m1[1]+m2[10]*m1[2]+ m2[14]*m1[3];
mOut[3] = m2[3]* m1[0]+m2[7]* m1[1]+m2[11]*m1[2]+ m2[15]*m1[3];
mOut[4] = m2[0]* m1[4]+m2[4]* m1[5]+ m2[8]*m1[6]+ m2[12]*m1[7];
mOut[5] = m2[1]* m1[4]+m2[5]* m1[5]+ m2[9]*m1[6]+ m2[13]*m1[7];
mOut[6] = m2[2]* m1[4]+m2[6]* m1[5]+m2[10]*m1[6]+ m2[14]*m1[7];
mOut[7] = m2[3]* m1[4]+m2[7]* m1[5]+m2[11]*m1[6]+ m2[15]*m1[7];
mOut[8] = m2[0]* m1[8]+m2[4]* m1[9]+ m2[8]*m1[10]+m2[12]*m1[11];
mOut[9] = m2[1]* m1[8]+m2[5]* m1[9]+ m2[9]*m1[10]+m2[13]*m1[11];
mOut[10] = m2[2]* m1[8]+m2[6]* m1[9]+m2[10]*m1[10]+m2[14]*m1[11];
mOut[11] = m2[3]* m1[8]+m2[7]* m1[9]+m2[11]*m1[10]+m2[15]*m1[11];
mOut[12] = m2[0]*m1[12]+m2[4]*m1[13]+ m2[8]*m1[14]+m2[12]*m1[15];
mOut[13] = m2[1]*m1[12]+m2[5]*m1[13]+ m2[9]*m1[14]+m2[13]*m1[15];
mOut[14] = m2[2]*m1[12]+m2[6]*m1[13]+m2[10]*m1[14]+m2[14]*m1[15];
mOut[15] = m2[3]*m1[12]+m2[7]*m1[13]+m2[11]*m1[14]+m2[15]*m1[15];
return mOut;
}
cubicvr_transform.prototype.m_mat = cubicvr_transform.prototype.multiply4_4by4_4;
cubicvr_transform.prototype.multiply1_4by4_4 = function(m1, m2)
{
var mOut = new Array();
mOut[0] = m2[0]* m1[0]+ m2[4]* m1[1]+ m2[8]* m1[2]+ m2[12]*m1[3];
mOut[1] = m2[1]* m1[0]+ m2[5]* m1[1]+ m2[9]* m1[2]+ m2[13]*m1[3];
mOut[2] = m2[2]* m1[0]+ m2[6]* m1[1]+ m2[10]*m1[2]+ m2[14]*m1[3];
mOut[3] = m2[3]* m1[0]+ m2[7]* m1[1]+ m2[11]*m1[2]+ m2[15]*m1[3];
return mOut;
}
cubicvr_transform.prototype.m_vector = cubicvr_transform.prototype.multiply1_4by4_4;
cubicvr_transform.prototype.multiply1_3by4_4 = function(m1, m2)
{
var mOut = new Array();
mOut[0] = m2[0]* m1[0]+ m2[4]* m1[1]+ m2[8]* m1[2]+ m2[12];
mOut[1] = m2[1]* m1[0]+ m2[5]* m1[1]+ m2[9]* m1[2]+ m2[13];
mOut[2] = m2[2]* m1[0]+ m2[6]* m1[1]+ m2[10]*m1[2]+ m2[14];
return mOut;
}
cubicvr_transform.prototype.m_point = cubicvr_transform.prototype.multiply1_3by4_4;
cubicvr_transform.prototype.translate = function(x, y, z)
{
var m = this.getIdentity();
m[12] = x;
m[13] = y;
m[14] = z;
this.m_stack[this.c_stack] = this.multiply4_4by4_4(this.m_stack[this.c_stack],m);
if (this.valid == this.c_stack && this.c_stack) this.valid--;
}
cubicvr_transform.prototype.scale = function(x, y, z)
{
var m = this.getIdentity();
m[0] = x;
m[5] = y;
m[10] = z;
this.m_stack[this.c_stack] = this.multiply4_4by4_4(this.m_stack[this.c_stack],m);
if (this.valid == this.c_stack && this.c_stack) this.valid--;
}
cubicvr_transform.prototype.rotate = function(ang, x, y, z)
{
var sAng,cAng
if (x||y||z)
{
sAng = Math.sin(ang*(M_PI/180.0));
cAng = Math.cos(ang*(M_PI/180.0));
}
if (x)
{
var X_ROT = this.getIdentity();
X_ROT[5] = cAng*x;
X_ROT[9] = sAng*x;
X_ROT[6] = -sAng*x;
X_ROT[10] = cAng*x;
this.m_stack[this.c_stack] = this.multiply4_4by4_4(this.m_stack[this.c_stack],X_ROT);
}
if (y)
{
var Y_ROT = this.getIdentity();
Y_ROT[0] = cAng*y;
Y_ROT[8] = -sAng*y;
Y_ROT[2] = sAng*y;
Y_ROT[10] = cAng*y;
this.m_stack[this.c_stack] = this.multiply4_4by4_4(this.m_stack[this.c_stack],Y_ROT);
}
if (z)
{
var Z_ROT = this.getIdentity();
Z_ROT[0] = cAng*z;
Z_ROT[4] = sAng*z;
Z_ROT[1] = -sAng*z;
Z_ROT[5] = cAng*z;
this.m_stack[this.c_stack] = this.multiply4_4by4_4(this.m_stack[this.c_stack],Z_ROT);
}
if (this.valid == this.c_stack && this.c_stack) this.valid--;
}
var cubicvr_xyz = function(x,y,z) { return [x?x:0,y?y:0,z?z:0]; }
var cubicvr_rgb = function(r,g,b) { return [r?r:0,g?g:0,b?b:0]; }
var cubicvr_rgba = function(r,g,b,a) { return [r?r:0,g?g:0,b?b:0,a?a:0]; }
var cubicvr_calcNormal = function(pt1,pt2,pt3)
{
var v1 = [pt1[0] - pt2[0], pt1[1] - pt2[1], pt1[2] - pt2[2]];
var v2 = [pt2[0] - pt3[0], pt2[1] - pt3[1], pt2[2] - pt3[2]];
return [v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]];
}
var cubicvr_normalize = function(pt)
{
var d = Math.sqrt(pt[0]*pt[0]+pt[1]*pt[1]+pt[2]*pt[2]);
return [pt[0]/d,pt[1]/d,pt[2]/d];
}
var cubicvr_length = function(pt)
{
return Math.sqrt(pt[0]*pt[0]+pt[1]*pt[1]+pt[2]*pt[2]);
}
var cubicvr_dp = function(v1,v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
var cubicvr_angle = function(v1,v2)
{
return Math.acos( cubicvr_dp(v1,v2) / (cubicvr_length(v1)*cubicvr_length(v2)) );
};
var cubicvr_crossProduct = function(vectA, vectB)
{
return [
vectA[1] * vectB[2] - vectB[1] * vectA[2], vectA[2] * vectB[0] - vectB[2] * vectA[0], vectA[0] * vectB[1] - vectB[0] * vectA[1]
];
};
/* Projection / Modelview matrix manipulation */
var cubicvr_perspective = function(fovy, aspect, near, far)
{
var yFac = Math.tan(fovy * M_PI / 360.0);
var xFac = yFac*aspect;
return [
1.0 / xFac, 0, 0, 0,
0, 1.0 / yFac, 0, 0,
0, 0, -(far+near)/(far-near), -1,
0, 0, -(2.0*far*near)/(far-near), 0
];
}
var cubicvr_lookat = function(eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ)
{
var view_vec = cubicvr_normalize([lookAtX - eyeX, lookAtY - eyeY, lookAtZ - eyeZ]);
var up_vec = cubicvr_normalize([upX, upY, upZ]);
var s = cubicvr_crossProduct(view_vec,up_vec);
var u = cubicvr_crossProduct(s,view_vec);
var mat = [
s[0], u[0], -view_vec[0], 0,
s[1], u[1], -view_vec[1], 0,
s[2], u[2], -view_vec[2], 0,
0, 0, 0, 1
];
trans = new cubicvr_transform();
trans.translate(-eyeX,-eyeY,-eyeZ);
trans.pushMatrix(mat);
mat = trans.getResult();
return mat;
}
var cubicvr_getScriptContents = function(id)
{
var shaderScript = document.getElementById(id);
if (!shaderScript)
{
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k)
{
if (k.nodeType == 3)
{
str += k.textContent;
}
k = k.nextSibling;
}
return str;
}
var cubicvr_compileShader = function(gl, str, type)
{
var shader;
if (type == "x-shader/x-fragment")
{
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (type == "x-shader/x-vertex")
{
shader = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var cubicvr_getShader = function(gl, id)
{
var shaderScript = document.getElementById(id);
if (!shaderScript)
{
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k)
{
if (k.nodeType == 3)
{
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment")
{
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (shaderScript.type == "x-shader/x-vertex")
{
shader = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
/* Faces */
cubicvr_face = function()
{
this.points = new Array();
this.point_normals = new Array();
this.normal = null;
this.material = 0;
this.segment = 0;
}
cubicvr_face.prototype.setUV = function(uvs,point_num)
{
if (typeof(this.uvs) == 'undefined') this.uvs = new Array();
if (typeof(point_num)!='undefined')
{
this.uvs[point_num] = uvs;
}
else
{
if (uvs.length!=2) this.uvs = uvs;
else this.uvs.push(uvs);
}
}
cubicvr_object = function()
{
this.points = new Array(); // point list
this.faces = new Array(); // faces with point references
this.currentFace = -1; // start with no faces
this.currentMaterial = 0; // null material
this.compiled = null; // VBO data
}
cubicvr_object.prototype.addPoint = function(p)
{
if (p.length != 3)
{
for (var i = 0; i < p.length; i++)
{
this.points.push(p[i]);
}
}
else
{
this.points.push(p);
}
return this.points.length-1;
}
cubicvr_object.prototype.setFaceMaterial = function(mat)
{
this.currentMaterial = (typeof(mat)=='object')?mat.material_id:mat;
if (this.currentFace > -1)
{
faces[this.currentFace].material = this.currentMaterial;
}
}
cubicvr_object.prototype.addFace = function(p_list,face_num,face_mat)
{
if (typeof(p_list[0]) != 'number')
{
for (var i in p_list)
{
this.addFace(p_list[i]);
}
return;
}
if (typeof(face_num)=='undefined')
{
this.currentFace = this.faces.length;
this.faces.push(new cubicvr_face());
}
else
{
if (typeof(this.faces[face_num])=='undefined')
{
this.faces[face_num] = new cubicvr_face();
}
this.currentFace = face_num;
}
if (typeof(p_list)=='object')
{
this.faces[this.currentFace].points = p_list;
}
if (typeof(face_mat)!='undefined')
{
this.faces[this.currentFace].material = (typeof(face_mat)=='object')?face_mat.material_id:face_mat;
}
else
{
this.faces[this.currentFace].material = this.currentMaterial;
}
return this.currentFace;
}
cubicvr_object.prototype.triangulateQuads = function()
{
for (var i = 0; i < this.faces.length; i++)
{
if (this.faces[i].points.length == 4)
{
var p = this.faces.length;
this.addFace([this.faces[i].points[2],this.faces[i].points[3],this.faces[i].points[0]],this.faces.length,this.faces[i].material);
this.faces[i].points.pop();
this.faces[p].normal = this.faces[i].normal;
if (typeof(this.faces[i].uvs) != 'undefined')
{
if (this.faces[i].uvs.length == 4)
{
this.faces[p].setUV(this.faces[i].uvs[2],0);
this.faces[p].setUV(this.faces[i].uvs[3],1);
this.faces[p].setUV(this.faces[i].uvs[0],2);
this.faces[i].uvs.pop();
}
}
if (this.faces[i].point_normals.length == 4)
{
this.faces[p].point_normals[0] = this.faces[i].point_normals[2];
this.faces[p].point_normals[1] = this.faces[i].point_normals[3];
this.faces[p].point_normals[2] = this.faces[i].point_normals[0];
this.faces[i].point_normals.pop();
}
}
}
}
cubicvr_object.prototype.calcFaceNormals = function()
{
for (var i = 0; i < this.faces.length; i++)
{
if (this.faces[i].points.length < 3)
{
this.faces[i].normal = [0,0,0];
continue;
}
this.faces[i].normal = cubicvr_normalize(cubicvr_calcNormal(this.points[this.faces[i].points[0]],
this.points[this.faces[i].points[1]],
this.points[this.faces[i].points[2]]));
}
}
cubicvr_object.prototype.calcNormals = function()
{
this.calcFaceNormals();
point_smoothRef = new Array();
// build a quick list of point/face sharing
for (var i = 0; i < this.faces.length; i++)
{
for (var j = 0; j < this.faces[i].points.length; j++)
{
var idx = this.faces[i].points[j];
if (typeof(point_smoothRef[idx])=='undefined') point_smoothRef[idx] = new Array();
point_smoothRef[idx].push([i,j]);
}
}
// step through smoothing references and compute normals
for (var i in point_smoothRef)
{
var numPts = point_smoothRef[i].length;
for (var j = 0; j < numPts; j++)
{
var ptCount = 1;
var faceNum = point_smoothRef[i][j][0];
var pointNum = point_smoothRef[i][j][1];
var max_smooth = CubicVR_Materials[this.faces[faceNum].material].max_smooth;
// set point to it's face's normal
this.faces[faceNum].point_normals[pointNum] = this.faces[faceNum].normal;
// step through all other faces which share this point
for (var k = 0; k < numPts; k++)
{
if (j==k) continue; // don't include self in comparison
var faceRefNum = point_smoothRef[i][k][0];
var ang = cubicvr_angle(this.faces[faceRefNum].normal, this.faces[faceNum].normal);
// note that ang != ang tests for infinity case where the normals are the same
if (ang != ang || ang*(180.0/M_PI) <= max_smooth)
{
this.faces[faceNum].point_normals[pointNum][0] += this.faces[faceRefNum].normal[0];
this.faces[faceNum].point_normals[pointNum][1] += this.faces[faceRefNum].normal[1];
this.faces[faceNum].point_normals[pointNum][2] += this.faces[faceRefNum].normal[2];
ptCount++;
}
}
this.faces[faceNum].point_normals[pointNum][0] /= ptCount;
this.faces[faceNum].point_normals[pointNum][1] /= ptCount;
this.faces[faceNum].point_normals[pointNum][2] /= ptCount;
this.faces[faceNum].point_normals[pointNum] = cubicvr_normalize(this.faces[faceNum].point_normals[pointNum]);
}
}
}
var cubicvr_vtx_eq = function(a,b)
{
if ((typeof(a)=='undefined' && typeof(a)!='undefined') ||
(typeof(b)=='undefined' && typeof(b)!='undefined'))
return false;
if (typeof(a)=='undefined'&&typeof(b)=='undefined') return true;
return (a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2]);
}
var cubicvr_uv_eq = function(a,b)
{
if ((typeof(a)=='undefined' && typeof(a)!='undefined') ||
(typeof(b)=='undefined' && typeof(b)!='undefined'))
return false;
if (typeof(a)=='undefined'&&typeof(b)=='undefined') return true;
return (a[0]==b[0]&&a[1]==b[1]);
}
cubicvr_object.prototype.compile = function()
{
this.compiled = new Object();
var compileRef = new Array();
for (var i = 0; i < this.faces.length; i++)
{
if (this.faces[i].points.length==3)
{
var matId = this.faces[i].material;
var segId = this.faces[i].segment;
if (typeof(compileRef[matId])=='undefined') compileRef[matId] = new Array();
if (typeof(compileRef[matId][segId])=='undefined') compileRef[matId][segId] = new Array();
compileRef[matId][segId].push(i);
}
}
var vtxRef = new Array();
this.compiled.vbo_normals = new Array();
this.compiled.vbo_points = new Array();
this.compiled.vbo_uvs = new Array();
for (var i in compileRef)
{
for (var j in compileRef[i])
{
var idxCount = 0;
for (var k = 0; k < compileRef[i][j].length; k++)
{
var faceNum = compileRef[i][j][k];
var found = false;
var hasUV = false;
var hasNorm = false;
for (var x = 0; x < 3; x++)
{
var ptNum = this.faces[faceNum].points[x];
hasUV = (this.faces[faceNum].uvs.length != 0);
hasNorm = (this.faces[faceNum].point_normals.length != 0);
var foundPt = -1;
if (typeof(vtxRef[ptNum])!='undefined')
{
for (var y = 0; y < vtxRef[ptNum].length; y++)
{
// face / point
var oFace = vtxRef[ptNum][y][0] // faceNum
var oPoint = vtxRef[ptNum][y][1]; // pointNum
var oIndex = vtxRef[ptNum][y][2]; // index
foundPt = oIndex;
if (hasNorm)
{
foundPt = (cubicvr_vtx_eq(
this.faces[oFace].point_normals[oPoint],
this.faces[faceNum].point_normals[x])
)?oIndex:-1;
}
if (hasUV)
{
foundPt = (cubicvr_uv_eq(
this.faces[oFace].uvs[oPoint],
this.faces[faceNum].uvs[x])
)?oIndex:-1;
}
}
}
if (foundPt!=-1)
{
if (typeof(this.compiled.elements)=='undefined') this.compiled.elements = new Array();
if (typeof(this.compiled.elements[i])=='undefined') this.compiled.elements[i] = new Array();
if (typeof(this.compiled.elements[i][j])=='undefined') this.compiled.elements[i][j] = new Array();
this.compiled.elements[i][j].push(foundPt);
}
else
{
this.compiled.vbo_points.push(this.points[ptNum][0]);
this.compiled.vbo_points.push(this.points[ptNum][1]);
this.compiled.vbo_points.push(this.points[ptNum][2]);
if (hasNorm)
{
this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][0]);
this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][1]);
this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][2]);
}
if (hasUV)
{
this.compiled.vbo_uvs.push(this.faces[faceNum].uvs[x][0]);
this.compiled.vbo_uvs.push(this.faces[faceNum].uvs[x][1]);
}
if (typeof(this.compiled.elements)=='undefined') this.compiled.elements = new Array();
if (typeof(this.compiled.elements[i])=='undefined') this.compiled.elements[i] = new Array();
if (typeof(this.compiled.elements[i][j])=='undefined') this.compiled.elements[i][j] = new Array();
this.compiled.elements[i][j].push(idxCount);
if (typeof(vtxRef[ptNum])=='undefined') vtxRef[ptNum] = new Array();
vtxRef[ptNum].push([faceNum,x,idxCount]);
idxCount++;
}
}
}
}
}
this.compiled.gl_points = CubicVR_GLCore.gl.createBuffer();
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, this.compiled.gl_points);
CubicVR_GLCore.gl.bufferData(CubicVR_GLCore.gl.ARRAY_BUFFER, new WebGLFloatArray(this.compiled.vbo_points), CubicVR_GLCore.gl.STATIC_DRAW);
this.compiled.gl_normals = CubicVR_GLCore.gl.createBuffer();
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, this.compiled.gl_normals);
CubicVR_GLCore.gl.bufferData(CubicVR_GLCore.gl.ARRAY_BUFFER, new WebGLFloatArray(this.compiled.vbo_normals), CubicVR_GLCore.gl.STATIC_DRAW);
this.compiled.gl_uvs = CubicVR_GLCore.gl.createBuffer();
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, this.compiled.gl_uvs);
CubicVR_GLCore.gl.bufferData(CubicVR_GLCore.gl.ARRAY_BUFFER, new WebGLFloatArray(this.compiled.vbo_uvs), CubicVR_GLCore.gl.STATIC_DRAW);
var gl_elements = new Array();
for (var i in this.compiled.elements)
{
for (var j in this.compiled.elements[i])
{
for (var k in this.compiled.elements[i][j])
{
gl_elements.push(this.compiled.elements[i][j][k]);
}
}
}
this.compiled.gl_elements = CubicVR_GLCore.gl.createBuffer();
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ELEMENT_ARRAY_BUFFER, this.compiled.gl_elements);
CubicVR_GLCore.gl.bufferData(CubicVR_GLCore.gl.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(gl_elements), CubicVR_GLCore.gl.STATIC_DRAW);
// console.log("vtx Ref: ",vtxRef);
// console.log("vtx Compiled Elems: ",this.compiled);
}
/* Projection enums */
var UV_PROJECTION_UV = 0;
var UV_PROJECTION_PLANAR = 1;
var UV_PROJECTION_CYLINDRICAL = 2;
var UV_PROJECTION_SPHERICAL = 3;
var UV_PROJECTION_CUBIC = 4;
/* Axis enums */
var UV_AXIS_X = 0;
var UV_AXIS_Y = 1;
var UV_AXIS_Z = 2;
cubicvr_uvmapper = function()
{
this.rotation = [0,0,0];
this.scale = [1,1,1];
this.center = [0,0,0];
this.projection_mode = UV_PROJECTION_PLANAR;
this.projection_axis = UV_AXIS_X;
this.wrap_w_count = 1;
this.wrap_h_count = 1;
}
// convert XYZ space to longitude
var xyz_to_h = function(x, y, z)
{
var h
if (x == 0 && z == 0)
{
h = 0;
}
else
{
if (z == 0)
{
h = (x < 0) ? M_HALF_PI : -M_HALF_PI;
}
else if (z < 0)
{
h = -Math.atan(x / z) + M_PI;
}
else
{
h = -Math.atan(x / z);
}
}
return h;
};
// convert XYZ space to latitude and longitude
var xyz_to_hp = function(x,y,z)
{
var h,p;
if (x == 0 && z == 0)
{
h = 0;
if (y != 0)
{
p = (y < 0) ? -M_HALF_PI : M_HALF_PI;
}
else
{
p = 0;
}
}
else
{
if (z == 0)
{
h = (x < 0) ? M_HALF_PI : -M_HALF_PI;
}
else if (z < 0)
{
h = -Math.atan(x / z) + M_PI;
}
else
{
h = -Math.atan(x / z);
}
x = Math.sqrt(x * x + z * z);
if (x == 0)
{
p = (y < 0) ? -M_HALF_PI : M_HALF_PI;
}
else
{
p = Math.atan(y / x);
}
}
return [h,p];
};
cubicvr_uvmapper.prototype.apply = function(obj,mat_num,seg_num)
{
var u,v,s,t,lat,lon;
var trans = new cubicvr_transform();
var transformed = false;
var t_result = null;
if (this.center[0]||this.center[1]||this.center[2])
{
trans.translate(-this.center[0],-this.center[1],-this.center[2]);
transformed = true;
}
if (this.rotation[0]||this.rotation[1]||this.rotation[2])
{
if (this.rotation[0]) trans.rotate(this.rotation[2],0,0,1);
if (this.rotation[1]) trans.rotate(this.rotation[1],0,1,0);
if (this.rotation[2]) trans.rotate(this.rotation[0],1,0,0);
transformed = true;
}
if (transformed) t_result = trans.getResult();
if (typeof(mat_num)=='object') mat_num = mat_num.material_id;
for (var i = 0; i < obj.faces.length; i++)
{
if (obj.faces[i].material != mat_num) continue;
if (typeof(seg_num) != 'undefined') if (obj.faces[i].segment != seg_num) continue;
var nx, ny, nz;
if (this.projection_mode == UV_PROJECTION_CUBIC)
{
nx = Math.abs(obj.faces[i].normal[0]);
ny = Math.abs(obj.faces[i].normal[1]);
nz = Math.abs(obj.faces[i].normal[2]);
}
for (j = 0; j < obj.faces[i].points.length; j++)
{
var uvpoint = obj.points[obj.faces[i].points[j]];
if (transformed) uvpoint = trans.m_point(uvpoint,t_result);
/* calculate the uv for the points referenced by this face's pointref vector */
switch (this.projection_mode)
{
case UV_PROJECTION_CUBIC: /* cubic projection needs to know the surface normal */
/* x portion of vector is dominant, we're mapping in the Y/Z plane */
if (nx >= ny && nx >= nz)
{
/* we use a .5 offset because texture coordinates range from 0->1, so to center it we need to offset by .5 */
s = uvpoint[2] / this.scale[2] + 0.5; /* account for scale here */
t = uvpoint[1] / this.scale[1] + 0.5;
}
/* y portion of vector is dominant, we're mapping in the X/Z plane */
if (ny >= nx && ny >= nz)
{
s = -uvpoint[0] / this.scale[0] + 0.5;
t = uvpoint[2] / this.scale[2] + 0.5;
}
/* z portion of vector is dominant, we're mapping in the X/Y plane */
if (nz >= nx && nz >= ny)
{
s = -uvpoint[0] / this.scale[0] + 0.5;
t = uvpoint[1] / this.scale[1] + 0.5;
}
if (obj.faces[i].normal[0] > 0) { s = -s; }
if (obj.faces[i].normal[1] < 0) { s = -s; }
if (obj.faces[i].normal[2] > 0) { s = -s; }
obj.faces[i].setUV([s,t],j);
break;
case UV_PROJECTION_PLANAR:
s = ((this.projection_axis == UV_AXIS_X) ? uvpoint[2] / this.scale[2] + 0.5 : -uvpoint[0] / this.scale[0] + 0.5);
t = ((this.projection_axis == UV_AXIS_Y) ? uvpoint[2] / this.scale[2] + 0.5 : uvpoint[1] / this.scale[1] + 0.5);
obj.faces[i].setUV([s,t],j);
break;
case UV_PROJECTION_CYLINDRICAL:
// Cylindrical is a little more tricky, we map based on the degree around the center point
switch (this.projection_axis)
{
case UV_AXIS_X:
// xyz_to_h takes the point and returns a value representing the 'unwrapped' height position of this point
lon = xyz_to_h(uvpoint[2],uvpoint[0],-uvpoint[1]);
t = -uvpoint[0] / this.scale[0] + 0.5;
break;
case UV_AXIS_Y:
lon = xyz_to_h(-uvpoint[0],uvpoint[1],uvpoint[2]);
t = -uvpoint[1] / this.scale[1] + 0.5;
break;
case UV_AXIS_Z:
lon = xyz_to_h(-uvpoint[0],uvpoint[2],-uvpoint[1]);
t = -uvpoint[2] / this.scale[2] + 0.5;
break;
}
// convert it from radian space to texture space 0 to 1 * wrap, TWO_PI = 360 degrees
lon = 1.0 - lon / (M_TWO_PI);
if (this.wrap_w_count != 1.0) lon = lon * this.wrap_w_count;
u = lon;
v = t;
obj.faces[i].setUV([u,v],j);
break;
case UV_PROJECTION_SPHERICAL:
var latlon;
// spherical is similar to cylindrical except we also unwrap the 'width'
switch(this.projection_axis)
{
case UV_AXIS_X:
// xyz to hp takes the point value and 'unwraps' the latitude and longitude that projects to that point
latlon = xyz_to_hp(uvpoint[2],uvpoint[0],-uvpoint[1]);
break;
case UV_AXIS_Y:
latlon = xyz_to_hp(uvpoint[0],-uvpoint[1],uvpoint[2]);
break;
case UV_AXIS_Z:
latlon = xyz_to_hp(-uvpoint[0],uvpoint[2],-uvpoint[1]);
break;
}
// convert longitude and latitude to texture space coordinates, multiply by wrap height and width
lon = 1.0 - latlon[0] / M_TWO_PI;
lat = 0.5 - latlon[1] / M_PI;
if (this.wrap_w_count != 1.0) lon = lon * this.wrap_w_count;
if (this.wrap_h_count != 1.0) lat = lat * this.wrap_h_count;
u = lon;
v = lat;
obj.faces[i].setUV([u,v],j);
break;
// case UV_PROJECTION_UV:
// // not handled here..
// break;
default: // else mapping cannot be handled here, this shouldn't have happened :P
u = 0;
v = 0;
obj.faces[i].setUV([u,v],j);
break;
}
}
}
}
var TEXTURE_MAP_COLOR = 0;
var TEXTURE_MAP_SPECULAR = 1;
var TEXTURE_MAP_NORMAL = 2;
var TEXTURE_MAP_BUMP = 3;
var TEXTURE_MAP_REFLECT = 4;
var TEXTURE_MAP_ENVSPHERE = 5;
cubicvr_material = function(mat_name)
{
if (typeof(mat_name)!='undefined')
{
CubicVR_Material_ref[mat_name] = this;
}
this.material_id = CubicVR_Materials.length;
CubicVR_Materials.push(this);
this.diffuse = [0.5,0.5,0.5];
this.specular = [0.5,0.5,0.5];
this.shininess = 1.0;
this.max_smooth = 60.0;
this.initialized = false;
this.textures = new Array();
this.shader = null;
}
cubicvr_material.prototype.setTexture = function(tex,tex_type)
{
if (typeof(tex_type)=='undefined') tex_type = 0;
this.textures[tex_type] = tex;
}
var SHADER_COLOR_MAP = 1;
var SHADER_SPECULAR_MAP = 2;
var SHADER_NORMAL_MAP = 4;
var SHADER_BUMP_MAP = 8;
var SHADER_REFLECT_MAP = 16;
var SHADER_ENVSPHERE_MAP = 32;
cubicvr_material.prototype.calcShaderMask = function()
{
var shader_mask = 0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_COLOR]) != 'undefined')?SHADER_COLOR_MAP:0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_SPECULAR]) != 'undefined')?SHADER_SPECULAR_MAP:0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_NORMAL]) != 'undefined')?SHADER_NORMAL_MAP:0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_BUMP]) != 'undefined')?SHADER_BUMP_MAP:0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_REFLECT]) != 'undefined')?SHADER_REFLECT_MAP:0;
shader_mask = shader_mask & (typeof(this.textures[TEXTURE_MAP_ENVSPHERE]) != 'undefined')?SHADER_ENVSPHERE_MAP:0;
return shader_mask;
}
cubicvr_material.prototype.getShaderHeader = function()
{
return "#define hasColorMap "+((typeof(this.textures[TEXTURE_MAP_COLOR]) != 'undefined')?1:0) +
"\n#define hasSpecularMap "+((typeof(this.textures[TEXTURE_MAP_SPECULAR]) != 'undefined')?1:0) +
"\n#define hasNormalMap "+((typeof(this.textures[TEXTURE_MAP_NORMAL]) != 'undefined')?1:0) +
"\n#define hasBumpMap "+((typeof(this.textures[TEXTURE_MAP_BUMP]) != 'undefined')?1:0) +
"\n#define hasReflectMap "+((typeof(this.textures[TEXTURE_MAP_REFLECT]) != 'undefined')?1:0) +
"\n#define hasEnvSphereMap "+((typeof(this.textures[TEXTURE_MAP_ENVSPHERE]) != 'undefined')?1:0) +
"\n\n";
}
cubicvr_material.prototype.bindObject = function(obj_in)
{
gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, obj_in.compiled.gl_points);
CubicVR_GLCore.gl.vertexAttribPointer(this.shader.uniforms["aVertexPosition"], 3, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, obj_in.compiled.gl_uvs);
if (this.textures.length!=0)
{
CubicVR_GLCore.gl.vertexAttribPointer(this.shader.uniforms["aTextureCoord"], 2, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, obj_in.compiled.gl_normals);
}
CubicVR_GLCore.gl.vertexAttribPointer(this.shader.uniforms["aNormal"], 3, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ELEMENT_ARRAY_BUFFER, obj_in.compiled.gl_elements);
// console.log(obj_in);
}
cubicvr_material.prototype.use = function(tex,tex_type)
{
if (this.shader == null)
{
var smask = this.calcShaderMask();
if (typeof(CubicVR_ShaderPool[smask])=='undefined')
{
var hdr = this.getShaderHeader(tex,tex_type);
var vs = hdr+CubicVR_GLCore.CoreShader_vs;
var fs = hdr+CubicVR_GLCore.CoreShader_fs;
CubicVR_ShaderPool[smask] = new cubicvr_shader(vs,fs);
if (typeof(this.textures[TEXTURE_MAP_COLOR]) != 'undefined') CubicVR_ShaderPool[smask].addInt("colorMap",0);
if (typeof(this.textures[TEXTURE_MAP_SPECULAR]) != 'undefined') CubicVR_ShaderPool[smask].addInt("specularMap",1);
if (typeof(this.textures[TEXTURE_MAP_NORMAL]) != 'undefined') CubicVR_ShaderPool[smask].addInt("normalMap",2);
if (typeof(this.textures[TEXTURE_MAP_BUMP]) != 'undefined') CubicVR_ShaderPool[smask].addInt("bumpMap",3)
if (typeof(this.textures[TEXTURE_MAP_REFLECT]) != 'undefined') CubicVR_ShaderPool[smask].addInt("reflectMap",4)
if (typeof(this.textures[TEXTURE_MAP_ENVSPHERE]) != 'undefined') CubicVR_ShaderPool[smask].addInt("envSphereMap",5)
CubicVR_ShaderPool[smask].addMatrix("uMVMatrix");
CubicVR_ShaderPool[smask].addMatrix("uPMatrix");
CubicVR_ShaderPool[smask].addMatrix("uOMatrix");
CubicVR_ShaderPool[smask].addVertexArray("aVertexPosition");
CubicVR_ShaderPool[smask].addVertexArray("aNormal");
if (this.textures.length!=0)
{
CubicVR_ShaderPool[smask].addUVArray("aTextureCoord");
}
CubicVR_ShaderPool[smask].init();
}
this.shader = CubicVR_ShaderPool[smask];
}
if (typeof(this.textures[TEXTURE_MAP_COLOR]) != 'undefined') this.textures[TEXTURE_MAP_COLOR].use(CubicVR_GLCore.gl.TEXTURE0);
if (typeof(this.textures[TEXTURE_MAP_SPECULAR]) != 'undefined') this.textures[TEXTURE_MAP_SPECULAR].use(CubicVR_GLCore.gl.TEXTURE1);
if (typeof(this.textures[TEXTURE_MAP_NORMAL]) != 'undefined') this.textures[TEXTURE_MAP_NORMAL].use(CubicVR_GLCore.gl.TEXTURE2);
if (typeof(this.textures[TEXTURE_MAP_BUMP]) != 'undefined') this.textures[TEXTURE_MAP_BUMP].use(CubicVR_GLCore.gl.TEXTURE3);
if (typeof(this.textures[TEXTURE_MAP_REFLECT]) != 'undefined') this.textures[TEXTURE_MAP_REFLECT].use(CubicVR_GLCore.gl.TEXTURE4);
if (typeof(this.textures[TEXTURE_MAP_ENVSPHERE]) != 'undefined') this.textures[TEXTURE_MAP_ENVSPHERE].use(CubicVR_GLCore.gl.TEXTURE5);
this.shader.use();
}
var UNIFORM_TYPE_MATRIX = 0;
var UNIFORM_TYPE_VECTOR = 1;
var UNIFORM_TYPE_FLOAT = 2;
var UNIFORM_TYPE_ARRAY_VERTEX = 3;
var UNIFORM_TYPE_ARRAY_UV = 4;
var UNIFORM_TYPE_ARRAY_FLOAT = 5;
var UNIFORM_TYPE_INT = 6;
cubicvr_shader = function(vs_id,fs_id)
{
var vertexShader;
var fragmentShader;
this.uniforms = new Array();
this.uniform_type = new Array();
if (vs_id.indexOf("\n")!=-1)
{
vertexShader = cubicvr_compileShader(CubicVR_GLCore.gl,vs_id,"x-shader/x-vertex");
}
else
{
vertexShader = cubicvr_getShader(CubicVR_GLCore.gl, vs_id);
}
if (fs_id.indexOf("\n")!=-1)
{
fragmentShader = cubicvr_compileShader(CubicVR_GLCore.gl,fs_id,"x-shader/x-fragment");
}
else
{
fragmentShader = cubicvr_getShader(CubicVR_GLCore.gl, fs_id);
}
this.shader = CubicVR_GLCore.gl.createProgram();
CubicVR_GLCore.gl.attachShader(this.shader, vertexShader);
CubicVR_GLCore.gl.attachShader(this.shader, fragmentShader);
CubicVR_GLCore.gl.linkProgram(this.shader);
if (!CubicVR_GLCore.gl.getProgramParameter(this.shader, CubicVR_GLCore.gl.LINK_STATUS))
{
alert("Could not initialise shader vert("+vs_id+"), frag("+fs_id+")");
return;
}
}
cubicvr_shader.prototype.addMatrix = function(uniform_id)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getUniformLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_MATRIX;
}
cubicvr_shader.prototype.addVector = function(uniform_id)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getUniformLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_VECTOR;
}
cubicvr_shader.prototype.addVertexArray = function(uniform_id)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getAttribLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_ARRAY_VERTEX;
}
cubicvr_shader.prototype.addUVArray = function(uniform_id)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getAttribLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_ARRAY_UV;
}
cubicvr_shader.prototype.addFloatArray = function(uniform_id)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getAttribLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_ARRAY_FLOAT;
}
cubicvr_shader.prototype.addInt = function(uniform_id,default_val)
{
this.use();
this.uniforms[uniform_id] = CubicVR_GLCore.gl.getUniformLocation(this.shader, uniform_id);
this.uniform_type[uniform_id] = UNIFORM_TYPE_INT;
if (typeof(default_val)!='undefined')
{
this.setInt(uniform_id,default_val);
}
}
cubicvr_shader.prototype.use = function()
{
CubicVR_GLCore.gl.useProgram(this.shader);
}
cubicvr_shader.prototype.init = function(istate)
{
if (typeof(istate)=='undefined') istate = true;
for (var i in this.uniforms)
{
switch (this.uniform_type[i])
{
case UNIFORM_TYPE_MATRIX:
break;
case UNIFORM_TYPE_VECTOR:
break;
case UNIFORM_TYPE_FLOAT:
break;
case UNIFORM_TYPE_ARRAY_VERTEX:
case UNIFORM_TYPE_ARRAY_UV:
case UNIFORM_TYPE_ARRAY_FLOAT:
if (istate) CubicVR_GLCore.gl.enableVertexAttribArray(this.uniforms[i]);
else CubicVR_GLCore.gl.disableVertexAttribArray(this.uniforms[i]);
break;
}
}
}
cubicvr_shader.prototype.setMatrix = function(uniform_id,mat)
{
CubicVR_GLCore.gl.uniformMatrix4fv(this.uniforms[uniform_id], false, new WebGLFloatArray(mat));
}
cubicvr_shader.prototype.setInt = function(uniform_id,val)
{
CubicVR_GLCore.gl.uniform1i(this.uniforms[uniform_id], val);
}
cubicvr_shader.prototype.setArray = function(uniform_id, buf)
{
switch (this.uniform_type[uniform_id])
{
case UNIFORM_TYPE_ARRAY_VERTEX:
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, buf);
CubicVR_GLCore.gl.vertexAttribPointer(this.uniforms[uniform_id], 3, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
case UNIFORM_TYPE_ARRAY_UV:
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, buf);
CubicVR_GLCore.gl.vertexAttribPointer(this.uniforms[uniform_id], 2, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
case UNIFORM_TYPE_ARRAY_FLOAT:
CubicVR_GLCore.gl.bindBuffer(CubicVR_GLCore.gl.ARRAY_BUFFER, buf);
CubicVR_GLCore.gl.vertexAttribPointer(this.uniforms[uniform_id], 1, CubicVR_GLCore.gl.FLOAT, false, 0, 0);
break;
}
}
cubicvr_texture = function(img_path)
{
this.tex_id = CubicVR_Textures.length;
CubicVR_Textures[this.tex_id] = CubicVR_GLCore.gl.createTexture();
CubicVR_Images[this.tex_id] = new Image();
CubicVR_Texture_ref[img_path] = this.tex_id;
CubicVR_GLCore.gl.bindTexture(CubicVR_GLCore.gl.TEXTURE_2D, CubicVR_Textures[this.tex_id]);
CubicVR_GLCore.gl.texParameteri(CubicVR_GLCore.gl.TEXTURE_2D, CubicVR_GLCore.gl.TEXTURE_MAG_FILTER, CubicVR_GLCore.gl.LINEAR);
CubicVR_GLCore.gl.texParameteri(CubicVR_GLCore.gl.TEXTURE_2D, CubicVR_GLCore.gl.TEXTURE_MIN_FILTER, CubicVR_GLCore.gl.LINEAR);
var texId = this.tex_id;
CubicVR_Images[this.tex_id].onload =
function()
{
CubicVR_GLCore.gl.bindTexture(CubicVR_GLCore.gl.TEXTURE_2D, CubicVR_Textures[texId]);
CubicVR_GLCore.gl.texImage2D(CubicVR_GLCore.gl.TEXTURE_2D, 0, CubicVR_Images[texId], true);
CubicVR_GLCore.gl.bindTexture(CubicVR_GLCore.gl.TEXTURE_2D, null);
}
//cubicvr_initTexture(this.tex_id);
CubicVR_Images[this.tex_id].src = img_path;
this.active_unit = -1;
}
cubicvr_texture.prototype.use = function(tex_unit)
{
CubicVR_GLCore.gl.activeTexture(tex_unit);
CubicVR_GLCore.gl.bindTexture(CubicVR_GLCore.gl.TEXTURE_2D, CubicVR_Textures[this.tex_id]);
this.active_unit = tex_unit;
}
cubicvr_texture.prototype.clear = function()
{
CubicVR_GLCore.gl.activeTexture(tex_unit);
CubicVR_GLCore.gl.bindTexture(CubicVR_GLCore.gl.TEXTURE_2D, null);
this.active_unit = -1;
}
function cubicvr_renderObject(obj_in,mv_matrix,p_matrix,o_matrix)
{
var ofs = 0;
for (i in obj_in.compiled.elements)
{
var mat = CubicVR_Materials[i];
mat.use();
mat.shader.setMatrix("uMVMatrix",mv_matrix);
mat.shader.setMatrix("uPMatrix",p_matrix);
// mat.shader.setMatrix("uOMatrix",o_matrix);
mat.bindObject(obj_in);
for (j in obj_in.compiled.elements[i])
{
var len = obj_in.compiled.elements[i][j].length;
CubicVR.core.gl.drawElements(CubicVR.core.gl.TRIANGLES, len, CubicVR.core.gl.UNSIGNED_SHORT, ofs);
ofs += len;
}
}
}
var LIGHT_TYPE_POINT = 0;
var LIGHT_TYPE_DIRECTIONAL = 1;
var LIGHT_TYPE_SPOT = 2;
var LIGHT_TYPE_AREA = 3;
var CubicVR = {
core: CubicVR_GLCore,
transform: cubicvr_transform,
object: cubicvr_object,
face: cubicvr_face,
material: cubicvr_material,
texture: cubicvr_texture,
uvmapper: cubicvr_uvmapper,
xyz: cubicvr_xyz,
rgb: cubicvr_rgb,
rgba: cubicvr_rgba,
shader: cubicvr_shader,
perspective: cubicvr_perspective,
lookat: cubicvr_lookat,
renderObject: cubicvr_renderObject
};
CubicVR_Materials.push(new cubicvr_material("(null)"));
/*
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title></title>
<script src="CubicVR.js" type="text/javascript"></script>
<script id="core-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aNormal;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec2 vTextureCoord;
varying vec3 vNormal;
#if hasBumpMap
varying vec3 eyeVec;
// varying vec3 u;
// varying vec3 v_n;
#endif
void main(void)
{
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
vNormal = aNormal;
#if hasBumpMap
vec3 tangent;
vec3 binormal;
vec3 c1 = cross( aNormal, vec3(0.0, 0.0, 1.0) );
vec3 c2 = cross( aNormal, vec3(0.0, 1.0, 0.0) );
if( length(c1)>length(c2) )
{
tangent = c1;
}
else
{
tangent = c2;
}
tangent = normalize(tangent);
binormal = cross(aNormal, tangent);
binormal = normalize(binormal);
mat3 TBNMatrix = mat3( (vec3 (uMVMatrix * vec4 (tangent, 0.0))), (vec3 (uMVMatrix * vec4 (binormal, 0.0))), (vec3 (uMVMatrix * vec4 (aNormal, 0.0))));
eyeVec = vec3(uMVMatrix * vec4(aVertexPosition, 1.0)) * TBNMatrix;
#endif
}
</script>
<script id="core-shader-fs" type="x-shader/x-fragment">
varying vec3 vNormal;
varying vec2 vTextureCoord;
#if hasColorMap
uniform sampler2D colorMap;
#endif
#if hasBumpMap
varying vec3 eyeVec;
// varying vec3 u;
// varying vec3 v_n;
uniform sampler2D bumpMap;
#endif
void main(void)
{
#if hasBumpMap
float height = texture2D(bumpMap, vTextureCoord.xy).r;
float v = (height) * 0.05 - 0.04; // * scale and - bias
vec3 eye = normalize(eyeVec);
vec2 texCoord = vTextureCoord.xy + (eye.xy * v);
#else
vec2 texCoord = vTextureCoord;
#endif
#if hasColorMap
gl_FragColor = texture2D(colorMap, vec2(texCoord.s, texCoord.t));
#else
gl_FragColor = vec4(1.0,0.0,1.0,0.0);
#endif
//gl_FragColor = vec4(1.0,0.0,1.0,0.0);
}
</script>
<script type='text/javascript'>
function makeBox(boxObj, box_size, box_mat)
{
var half_box = box_size/2.0;
boxObj.setFaceMaterial(box_mat);
boxObj.addPoint([
[ half_box,-half_box, half_box],
[ half_box, half_box, half_box],
[-half_box, half_box, half_box],
[-half_box,-half_box, half_box],
[ half_box,-half_box,-half_box],
[ half_box, half_box,-half_box],
[-half_box, half_box,-half_box],
[-half_box,-half_box,-half_box]
]);
boxObj.addFace([
[0,1,2,3],
[7,6,5,4],
[4,5,1,0],
[5,6,2,1],
[6,7,3,2],
[7,4,0,3]
]);
boxObj.calcNormals();
}
var obj_test;
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewport(0, 0, canvas.width, canvas.height);
} catch(e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
CubicVR.core.init(gl,"core-shader-vs","core-shader-fs");
}
var shaderProgram = null;
var texSet = new Array()
var boxMaterial = null;
function webGLStart()
{
var canvas = document.getElementById("cubicvr-canvas");
initGL(canvas);
obj_test = new CubicVR.object();
// Make a material named test
boxMaterial = new CubicVR.material("box");
// Build a box, set face material to boxMaterial
makeBox(obj_test,1.0,boxMaterial);
// Create a UV Mapper and apply it to boxMaterial
boxMaterialMap = new CubicVR.uvmapper();
boxMaterialMap.projection_mode = UV_PROJECTION_CUBIC;
boxMaterialMap.scale = [0.5,0.5,0.5];
boxMaterialMap.apply(obj_test,boxMaterial);
obj_test.triangulateQuads();
obj_test.compile();
texSet.push([new CubicVR.texture("2576-diffuse.jpg"),new CubicVR.texture("2576-bump.jpg")]);
texSet.push([new CubicVR.texture("2282-diffuse.jpg"),new CubicVR.texture("2282-bump.jpg")]);
texSet.push([new CubicVR.texture("4734-diffuse.jpg"),new CubicVR.texture("4734-bump.jpg")]);
texSet.push([new CubicVR.texture("1422-diffuse.jpg"),new CubicVR.texture("1422-bump.jpg")]);
boxMaterial.setTexture(texSet[0][0],TEXTURE_MAP_COLOR);
boxMaterial.setTexture(texSet[0][1],TEXTURE_MAP_BUMP);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
setInterval(drawScene, 30);
}
var xp = 0;
var activeTex = 0;
var lastTex = -1;
function drawScene()
{
xp += 0.01;
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (activeTex != lastTex)
{
boxMaterial.setTexture(texSet[activeTex][0],TEXTURE_MAP_COLOR);
boxMaterial.setTexture(texSet[activeTex][1],TEXTURE_MAP_BUMP);
}
modelViewMat = CubicVR.lookat(1.0*Math.sin(xp), 1.0*Math.sin(xp), 1.0*Math.cos(xp), 0, 0, 0, 0, 1, 0);
projectionMat = CubicVR.perspective(40, 1.0, 0.1, 100.0);
CubicVR.renderObject(obj_test,modelViewMat,projectionMat,null);
}
</script>
</head>
<body onLoad="webGLStart();">
<div style='font-family:Arial;font-size:11px'>Parallax Test</div>
<div style='font-family:Arial;font-size:12px'><strong>Texture chooser:</strong>
<input type='button' value='Hex Tile' onclick='activeTex=0'>
<input type='button' value='Hex Tile 2' onclick='activeTex=1'>
<input type='button' value='Rock' onclick='activeTex=2'>
<input type='button' value='Grille' onclick='activeTex=3'>
</div>
<div><canvas id="cubicvr-canvas" style="border: none;" width="640" height="640"></canvas></div>
<div style='font-family:Arial;font-size:11px'>Javascript port of CubicVR 3D Engine by Charles J. Cliffe - <a href="http://www.cubicvr.org/">http://www.cubicvr.org/</a></div>
</body>
</html>
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment