/**
* Create a renderer object working fully in WebGL
* Here is a sample set of command to illustrate how to use this renderer
*
* var renderer = new WebGLRenderer('rendererId','http://localhost:8080/ParaViewWebService')
* renderer.init(sessionId, viewId);
* renderer.bindToElementId('containerID'); // => Add a WebGL canvas inside a div tag id 'containerID'
* renderer.start();
*
* renderer.init(otherSessionId, otherViewId);
* renderer.view.width = '100';
* renderer.view.height = '400';
* renderer.setSize('100', '400');
*
* renderer.unbindToElementId('containerID');
*/
// Global object to keep track of WebGL renderers
var webglRenderers = new Object();
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 60);
};
})();
function WebGLRenderer(rendererId, coreServiceURL) {
this.baseURL = coreServiceURL + "/WebGL";
this.rendererId = rendererId;
this.sessionId = "";
this.viewId = "";
this.nbError = 0;
this.localTimeStamp = 0;
this.offlineMode = false;
this.setServerMode(false);
this.forceSquareSize = false;
this.view = new Object();
this.view.width = 100;
this.view.height = 100;
this.view.id = rendererId;
this.view.alt = "ParaView Renderer";
//Default Shaders
this.view.shaderfs = document.createElement("script");
this.view.shaderfs.id = "shader-fs";
this.view.shaderfs.type = "x-shader/x-fragment";
this.view.shaderfs.innerHTML = "\
#ifdef GL_ES\n\
precision highp float;\n\
#endif\n\
uniform bool uIsLine;\
varying vec4 vColor;\
varying vec4 vTransformedNormal;\
varying vec4 vPosition;\
void main(void) {\
float directionalLightWeighting1 = max(dot(normalize(vTransformedNormal.xyz), vec3(0.0, 0.0, 1.0)), 0.0); \
float directionalLightWeighting2 = max(dot(normalize(vTransformedNormal.xyz), vec3(0.0, 0.0, -1.0)), 0.0);\
vec3 lightWeighting = max(vec3(1.0, 1.0, 1.0) * directionalLightWeighting1, vec3(1.0, 1.0, 1.0) * directionalLightWeighting2);\
if (uIsLine == false){\
gl_FragColor = vec4(vColor.rgb * lightWeighting, vColor.a);\
} else {\
gl_FragColor = vColor*vec4(1.0, 1.0, 1.0, 1.0);\
}\
}";
this.view.shadervs = document.createElement("script");
this.view.shadervs.id = "shader-vs";
this.view.shadervs.type = "x-shader/x-vertex";
this.view.shadervs.innerHTML = "\
attribute vec3 aVertexPosition;\
attribute vec4 aVertexColor;\
attribute vec3 aVertexNormal;\
uniform mat4 uMVMatrix;\
uniform mat4 uPMatrix;\
uniform mat4 uNMatrix;\
varying vec4 vColor;\
varying vec4 vPosition;\
varying vec4 vTransformedNormal;\
void main(void) {\
vPosition = uMVMatrix * vec4(aVertexPosition, 1.0);\
gl_Position = uPMatrix * vPosition;\
vTransformedNormal = uNMatrix * vec4(aVertexNormal, 1.0);\
vColor = aVertexColor;\
}";
// Point Shaders
this.view.shaderfsPoint = document.createElement("script");
this.view.shaderfsPoint.id = "shader-fs-Point";
this.view.shaderfsPoint.type = "x-shader/x-fragment";
this.view.shaderfsPoint.innerHTML = "\
#ifdef GL_ES\n\
precision highp float;\n\
#endif\n\
varying vec4 vColor;\
void main(void) {\
gl_FragColor = vColor;\
}";
this.view.shadervsPoint = document.createElement("script");
this.view.shadervsPoint.id = "shader-vs-Point";
this.view.shadervsPoint.type = "x-shader/x-vertex";
this.view.shadervsPoint.innerHTML = "\
attribute vec3 aVertexPosition;\
attribute vec4 aVertexColor;\
uniform mat4 uMVMatrix;\
uniform mat4 uPMatrix;\
uniform mat4 uNMatrix;\
uniform float uPointSize;\
varying vec4 vColor;\
void main(void) {\
vec4 pos = uMVMatrix * vec4(aVertexPosition, 1.0);\
gl_Position = uPMatrix * pos;\
vColor = aVertexColor*vec4(1.0, 1.0, 1.0, 1.0);\
gl_PointSize = uPointSize;\
}";
//
this.canvasName = "glcanvas" + rendererId;
this.view.html = '
';
this.view.html += '
';
this.fps = 0;
// Register in global var
webglRenderers[rendererId] = this;
}
WebGLRenderer.prototype.bindToElementId = function (elementId) {
this.oldInnerHTML = document.getElementById(elementId).innerHTML;
document.getElementById(elementId).innerHTML = this.view.html;
document.getElementById(elementId).appendChild(this.view.shaderfs);
document.getElementById(elementId).appendChild(this.view.shadervs);
document.getElementById(elementId).appendChild(this.view.shaderfsPoint);
document.getElementById(elementId).appendChild(this.view.shadervsPoint);
}
WebGLRenderer.prototype.unbindToElementId = function (elementId) {
document.getElementById(elementId).innerHTML = this.oldInnerHTML;
clearTimeout(this.drawInterval);
if (typeof(paraview) != "undefined") paraview.updateConfiguration(true, "JPEG", "NO");
}
WebGLRenderer.prototype.setOfflineMode = function (mode) {
this.offlineMode = mode;
this.requestMetaData();
}
WebGLRenderer.prototype.bindToElement = function (element) {
this.oldInnerHTML = element.innerHTML;
element.innerHTML = this.view.html;
element.appendChild(this.view.shaderfs);
element.appendChild(this.view.shadervs);
element.appendChild(this.view.shaderfsPoint);
element.appendChild(this.view.shadervsPoint);
}
WebGLRenderer.prototype.unbindToElement = function (element) {
element.innerHTML = this.oldInnerHTML;
clearTimeout(this.drawInterval);
if (typeof(paraview) != "undefined") paraview.updateConfiguration(true, "JPEG", "NO");
}
WebGLRenderer.prototype.init = function (sessionId, viewId) {
this.sessionId = sessionId;
this.viewId = viewId;
}
WebGLRenderer.prototype.start = function(metadata, objects) {
if (typeof(renderers) == "undefined"){
renderers = Object();
renderers.current = this;
}
if (typeof(paraview) != "undefined") paraview.updateConfiguration(true, "JPEG", "WebGL");
canvas = document.getElementById(this.canvasName);
canvas.width = this.view.width;
canvas.height = this.view.height;
this.hasSceneChanged = true; //Scene Graph Has Changed
this.oldCamPos = null; //Last Known Camera Position
this.sceneJSON = null; //Current Scene Graph
this.up = [];
this.right = [];
this.z_dir = [];
this.objects = []; //List of objects
this.nbErrors = 0; //Number of Errors
this.background = null; //Background object: mesh, normals, colors, render
this.interactionRatio = 2;
this.requestInterval = 250; //Frequency it request new data from the server
this.requestOldInterval = 250; //
this.updateInterval = 100; //Frequency the server will be updated
this.fps = 0;
this.frames = 0;
this.lastTime = new Date().getTime();
this.view.aspectRatio = 1;
this.lookAt = [0,0,0,0,1,0,0,0,1];
this.offlineMode = !(typeof(metadata)=="undefined" || typeof(objects)=="undefined");
this.cachedObjects = []; //List of Cached Objects
this.isCaching = false; //Is Caching or Not
this.processQueue = []; //List of process to be executed
this.objScale = 1.0; //Scale applied locally in the scene
this.translation = [0.0, 0.0, 0.0]; //Translation
this.rotMatrix = mat4.create(); //Rotation Matrix
mat4.identity(this.rotMatrix);
this.rotMatrix2 = mat4.create(this.rotMatrix);
this.mouseDown = false;
this.lastMouseX = 0;
this.lastMouseY = 0;
this.mvMatrix = mat4.create(this.rotMatrix);
this.pMatrix = mat4.create(this.rotMatrix);
// Initialize the GL context
this.gl = null;
try {
this.gl = canvas.getContext("experimental-webgl");
this.gl.viewportWidth = this.view.width;
this.gl.viewportHeight = this.view.height;
} catch(e) {}
if (this.gl) {
this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.gl.clearDepth(1.0);
this.gl.enable(this.gl.DEPTH_TEST);
this.gl.depthFunc(this.gl.LEQUAL);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
this.initShaders();
this.ctx2d = document.getElementById(this.canvasName + "Widget").getContext('2d');
// Set up to draw the scene periodically.
this.drawInterval = requestAnimFrame(new Function("webglRenderers['" + this.view.id + "'].drawScene();"));
if (!this.offlineMode){
this.requestMetaData();
this.updateCamera();
} else {
this.sceneJSON = JSON.parse(metadata);
for(aw=0; aw height) height = width;
else width = height;
}
this.view.width = width;
this.view.height = height;
canvas = document.getElementById(this.canvasName);
canvasWidget = document.getElementById(this.canvasName + "Widget");
if (canvas){
canvas.width = this.view.width;
canvas.height = this.view.height;
canvasWidget.width = this.view.width;
canvasWidget.height = this.view.height;
if (typeof(this.gl) != "undefined" && this.gl != null){
if (!this.offlineMode) updateRendererSize(this.sessionId, this.viewId, width, height);
this.gl.viewportWidth = this.view.width;
this.gl.viewportHeight = this.view.height;
}
left = 0; tt = 0;
if (this.forceSquareSize){
left = Math.round((w-this.view.width)/2);
tt = Math.round((h-this.view.height)/2);
}
this.view.left = left;
this.view.top = top;
if(this.forceSquareSize == true){
canvas.setAttribute("style", "position: absolute; overflow: hidden; left: " + left + "px; top: " + tt + "px; right: 0px; z-index:0;");
canvasWidget.setAttribute("style", "position: absolute; overflow: hidden; left: " + left + "px; top: " + tt + "px; right: 0px; z-index:1;");
} else {
canvas.setAttribute("style", "overflow: hidden; left: " + left + "px; top: " + tt + "px; right: 0px; z-index:0;");
canvasWidget.setAttribute("style", "position: absolute; overflow: hidden; left: " + left + "px; top: " + tt + "px; right: 0px; z-index:1;");
}
}
}
WebGLRenderer.prototype.requestMetaData = function() {
if (this.mouseDown || renderers.current != this) return;
if (this.offlineMode) return;
interval = this.requestInterval;
if (this.serverMode) interval = interval/2;
this.timer = setTimeout("webglRenderers[\'" + this.view.id + "\'].requestMetaData()", interval);
var request = new XMLHttpRequest();
request.requester = this;
filename = this.baseURL + "?sid=" + this.sessionId + "&vid=" + this.viewId + "&q=meta";
try {
request.open("GET", filename, false);
request.overrideMimeType('text/plain; charset=x-user-defined');
request.onreadystatechange = function() {
if(this.requester.mouseDown) return;
if (request.status != 200) this.requester.nbErrors++
else if (request.readyState == 4) {
aux = JSON.parse(request.responseText);
this.requester.hasSceneChanged = JSON.stringify(aux)!=JSON.stringify(this.requester.sceneJSON);
this.requester.sceneJSON = JSON.parse(request.responseText);
if (this.requester.hasSceneChanged) this.requester.updateScene();
}
}
request.send();
} catch (e) {
this.nbErrors++;
}
}
WebGLRenderer.prototype.updateScene = function(){
if (typeof(this.sceneJSON) == "undefined" || this.sceneJSON == null) return;
c1 = [0,0,0];
c2 = [0,0,0];
for(l=0; l= 50 && this.nbErrors < 5){
this.frames = 0;
ko = new Date();
currTime = ko.getTime();
diff = currTime - this.lastTime;
this.lastTime = currTime;
this.fps = 50000/diff;
}
this.processObject();
this.gl.viewport(0, 0, this.gl.viewportWidth, this.gl.viewportHeight);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
mat4.ortho(-1.0, 1.0, -1.0, 1.0, 1.0, 1000000.0, this.pMatrix);
mat4.identity(this.mvMatrix);
this.gl.disable(this.gl.DEPTH_TEST);
this.renderBackground();
this.gl.enable(this.gl.DEPTH_TEST);
this.ctx2d.clearRect(0, 0, this.view.width, this.view.height);
for(rr=this.sceneJSON.Renderers.length-1; rr>=0 ; rr--){
renderer = this.sceneJSON.Renderers[rr];
width = renderer.size[0]-renderer.origin[0];
height = renderer.size[1]-renderer.origin[1];
width = width*this.view.width;
height = height*this.view.height;
x = renderer.origin[0]*this.view.width;
y = renderer.origin[1]*this.view.height;
if (y < 0) y = 0;
this.gl.viewport(x, y, width, height);
//this.gl.clear(this.gl.DEPTH_BUFFER_BIT);
mat4.perspective(renderer.LookAt[0], width/height, 0.1, 1000000.0, this.pMatrix);
mat4.identity(this.mvMatrix);
mat4.lookAt([renderer.LookAt[7], renderer.LookAt[8], renderer.LookAt[9]],
[renderer.LookAt[1], renderer.LookAt[2], renderer.LookAt[3]],
[renderer.LookAt[4], renderer.LookAt[5], renderer.LookAt[6]],
this.mvMatrix);
for(r=0; r