Commits

Diego Cantor committed 9b76b4a

Jan 29th 2012 Chapter 8 code updated

  • Participants
  • Parent commits 0e821d8

Comments (0)

Files changed (12)

File 1727_08.zip

Binary file removed.

File 1727_08/ch8_Picking.html

     gl.clearDepth(100.0);
     gl.enable(gl.DEPTH_TEST);
     gl.depthFunc(gl.LESS);
+	gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);
     
     //Creates and sets up the camera location
     camera = new Camera(CAMERA_ORBITING_TYPE);
     camera.setFocus([0.0,0.0,0.0]);
     camera.setElevation(-40);
     camera.setAzimuth(-30);
-    camera.hookRenderer = draw;
+    camera.hookRenderer = render;
     
     
     var canvas  = document.getElementById('canvas-element-id');
     
     //Scene Picker
     picker = new Picker(canvas);
+    picker.processHitsCallback = processHits;
+    picker.addHitCallback      = addHit;
+    picker.removeHitCallback   = removeHit;
+    picker.hitPropertyCallback = hitProperty;
+    picker.moveCallback        = movePickedObjects;
     
     //Creates and sets up the mouse and keyboard interactor
     interactor = new CameraInteractor(camera, canvas);
     gl.uniform1f(Program.uAlpha, 1.0);
 }
 
-var createTexture = function(o){
-    if (o.image != null){
-        o.texture = new Texture(o.image);
-    }
-}
-
 /**
 * Loads the scene
 */
     Floor.build(80,2);
     Scene.addObject(Floor);
     Scene.loadObject('models/geometry/ball.json',   'ball', {position:[  0, 0, -4],    scale:[3,3,3]});
-    Scene.loadObject('models/geometry/ball.json',   'ball2',{position:[  -10, 0, -10], scale:[3,0.5,3],  diffuse:[0.3,0.1,0.9,1.0]});
+    Scene.loadObject('models/geometry/ball.json',   'disk',{position:[  -10, 0, -10], scale:[3,0.5,3],  diffuse:[0.3,0.1,0.9,0.5]});
     Scene.loadObject('models/geometry/flag.json',   'flag', {position:[-10, 0 ,0],     scale:[1,1,1]});
     Scene.loadObject('models/geometry/cone.json',   'cone', {position:[ 10, 0, 5],     scale:[1,1,1]});
     Scene.loadObject('models/geometry/cone.json',   'cone2',{position:[ -7, 0, 2],     scale:[0.5,1,0.5], diffuse:[0.3,0.3,0.6,1.0]});
-    Scene.loadObject('models/geometry/texCube.json','cube', {position:[1,2,7],         scale:[4,4,4],     ambient:[0.4,0.4,0.4,1.0]}, createTexture);
+    Scene.loadObject('models/geometry/texCube.json','cube', {position:[1,2,7],         scale:[4,4,4],     ambient:[0.4,0.4,0.4,1.0]});
 }
 
 
 
