1 /*
  2   Copyright (c) 2008 Seneca College
  3   Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  4 */
  5 
  6 
  7 /*
  8 */
  9 c3dl.cartoon_callback = function(renderingObj)
 10 {
 11   var renderer = renderingObj.getRenderer();
 12   var gl = renderingObj.getContext();
 13   var geometry = renderingObj.getGeometry();
 14   var effect = geometry.getEffect();
 15   var programObjID = renderingObj.getProgramObjectID();
 16 
 17   gl.useProgram(programObjID);
 18 
 19   if(effect.getParameter("qMap") == null)
 20   {
 21     c3dl.debug.logWarning('"qMap" is a required parameter for c3dl.effects.CARTOON');
 22     return;
 23   }
 24 
 25   var modelViewMatrix = c3dl.peekMatrix();
 26   c3dl.matrixMode(c3dl.PROJECTION);
 27   var projectionMatrix = c3dl.peekMatrix();
 28   c3dl.matrixMode(c3dl.MODELVIEW);
 29 
 30   // create a ModelViewProjection matrix.  By doing this, we can multiply
 31   // 3 matrices together once per model instead of once per vertex
 32   var modelViewProjMatrix = c3dl.multiplyMatrixByMatrix(projectionMatrix, modelViewMatrix);
 33   renderer.setUniformMatrix(programObjID, "modelViewMatrix", modelViewMatrix);
 34   renderer.setUniformMatrix(programObjID, "modelViewProjMatrix", modelViewProjMatrix);
 35   
 36   // Commenting out until a fix is solved for the 2-object outline bug
 37 
 38   // Only render the outline, which is a single pixel thick if the user
 39   // wants it and the effect exists.
 40   if(effect.getParameter("outline") == true && renderer.SOLID_COLOR_EFFECT_ID)
 41   {
 42     gl.enable(gl.POLYGON_OFFSET_FILL);
 43     gl.polygonOffset(2.0, 2.0);
 44 
 45     // use the solid color effect since it's fast and we don't have
 46     // to send unnecessary data.
 47     var outlineProgID = renderer.SOLID_COLOR_EFFECT_ID;
 48 
 49     gl.enable(gl.CULL_FACES);
 50     gl.cullFace(gl.FRONT);
 51     gl.useProgram(outlineProgID);
 52     renderer.setUniformf(outlineProgID, "color",[0,0,0]);
 53 
 54     var modelViewMatrix = c3dl.peekMatrix();
 55     c3dl.matrixMode(c3dl.PROJECTION);
 56     var projectionMatrix = c3dl.peekMatrix();
 57     c3dl.matrixMode(c3dl.MODELVIEW);
 58 
 59     var MVPMatrix = c3dl.multiplyMatrixByMatrix(projectionMatrix, modelViewMatrix);
 60     renderer.setUniformMatrix(outlineProgID, "modelViewProjMatrix", MVPMatrix);
 61 
 62     var contextWidth = renderer.getContextWidth();
 63     var contextHeight = renderer.getContextHeight();
 64 
 65     for(var primSet = 0; primSet < geometry.getPrimitiveSets().length; primSet++)
 66     {
 67       var currColl = geometry.getPrimitiveSets()[primSet];
 68 
 69     // Prevent C3DL from reporting an error, so check if attrib exsits
 70     // before trying to set it.
 71     // This is  a kludge for Safari and Chrome since they want these attributes
 72     ////////////////////////////
 73     var normalAttribLoc = gl.getAttribLocation(outlineProgID,"Normal");
 74 		if(normalAttribLoc != -1 && currColl.getNormals())
 75 		{
 76       renderer.setVertexAttribArray(outlineProgID, "Normal", 3, currColl.getVBONormals());
 77 		}
 78 		var texAttribLoc = gl.getAttribLocation(outlineProgID, "Texture");
 79 		if(texAttribLoc != -1 && currColl.getTexCoords())
 80 		{
 81 			renderer.setVertexAttribArray(outlineProgID, "Texture", 2, currColl.getVBOTexCoords());
 82 		}
 83     ////////////////////////// End kludge
 84     
 85     
 86       renderer.setVertexAttribArray(outlineProgID, "Vertex", 3, currColl.getVBOVertices());        
 87 
 88       gl.viewport( 1,-1, contextWidth,contextHeight);          
 89       gl.drawArrays(renderer.getFillMode(), 0, currColl.getVertices().length/3);
 90 
 91       gl.viewport(-1,-1, contextWidth,contextHeight);          
 92       gl.drawArrays(renderer.getFillMode(), 0, currColl.getVertices().length/3);
 93 
 94       gl.viewport(-1, 1, contextWidth,contextHeight);          
 95       gl.drawArrays(renderer.getFillMode(), 0, currColl.getVertices().length/3);
 96 
 97       gl.viewport( 1, 1,contextWidth,contextHeight);
 98       gl.drawArrays(renderer.getFillMode(), 0, currColl.getVertices().length/3);
 99     }
100 
101     // restore normal backface culling
102     gl.cullFace(gl.BACK);
103     gl.viewport(0,0,contextWidth,contextHeight);
104 
105     gl.disable(gl.POLYGON_OFFSET_FILL);
106     gl.polygonOffset(0.0, 0.0);
107     gl.useProgram(programObjID);
108   }
109 
110   renderer.setUniformi(programObjID, "lightingOn", true);
111   // render all the collation elements. Every collation element in an object will 
112   // have the same tranformation
113   for(var coll = 0; coll < geometry.getPrimitiveSets().length; coll++)
114   {
115     var currColl = geometry.getPrimitiveSets()[coll];
116 
117     var normalAttribLoc = gl.getAttribLocation(programObjID, "Normal");
118 
119     // if the object acutally has normals and the normal attribute was found
120     // NORMALS	
121     if(currColl.getNormals())
122     {				
123       // the top matrix is the modelview matrix.
124       var NormalMatrix = c3dl.inverseMatrix(modelViewMatrix);
125       NormalMatrix = c3dl.transposeMatrix(NormalMatrix);
126       renderer.setUniformMatrix(programObjID, "normalMatrix", NormalMatrix);
127       renderer.setVertexAttribArray(programObjID, "Normal", 3, currColl.getVBONormals());
128     }
129     else
130     {
131       gl.disableVertexAttribArray(normalAttribLoc);
132     }
133 
134     // TEXTURE
135     var texAttribLoc = gl.getAttribLocation(programObjID, "Texture");
136     var texID = renderer.getTextureID(currColl.getTexture());
137 
138     // if the texture isn't loaded, but this collation element has one, 
139     // queue one up
140     if(texID == -1 && currColl.getTexture())
141     {
142       renderer.addTexture(currColl.getTexture());
143     }
144 
145     if( texID != -1 && currColl.getTexture() && currColl.getTexCoords() && texAttribLoc != -1 )
146     {
147       // make texture unit 0 active
148       gl.activeTexture(gl.TEXTURE0);
149 
150       // bind the collations texture object to texture unit 0 and make it active.
151       gl.bindTexture(gl.TEXTURE_2D, texID);
152 
153       renderer.setVertexAttribArray(programObjID, "Texture", 2, currColl.getVBOTexCoords());
154 
155       renderer.setUniformi(programObjID, "myTex", 0);
156       renderer.setUniformi(programObjID, "usingTexture", true);
157     }
158     else
159     {
160       gl.disableVertexAttribArray(texAttribLoc);
161       renderer.setUniformi(programObjID, "usingTexture", false);
162     }
163 
164     // Quantization Map
165     var qMap = effect.getParameter("qMap");
166     shadesTexID = renderer.getTextureID(qMap);
167 
168     // if the user added the parameter, but didn't add the texture
169     // to the renderer with renderer.addTexture.
170     if(shadesTexID == -1)
171     {
172       renderer.addTexture(qMap);
173     }
174 
175     gl.activeTexture(gl.TEXTURE1);
176  
177     // Minefield is throwing an exception here, but still running?
178     gl.bindTexture(gl.TEXTURE_2D, shadesTexID);
179     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
180     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
181     renderer.setUniformi(programObjID, "celShadeTex", 1);
182 
183     // VERTICES
184     renderer.setVertexAttribArray(programObjID, "Vertex", 3, currColl.getVBOVertices());
185     gl.drawArrays(renderer.getFillMode(), 0, currColl.getVertices().length/3);
186   }
187 }
188