API Documentation
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 593 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 593 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 606 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 606 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 691 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 691 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 695 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 695 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 709 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 709 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 716 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 716 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 832 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 833 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 834 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1133 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1133 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1143 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1143 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
1 /* 2 GLGE WebGL Graphics Engine 3 Copyright (c) 2010, Paul Brunt 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 * Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in the 12 documentation and/or other materials provided with the distribution. 13 * Neither the name of GLGE nor the 14 names of its contributors may be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @fileOverview 31 * @name glge_object.js 32 * @author me@paulbrunt.co.uk 33 */ 34 35 36 (function(GLGE){ 37 38 /** 39 * @name GLGE.Object#downloadComplete 40 * @event fires when all the assets for this class have finished loading 41 * @param {object} data 42 */ 43 44 /** 45 * @name GLGE.Object#willRender 46 * @event fires when all the assets will be rendered 47 * @param {object} data 48 */ 49 50 /** 51 * @name GLGE.Object#willRender 52 * @event fires when all the assets will culled 53 * @param {object} data 54 */ 55 56 /** 57 * @class An object that can be rendered in a scene 58 * @augments GLGE.Animatable 59 * @augments GLGE.Placeable 60 * @augments GLGE.QuickNotation 61 * @augments GLGE.JSONLoader 62 */ 63 GLGE.Object=function(uid){ 64 this.multimaterials=[]; 65 66 this.renderCaches=[]; 67 var that=this; 68 this.downloadComplete=function(){ 69 if(that.isComplete()) that.fireEvent("downloadComplete"); 70 } 71 GLGE.Assets.registerAsset(this,uid); 72 } 73 GLGE.augment(GLGE.Placeable,GLGE.Object); 74 GLGE.augment(GLGE.Animatable,GLGE.Object); 75 GLGE.augment(GLGE.QuickNotation,GLGE.Object); 76 GLGE.augment(GLGE.JSONLoader,GLGE.Object); 77 GLGE.Object.prototype.className="Object"; 78 GLGE.Object.prototype.mesh=null; 79 GLGE.Object.prototype.skeleton=null; 80 GLGE.Object.prototype.scene=null; 81 GLGE.Object.prototype.transformMatrix=GLGE.identMatrix(); 82 GLGE.Object.prototype.material=null; 83 GLGE.Object.prototype.gl=null; 84 GLGE.Object.prototype.multimaterials=null; 85 GLGE.Object.prototype.zTrans=false; 86 GLGE.Object.prototype.renderCaches=null; 87 GLGE.Object.prototype.id=""; 88 GLGE.Object.prototype.pickable=true; 89 GLGE.Object.prototype.drawType=GLGE.DRAW_TRIS; 90 GLGE.Object.prototype.pointSize=1; 91 GLGE.Object.prototype.lineWidth=1; 92 GLGE.Object.prototype.cull=true; 93 GLGE.Object.prototype.culled=true; 94 GLGE.Object.prototype.visible=true; 95 GLGE.Object.prototype.depthTest=true; 96 GLGE.Object.prototype.meshFrame1=0; 97 GLGE.Object.prototype.meshFrame2=0; 98 GLGE.Object.prototype.meshBlendFactor=0; 99 GLGE.Object.prototype.noCastShadows=null; 100 101 102 //shadow fragment 103 var shfragStr=[]; 104 shfragStr.push("#ifdef GL_ES\nprecision highp float;\n#endif\n"); 105 shfragStr.push("uniform float distance;\n"); 106 shfragStr.push("uniform bool shadowtype;\n"); 107 shfragStr.push("varying vec3 eyevec;\n"); 108 shfragStr.push("void main(void)\n "); 109 shfragStr.push("{\n"); 110 shfragStr.push("float depth = gl_FragCoord.z / gl_FragCoord.w;\n"); 111 shfragStr.push("if(shadowtype) depth=length(eyevec);\n"); 112 shfragStr.push("vec4 rgba=fract(depth/distance * vec4(16777216.0, 65536.0, 256.0, 1.0));\n"); 113 shfragStr.push("gl_FragColor=rgba-rgba.rrgb*vec4(0.0,0.00390625,0.00390625,0.00390625);\n"); 114 shfragStr.push("}\n"); 115 GLGE.Object.prototype.shfragStr=shfragStr.join(""); 116 117 //normal fragment 118 var nfragStr=[]; 119 nfragStr.push("#ifdef GL_ES\nprecision highp float;\n#endif\n"); 120 nfragStr.push("varying vec3 n;\n"); 121 nfragStr.push("void main(void)\n"); 122 nfragStr.push("{\n"); 123 nfragStr.push("float depth = gl_FragCoord.z / gl_FragCoord.w;\n"); 124 nfragStr.push("gl_FragColor=vec4(normalize(n)/2.0+0.5,depth/1000.0);\n"); 125 nfragStr.push("}\n"); 126 GLGE.Object.prototype.nfragStr=nfragStr.join(""); 127 128 129 //picking fragment 130 var pkfragStr=[]; 131 pkfragStr.push("#ifdef GL_ES\nprecision highp float;\n#endif\n"); 132 pkfragStr.push("uniform float far;\n"); 133 pkfragStr.push("uniform vec3 pickcolor;\n"); 134 pkfragStr.push("varying vec3 n;\n"); 135 pkfragStr.push("varying vec4 UVCoord;\n"); 136 pkfragStr.push("void main(void)\n"); 137 pkfragStr.push("{\n"); 138 pkfragStr.push("float Xcoord = gl_FragCoord.x+0.5;\n"); 139 pkfragStr.push("if(Xcoord>0.0) gl_FragColor = vec4(pickcolor,1.0);\n"); 140 pkfragStr.push("if(Xcoord>1.0) gl_FragColor = vec4(n,1.0);\n"); 141 pkfragStr.push("if(Xcoord>2.0){"); 142 pkfragStr.push("vec3 rgb=fract((gl_FragCoord.z/gl_FragCoord.w) * vec3(65536.0, 256.0, 1.0));\n"); 143 pkfragStr.push("gl_FragColor=vec4(rgb-rgb.rrg*vec3(0.0,0.00390625,0.00390625),1.0);\n"); 144 pkfragStr.push("}"); 145 //x tex coord 146 pkfragStr.push("if(Xcoord>3.0){"); 147 pkfragStr.push("vec3 rgb=fract(UVCoord.x * vec3(65536.0, 256.0, 1.0));\n"); 148 pkfragStr.push("gl_FragColor=vec4(rgb-rgb.rrg*vec3(0.0,0.00390625,0.00390625),1.0);\n"); 149 pkfragStr.push("}"); 150 //y tex coord 151 pkfragStr.push("if(Xcoord>4.0){"); 152 pkfragStr.push("vec3 rgb=fract(UVCoord.y * vec3(65536.0, 256.0, 1.0));\n"); 153 pkfragStr.push("gl_FragColor=vec4(rgb-rgb.rrg*vec3(0.0,0.00390625,0.00390625),1.0);\n"); 154 pkfragStr.push("}"); 155 pkfragStr.push("}\n"); 156 GLGE.Object.prototype.pkfragStr=pkfragStr.join(""); 157 158 159 /** 160 * Sets the object visibility 161 * @param {boolean} visable flag to indicate the objects visibility 162 */ 163 GLGE.Object.prototype.setVisible=function(visible){ 164 this.visible=visible; 165 return this; 166 } 167 168 /** 169 * Gets the object visibility 170 * @returns flag to indicate the objects visibility 171 */ 172 GLGE.Object.prototype.getVisible=function(){ 173 return this.visible; 174 } 175 176 /** 177 * Sets the first mesh frame to use when using an animated mesh 178 * @param {boolean} frame the inital frame 179 */ 180 GLGE.Object.prototype.setMeshFrame1=function(frame){ 181 this.meshFrame1=frame; 182 return this; 183 } 184 /** 185 * Sets the second mesh frame to use when using an animated mesh 186 * @param {boolean} frame the final frame 187 */ 188 GLGE.Object.prototype.setMeshFrame2=function(frame){ 189 this.meshFrame2=frame; 190 return this; 191 } 192 /** 193 * blending between frames 194 * @param {boolean} frame value 0-1 morth between frame1 and frame2 195 */ 196 GLGE.Object.prototype.setMeshBlendFactor=function(factor){ 197 this.meshBlendFactor=factor; 198 return this; 199 } 200 /** 201 * Gets blending between frames 202 * @returns blender factor 203 */ 204 GLGE.Object.prototype.getMeshBlendFactor=function(){ 205 return this.meshBlendFactor; 206 } 207 208 /** 209 * Gets the pickable flag for the object 210 */ 211 GLGE.Object.prototype.getPickable=function(){ 212 return this.pickable; 213 } 214 /** 215 * Sets the pickable flag for the object 216 * @param {boolean} value the culling flag 217 */ 218 GLGE.Object.prototype.setPickable=function(pickable){ 219 this.pickable=pickable; 220 return this; 221 } 222 223 224 /** 225 * Gets the depth test flag for the object 226 */ 227 GLGE.Object.prototype.getDepthTest=function(){ 228 return this.depthTest; 229 } 230 /** 231 * Sets the depth test flag for the object 232 * @param {boolean} value the culling flag 233 */ 234 GLGE.Object.prototype.setDepthTest=function(test){ 235 this.depthTest=test; 236 return this; 237 } 238 239 240 /** 241 * Gets the culling flag for the object 242 */ 243 GLGE.Object.prototype.getCull=function(){ 244 return this.cull; 245 } 246 /** 247 * Sets the culling flag for the object 248 * @param {boolean} value the culling flag 249 */ 250 GLGE.Object.prototype.setCull=function(cull){ 251 this.cull=cull; 252 return this; 253 } 254 255 /** 256 * Gets the objects draw type 257 */ 258 GLGE.Object.prototype.getDrawType=function(){ 259 return this.drawType; 260 } 261 /** 262 * Sets the objects draw type 263 * @param {GLGE.number} value the draw type of this object 264 */ 265 GLGE.Object.prototype.setDrawType=function(value){ 266 this.drawType=value; 267 return this; 268 } 269 270 /** 271 * Gets the objects draw point size 272 */ 273 GLGE.Object.prototype.getPointSize=function(){ 274 return this.pointSize; 275 } 276 /** 277 * Sets the objects draw points size 278 * @param {GLGE.number} value the point size to render 279 */ 280 GLGE.Object.prototype.setPointSize=function(value){ 281 this.pointSize=parseFloat(value); 282 return this; 283 } 284 285 /** 286 * Gets the objects line width 287 */ 288 GLGE.Object.prototype.getLineWidth=function(){ 289 return this.lineWidth; 290 } 291 /** 292 * Sets the objects line width 293 * @param {GLGE.number} value the line width 294 */ 295 GLGE.Object.prototype.setLineWidth=function(value){ 296 this.lineWidth=parseFloat(value); 297 return this; 298 } 299 300 /** 301 * Sets a custom usinform on this object 302 * @param {string} type the uniform type eg 1i, 3fv, Matrix4fv, etc 303 * @param {string} name the uniform name 304 * @param {array} value the value of the uniform 305 */ 306 GLGE.Object.prototype.setUniform=function(type,name,value){ 307 if(!this.uniforms) this.uniforms={}; 308 this.uniforms[name]={type:type,value:value}; 309 } 310 /** 311 * Gets the value of a custom uniform 312 * @param {string} name the name of the uniform to return 313 * @returns {number} the value of the uniform 314 */ 315 GLGE.Object.prototype.getUniform=function(name){ 316 if(!this.uniforms) this.uniforms={}; 317 return this.uniforms[name].value 318 } 319 /** 320 * Gets the type of a custom uniform 321 * @param {string} name the name of the uniform to return 322 * @returns {number} the type of the uniform 323 */ 324 GLGE.Object.prototype.getUniformType=function(name){ 325 if(!this.uniforms) this.uniforms={}; 326 return this.uniforms[name].type; 327 } 328 329 /** 330 * Sets the code to inject into the vertex shader 331 * @param {string} shader the glsl code to inject into the vertex shader of this object GLGE will call the function GLGE_Position(vec4 position) to modify the position 332 */ 333 GLGE.Object.prototype.setVertexShaderInjection=function(shader){ 334 this.shaderVertexInjection=shader; 335 this.updateProgram(); 336 return this; 337 } 338 339 /** 340 * Gets the glsl code injected into the vertex shader of this object 341 * @returns {string} shader the glsl code injected into the vertex shader of this object 342 */ 343 GLGE.Object.prototype.getVertexShaderInjection=function(shader){ 344 return this.shaderVertexInjection; 345 } 346 347 348 /** 349 * Gets the objects skeleton 350 * @returns GLGE.Group 351 */ 352 GLGE.Object.prototype.getSkeleton=function(){ 353 return this.skeleton; 354 } 355 /** 356 * Sets the objects skeleton 357 * @param {GLGE.Group} value the skeleton group to set 358 */ 359 GLGE.Object.prototype.setSkeleton=function(value){ 360 this.skeleton=value; 361 this.bones=null; 362 return this; 363 } 364 365 GLGE.Object.prototype.getBoundingVolume=function(local){ 366 if(!local) local=0; 367 if(!this.boundingVolume) this.boundingVolume=[]; 368 if(!this.boundmatrix) this.boundmatrix=[]; 369 var matrix=this.getModelMatrix(); 370 if(matrix!=this.boundmatrix[local] || !this.boundingVolume[local]){ 371 var multimaterials=this.multimaterials; 372 var boundingVolume; 373 for(var i=0;i<multimaterials.length;i++){ 374 if(multimaterials[i].lods[0].mesh){ 375 if(!boundingVolume){ 376 boundingVolume=multimaterials[i].lods[0].mesh.getBoundingVolume().clone(); 377 }else{ 378 boundingVolume.addBoundingVolume(multimaterials[i].lods[0].mesh.getBoundingVolume()); 379 } 380 } 381 } 382 if(!boundingVolume) boundingVolume=new GLGE.BoundingVolume(0,0,0,0,0,0); 383 384 if(local){ 385 boundingVolume.applyMatrix(this.getLocalMatrix()); 386 }else{ 387 boundingVolume.applyMatrix(this.getModelMatrix()); 388 } 389 this.boundingVolume[local]=boundingVolume; 390 } 391 this.boundmatrix[local]=matrix; 392 return this.boundingVolume[local]; 393 } 394 395 396 /** 397 * Sets the the show casting flag 398 * @param {boolean} value cast or not 399 */ 400 GLGE.Object.prototype.setCastShadows=function(value){ 401 this.noCastShadows=!value; 402 return this; 403 } 404 /** 405 * Gets the the show casting flag 406 * @returns boolean 407 */ 408 GLGE.Object.prototype.getCastShadows=function(){ 409 return !this.noCastShadows; 410 } 411 412 /** 413 * Sets the Z Transparency of this object 414 * @param {boolean} value Does this object need blending? 415 */ 416 GLGE.Object.prototype.setZtransparent=function(value){ 417 this.zTrans=value; 418 return this; 419 } 420 /** 421 * Gets the z transparency 422 * @returns boolean 423 */ 424 GLGE.Object.prototype.isZtransparent=function(){ 425 return this.zTrans; 426 } 427 428 /** 429 * Checks if resources have finished downloading 430 * @returns {boolean} 431 */ 432 GLGE.Object.prototype.isComplete=function(){ 433 for(var i=0;i<this.multimaterials.length;i++){ 434 if(!this.multimaterials[i].isComplete()) return false; 435 } 436 return true; 437 } 438 439 440 /** 441 * Sets the material associated with the object 442 * @param GLGE.Material 443 */ 444 GLGE.Object.prototype.setMaterial=function(material,idx){ 445 if(typeof material=="string") material=GLGE.Assets.get(material); 446 if(!idx) idx=0; 447 if(!this.multimaterials[idx]){ 448 this.multimaterials[idx]=new GLGE.MultiMaterial(); 449 this.multimaterials[idx].addEventListener("downloadComplete",this.downloadComplete); 450 } 451 if(this.multimaterials[idx].getMaterial()!=material){ 452 this.multimaterials[idx].setMaterial(material); 453 this.updateProgram(); 454 } 455 return this; 456 } 457 /** 458 * Gets the material associated with the object 459 * @returns GLGE.Material 460 */ 461 GLGE.Object.prototype.getMaterial=function(idx){ 462 if(!idx) idx=0; 463 if(this.multimaterials[idx]) { 464 return this.multimaterials[idx].getMaterial(); 465 }else{ 466 return false; 467 } 468 } 469 /** 470 * Sets the mesh associated with the object 471 * @param GLGE.Mesh 472 */ 473 GLGE.Object.prototype.setMesh=function(mesh,idx){ 474 if(typeof mesh=="string") mesh=GLGE.Assets.get(mesh); 475 if(!idx) idx=0; 476 if(!this.multimaterials[idx]){ 477 var object=this; 478 this.multimaterials[idx]=new GLGE.MultiMaterial(); 479 this.multimaterials[idx].addEventListener("downloadComplete",this.downloadComplete); 480 this.multimaterials[idx].addEventListener("boundupdate",function(){object.boundingVolume=null}); 481 } 482 this.multimaterials[idx].setMesh(mesh); 483 this.boundingVolume=null; 484 return this; 485 486 } 487 /** 488 * Gets the mesh associated with the object 489 * @returns GLGE.Mesh 490 */ 491 GLGE.Object.prototype.getMesh=function(idx){ 492 if(!idx) idx=0; 493 if(this.multimaterials[idx]) { 494 return this.multimaterials[idx].getMesh(); 495 }else{ 496 return false; 497 } 498 } 499 /** 500 * Initiallize all the GL stuff needed to render to screen 501 * @private 502 */ 503 GLGE.Object.prototype.GLInit=function(gl){ 504 this.gl=gl; 505 } 506 /** 507 * Cleans up all the GL stuff we sets 508 * @private 509 */ 510 GLGE.Object.prototype.GLDestory=function(gl){ 511 } 512 /** 513 * Updates the GL shader program for the object 514 * @private 515 */ 516 GLGE.Object.prototype.updateProgram=function(){ 517 for(var i=0; i<this.multimaterials.length;i++){ 518 this.multimaterials[i].updateProgram(); 519 } 520 } 521 /** 522 * Adds another material to this object 523 * @returns GLGE.Material 524 */ 525 GLGE.Object.prototype.addMultiMaterial=function(multimaterial){ 526 if(typeof multimaterial=="string") multimaterial=GLGE.Assets.get(multimaterial); 527 this.multimaterials.push(multimaterial); 528 multimaterial.addEventListener("downloadComplete",this.downloadComplete); 529 var object=this; 530 multimaterial.addEventListener("boundupdate",function(){object.boundingVolume=null}); 531 this.boundingVolume=null; 532 return this; 533 } 534 /** 535 * gets all of the objects materials and meshes 536 * @returns array of GLGE.MultiMaterial objects 537 */ 538 GLGE.Object.prototype.getMultiMaterials=function(){ 539 return this.multimaterials; 540 } 541 /** 542 * Creates the shader program for the object 543 * @private 544 */ 545 GLGE.Object.prototype.GLGenerateShader=function(gl){ 546 //create the programs strings 547 //Vertex Shader 548 var colors=UV=joints1=joints2=false; 549 var lights=gl.lights; 550 var vertexStr=["#define GLGE_VERTEX\n"]; 551 var tangent=false; 552 if(!this.mesh.normals) this.mesh.calcNormals(); 553 vertexStr.push("attribute vec3 position;\n"); 554 vertexStr.push("attribute vec3 normal;\n"); 555 for(var i=0;i<this.mesh.buffers.length;i++){ 556 if(this.mesh.buffers[i].name=="tangent0") tangent=true; 557 if(this.mesh.buffers[i].exclude) continue; 558 if(this.mesh.buffers[i].size>1){ 559 vertexStr.push("attribute vec"+this.mesh.buffers[i].size+" "+this.mesh.buffers[i].name+";\n"); 560 }else{ 561 vertexStr.push("attribute float "+this.mesh.buffers[i].name+";\n"); 562 } 563 if(this.mesh.buffers[i].name=="UV") UV=true; 564 if(this.mesh.buffers[i].name=="color") colors=true; 565 if(this.mesh.buffers[i].name=="joints1") joints1=this.mesh.buffers[i]; 566 if(this.mesh.buffers[i].name=="joints2") joints2=this.mesh.buffers[i]; 567 } 568 if(this.mesh.framePositions.length>1){ 569 var morph=true; 570 vertexStr.push("attribute vec3 position2;\n"); 571 vertexStr.push("attribute vec3 normal2;\n"); 572 vertexStr.push("uniform float framesBlend;\n"); 573 if(tangent) vertexStr.push("attribute vec3 tangent2;\n"); 574 } 575 if(tangent) vertexStr.push("attribute vec3 tangent;\n"); 576 vertexStr.push("uniform mat4 worldView;\n"); 577 vertexStr.push("uniform mat4 projection;\n"); 578 vertexStr.push("uniform mat4 worldInverseTranspose;\n"); 579 vertexStr.push("uniform mat4 envMat;\n"); 580 //vertexStr.push("uniform vec3 cameraPos;\n"); 581 vertexStr.push("uniform float cascadeLevel;\n"); 582 583 for(var i=0; i<lights.length;i++){ 584 if(lights[i].type==GLGE.L_OFF) continue; 585 vertexStr.push("uniform vec3 lightpos"+i+";\n"); 586 vertexStr.push("uniform vec3 lightdir"+i+";\n"); 587 588 if((lights[i].type==GLGE.L_SPOT || lights[i].type==GLGE.L_DIR) && lights[i].getCastShadows() ){ 589 vertexStr.push("uniform mat4 lightmat"+i+";\n"); 590 vertexStr.push("varying vec4 spotcoord"+i+";\n"); 591 } 592 } 593 594 vertexStr.push("varying vec3 eyevec;\n"); 595 for(var i=0; i<lights.length;i++){ 596 if(lights[i].type==GLGE.L_OFF) continue; 597 vertexStr.push("varying vec3 lightvec"+i+";\n"); 598 vertexStr.push("varying float lightdist"+i+";\n"); 599 } 600 601 if(this.mesh.joints && this.mesh.joints.length>0){ 602 vertexStr.push("uniform vec4 jointMat["+(3*this.mesh.joints.length)+"];\n"); 603 } 604 605 if(this.material) vertexStr.push(this.material.getVertexVarying(vertexStr)); 606 607 vertexStr.push("varying vec3 n;\n"); 608 vertexStr.push("varying vec3 t;\n"); 609 if(colors) vertexStr.push("varying vec4 vcolor;\n"); 610 vertexStr.push("varying vec4 UVCoord;\n"); 611 vertexStr.push("varying vec3 OBJCoord;\n"); 612 613 if(this.shaderVertexInjection){ 614 vertexStr.push(this.shaderVertexInjection); 615 } 616 617 vertexStr.push("void main(void)\n"); 618 vertexStr.push("{\n"); 619 if(colors) vertexStr.push("vcolor=color;\n"); 620 if(UV) vertexStr.push("UVCoord=UV;\n"); 621 else vertexStr.push("UVCoord=vec4(0.0,0.0,0.0,0.0);\n"); 622 vertexStr.push("OBJCoord = position;\n"); 623 vertexStr.push("vec3 tang;\n"); 624 vertexStr.push("vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n"); 625 vertexStr.push("vec4 norm = vec4(0.0, 0.0, 0.0, 1.0);\n"); 626 if(tangent) vertexStr.push("vec4 tang4 = vec4(0.0, 0.0, 0.0, 1.0);\n"); 627 628 if(joints1){ 629 if(joints1.size==1){ 630 vertexStr.push("pos += vec4(dot(jointMat[int(3.0*joints1)],vec4(position,1.0)),\n"+ 631 " dot(jointMat[int(3.0*joints1+1.0)],vec4(position,1.0)),\n"+ 632 " dot(jointMat[int(3.0*joints1+2.0)],vec4(position,1.0)),1.0)*weights1;\n"); 633 634 vertexStr.push("norm += vec4(dot(jointMat[int(3.0*joints1)].xyz,normal),\n"+ 635 " dot(jointMat[int(3.0*joints1+1.0)].xyz,normal),\n"+ 636 " dot(jointMat[int(3.0*joints1+2.0)].xyz,normal),1.0)*weights1;\n"); 637 if (tangent) 638 vertexStr.push("tang4 += vec4(dot(jointMat[int(3.0*joints1)].xyz,tangent),\n"+ 639 " dot(jointMat[int(3.0*joints1+1.0)].xyz,tangent),\n"+ 640 " dot(jointMat[int(3.0*joints1+2.0)].xyz,tangent),1.0)*weights1;\n"); 641 }else{ 642 for(var i=0;i<joints1.size;i++){ 643 vertexStr.push("pos += vec4(dot(jointMat[int(3.0*joints1["+i+"])],vec4(position,1.0)),\n"+ 644 " dot(jointMat[int(3.0*joints1["+i+"]+1.0)],vec4(position,1.0)),\n"+ 645 " dot(jointMat[int(3.0*joints1["+i+"]+2.0)],vec4(position,1.0)),1.0)*weights1["+i+"];\n"); 646 vertexStr.push("norm += vec4(dot(jointMat[int(3.0*joints1["+i+"])].xyz,normal),\n"+ 647 " dot(jointMat[int(3.0*joints1["+i+"]+1.0)].xyz,normal),\n"+ 648 " dot(jointMat[int(3.0*joints1["+i+"]+2.0)].xyz,normal),1.0)*weights1["+i+"];\n"); 649 if (tangent) 650 vertexStr.push("tang4 += vec4(dot(jointMat[int(3.0*joints1["+i+"])].xyz,tangent),\n"+ 651 " dot(jointMat[int(3.0*joints1["+i+"]+1.0)].xyz,tangent),\n"+ 652 " dot(jointMat[int(3.0*joints1["+i+"]+2.0)].xyz,tangent),1.0)*weights1["+i+"];\n"); 653 } 654 } 655 656 657 if(joints2){ 658 if(joints2.size==1){ 659 vertexStr.push("pos += vec4(dot(jointMat[int(3.0*joints2)],vec4(position,1.0)),\n"+ 660 " dot(jointMat[int(3.0*joints2+1.0)],vec4(position,1.0)),\n"+ 661 " dot(jointMat[int(3.0*joints2+2.0)],vec4(position,1.0)),1.0)*weights2;\n"); 662 vertexStr.push("norm += vec4(dot(jointMat[int(3.0*joints2)].xyz,normal),\n"+ 663 " dot(jointMat[int(3.0*joints2+1.0)].xyz,normal),\n"+ 664 " dot(jointMat[int(3.0*joints2+2.0)].xyz,normal),1.0)*weights2;\n"); 665 if (tangent) 666 vertexStr.push("tang4 += vec4(dot(jointMat[int(3.0*joints2)].xyz,tangent),\n"+ 667 " dot(jointMat[int(3.0*joints2+1.0)].xyz,tangent),\n"+ 668 " dot(jointMat[int(3.0*joints2+2.0)].xyz,tangent),1.0)*weights2;\n"); 669 }else{ 670 for(var i=0;i<joints2.size;i++){ 671 vertexStr.push("pos += vec4(dot(jointMat[int(3.0*joints2["+i+"])],vec4(position,1.0)),\n"+ 672 " dot(jointMat[int(3.0*joints2["+i+"]+1.0)],vec4(position,1.0)),\n"+ 673 " dot(jointMat[int(3.0*joints2["+i+"]+2.0)],vec4(position,1.0)),1.0)*weights2["+i+"];\n"); 674 vertexStr.push("norm += vec4(dot(jointMat[int(3.0*joints2["+i+"])].xyz,normal),\n"+ 675 " dot(jointMat[int(3.0*joints2["+i+"]+1.0)].xyz,normal),\n"+ 676 " dot(jointMat[int(3.0*joints2["+i+"]+2.0)].xyz,normal),1.0)*weights2["+i+"];\n"); 677 if (tangent) 678 vertexStr.push("tang4 += vec4(dot(jointMat[int(3.0*joints2["+i+"])].xyz,tangent),\n"+ 679 " dot(jointMat[int(3.0*joints2["+i+"]+1.0)].xyz,tangent),\n"+ 680 " dot(jointMat[int(3.0*joints2["+i+"]+2.0)].xyz,tangent),1.0)*weights2["+i+"];\n"); 681 } 682 } 683 } 684 685 for(var i=0; i<lights.length;i++){ 686 if(lights[i].type==GLGE.L_OFF) continue; 687 if((lights[i].type==GLGE.L_SPOT || lights[i].type==GLGE.L_DIR) && lights[i].getCastShadows() ){ 688 vertexStr.push("spotcoord"+i+"=lightmat"+i+"*vec4(pos.xyz,1.0);\n"); 689 } 690 } 691 if(this.shaderVertexInjection && this.shaderVertexInjection.indexOf("GLGE_Position")>-1){ 692 vertexStr.push("pos=GLGE_Position(vec4(pos.xyz, 1.0));\n"); 693 } 694 vertexStr.push("pos = worldView * vec4(pos.xyz, 1.0);\n"); 695 vertexStr.push("norm = worldInverseTranspose * vec4(norm.xyz, 1.0);\n"); 696 if(tangent) vertexStr.push("tang = (worldInverseTranspose*vec4(tang4.xyz,1.0)).xyz;\n"); 697 }else{ 698 if(morph){ 699 vertexStr.push("vec4 pos4=vec4(mix(position,position2,framesBlend),1.0);\n"); 700 }else{ 701 vertexStr.push("vec4 pos4=vec4(position,1.0);\n"); 702 } 703 704 705 if(this.shaderVertexInjection && this.shaderVertexInjection.indexOf("GLGE_Position")>-1){ 706 vertexStr.push("pos4=GLGE_Position(pos4);\n"); 707 } 708 709 //vertexStr.push("pos4.xyz = (pos4.xyz-cameraPos.xyz)/(pow(length(pos4.xyz-cameraPos.xyz),0.5))+cameraPos.xyz;\n"); 710 for(var i=0; i<lights.length;i++){ 711 if(lights[i].type==GLGE.L_OFF) continue; 712 if((lights[i].type==GLGE.L_SPOT || lights[i].type==GLGE.L_DIR) && lights[i].getCastShadows() ){ 713 vertexStr.push("spotcoord"+i+"=lightmat"+i+"*pos4;\n"); 714 //vertexStr.push("spotcoord"+i+".w/=2.0;\n"); 715 } 716 } 717 718 vertexStr.push("pos = worldView * pos4;\n"); 719 if(morph){ 720 vertexStr.push("norm = worldInverseTranspose * vec4(mix(normal,normal2,framesBlend), 1.0);\n"); 721 if(tangent) vertexStr.push("tang = (worldInverseTranspose*vec4(mix(tangent,tangent2,framesBlend),1.0)).xyz;\n"); 722 }else{ 723 vertexStr.push("norm = worldInverseTranspose * vec4(normal, 1.0);\n"); 724 if(tangent) vertexStr.push("tang = (worldInverseTranspose*vec4(tangent,1.0)).xyz;\n"); 725 } 726 } 727 728 729 730 731 vertexStr.push("eyevec = -pos.xyz;\n"); 732 733 if(tangent) vertexStr.push("t = normalize(tang);"); 734 else vertexStr.push("t = vec3(0.0,0.0,0.0);"); 735 vertexStr.push("n = normalize(norm.rgb);"); 736 737 738 for(var i=0; i<lights.length;i++){ 739 if(lights[i].type==GLGE.L_OFF) continue; 740 if(lights[i].getType()==GLGE.L_DIR){ 741 vertexStr.push("lightvec"+i+" = -lightdir"+i+";\n"); 742 }else{ 743 vertexStr.push("lightvec"+i+" = pos.xyz-lightpos"+i+";\n"); 744 } 745 746 vertexStr.push("lightdist"+i+" = length(lightpos"+i+".xyz-pos.xyz);\n"); 747 } 748 if(this.material) vertexStr.push(this.material.getLayerCoords(this.shaderVertexInjection)); 749 vertexStr.push("gl_Position = projection * pos;\n"); 750 vertexStr.push("gl_PointSize="+(this.pointSize.toFixed(5))+";\n"); 751 vertexStr.push("}\n"); 752 753 vertexStr=vertexStr.join(""); 754 755 //Fragment Shader 756 fragStr=this.material.getFragmentShader(lights,colors,this.shaderVertexInjection); 757 758 this.GLFragmentShaderNormal=GLGE.getGLShader(gl,gl.FRAGMENT_SHADER,this.nfragStr); 759 this.GLFragmentShaderShadow=GLGE.getGLShader(gl,gl.FRAGMENT_SHADER,this.shfragStr); 760 this.GLFragmentShaderPick=GLGE.getGLShader(gl,gl.FRAGMENT_SHADER,this.pkfragStr); 761 this.GLFragmentShader=GLGE.getGLShader(gl,gl.FRAGMENT_SHADER,fragStr); 762 this.GLVertexShader=GLGE.getGLShader(gl,gl.VERTEX_SHADER,vertexStr+"//default"); 763 this.GLVertexShaderShadow=GLGE.getGLShader(gl,gl.VERTEX_SHADER,vertexStr+"//shadow"); 764 this.GLVertexShaderPick=GLGE.getGLShader(gl,gl.VERTEX_SHADER,vertexStr+"//pick"); 765 this.GLVertexShaderNormal=GLGE.getGLShader(gl,gl.VERTEX_SHADER,vertexStr+"//normal"); 766 767 this.GLShaderProgramPick=GLGE.getGLProgram(gl,this.GLVertexShaderPick,this.GLFragmentShaderPick); 768 this.GLShaderProgramNormal=GLGE.getGLProgram(gl,this.GLVertexShaderNormal,this.GLFragmentShaderNormal); 769 this.GLShaderProgramShadow=GLGE.getGLProgram(gl,this.GLVertexShaderShadow,this.GLFragmentShaderShadow); 770 this.GLShaderProgram=GLGE.getGLProgram(gl,this.GLVertexShaderShadow,this.GLFragmentShader); 771 772 //if we failed then check for fallback option 773 if (!gl.getProgramParameter(this.GLShaderProgram, gl.LINK_STATUS)) { 774 if(this.material.fallback){ 775 this.material=this.material.fallback; 776 this.multimaterial.material=this.material; 777 this.GLGenerateShader(gl); 778 } 779 } 780 781 } 782 /** 783 * creates shader programs; 784 * @param multimaterial the multimaterial object to create the shader programs for 785 * @private 786 */ 787 GLGE.Object.prototype.createShaders=function(multimaterial){ 788 if(this.gl){ 789 this.mesh=multimaterial.mesh; 790 this.material=multimaterial.material; 791 this.multimaterial=multimaterial; 792 this.GLGenerateShader(this.gl); 793 multimaterial.GLShaderProgramPick=this.GLShaderProgramPick; 794 multimaterial.GLShaderProgramShadow=this.GLShaderProgramShadow; 795 multimaterial.GLShaderProgram=this.GLShaderProgram; 796 } 797 } 798 799 /** 800 * Sets the shader program uniforms ready for rendering 801 * @private 802 */ 803 GLGE.Object.prototype.GLUniforms=function(gl,renderType,pickindex){ 804 var program; 805 switch(renderType){ 806 case GLGE.RENDER_DEFAULT: 807 program=this.GLShaderProgram; 808 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "emitpass"), 0); 809 break; 810 case GLGE.RENDER_EMIT: 811 program=this.GLShaderProgram; 812 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "emitpass"), 1); 813 break; 814 case GLGE.RENDER_SHADOW: 815 program=this.GLShaderProgramShadow; 816 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "shadowtype"), 1); 817 break; 818 case GLGE.RENDER_DEPTH: 819 program=this.GLShaderProgramShadow; 820 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,program, "cascadeLevel"), 2); 821 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "shadowtype"), 0); 822 break; 823 case GLGE.RENDER_NORMAL: 824 program=this.GLShaderProgramNormal; 825 break; 826 case GLGE.RENDER_PICK: 827 program=this.GLShaderProgramPick; 828 var b = pickindex >> 16 & 0xFF; 829 var g = pickindex >> 8 & 0xFF; 830 var r = pickindex & 0xFF; 831 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "pickcolor"), r/255,g/255,b/255); 832 break; 833 } 834 //set the line width 835 gl.lineWidth(this.lineWidth); 836 837 //set custom uinforms 838 for(var key in this.uniforms){ 839 var uniform=this.uniforms[key]; 840 if(uniform.type=="Matrix4fv"){ 841 GLGE.setUniformMatrix(gl,"Matrix4fv",GLGE.getUniformLocation(gl,program, key),false,uniform.value); 842 }else{ 843 GLGE.setUniform(gl,uniform.type,GLGE.getUniformLocation(gl,program, key),uniform.value); 844 } 845 } 846 847 if(!program.caches) program.caches={}; 848 if(!program.glarrays) program.glarrays={}; 849 var pc=program.caches; 850 var pgl=program.glarrays; 851 var scene=gl.scene; 852 var camera=scene.camera; 853 854 if(pc.far!=camera.far){ 855 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "far"), camera.far); 856 pc.far=camera.far; 857 } 858 if(renderType==GLGE.RENDER_DEFAULT || renderType==GLGE.RENDER_EMIT){ 859 if(pc.ambientColor!=scene.ambientColor){ 860 var ambientColor=scene.ambientColor; 861 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "amb"), ambientColor.r,ambientColor.g,ambientColor.b); 862 pc.ambientColor=ambientColor; 863 } 864 if(pc.fogFar!=scene.fogFar){ 865 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,program, "fogfar"), scene.fogFar); 866 pc.fogFar=scene.fogFar; 867 } 868 if(pc.fogNear!=scene.fogNear){ 869 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,program, "fognear"), scene.fogNear); 870 pc.fogNear=scene.fogNear; 871 } 872 if(pc.fogType!=scene.fogType){ 873 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,program, "fogtype"), scene.fogType); 874 pc.fogType=scene.fogType; 875 } 876 if(pc.fogType!=scene.fogcolor){ 877 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "fogcolor"), scene.fogColor.r,scene.fogColor.g,scene.fogColor.b); 878 pc.fogcolor=scene.fogcolor; 879 } 880 } 881 if(pc.meshBlendFactor!=this.meshBlendFactor){ 882 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,program, "framesBlend"), this.meshBlendFactor); 883 pc.meshBlendFactor=this.meshBlendFactor; 884 } 885 886 887 888 var cameraMatrix=camera.getViewMatrix(); 889 var objMatrix=modelMatrix=this.getModelMatrix(); 890 891 if(!pc.mvMatrix) pc.mvMatrix={cameraMatrix:null,modelMatrix:null}; 892 var mvCache=pc.mvMatrix; 893 894 if(mvCache.cameraMatrix!=cameraMatrix || mvCache.modelMatrix!=modelMatrix){ 895 //generate and set the modelView matrix 896 if(!this.caches.mvMatrix) this.caches.mvMatrix=GLGE.mulMat4(cameraMatrix,modelMatrix); 897 mvMatrix=this.caches.mvMatrix; 898 899 if(this.mesh.joints){ 900 mvMatrix=cameraMatrix; 901 } 902 903 //GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "cameraPos"),camera.location[0],camera.location[1],camera.location[2]); 904 905 var mvUniform = GLGE.getUniformLocation(gl,program, "worldView"); 906 var M1=GLGE.transposeMat4(mvMatrix); 907 if(!pgl.mvMatrix){ 908 pgl.mvMatrixT=new Float32Array(M1); 909 }else{ 910 GLGE.mat4gl(M1,pgl.mvMatrixT); 911 } 912 //GLGE.reuseMatrix4(M1); 913 pgl.mvMatrix=mvMatrix; 914 GLGE.setUniformMatrix(gl,"Matrix4fv",mvUniform, false, program.glarrays.mvMatrixT); 915 916 //invCamera matrix 917 var icUniform = GLGE.getUniformLocation(gl,program, "envMat"); 918 if(icUniform){ 919 if(!this.caches.envMat){ 920 var envMat = GLGE.inverseMat4(mvMatrix); 921 envMat[3]=0; 922 envMat[7]=0; 923 envMat[11]=0; 924 this.caches.envMat = envMat; 925 } 926 envMat=this.caches.envMat; 927 M1=GLGE.transposeMat4(envMat); 928 if(!program.glarrays.envMat){ 929 pgl.envMatT=new Float32Array(M1); 930 }else{ 931 GLGE.mat4gl(M1,pgl.envMatT); 932 } 933 //GLGE.reuseMatrix4(M1); 934 pgl.envMat=envMat; 935 936 GLGE.setUniformMatrix(gl,"Matrix4fv",icUniform, false, pgl.envMatT); 937 } 938 //normalising matrix 939 if(!this.caches.normalMatrix){ 940 var normalMatrix = GLGE.inverseMat4(mvMatrix); 941 this.caches.normalMatrix = normalMatrix; 942 } 943 normalMatrix=this.caches.normalMatrix; 944 var nUniform = GLGE.getUniformLocation(gl,program, "worldInverseTranspose"); 945 946 if(!pgl.normalMatrix) pgl.normalMatrix=new Float32Array(normalMatrix); 947 else GLGE.mat4gl(normalMatrix,pgl.normalMatrix); 948 GLGE.setUniformMatrix(gl,"Matrix4fv",nUniform, false, pgl.normalMatrix); 949 950 var cUniform = GLGE.getUniformLocation(gl,program, "view"); 951 M1=GLGE.transposeMat4(cameraMatrix); 952 if(!pgl.cameraMatrix){ 953 pgl.cameraMatrixT=new Float32Array(M1); 954 }else{ 955 GLGE.mat4gl(M1,pgl.cameraMatrixT); 956 } 957 //GLGE.reuseMatrix4(M1); 958 pgl.cameraMatrix=cameraMatrix; 959 960 GLGE.setUniformMatrix(gl,"Matrix4fv",cUniform, false, pgl.cameraMatrixT); 961 962 mvCache.cameraMatrix=cameraMatrix; 963 mvCache.modelMatrix=modelMatrix; 964 } 965 966 967 var pUniform = GLGE.getUniformLocation(gl,program, "projection"); 968 M1=GLGE.transposeMat4(camera.getProjectionMatrix()); 969 if(!pgl.pMatrix){ 970 pgl.pMatrixT=new Float32Array(M1); 971 }else{ 972 GLGE.mat4gl(M1,pgl.pMatrixT); 973 } 974 //GLGE.reuseMatrix4(M1); 975 pgl.pMatrix=camera.getProjectionMatrix(); 976 977 GLGE.setUniformMatrix(gl,"Matrix4fv",pUniform, false, pgl.pMatrixT); 978 979 980 981 982 //light 983 //dont' need lighting for picking 984 if(renderType==GLGE.RENDER_DEFAULT || renderType==GLGE.RENDER_SHADOW || renderType==GLGE.RENDER_DEPTH || renderType==GLGE.RENDER_EMIT){ 985 var pos,lpos; 986 var lights=gl.lights 987 if(!pc.lights) pc.lights=[]; 988 if(!pgl.lights) pgl.lights=[]; 989 if(!this.caches.lights) this.caches.lights=[]; 990 var lightCache=pc.lights; 991 for(var i=0; i<lights.length;i++){ 992 if(lights[i].type==GLGE.L_OFF) continue; 993 if(!lightCache[i]) lightCache[i]={modelMatrix:null,cameraMatrix:null}; 994 if(lightCache[i].modelMatrix!=modelMatrix || lightCache[i].cameraMatrix!=cameraMatrix){ 995 if(!this.caches.lights[i])this.caches.lights[i]={}; 996 997 if(!this.caches.lights[i].pos) this.caches.lights[i].pos=GLGE.mulMat4Vec4(GLGE.mulMat4(cameraMatrix,lights[i].getModelMatrix()),[0,0,0,1]); 998 pos=this.caches.lights[i].pos; 999 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "lightpos"+i), pos[0],pos[1],pos[2]); 1000 1001 1002 if(!this.caches.lights[i].lpos) this.caches.lights[i].lpos=GLGE.mulMat4Vec4(GLGE.mulMat4(cameraMatrix,lights[i].getModelMatrix()),[0,0,1,1]); 1003 lpos=this.caches.lights[i].lpos; 1004 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,program, "lightdir"+i),lpos[0]-pos[0],lpos[1]-pos[1],lpos[2]-pos[2]); 1005 1006 if(lights[i].s_cache){ 1007 var lightmat=GLGE.mulMat4(lights[i].s_cache.smatrix,modelMatrix); 1008 if(!pgl.lights[i]) pgl.lights[i]=new Float32Array(lightmat); 1009 else GLGE.mat4gl(lightmat,pgl.lights[i]); 1010 GLGE.setUniformMatrix(gl,"Matrix4fv",GLGE.getUniformLocation(gl,program, "lightmat"+i), true,pgl.lights[i]); 1011 GLGE.setUniform2(gl,"2f",GLGE.getUniformLocation(gl,program, "shadowoffset"+i), lights[i].s_cache.pmatrix[3],lights[i].s_cache.pmatrix[7]); 1012 lightCache[i].modelMatrix=modelMatrix; 1013 lightCache[i].cameraMatrix=cameraMatrix; 1014 }else{ 1015 lightCache[i].modelMatrix=modelMatrix; 1016 lightCache[i].cameraMatrix=cameraMatrix; 1017 } 1018 } 1019 } 1020 } 1021 1022 if(this.mesh.joints){ 1023 if(!pc.joints) pc.joints=[]; 1024 if(!pgl.joints) pgl.joints=[]; 1025 if(!pgl.jointsT) pgl.jointsT=[]; 1026 if(!pgl.jointsinv) pgl.jointsinv=[]; 1027 if ((!pgl.jointsCombined)||pgl.jointsCombined.length!=this.mesh.joints.length*12) 1028 pgl.jointsCombined = new Float32Array(this.mesh.joints.length*12); 1029 var jointCache=pc.joints; 1030 var ident=GLGE.identMatrix(); 1031 for(i=0;i<this.mesh.joints.length;i++){ 1032 if(!jointCache[i]) jointCache[i]={modelMatrix:null,invBind:null}; 1033 if(typeof this.mesh.joints[i]=="string"){ 1034 if(!this.bones) this.bones=this.skeleton.getNames(); 1035 if(this.bones){ 1036 var modelMatrix=this.bones[this.mesh.joints[i]].getModelMatrix(); 1037 } 1038 }else{ 1039 var modelMatrix=this.mesh.joints[i].getModelMatrix(); 1040 } 1041 var invBind=this.mesh.invBind[i]; 1042 if(jointCache[i].modelMatrix!=modelMatrix || jointCache[i].invBind!=invBind){ 1043 var jointmat=GLGE.mulMat4(modelMatrix,invBind); 1044 //jointmat=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]; 1045 if(!pgl.joints[i]){ 1046 pgl.jointsT[i]=new Float32Array(GLGE.transposeMat4(jointmat)); 1047 }else{ 1048 GLGE.mat4gl(GLGE.transposeMat4(jointmat),pgl.jointsT[i]); 1049 } 1050 pgl.joints[i]=jointmat; 1051 if(!pgl.jointsinv[i]) pgl.jointsinv[i]=new Float32Array(GLGE.inverseMat4(jointmat)); 1052 else GLGE.mat4gl(GLGE.inverseMat4(jointmat),pgl.jointsinv[i]); 1053 var mat=pgl.jointsT[i]; 1054 var combinedMat=pgl.jointsCombined; 1055 combinedMat[i*12]=mat[0]; 1056 combinedMat[i*12+1]=mat[4]; 1057 combinedMat[i*12+2]=mat[8]; 1058 combinedMat[i*12+3]=mat[12]; 1059 1060 combinedMat[i*12+4]=mat[1]; 1061 combinedMat[i*12+5]=mat[5]; 1062 combinedMat[i*12+6]=mat[9]; 1063 combinedMat[i*12+7]=mat[13]; 1064 1065 1066 combinedMat[i*12+8]=mat[2]; 1067 combinedMat[i*12+9]=mat[6]; 1068 combinedMat[i*12+10]=mat[10]; 1069 combinedMat[i*12+11]=mat[14]; 1070 1071 //GLGE.setUniform4(gl,"4f",GLGE.getUniformLocation(gl,program, "jointMat["+(i*3)+"]"), mat[0],mat[4],mat[8],mat[12]); 1072 //GLGE.setUniform4(gl,"4f",GLGE.getUniformLocation(gl,program, "jointMat["+(i*3+1)+"]"), mat[1],mat[5],mat[9],mat[13]); 1073 //GLGE.setUniform4(gl,"4f",GLGE.getUniformLocation(gl,program, "jointMat["+(i*3+2)+"]"), mat[2],mat[6],mat[10],mat[14]); 1074 jointCache[i].modelMatrix=modelMatrix; 1075 jointCache[i].invBind=invBind; 1076 } 1077 } 1078 gl.uniform4fv(GLGE.getUniformLocation(gl,program, "jointMat"),pgl.jointsCombined); 1079 } 1080 1081 1082 if(this.material && (renderType==GLGE.RENDER_DEFAULT || renderType==GLGE.RENDER_EMIT) && gl.scene.lastMaterial!=this.material){ 1083 this.material.textureUniforms(gl,program,lights,this); 1084 gl.scene.lastMaterial=this.material; 1085 } 1086 } 1087 /** 1088 * Renders the object to the screen 1089 * @private 1090 */ 1091 GLGE.Object.prototype.GLRender=function(gl,renderType,pickindex,multiMaterial,distance){ 1092 if(!gl) return; 1093 if(!this.gl) this.GLInit(gl); 1094 1095 //if look at is set then look 1096 if(this.lookAt) this.Lookat(this.lookAt); 1097 1098 //animate this object 1099 if(renderType==GLGE.RENDER_DEFAULT){ 1100 if(this.animation) this.animate(); 1101 } 1102 1103 if(!this.renderCaches[renderType]) this.renderCaches[renderType]={}; 1104 1105 var cameraMatrix=gl.scene.camera.getViewMatrix(); 1106 var modelMatrix=this.getModelMatrix(); 1107 1108 if(this.renderCaches[renderType].cameraMatrix!=cameraMatrix || this.renderCaches[renderType].modelMatrix!=modelMatrix){ 1109 this.renderCaches[renderType]={}; 1110 this.renderCaches[renderType].cameraMatrix=cameraMatrix; 1111 this.renderCaches[renderType].modelMatrix=modelMatrix; 1112 } 1113 1114 this.caches=this.renderCaches[renderType]; 1115 1116 1117 1118 1119 var pixelsize; 1120 1121 if(multiMaterial==undefined){ 1122 var start=0; 1123 var end=this.multimaterials.length; 1124 }else{ 1125 var start=multiMaterial; 1126 var end=multiMaterial+1; 1127 } 1128 1129 for(var i=start; i<end;i++){ 1130 if(this.multimaterials[i].lods.length>1 && !pixelsize){ 1131 var camerapos=gl.scene.camera.getPosition(); 1132 var modelpos=this.getPosition(); 1133 var dist=GLGE.lengthVec3([camerapos.x-modelpos.x,camerapos.y-modelpos.y,camerapos.z-modelpos.z]); 1134 dist=GLGE.mulMat4Vec4(gl.scene.camera.getProjectionMatrix(),[this.getBoundingVolume().getSphereRadius(),0,-dist,1]); 1135 pixelsize=dist[0]/dist[3]*gl.scene.renderer.canvas.width; 1136 } 1137 1138 var lod=this.multimaterials[i].getLOD(pixelsize); 1139 1140 if(lod.mesh && lod.mesh.loaded){ 1141 if(renderType==GLGE.RENDER_NULL){ 1142 if(lod.material) lod.material.registerPasses(gl,this); 1143 break; 1144 } 1145 if(!lod.GLShaderProgram){ 1146 this.createShaders(lod); 1147 }else{ 1148 this.GLShaderProgramPick=lod.GLShaderProgramPick; 1149 this.GLShaderProgramShadow=lod.GLShaderProgramShadow; 1150 this.GLShaderProgram=lod.GLShaderProgram; 1151 } 1152 this.mesh=lod.mesh; 1153 this.material=lod.material; 1154 1155 var drawType; 1156 switch(this.drawType){ 1157 case GLGE.DRAW_LINES: 1158 drawType=gl.LINES; 1159 break; 1160 case GLGE.DRAW_POINTS: 1161 drawType=gl.POINTS; 1162 break; 1163 case GLGE.DRAW_LINELOOPS: 1164 drawType=gl.LINE_LOOP; 1165 break; 1166 case GLGE.DRAW_LINESTRIPS: 1167 drawType=gl.LINE_STRIP; 1168 break; 1169 case GLGE.DRAW_TRIANGLESTRIP: 1170 drawType=gl.TRIANGLE_STRIP; 1171 break; 1172 default: 1173 drawType=gl.TRIANGLES; 1174 break; 1175 } 1176 1177 switch(renderType){ 1178 case GLGE.RENDER_DEFAULT: 1179 case GLGE.RENDER_EMIT: 1180 if(gl.program!=this.GLShaderProgram){ 1181 gl.useProgram(this.GLShaderProgram); 1182 gl.program=this.GLShaderProgram; 1183 1184 } 1185 this.mesh.GLAttributes(gl,this.GLShaderProgram,this.meshFrame1,this.meshFrame2); 1186 break; 1187 case GLGE.RENDER_SHADOW: 1188 case GLGE.RENDER_DEPTH: 1189 if(gl.program!=this.GLShaderProgramShadow){ 1190 gl.useProgram(this.GLShaderProgramShadow,this.meshFrame1,this.meshFrame2); 1191 gl.program=this.GLShaderProgramShadow; 1192 } 1193 if(!distance) distance=gl.scene.camera.getFar(); 1194 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,this.GLShaderProgramShadow, "distance"), distance); 1195 this.mesh.GLAttributes(gl,this.GLShaderProgramShadow,this.meshFrame1,this.meshFrame2); 1196 break; 1197 case GLGE.RENDER_NORMAL: 1198 if(gl.program!=this.GLShaderProgramNormal){ 1199 gl.useProgram(this.GLShaderProgramNormal); 1200 gl.program=this.GLShaderProgramNormal; 1201 } 1202 this.mesh.GLAttributes(gl,this.GLShaderProgramNormal,this.meshFrame1,this.meshFrame2); 1203 break; 1204 case GLGE.RENDER_PICK: 1205 if(gl.program!=this.GLShaderProgramPick){ 1206 gl.useProgram(this.GLShaderProgramPick); 1207 gl.program=this.GLShaderProgramPick; 1208 } 1209 this.mesh.GLAttributes(gl,this.GLShaderProgramPick,this.meshFrame1,this.meshFrame2); 1210 drawType=gl.TRIANGLES; 1211 break; 1212 } 1213 //render the object 1214 this.GLUniforms(gl,renderType,pickindex); 1215 switch (this.mesh.windingOrder) { 1216 case GLGE.Mesh.WINDING_ORDER_UNKNOWN: 1217 if (gl.scene.renderer.cullFaces) 1218 gl.enable(gl.CULL_FACE); 1219 else 1220 gl.disable(gl.CULL_FACE); 1221 break; 1222 case GLGE.Mesh.WINDING_ORDER_CLOCKWISE: 1223 gl.enable(gl.CULL_FACE); 1224 break; 1225 case GLGE.Mesh.WINDING_ORDER_COUNTER: 1226 gl.cullFace(gl.FRONT); 1227 gl.enable(gl.CULL_FACE); 1228 1229 default: 1230 break; 1231 } 1232 if(this.mesh.GLfaces){ 1233 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mesh.GLfaces); 1234 gl.drawElements(drawType, this.mesh.GLfaces.numItems, gl.UNSIGNED_SHORT, 0); 1235 }else{ 1236 gl.drawArrays(drawType, 0, this.mesh.positions.length/3); 1237 } 1238 1239 switch (this.mesh.windingOrder) { 1240 case GLGE.Mesh.WINDING_ORDER_UNKNOWN: 1241 if (gl.scene.renderer.cullFaces) 1242 gl.enable(gl.CULL_FACE); 1243 break; 1244 case GLGE.Mesh.WINDING_ORDER_COUNTER: 1245 gl.cullFace(gl.BACK); 1246 default: 1247 break; 1248 } 1249 var matrix=this.matrix; 1250 var caches=this.caches; 1251 1252 1253 this.matrix=matrix; 1254 this.caches=caches; 1255 } 1256 } 1257 } 1258 1259 })(GLGE);