-function draw2(){
-    if (!interactor.picking){
-        //off-screen rendering
-        gl.bindFramebuffer(gl.FRAMEBUFFER, picker.framebuffer);
-        gl.uniform1i(Program.uOffscreen, true);
-        draw();
-    }
-    
+function render(){
+    //off-screen rendering
+    gl.bindFramebuffer(gl.FRAMEBUFFER, picker.framebuffer);
+    gl.uniform1i(Program.uOffscreen, true);
+    draw();
     //on-screen rendering
     gl.uniform1i(Program.uOffscreen, showPickingImage);
     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
     draw();
 }
 
+function hitProperty(ob){
+    return ob.diffuse;
+}
+
+function addHit(ob){
+ ob.previous = ob.diffuse.slice(0);     
+ ob.diffuse[3] = 0.5;
+ render();
+}
+
+function removeHit(ob){
+    ob.diffuse = ob.previous.slice(0);
+    render();
+
+}
+
+function processHits(hits){
+    var names = '';
+    for(var i = 0; i < hits.length; i++){
+        var ob = hits[i];
+        ob.diffuse = ob.previous;
+        names += ob.alias + ' ';
+    }
+    render();
+    alert('You picked: ' + names);
+}
+
+function movePickedObjects(interactor,dx,dy){
+    
+    if (picker.plist.length == 0) return;
+    
+    var camera = interactor.camera;
+    var depth = (interactor.alt!=0);
+    
+    for (var i = 0, max = picker.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        var pos = vec3.create([ob.position[0], ob.position[1], ob.position[2]]);
+        
+        var scaleY = vec3.create();
+        var scaleX = vec3.create();
+        
+        var factor = Math.max(Math.max(camera.position[0], camera.position[1]), camera.position[2])/1000;
+       
+        if (!depth){
+            vec3.scale(camera.up,   -dy * factor, scaleY);
+            vec3.scale(camera.right, dx * factor, scaleX);
+        }
+        else{
+            vec3.scale(camera.normal, dy * factor, scaleY);
+        }
+
+        vec3.add(pos, scaleY);
+        vec3.add(pos, scaleX);
+        
+        ob.position[0] = pos[0];
+        ob.position[1] = pos[1];
+        ob.position[2] = pos[2];
+    }
+    render();
+}
 
 
 /**
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     transforms.updatePerspective();
     try{
+        var offscreen  = Program.getUniform(Program.uOffscreen);
+        
         for (var i = 0; i < Scene.objects.length; i++){
                 
             var object = Scene.objects[i];
+            
+            if (object.alias == 'floor' && (showPickingImage || offscreen)){
+                continue;
+            }
+            
+            if(object.diffuse[3] < 1.0 && !offscreen) {
+				gl.disable(gl.DEPTH_TEST);
+				gl.enable(gl.BLEND);
+			} else {
+				gl.enable(gl.DEPTH_TEST);
+				gl.disable(gl.BLEND);
+			}
 
             transforms.calculateModelView();           
             transforms.push();
             gl.bindBuffer(gl.ARRAY_BUFFER, object.vbo);
             gl.vertexAttribPointer(Program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
             gl.enableVertexAttribArray(Program.aVertexPosition);
-            
-
-            var offscreen  = Program.getUniform(Program.uOffscreen);
-            
-            
+           
             if(!offscreen && !showPickingImage){
                 //render scalars
                 if (object.scalars != null){
 */
 var app = null;
 function runWebGLApp() {
-    app = new WebGLApp("canvas-element-id")
+    app = new WebGLApp("canvas-element-id");
     app.configureGLHook = configure;
     app.loadSceneHook   = load;
-    app.drawSceneHook   = draw2;
+    app.drawSceneHook   = render;
     app.run();
 }
 </script>
 $('#reset-btn').click(function(){
     
     Scene.getObject('ball').position    = [  0,   0,  -4];
-    Scene.getObject('ball2').position   = [-10,   0, -10];
+    Scene.getObject('disk').position   = [-10,   0, -10];
     Scene.getObject('flag').position    = [-10,   0 ,  0];
     Scene.getObject('cone').position    = [ 10,   0,   5];
     Scene.getObject('cone2').position   = [ -7,   0,   2];

File 1727_08/ch8_Picking_Final.html

+<html>
+
+<head>
+<title>WebGL Beginner's Guide - Chapter 8 - Basic Picking</title>
+<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>
+
+<!-- CSS Styles //-->
+<link href='css/styles.css'   type='text/css' rel='stylesheet'>
+<link href='css/prettify_desert.css'  type='text/css' rel='stylesheet'/>
+<link href='css/colorpicker.css'  type='text/css' rel='stylesheet'/>
+
+<link href='css/smoothness/jquery-ui-1.8.13.custom.css' type='text/css' rel='stylesheet' />
+<!-- GUI Libraries //-->
+<script type='text/javascript' src='js/gui/jquery-1.5.1.min.js'></script>
+<script type='text/javascript' src='js/gui/jquery-ui-1.8.13.custom.min.js'></script> 
+<script type='text/javascript' src='js/gui/colorpicker.js'></script>
+<script type='text/javascript' src='js/gui/prettify.js'></script>
+<script type='text/javascript' src='js/gui/codeview.js'></script>
+<!-- MATH Libraries //-->
+<script type='text/javascript' src='js/math/glMatrix-0.9.5.min.js'></script>
+<!-- WEBGL Libraries //-->
+<script type='text/javascript' src='js/webgl/Globals.js'></script>
+<script type='text/javascript' src='js/webgl/Utils.js'></script>
+<script type='text/javascript' src='js/webgl/Program.js'></script>
+<script type='text/javascript' src='js/webgl/Scene.js'></script>
+<script type='text/javascript' src='js/webgl/Axis.js'></script>
+<script type='text/javascript' src='js/webgl/Floor.js'></script>
+<script type='text/javascript' src='js/webgl/Camera.js'></script>
+<script type='text/javascript' src='js/webgl/CameraInteractor.js'></script>
+<script type='text/javascript' src='js/webgl/SceneTransforms.js'></script>
+<script type='text/javascript' src='js/webgl/Texture.js'></script>
+<script type='text/javascript' src='js/webgl/WebGLApp.js'></script>
+<script type='text/javascript' src='js/webgl/Picker.js'></script>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+
+attribute vec3 aVertexPosition;
+attribute vec3 aVertexNormal;
+attribute vec4 aVertexColor;
+attribute vec2 aVertexTextureCoords;
+
+uniform mat4 uMVMatrix;
+uniform mat4 uPMatrix;
+uniform mat4 uNMatrix;
+uniform vec3 uLightPosition;
+uniform vec4 uMaterialDiffuse;
+uniform bool uWireframe;
+uniform bool uUseVertexColor;
+uniform bool uUseTextures;
+
+varying vec3 vNormal;
+varying vec3 vLightRay;
+varying vec3 vEyeVec;
+varying vec4 vFinalColor;
+varying vec2 vTextureCoord;
+
+void main(void) {
+    
+ vFinalColor = uMaterialDiffuse;
+ vTextureCoord = vec2(0.0);
+
+ if (uUseVertexColor){
+    vFinalColor = aVertexColor;
+ }
+ 
+ if (uUseTextures){
+    vTextureCoord = aVertexTextureCoords;
+ }
+
+ vec4 vertex = uMVMatrix * vec4(aVertexPosition, 1.0);
+ vNormal = vec3(uNMatrix * vec4(aVertexNormal, 1.0));
+ vec4 light = vec4(uLightPosition,1.0);
+ vLightRay = vertex.xyz-light.xyz;
+ vEyeVec = -vec3(vertex.xyz);
+ 
+ gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
+ 
+}	
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+
+uniform bool uWireframe;
+uniform bool uUseTextures; 
+
+uniform vec4 uLightAmbient;
+uniform vec4 uLightDiffuse;
+uniform vec4 uMaterialAmbient;
+uniform vec4 uMaterialDiffuse;
+uniform vec4 uPickingColor;
+uniform bool uOffscreen;  
+
+uniform sampler2D uSampler;  
+
+varying vec3 vNormal; 
+varying vec3 vLightRay;
+varying vec3 vEyeVec;
+varying vec4 vFinalColor;
+varying vec2 vTextureCoord;
+
+void main(void)
+{
+    if(uOffscreen){
+        gl_FragColor = uPickingColor;
+        return;
+    }
+    
+    if(uWireframe){
+        gl_FragColor = vFinalColor;
+    }
+    else{
+        //ambient term
+        vec4 Ia = uLightAmbient * uMaterialAmbient;
+        
+        //diffuse term
+        vec3 L = normalize(vLightRay);
+        vec3 N = normalize(vNormal);
+        float lambertTerm = max(dot(N,-L),0.33);
+        vec4 Id = uLightDiffuse * uMaterialDiffuse * lambertTerm; 
+        
+        //specular term
+        vec3 E = normalize(vEyeVec);
+        vec3 R = reflect(L, N);
+        float specular = pow( max(dot(R, E), 0.5), 50.0);
+        vec4 Is = vec4(0.5) * specular;
+
+        //result
+        vec4 finalColor = Ia + Id + Is;
+        
+        if (uMaterialDiffuse.a != 1.0) {   
+            finalColor.a = uMaterialDiffuse.a; 
+        }
+        else {
+            finalColor.a = 1.0;
+        }
+       
+        if (uUseTextures){
+            gl_FragColor =  finalColor * texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
+        }
+        else{
+            gl_FragColor = finalColor;
+        }
+    }
+
+}
+</script>
+
+<script id='code-js' type="text/javascript">
+
+var camera 		= null;
+var interactor 	= null;
+var picker 		= null;
+var transforms	= null;
+var showPickingImage 	= false;
+
+
+function configure(){
+    gl.clearColor(0.3,0.3,0.3, 1.0);
+    gl.clearDepth(100.0);
+    gl.enable(gl.DEPTH_TEST);
+    gl.depthFunc(gl.LESS);
+	gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);
+    
+    //Creates and sets up the camera location
+    camera = new Camera(CAMERA_ORBITING_TYPE);
+    camera.goHome([0,0,192]);
+    camera.setFocus([0.0,0.0,0.0]);
+    camera.setElevation(-22);
+    camera.setAzimuth(37);
+    camera.hookRenderer = render;
+    
+    
+    var canvas  = document.getElementById('canvas-element-id');
+    
+    //Scene Picker
+    picker = new Picker(canvas);
+    picker.processHitsCallback = processHits;
+    picker.addHitCallback      = addHit;
+    picker.removeHitCallback   = removeHit;
+    picker.hitPropertyCallback = hitProperty;
+    picker.moveCallback        = movePickedObjects;
+    
+    //Creates and sets up the mouse and keyboard interactor
+    interactor = new CameraInteractor(camera, canvas);
+    interactor.setPicker(picker);
+        
+    //Scene Transforms
+    transforms = new SceneTransforms(camera);
+   
+    //init transforms
+    transforms.init();
+    
+    //Program
+    attributeList = ["aVertexPosition",
+                    "aVertexNormal",
+                    "aVertexColor",
+                    "aVertexTextureCoords"];
+
+    uniformList = [	"uPMatrix", 
+                    "uMVMatrix", 
+                    "uNMatrix",
+                    "uMaterialDiffuse",
+                    "uMaterialAmbient",
+                    "uLightAmbient",
+                    "uLightDiffuse",
+                    "uLightPosition",
+                    "uWireframe",
+                    "uAlpha",
+                    "uUseVertexColor",
+                    "uOffscreen",
+                    "uSampler",
+                    "uUseTextures",
+                    "uPickingColor"
+                    ];
+    
+    
+    Program.load(attributeList, uniformList);
+    
+    gl.uniform3fv(Program.uLightPosition,   [0,5,20]);
+    gl.uniform3fv(Program.uLightAmbient,    [1.0,1.0,1.0,1.0]);
+    gl.uniform4fv(Program.uLightDiffuse,    [1.0,1.0,1.0,1.0]);
+    gl.uniform1f(Program.uAlpha, 1.0);
+}
+
+function generatePosition(){    
+    var x = Math.floor(Math.random()*60);
+    var y = 0;
+    var z = Math.floor(Math.random()*60);
+    var flagX = Math.floor(Math.random()*10);
+    var flagZ = Math.floor(Math.random()*10);
+    
+    if (flagX >= 5) {x=-x;}
+    if (flagZ >= 5) {z=-z;}
+    return [x,y,z];
+}
+
+/**
+* Loads the scene
+*/
+function load(){
+    Floor.build(80,5);
+    Floor.pcolor = [0.0,0.0,0.0,1.0];
+    Scene.addObject(Floor);
+    var pos = [];   //position
+    var dif = [];   //diffuse color
+    var sca = [];   //scale
+    var pcol = [];  //picking color
+    var f = 1.0;    //factor
+    var type = 0;
+    for (var i = 0; i < 100; i++){
+        pos = generatePosition();
+        f = Math.random()+0.1; dif = [f, f, f, 1.0];
+        f = Math.random()+0.3; sca = [f, f, f];
+        pcol = [Math.random(), Math.random(),Math.random(),1.0];
+        type = Math.floor(Math.random()*2);
+        switch (type){
+            case 1: Scene.loadObject('models/geometry/sphere.json',   'ball_'+i, {position:pos,scale:sca, diffuse:dif, pcolor:pcol}); break;
+            case 0: Scene.loadObject('models/geometry/cylinder.json',   'cylinder_'+i, {position:pos,scale:sca, diffuse:dif, pcolor:pcol}); break;
+        }
+   }
+}
+
+
+
+
+function render(){
+
+    //off-screen rendering
+    gl.bindFramebuffer(gl.FRAMEBUFFER, picker.framebuffer);
+    gl.uniform1i(Program.uOffscreen, true);
+    draw();
+    //on-screen rendering
+    gl.uniform1i(Program.uOffscreen, showPickingImage);
+    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+    draw();
+}
+
+function hitProperty(ob){
+    return ob.pcolor;
+}
+
+function addHit(ob){
+ ob.previous = ob.diffuse.slice(0);     
+ ob.diffuse = ob.pcolor;
+ render();
+}
+
+function removeHit(ob){
+    ob.diffuse = ob.previous.slice(0);
+    render();
+
+}
+
+function processHits(hits){
+    for(var i = 0; i < hits.length; i++){
+        var ob = hits[i];
+        ob.diffuse = ob.previous;
+        Scene.removeObject(ob.alias);
+    }
+    render();
+}
+
+function movePickedObjects(interactor,dx,dy){
+    
+    if (picker.plist.length == 0) return;
+    
+    var camera = interactor.camera;
+    var depth = (interactor.alt!=0);
+    
+    for (var i = 0, max = picker.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        var pos = vec3.create([ob.position[0], ob.position[1], ob.position[2]]);
+        
+        var scaleY = vec3.create();
+        var scaleX = vec3.create();
+        
+        var factor = Math.max(Math.max(camera.position[0], camera.position[1]), camera.position[2])/1000;
+       
+        if (!depth){
+            vec3.scale(camera.up,   -dy * factor, scaleY);
+            vec3.scale(camera.right, dx * factor, scaleX);
+        }
+        else{
+            vec3.scale(camera.normal, dy * factor, scaleY);
+        }
+
+        vec3.add(pos, scaleY);
+        vec3.add(pos, scaleX);
+        
+        ob.position[0] = pos[0];
+        ob.position[1] = pos[1];
+        ob.position[2] = pos[2];
+    }
+    render();
+}
+
+
+/**
+* invoked on every rendering cycle
+*/
+function draw() {
+    gl.viewport(0, 0, c_width, c_height);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+    transforms.updatePerspective();
+    try{
+        var offscreen  = Program.getUniform(Program.uOffscreen);
+        
+        for (var i = 0; i < Scene.objects.length; i++){
+                
+            var object = Scene.objects[i];
+            
+            if (object.alias == 'floor' && (showPickingImage || offscreen)){
+                continue;
+            }
+            
+            if(object.diffuse[3] < 1.0 && !offscreen) {
+				gl.disable(gl.DEPTH_TEST);
+				gl.enable(gl.BLEND);
+			} else {
+				gl.enable(gl.DEPTH_TEST);
+				gl.disable(gl.BLEND);
+			}
+
+            transforms.calculateModelView();           
+            transforms.push();
+            if (object.alias != 'floor'){
+                mat4.translate(transforms.mvMatrix, object.position);
+                mat4.scale(transforms.mvMatrix, object.scale);
+            }
+            transforms.setMatrixUniforms();
+            transforms.pop();
+
+            //Setting uniforms
+            gl.uniform4fv(Program.uMaterialDiffuse, object.diffuse);
+            gl.uniform4fv(Program.uMaterialAmbient, object.ambient);
+            gl.uniform1i(Program.uWireframe,object.wireframe);
+            gl.uniform4fv(Program.uPickingColor, object.pcolor);
+            gl.uniform1i(Program.uUseVertexColor, false);
+            gl.uniform1i(Program.uUseTextures, false);
+            
+            //Setting attributes
+            gl.enableVertexAttribArray(Program.aVertexPosition);
+            gl.disableVertexAttribArray(Program.aVertexNormal);
+            gl.disableVertexAttribArray(Program.aVertexColor);
+            gl.disableVertexAttribArray(Program.aVertexTextureCoords);
+            
+            //Bind Array Buffer
+            gl.bindBuffer(gl.ARRAY_BUFFER, object.vbo);
+            gl.vertexAttribPointer(Program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
+            gl.enableVertexAttribArray(Program.aVertexPosition);
+           
+            if(!offscreen && !showPickingImage){
+                //render scalars
+                if (object.scalars != null){
+                    gl.enableVertexAttribArray(Program.aVertexColor);
+                    gl.uniform1i(Program.uUseVertexColor, true);
+                    gl.bindBuffer(gl.ARRAY_BUFFER, object.cbo);
+                    gl.vertexAttribPointer(Program.aVertexColor, 4, gl.FLOAT, false, 0, 0);
+                    
+                }
+                
+                //render textures
+                if (object.texture_coords){
+                    gl.enableVertexAttribArray(Program.aVertexTextureCoords);
+                    gl.uniform1i(Program.uUseTextures, true);
+                    gl.bindBuffer(gl.ARRAY_BUFFER, object.tbo);
+                    gl.vertexAttribPointer(Program.aVertexTextureCoords, 2, gl.FLOAT, false, 0, 0);
+                    gl.activeTexture(gl.TEXTURE0);
+                    gl.bindTexture(gl.TEXTURE_2D, object.texture.tex);
+                    gl.uniform1i(Program.uSampler, 0);
+                }
+            }
+            else{
+                gl.uniform1i(Program.uUseTextures, false);
+                gl.uniform1i(Program.uUseVertexColors, false);
+            }
+            
+            if(!object.wireframe){
+                gl.bindBuffer(gl.ARRAY_BUFFER, object.nbo);
+                gl.vertexAttribPointer(Program.aVertexNormal, 3, gl.FLOAT, false, 0, 0);
+                gl.enableVertexAttribArray(Program.aVertexNormal);
+            }
+            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.ibo);
+            
+            if (object.wireframe){
+                gl.drawElements(gl.LINES, object.indices.length, gl.UNSIGNED_SHORT,0);
+            }
+            else{
+                gl.drawElements(gl.TRIANGLES, object.indices.length, gl.UNSIGNED_SHORT,0);
+            }
+            
+            gl.bindBuffer(gl.ARRAY_BUFFER, null);
+            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+        }
+    }
+    catch(err){
+        alert(err);
+        console.error(err.description);
+    }
+}
+
+
+/**
+* Entry point. This function is invoked when the page is loaded
+*/
+var app = null;
+function runWebGLApp() {
+    app = new WebGLApp("canvas-element-id");
+    app.configureGLHook = configure;
+    app.loadSceneHook   = load;
+    app.drawSceneHook   = render;
+    app.run();
+}
+</script>
+</head>
+
+<body onLoad='runWebGLApp()'>
+<div id='top'>
+<h1>WebGL Beginner's Guide - Chapter 8</h1>
+<h2 id='title-id'>Basic Picking</h2>
+
+<div id='logo-packt'><img src='packt.gif'/></div>
+<p></p>
+</div>
+
+<div id='contents'>
+<div id='canvasContainer'>
+<canvas id='canvas-element-id' width='480' height='400'>
+Your browser does not support the HTML5 canvas element.
+</canvas>
+</div>
+</div>
+
+<div id='bottom'>
+<table style='padding=0px'>
+<tr>
+    <td>
+    <table id='coloring-table'>
+    <tr>
+    <td><input type="checkbox" id="show-picking-btn" /><label for="show-picking-btn">Show Picking Image</label></td>
+    <td><a id="reset-btn" />Reset Scene</a></td>
+  
+    </tr>		
+    </table>
+    </td>
+</tr>	
+
+</table>
+</div>
+<script> 
+
+
+$('#show-picking-btn, #reset-btn').button();
+
+
+$('#show-picking-btn').click(function(){
+    showPickingImage = !showPickingImage
+    
+});
+
+$('#reset-btn').click(function(){
+    
+    Scene.objects = [];
+    load();
+    camera.goHome([0,0,192]);
+    camera.setFocus([0.0,0.0,0.0]);
+    camera.setElevation(-22);
+    camera.setAzimuth(37);
+    showPickingImage = false;
+ }); 
+
+
+</script>
+<script>cview.run(cview.MODE_VIEW,false,470);</script>
+</body>
+</html>

File 1727_08/js/webgl/CameraInteractor.js

 		left += obj.offsetLeft;
 		obj = obj.offsetParent;
 	}
+    
+    left += window.pageXOffset;
+    top  += window.pageYOffset;
  
 	// return relative mouse position
-	x = ev.clientX - left + window.pageXOffset;
-	y = this.canvas.clientHeight - (ev.clientY - top + window.pageYOffset);
+	x = ev.clientX - left;
+	y = c_height - (ev.clientY - top); //c_height is a global variable that we maintain in codeview.js
+                                       //this variable contains the height of the canvas and it updates dynamically
+                                       //as we resize the browser window.
 	
 	return {x:x,y:y};
 }
 
 CameraInteractor.prototype.onMouseUp = function(ev){
-	var coords = this.get2DCoords(ev);
-	if (this.picker != null){
-		if (!this.picker.find(coords)){
-            this.picker.clear();
-            this.picking = false;
-             $('#title-id').html('Please select an object and drag it. (Alt key drags on the camera axis)');
-        }
-        else{
-            this.picking = true;
-            var count = this.picker.plist.length;
-            var message = count==1?count+' object has been selected': count+' objects have been selected';
-            $('#title-id').html(message);
-        }
- 	}
 	this.dragging = false;
+    
+    if (!ev.shiftKey){
+        this.picking = false;
+        this.picker.stop();
+    }
 }
 
 CameraInteractor.prototype.onMouseDown = function(ev){
 	this.y = ev.clientY;
 	this.button = ev.button;
 	this.dstep = Math.max(this.camera.position[0],this.camera.position[1],this.camera.position[2])/100;
+    
+    if (this.picker == null) return;
+    
+    var coords = this.get2DCoords(ev);
+    this.picking = this.picker.find(coords);
+    
+    if (this.picking){
+        var count = this.picker.plist.length;
+        var message = count==1?count+' object has been selected': count+' objects have been selected';
+        $('#title-id').html(message);
+    }
+    else{
+        this.picker.stop();
+        $('#title-id').html('Please select an object and drag it. (Alt key drags on the camera axis)');
+    }
 }
 
 CameraInteractor.prototype.onMouseMove = function(ev){
 	var dx = this.x - this.lastX;
 	var dy = this.y - this.lastY;
     
-    if (this.picking){
-        this.picker.move(dx,dy, this.camera, this.alt != 0);
+    if (this.picking && this.picker.moveCallback){
+        this.picker.moveCallback(this,dx,dy);
         return;
     }
 	
         }
         
 	}
