-
-
Save cjcliffe/372115 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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