-    else if (this.key == 80){
-            this.picking = !this.picking;
-            var mode = this.picking?'ON':'OFF';
-            console.info('Picking mode is ' + mode);
-            if (!this.picking){
-                this.picker.clear();
-            }
-        }
-     
 }
 
 CameraInteractor.prototype.onKeyUp = function(ev){

File 1727_08/js/webgl/Picker.js

 	this.texture = null;
 	this.framebuffer = null;
 	this.renderbuffer = null;
+    
+    this.processHitsCallback = null;
+    this.addHitCallback = null;
+    this.removeHitCallback = null;
+    this.hitPropertyCallback = null;
+    this.moveCallback = null;
+    
 	this.configure();
+    
 };
 
 Picker.prototype.configure = function(){
 
-	//1. Init Frame Buffer
-	this.framebuffer = gl.createFramebuffer();
-	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
-	this.framebuffer.width = 512*4;
-	this.framebuffer.height = 512*2;
+	var width = 512*4;
+	var height = 512*2;
 	
-	//2. Init Picking Texture
+	//1. Init Picking Texture
 	this.texture = gl.createTexture();
 	gl.bindTexture(gl.TEXTURE_2D, this.texture);
 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
 	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
     gl.generateMipmap(gl.TEXTURE_2D);
-    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.framebuffer.width, this.framebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
 	
-	//3. Init Render Buffer
+	//2. Init Render Buffer
 	this.renderbuffer = gl.createRenderbuffer();
     gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
-    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.framebuffer.width, this.framebuffer.height);
+    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
 	
+    
+    //3. Init Frame Buffer
+    this.framebuffer = gl.createFramebuffer();
+	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
 	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderbuffer);
 	
     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
 };
 
-Picker.prototype._compare = function(readout, object){
-    var color = object.diffuse;
-    return (Math.floor(color[0]*255) == readout[0] &&
-			Math.floor(color[1]*255) == readout[1] && 
-			Math.floor(color[2]*255) == readout[2]);
+Picker.prototype._compare = function(readout, color){
+    //console.info('comparing object '+object.alias+' diffuse ('+Math.round(color[0]*255)+','+Math.round(color[1]*255)+','+Math.round(color[2]*255)+') == readout ('+ readout[0]+','+ readout[1]+','+ readout[2]+')');
+    return (Math.abs(Math.round(color[0]*255) - readout[0]) <= 1 &&
+			Math.abs(Math.round(color[1]*255) - readout[1]) <= 1 && 
+			Math.abs(Math.round(color[2]*255) - readout[2]) <= 1);
 }
 
 Picker.prototype.find = function(coords){
 	
 	//read one pixel
 	var readout = new Uint8Array(1 * 1 * 4);
-		
 	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
 	gl.readPixels(coords.x,coords.y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,readout);
 	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
 
     var found = false;
     
-	for(var i = 0, max = Scene.objects.length; i < max; i+=1){
-		var ob = Scene.objects[i];
+    if (this.hitPropertyCallback == undefined) {alert('The picker needs an object property to perform the comparison'); return;}
+
+    for(var i = 0, max = Scene.objects.length; i < max; i+=1){
+        var ob = Scene.objects[i];
         if (ob.alias == 'floor') continue;
-		if (this._compare(readout, ob)){
-				ob.diffuse[3] = 0.7;
+                
+        var property  = this.hitPropertyCallback(ob);
+    
+        if (this._compare(readout, property)){
+            var idx  = this.plist.indexOf(ob);
+            if (idx != -1){
+                this.plist.splice(idx,1);
+                if (this.removeHitCallback){
+                    this.removeHitCallback(ob); 
+                }
+            }
+            else {
                 this.plist.push(ob);
-                found = true;
-                break;
-		}
-	}
+                if (this.addHitCallback){
+                    this.addHitCallback(ob); 
+                }
+            }
+            found = true;
+            break;
+        }
+    }
+    draw();
     return found;
 };
 
-Picker.prototype.clear = function(){
-    for(var i = 0, max = this.plist.length; i < max; i+=1){
-        var ob = this.plist[i];
-        ob.diffuse[3] = 1.0;
+Picker.prototype.stop = function(){
+    if (this.processHitsCallback != null && this.plist.length > 0){
+        this.processHitsCallback(this.plist);
     }
     this.plist = [];
 }
 
-Picker.prototype.getHits = function(){
-    return this.plist;
-}
 
-Picker.prototype.move = function(dx,dy,camera,depth){
-    
-    if (this.plist.length == 0) return;
-    
-    for (var i = 0, max = this.plist.length; i < max; i+=1){
-        var ob = this.plist[i];
-        var pos = vec3.create([ob.position[0], ob.position[1], ob.position[2]]);
-        
-        var scaleY = vec3.create();
-        var scaleX = vec3.create();
-       
-        if (!depth){
-            vec3.scale(camera.up,   -dy * 0.05, scaleY);
-            vec3.scale(camera.right, dx * 0.05, scaleX);
-        }
-        else{
-            vec3.scale(camera.normal, dy * 0.05, scaleY);
-        }
-        
-        
-        
-        vec3.add(pos, scaleY);
-        vec3.add(pos, scaleX);
-        
-        ob.position[0] = pos[0];
-        ob.position[1] = pos[1];
-        ob.position[2] = pos[2];
-    }
-    draw();
-}

File 1727_08/js/webgl/Scene.js

 			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(object.texture_coords), gl.STATIC_DRAW);
 			object.tbo = textureBufferObject;
 		}
+        
+        if (object.image){
+            object.texture = new Texture(object.image);
+        }
     
         var indexBufferObject = gl.createBuffer();
         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBufferObject);

File 1727_08/models/geometry/cylinder.json

+{
+  "vertices" : [5.0,10.0,0.0,5.0,0.0,0.0,4.75528,10.0,-1.54508,4.75528,0.0,-1.54508,4.04508,10.0,-2.93893,4.04508,0.0,-2.93893,2.93893,10.0,-4.04508,2.93893,0.0,-4.04508,1.54508,10.0,-4.75528,1.54508,0.0,-4.75528,-1.02552e-09,10.0,-5.0,-1.02552e-09,0.0,-5.0,-1.54508,10.0,-4.75528,-1.54508,0.0,-4.75528,-2.93893,10.0,-4.04508,-2.93893,0.0,-4.04508,-4.04508,10.0,-2.93893,-4.04508,0.0,-2.93893,-4.75528,10.0,-1.54508,-4.75528,0.0,-1.54508,-5.0,10.0,2.05103e-09,-5.0,0.0,2.05103e-09,-4.75528,10.0,1.54508,-4.75528,0.0,1.54508,-4.04508,10.0,2.93893,-4.04508,0.0,2.93893,-2.93893,10.0,4.04508,-2.93893,0.0,4.04508,-1.54508,10.0,4.75528,-1.54508,0.0,4.75528,3.07655e-09,10.0,5.0,3.07655e-09,0.0,5.0,1.54508,10.0,4.75528,1.54508,0.0,4.75528,2.93893,10.0,4.04508,2.93893,0.0,4.04508,4.04508,10.0,2.93893,4.04508,0.0,2.93893,4.75528,10.0,1.54508,4.75528,0.0,1.54508,5.0,10.0,0.0,4.75528,10.0,-1.54508,4.75528,10.0,1.54508,4.04508,10.0,2.93893,2.93893,10.0,4.04508,1.54508,10.0,4.75528,3.07655e-09,10.0,5.0,-1.54508,10.0,4.75528,-2.93893,10.0,4.04508,-4.04508,10.0,2.93893,-4.75528,10.0,1.54508,-5.0,10.0,2.05103e-09,-4.75528,10.0,-1.54508,-4.04508,10.0,-2.93893,-2.93893,10.0,-4.04508,4.04508,10.0,-2.93893,2.93893,10.0,-4.04508,-1.54508,10.0,-4.75528,-1.02552e-09,10.0,-5.0,1.54508,10.0,-4.75528,3.07655e-09,0.0,5.0,-1.54508,0.0,4.75528,1.54508,0.0,4.75528,2.93893,0.0,4.04508,4.04508,0.0,2.93893,4.75528,0.0,1.54508,5.0,0.0,0.0,4.75528,0.0,-1.54508,4.04508,0.0,-2.93893,2.93893,0.0,-4.04508,1.54508,0.0,-4.75528,-1.02552e-09,0.0,-5.0,-1.54508,0.0,-4.75528,-2.93893,0.0,-4.04508,-4.04508,0.0,-2.93893,-2.93893,0.0,4.04508,-4.04508,0.0,2.93893,-4.75528,0.0,-1.54508,-5.0,0.0,2.05103e-09,-4.75528,0.0,1.54508],
+  "indices" : [0,1,2,3,2,1,2,3,4,4,3,5,4,5,6,7,6,5,6,7,8,8,7,9,8,9,10,11,10,9,10,11,12,13,12,11,12,13,14,14,13,15,14,15,16,17,16,15,16,17,18,18,17,19,18,19,20,21,20,19,20,21,22,23,22,21,22,23,24,24,23,25,24,25,26,27,26,25,26,27,28,28,27,29,28,29,30,31,30,29,30,31,32,33,32,31,32,33,34,34,33,35,34,35,36,37,36,35,36,37,38,38,37,39,38,39,0,1,0,39,40,41,42,42,41,43,43,41,44,44,41,45,45,41,46,46,41,47,47,41,48,48,41,49,49,41,50,50,41,51,51,41,52,52,41,53,53,41,54,41,55,54,55,56,54,54,56,57,57,56,58,59,58,56,60,61,62,62,61,63,63,61,64,64,61,65,65,61,66,66,61,67,67,61,68,68,61,69,69,61,70,70,61,71,71,61,72,72,61,73,73,61,74,61,75,74,75,76,74,74,76,77,77,76,78,79,78,76]
+}

File 1727_08/models/geometry/cylinder.vtk

+# vtk DataFile Version 3.0
+vtk output
+ASCII
+DATASET POLYDATA
+POINTS 80 float
+5 10 0 5 0 0 4.75528 10 -1.54508 
+4.75528 0 -1.54508 4.04508 10 -2.93893 4.04508 0 -2.93893 
+2.93893 10 -4.04508 2.93893 0 -4.04508 1.54508 10 -4.75528 
+1.54508 0 -4.75528 -1.02552e-009 10 -5 -1.02552e-009 0 -5 
+-1.54508 10 -4.75528 -1.54508 0 -4.75528 -2.93893 10 -4.04508 
+-2.93893 0 -4.04508 -4.04508 10 -2.93893 -4.04508 0 -2.93893 
+-4.75528 10 -1.54508 -4.75528 0 -1.54508 -5 10 2.05103e-009 
+-5 0 2.05103e-009 -4.75528 10 1.54508 -4.75528 0 1.54508 
+-4.04508 10 2.93893 -4.04508 0 2.93893 -2.93893 10 4.04508 
+-2.93893 0 4.04508 -1.54508 10 4.75528 -1.54508 0 4.75528 
+3.07655e-009 10 5 3.07655e-009 0 5 1.54508 10 4.75528 
+1.54508 0 4.75528 2.93893 10 4.04508 2.93893 0 4.04508 
+4.04508 10 2.93893 4.04508 0 2.93893 4.75528 10 1.54508 
+4.75528 0 1.54508 5 10 0 4.75528 10 -1.54508 
+4.04508 10 -2.93893 2.93893 10 -4.04508 1.54508 10 -4.75528 
+-1.02552e-009 10 -5 -1.54508 10 -4.75528 -2.93893 10 -4.04508 
+-4.04508 10 -2.93893 -4.75528 10 -1.54508 -5 10 2.05103e-009 
+-4.75528 10 1.54508 -4.04508 10 2.93893 -2.93893 10 4.04508 
+-1.54508 10 4.75528 3.07655e-009 10 5 1.54508 10 4.75528 
+2.93893 10 4.04508 4.04508 10 2.93893 4.75528 10 1.54508 
+4.75528 0 1.54508 4.04508 0 2.93893 2.93893 0 4.04508 
+1.54508 0 4.75528 3.07655e-009 0 5 -1.54508 0 4.75528 
+-2.93893 0 4.04508 -4.04508 0 2.93893 -4.75528 0 1.54508 
+-5 0 2.05103e-009 -4.75528 0 -1.54508 -4.04508 0 -2.93893 
+-2.93893 0 -4.04508 -1.54508 0 -4.75528 -1.02552e-009 0 -5 
+1.54508 0 -4.75528 2.93893 0 -4.04508 4.04508 0 -2.93893 
+4.75528 0 -1.54508 5 0 0 
+POLYGONS 76 304
+3 0 1 2 
+3 3 2 1 
+3 2 3 4 
+3 4 3 5 
+3 4 5 6 
+3 7 6 5 
+3 6 7 8 
+3 8 7 9 
+3 8 9 10 
+3 11 10 9 
+3 10 11 12 
+3 13 12 11 
+3 12 13 14 
+3 14 13 15 
+3 14 15 16 
+3 17 16 15 
+3 16 17 18 
+3 18 17 19 
+3 18 19 20 
+3 21 20 19 
+3 20 21 22 
+3 23 22 21 
+3 22 23 24 
+3 24 23 25 
+3 24 25 26 
+3 27 26 25 
+3 26 27 28 
+3 28 27 29 
+3 28 29 30 
+3 31 30 29 
+3 30 31 32 
+3 33 32 31 
+3 32 33 34 
+3 34 33 35 
+3 34 35 36 
+3 37 36 35 
+3 36 37 38 
+3 38 37 39 
+3 38 39 0 
+3 1 0 39 
+3 40 41 59 
+3 59 41 58 
+3 58 41 57 
+3 57 41 56 
+3 56 41 55 
+3 55 41 54 
+3 54 41 53 
+3 53 41 52 
+3 52 41 51 
+3 51 41 50 
+3 50 41 49 
+3 49 41 48 
+3 48 41 47 
+3 41 42 47 
+3 42 43 47 
+3 47 43 46 
+3 46 43 45 
+3 44 45 43 
+3 64 65 63 
+3 63 65 62 
+3 62 65 61 
+3 61 65 60 
+3 60 65 79 
+3 79 65 78 
+3 78 65 77 
+3 77 65 76 
+3 76 65 75 
+3 75 65 74 
+3 74 65 73 
+3 73 65 72 
+3 72 65 71 
+3 65 66 71 
+3 66 67 71 
+3 71 67 70 
+3 70 67 69 
+3 68 69 67 
+
+POINT_DATA 80
+NORMALS Normals float
+1 0 -0 1 0 -0 0.951057 0 -0.309017 
+0.951057 0 -0.309017 0.809017 0 -0.587785 0.809017 0 -0.587785 
+0.587785 0 -0.809017 0.587785 0 -0.809017 0.309017 0 -0.951057 
+0.309017 0 -0.951057 -2.05103e-010 0 -1 -2.05103e-010 0 -1 
+-0.309017 0 -0.951057 -0.309017 0 -0.951057 -0.587785 0 -0.809017 
+-0.587785 0 -0.809017 -0.809017 0 -0.587785 -0.809017 0 -0.587785 
+-0.951057 0 -0.309017 -0.951057 0 -0.309017 -1 0 4.10207e-010 
+-1 0 4.10207e-010 -0.951057 0 0.309017 -0.951057 0 0.309017 
+-0.809017 0 0.587785 -0.809017 0 0.587785 -0.587785 0 0.809017 
+-0.587785 0 0.809017 -0.309017 0 0.951057 -0.309017 0 0.951057 
+6.1531e-010 0 1 6.1531e-010 0 1 0.309017 0 0.951057 
+0.309017 0 0.951057 0.587785 0 0.809017 0.587785 0 0.809017 
+0.809017 0 0.587785 0.809017 0 0.587785 0.951057 0 0.309017 
+0.951057 0 0.309017 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 1 0 0 1 0 0 1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 0 -1 0 
+0 -1 0 0 -1 0 
+TEXTURE_COORDINATES TCoords 2 float
+1 0 1 1 0.9 0 0.9 1 0.8 
+0 0.8 1 0.7 0 0.7 1 0.6 0 
+0.6 1 0.5 0 0.5 1 0.4 0 0.4 
+1 0.3 0 0.3 1 0.2 0 0.2 1 
+0.1 0 0.1 1 0 0 0 1 0.1 
+0 0.1 1 0.2 0 0.2 1 0.3 0 
+0.3 1 0.4 0 0.4 1 0.5 0 0.5 
+1 0.6 0 0.6 1 0.7 0 0.7 1 
+0.8 0 0.8 1 0.9 0 0.9 1 5 
+-0 4.75528 -1.54508 4.04508 -2.93893 2.93893 -4.04508 1.54508 -4.75528 
+-1.02552e-009 -5 -1.54508 -4.75528 -2.93893 -4.04508 -4.04508 -2.93893 -4.75528 
+-1.54508 -5 2.05103e-009 -4.75528 1.54508 -4.04508 2.93893 -2.93893 4.04508 
+-1.54508 4.75528 3.07655e-009 5 1.54508 4.75528 2.93893 4.04508 4.04508 
+2.93893 4.75528 1.54508 4.75528 1.54508 4.04508 2.93893 2.93893 4.04508 
+1.54508 4.75528 3.07655e-009 5 -1.54508 4.75528 -2.93893 4.04508 -4.04508 
+2.93893 -4.75528 1.54508 -5 2.05103e-009 -4.75528 -1.54508 -4.04508 -2.93893 
+-2.93893 -4.04508 -1.54508 -4.75528 -1.02552e-009 -5 1.54508 -4.75528 2.93893 
+-4.04508 4.04508 -2.93893 4.75528 -1.54508 5 -0 

File 1727_08/models/geometry/vtk2json.py

+import sys,string,traceback
+from threading import Thread
+
+#vtk2json.py only has one argument: the name of the vtk file to process (include the extension please)
+
+ARRAY_SIZE = 65536*3
+# ver - vertices
+# ind - indices
+# seg - segment
+def tesellate(ver,ind, pod, blockID):
+    lowerBound  = ARRAY_SIZE*blockID
+    upperBound = ARRAY_SIZE*(blockID+1);
+    if upperBound > len(ind):
+        upperBound = len(ind)
+    newindex = dict()
+    mapIndexToVertex = dict()
+    vtxBlock = []
+    idxBlock = []
+    pdxBlock = []
+    hasPointData = len(pod)>0
+    # Set of indices to be processed
+    aux = ind[lowerBound:upperBound]
+    nidx = -1
+    #item = 1
+    
+    print 'Processing block #' + str(blockID+1) + '['+str(lowerBound)+','+str(upperBound)+']'
+    
+    try:
+    #for each index to be processed
+        for oidx in aux:
+            # if index hasn't been mapped
+            if oidx not in newindex.keys():
+                nidx = nidx + 1
+                # create new index for the old index (incrementally)
+                idxBlock.append(nidx)
+                # save in the map for posterior searches
+                newindex[oidx] = nidx
+                # multiply by three to find the right starting point in the vertex array
+                index = oidx * 3
+                # add the correspondant vertex into the new position in the new vertex array
+                vtxBlock.append(ver[index])
+                vtxBlock.append(ver[index+1])
+                vtxBlock.append(ver[index+2])
+                # add the correspondant point data if any
+                if hasPointData :
+                    pdxBlock.append(pod[oidx])
+            else:
+                # if the index was mapped then use it in the new index array
+                idxBlock.append(newindex[oidx])
+    except:
+        #traceback.print_stack()
+        raise
+    return vtxBlock, idxBlock, pdxBlock
+    
+def writejson(fname,ver,ind, pod):
+    f = open(fname,'w')
+    f.write('{\n')
+    f.write('  "vertices" : [')
+    for v in ver[0:len(ver)-1]:
+        f.write(str(v)+',')
+    f.write(str(ver[len(ver)-1])+'],\n')
+    f.write('  "indices" : [')
+    for i in ind[0:len(ind)-1]:
+        f.write(str(i)+',')
+    f.write(str(ind[len(ind)-1])+']')
+    if len(pod) > 0:
+        f.write(',\n  "scalars" : [')
+        for pd in  pod[0:len(pod)-1]:
+            f.write(str(pd)+',')
+        f.write(str(pod[len(pod)-1])+']\n')
+    else:
+        f.write('\n');
+    f.write('}')
+    f.close()
+
+
+    
+def processBlock(vertices, indices, scalars, blockID):
+    fname = sys.argv[1][:-4]
+    vv, ii, dd = tesellate(vertices, indices, scalars, blockID)
+    filename =fname+'_'+str(blockID)+'.json'
+    writejson(filename,vv,ii,dd)
+    print 'Block #' + str(blockID) +' processed'
+
+
+NOWHERE = 0    
+POINTS = 1
+POLYGONS = 2
+POINT_DATA = 3
+NORMALS = 4
+CELL_DATA = 5
+TEXTURE_COORDINATES = 6
+SCALARS = 7;
+LOOKUP_TABLE = 8;
+
+location = NOWHERE
+
+vertices = []
+indices = []
+normals = []
+scalars = []
+
+linenumber = 0;
+
+for line in open(sys.argv[1], 'r').readlines():
+    linenumber = linenumber + 1
+    try:
+        if line.startswith('POINTS'):
+            print line
+            location = POINTS
+            continue
+        elif line.startswith('POLYGONS'):
+            print line
+            location = POLYGONS
+            continue
+        elif line.startswith('POINT_DATA'):
+            location = POINT_DATA
+            continue
+        elif line.startswith('NORMALS'):
+            print line
+            location = NORMALS
+            continue
+        elif line.startswith('CELL_DATA'):
+            print line
+            location = CELL_DATA
+            continue
+        elif line.startswith('TEXTURE_COORDINATES'):
+            print line
+            location = TEXTURE_COORDINATES
+            continue
+        elif line.startswith('SCALARS'):
+            print line
+            location = SCALARS
+            continue
+        elif line.startswith('LOOKUP_TABLE'):
+            print line
+            location = LOOKUP_TABLE
+            continue
+        
+        elif location == POINTS:
+            for v in line.split():
+                vertices.append(float(v))
+        
+        elif location == POLYGONS:
+            tt = line.split()
+            if len(tt)>0 and tt[0] != '3':
+                raise AssertionError('Not triangles here')
+            for i in tt[1:len(tt)]:
+                indices.append(int(i))
+        
+        elif location == LOOKUP_TABLE:
+            if line.startswith('LOOKUP_TABLE'):
+                continue
+            else:
+                for pd in line.split():
+                    scalars.append(float(pd))
+        
+        elif location == NORMALS:
+            for n in line.split():
+                normals.append(float(n))
+    except:
+        print 'Error while processing line '+str(linenumber)
+        print line
+        raise
+
+v_count = len(vertices)/3
+v_err = (v_count % 3 != 0)        
+
+n_count = len(normals)/3
+n_err = (n_count % 3 != 0)
+
+ii_count =len(indices)
+i_count = ii_count/3
+
+pd_count = len(scalars)
+
+print 'vertices: ' + str(v_count) +'\n normals: ' + str(n_count) + '\n indices: ' + str(ii_count)+'\n triangle count: ' + str(i_count) + '\n scalars: ' + str(pd_count) + '\n' 
+
+if (v_err or n_err):
+    print 'vertex error = ' + str(v_err) +', normal error = ' + str(n_err)
+    
+
+numBlocks = ii_count // ARRAY_SIZE
+if(ii_count % ARRAY_SIZE != 0):
+    numBlocks = numBlocks + 1
+print 'Number of Blocks: ' + str(numBlocks)
+
+for i in range(numBlocks):
+    try:
+        #Thread(target=processBlock, args=(vertices, indices, scalars, i)).start()
+        processBlock(vertices, indices, scalars,i);
+    except Exception, errtxt:
+        print errtxt
+    

File 1727_08/webgl2.jpg

Added
New image

File 1727_10/PickerFinal.js

+function Picker(canvas){
+    this.plist = [];
+	this.canvas = canvas;
+	this.texture = null;
+	this.framebuffer = null;
+	this.renderbuffer = null;
+	this.configure();
+};
+
+Picker.prototype.configure = function(){
+
+	var width = 512*4;
+	var height = 512*2;
+	
+	//1. Init Picking Texture
+	this.texture = gl.createTexture();
+	gl.bindTexture(gl.TEXTURE_2D, this.texture);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+    gl.generateMipmap(gl.TEXTURE_2D);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+	
+	//2. Init Render Buffer
+	this.renderbuffer = gl.createRenderbuffer();
+    gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
+    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+	
+    
+    //3. Init Frame Buffer
+    this.framebuffer = gl.createFramebuffer();
+	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
+    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderbuffer);
+	
+
+	//4. Clean up
+	gl.bindTexture(gl.TEXTURE_2D, null);
+    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+Picker.prototype._compare = function(readout, color){
+    //console.info('comparing object '+object.alias+' diffuse ('+Math.round(color[0]*255)+','+Math.round(color[1]*255)+','+Math.round(color[2]*255)+') == readout ('+ readout[0]+','+ readout[1]+','+ readout[2]+')');
+    return (Math.abs(Math.round(color[0]*255)-readout[0]) <= 1 &&
+			Math.abs(Math.round(color[1]*255)- readout[1]) <= 1 && 
+			Math.abs(Math.round(color[2]*255)-readout[2]) <= 1);
+}
+
+Picker.prototype.find = function(coords){
+	
+	//read one pixel
+	var readout = new Uint8Array(1 * 1 * 4);
+	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+	gl.readPixels(coords.x,coords.y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,readout);
+	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+    var found = false;
+
+    for(var i = 0, max = Scene.objects.length; i < max; i+=1){
+        var ob = Scene.objects[i];
+        if (ob.alias == 'floor') continue;
+        
+        var color = ob.diffuse;
+        if (ob.pcolor) {color = ob.pcolor;}
+    
+        if (this._compare(readout, color)){
+            if (ob.picked){
+                //deselect
+                ob.picked = false;
+                ob.diffuse = ob.previous.slice(0);
+                this.plist.splice(this.plist.indexOf(ob),1);
+            }
+            else {
+                ob.picked = true;
+                ob.previous = ob.diffuse.slice(0);
+                if (ob.pcolor){
+                    ob.diffuse = ob.pcolor.slice(0);
+                }
+                else {
+                    ob.diffuse[3] = 0.5;
+                }
+                this.plist.push(ob);
+            }
+            found = true;
+            break;
+        }
+        
+    }
+    draw();
+    return found;
+};
+
+var notifica_balls = false;
+Picker.prototype.stop = function(){
+    for(var i = 0, max = this.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        ob.diffuse = ob.previous;
+        Scene.removeObject(ob.alias);
+        
+        ob.picked = false;
+    }
+    this.plist = [];
+}
+
+Picker.prototype.getHits = function(){
+    return this.plist;
+}
+
+Picker.prototype.move = function(dx,dy,camera,depth){
+    
+    if (this.plist.length == 0) return;
+    
+    for (var i = 0, max = this.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        var pos = vec3.create([ob.position[0], ob.position[1], ob.position[2]]);
+        
+        var scaleY = vec3.create();
+        var scaleX = vec3.create();
+        
+        var factor = Math.max(Math.max(camera.position[0], camera.position[1]), camera.position[2])/1000;
+       
+        if (!depth){
+            vec3.scale(camera.up,   -dy * factor, scaleY);
+            vec3.scale(camera.right, dx * factor, scaleX);
+        }
+        else{
+            vec3.scale(camera.normal, dy * factor, scaleY);
+        }
+
+        vec3.add(pos, scaleY);
+        vec3.add(pos, scaleX);
+        
+        ob.position[0] = pos[0];
+        ob.position[1] = pos[1];
+        ob.position[2] = pos[2];
+    }
+    render();
+}

File 1727_10/PickerFinal2.js

+function Picker(canvas){
+    this.plist = [];
+	this.canvas = canvas;
+	this.texture = null;
+	this.framebuffer = null;
+	this.renderbuffer = null;
+	this.configure();
+};
+
+Picker.prototype.configure = function(){
+
+	var width = 512*4;
+	var height = 512*2;
+	
+	//1. Init Picking Texture
+	this.texture = gl.createTexture();
+	gl.bindTexture(gl.TEXTURE_2D, this.texture);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+    gl.generateMipmap(gl.TEXTURE_2D);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+	
+	//2. Init Render Buffer
+	this.renderbuffer = gl.createRenderbuffer();
+    gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
+    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+	
+    
+    //3. Init Frame Buffer
+    this.framebuffer = gl.createFramebuffer();
+	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
+    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderbuffer);
+	
+
+	//4. Clean up
+	gl.bindTexture(gl.TEXTURE_2D, null);
+    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+};
+
+Picker.prototype._compare = function(readout, color){
+    //console.info('comparing object '+object.alias+' diffuse ('+Math.round(color[0]*255)+','+Math.round(color[1]*255)+','+Math.round(color[2]*255)+') == readout ('+ readout[0]+','+ readout[1]+','+ readout[2]+')');
+    return (Math.abs(Math.round(color[0]*255)-readout[0]) <= 1 &&
+			Math.abs(Math.round(color[1]*255)- readout[1]) <= 1 && 
+			Math.abs(Math.round(color[2]*255)-readout[2]) <= 1);
+}
+
+Picker.prototype.find = function(coords){
+	
+	//read one pixel
+	var readout = new Uint8Array(1 * 1 * 4);
+	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+	gl.readPixels(coords.x,coords.y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,readout);
+	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+    var found = false;
+
+    for(var i = 0, max = Scene.objects.length; i < max; i+=1){
+        var ob = Scene.objects[i];
+        if (ob.alias == 'floor') continue;
+        
+        var color = ob.diffuse;
+        if (ob.pcolor) {color = ob.pcolor;}
+    
+        if (this._compare(readout, color)){
+            if (ob.picked){
+                //deselect
+                ob.picked = false;
+                ob.diffuse = ob.previous.slice(0);
+                this.plist.splice(this.plist.indexOf(ob),1);
+            }
+            else {
+                ob.picked = true;
+                ob.previous = ob.diffuse.slice(0);
+                if (ob.pcolor){
+                    ob.diffuse = ob.pcolor.slice(0);
+                }
+                else {
+                    ob.diffuse[3] = 0.5;
+                }
+                this.plist.push(ob);
+            }
+            found = true;
+            break;
+        }
+        
+    }
+    draw();
+    return found;
+};
+
+var notifica_balls = false;
+Picker.prototype.stop = function(){
+    for(var i = 0, max = this.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        ob.diffuse = ob.previous;
+        Scene.removeObject(ob.alias);
+        
+        ob.picked = false;
+    }
+    this.plist = [];
+    if(!notifica_balls){
+        var balls = 0;
+        for(var i = 0, max = Scene.objects.length; i < max; i +=1){
+            var ob = Scene.objects[i];
+            if (ob.alias.indexOf('ball_') == 0) {balls++};
+            
+        }
+        if (balls == 0) {alert('You have removed all the balls from the scene'); notifica_balls = true;}
+    }
+}
+
+Picker.prototype.getHits = function(){
+    return this.plist;
+}
+
+Picker.prototype.move = function(dx,dy,camera,depth){
+    
+    if (this.plist.length == 0) return;
+    
+    for (var i = 0, max = this.plist.length; i < max; i+=1){
+        var ob = this.plist[i];
+        var pos = vec3.create([ob.position[0], ob.position[1], ob.position[2]]);
+        
+        var scaleY = vec3.create();
+        var scaleX = vec3.create();
+        
+        var factor = Math.max(Math.max(camera.position[0], camera.position[1]), camera.position[2])/1000;
+       
+        if (!depth){
+            vec3.scale(camera.up,   -dy * factor, scaleY);
+            vec3.scale(camera.right, dx * factor, scaleX);
+        }
+        else{
+            vec3.scale(camera.normal, dy * factor, scaleY);
+        }
+
+        vec3.add(pos, scaleY);
+        vec3.add(pos, scaleX);
+        
+        ob.position[0] = pos[0];
+        ob.position[1] = pos[1];
+        ob.position[2] = pos[2];
+    }
+    render();
+}