1 /* 2 GLGE WebGL Graphics Engine 3 Copyright (C)2009 Paul Brunt 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /** 21 * @fileOverview 22 * @name glge.js 23 * @author paul.brunt@armourhome.co.uk 24 */ 25 26 // Start of compatibility code 27 try 28 { 29 WebGLFloatArray; 30 } 31 catch (e) 32 { 33 try 34 { 35 WebGLFloatArray = CanvasFloatArray; 36 WebGLUnsignedShortArray = CanvasUnsignedShortArray; 37 } 38 catch (e) 39 { 40 alert("Could not find any WebGL array types."); 41 } 42 } 43 // End of compatibility code 44 45 46 /** 47 * @namespace Holds the functionality of the library 48 */ 49 var GLGE={}; 50 51 (function(GLGE){ 52 53 54 55 /** 56 * @constant 57 * @description Enumeration for TRUE 58 */ 59 GLGE.TRUE=1; 60 /** 61 * @constant 62 * @description Enumeration for FALSE 63 */ 64 GLGE.FALSE=0; 65 66 /** 67 * @class Document class to load scene, object, mesh etc from an external XML file 68 * @param {string} url URL of the resource to load 69 */ 70 GLGE.Document=function(url){ 71 this.listeners=[]; 72 this.documents=[]; 73 this.rootURL=url; 74 this.loadDocument(url,null); 75 } 76 GLGE.Document.prototype.listeners=null; 77 GLGE.Document.prototype.documents=null; 78 GLGE.Document.prototype.rootURL=null; 79 GLGE.Document.prototype.loadCount=0; 80 /** 81 * Gets the absolute path given an import path and the path it's relative to 82 * @param {string} path the path to get the absolute path for 83 * @param {string} relativeto the path the supplied path is relativeto 84 * @returns {string} absolute path 85 * @private 86 */ 87 GLGE.Document.prototype.getAbsolutePath=function(path,relativeto){ 88 if(path.substr(0,7)=="http://"){ 89 return path; 90 } 91 else 92 { 93 if(!relativeto){ 94 relativeto=window.location.href; 95 } 96 //find the path compoents 97 var bits=relativeto.split("/"); 98 var domain=bits[2]; 99 var initpath=[]; 100 for(var i=3;i<bits.length-1;i++){ 101 initpath.push(bits[i]); 102 } 103 //relative to domain 104 if(path.substr(0,1)=="/"){ 105 initpath=[]; 106 } 107 var locpath=path.split("/"); 108 for(i=0;i<locpath.length;i++){ 109 if(locpath[i]=="..") initpath.pop(); 110 else if(locpath[i]!="") initpath.push(locpath[i]); 111 } 112 return "http://"+domain+"/"+initpath.join("/"); 113 } 114 } 115 /** 116 * Loads an additional documents into the collection 117 * @param {string} url URL of the resource to load 118 * @param {string} relativeto the path the URL is relative to, null for default 119 */ 120 GLGE.Document.prototype.loadDocument=function(url,relativeto){ 121 this.loadCount++; 122 url=this.getAbsolutePath(url,relativeto); 123 var req = new XMLHttpRequest(); 124 if(req) { 125 req.docurl=url; 126 req.docObj=this; 127 req.onreadystatechange = function() { 128 if(this.readyState == 4) 129 { 130 if(this.status == 200){ 131 this.docObj.loaded(this.docurl,this.responseXML); 132 }else{ 133 GLGE.error("Error loading Document: "+this.docurl); 134 } 135 } 136 }; 137 req.open("GET", url, true); 138 req.send(""); 139 } 140 } 141 /** 142 * Trigered when a document has finished loading 143 * @param {string} url the absolute url of the document that has loaded 144 * @param {XMLDoc} responceXML the xml document that has finished loading 145 * @private 146 */ 147 GLGE.Document.prototype.loaded=function(url,responceXML){ 148 this.loadCount--; 149 this.documents[url]={xml:responceXML}; 150 var imports=responceXML.getElementsByTagName("import"); 151 for(var i=0; i<imports.length;i++){ 152 if(!this.documents[this.getAbsolutePath(imports[i].getAttribute("url"),url)]){ 153 this.documents[this.getAbsolutePath(imports[i].getAttribute("url"),url)]={}; 154 this.loadDocument(imports[i].getAttribute("url"),url); 155 } 156 } 157 if(this.loadCount==0){ 158 this.finishedLoading(); 159 } 160 } 161 /** 162 * Called when all documents have finished loading 163 * @private 164 */ 165 GLGE.Document.prototype.finishedLoading=function(){ 166 for(var i=0; i<this.listeners.length;i++){ 167 this.listeners[i](this.listeners.rootURL); 168 } 169 this.onLoad(); 170 } 171 /** 172 * Called when all documents have finished loading 173 * @event 174 */ 175 GLGE.Document.prototype.onLoad=function(){}; 176 /** 177 * Converts and attribute name into a class name 178 * @param {string} name attribute name to convert 179 * @private 180 */ 181 GLGE.Document.prototype.classString=function(name){ 182 if(!name) return false; 183 var names=name.split("_"); 184 var converted=""; 185 for(var i=0;i<names.length;i++){ 186 converted=converted+names[i][0].toUpperCase()+names[i].substr(1); 187 } 188 return converted; 189 } 190 /** 191 * Sets the properties of an object based on the attributes of the corresponding dom element 192 * @param {object} Obj the DOM element to apply the attributes of 193 * @private 194 */ 195 GLGE.Document.prototype.setProperties=function(Obj){ 196 var set_method; 197 var attribute_name; 198 var value; 199 for(var i=0; i<Obj.attributes.length; i++){ 200 set_method="set"+this.classString(Obj.attributes[i].nodeName); 201 if(Obj.attributes[i].value[0]=="#"){ 202 value=this.getElement(Obj.attributes[i].value.substr(1)); 203 } 204 else 205 { 206 //if this is a GLGE contsant then set the constant value otherwise just literal 207 if(typeof(GLGE[Obj.attributes[i].value]) != "undefined"){ 208 value=GLGE[Obj.attributes[i].value]; 209 } 210 else 211 { 212 value=Obj.attributes[i].value; 213 } 214 } 215 if(Obj.object[set_method]) Obj.object[set_method](value); 216 } 217 } 218 /** 219 * Adds child objects 220 * @param {object} Obj the DOM element to apply the children of 221 * @private 222 */ 223 GLGE.Document.prototype.addChildren=function(Obj){ 224 //loop though and add the children 225 var add_method; 226 var child=Obj.firstChild; 227 while(child){ 228 add_method="add"+this.classString(child.tagName); 229 if(Obj.object[add_method]) Obj.object[add_method](this.getElement(child)); 230 child=child.nextSibling; 231 } 232 } 233 /** 234 * Gets an object from the XML document based on the dom element 235 * @param {string|domelement} ele the id of the element to get or the dom node 236 */ 237 GLGE.Document.prototype.getElement=function(ele){ 238 var docele,doc; 239 if(typeof(ele)=="string"){ 240 for(doc in this.documents){ 241 if(this.documents[doc].xml){ 242 docele=this.documents[doc].xml.getElementById(ele); 243 if(docele){ 244 ele=docele; 245 break; 246 } 247 } 248 } 249 } 250 if(typeof(ele)=="string"){ 251 //if element is still a string at this point there there is an issue 252 GLGE.error("Element "+ele+" not found in document"); 253 return false; 254 } 255 else 256 { 257 if(this["get"+this.classString(ele.tagName)]){ 258 return this["get"+this.classString(ele.tagName)](ele); 259 } 260 else 261 { 262 return this.getDefault(ele); 263 } 264 } 265 } 266 /** 267 * Parses the dom element and creates any objects that are required 268 * @param {domelement} ele the element to create the objects from 269 * @private 270 */ 271 GLGE.Document.prototype.getDefault=function(ele){ 272 if(!ele.object){ 273 if(GLGE[this.classString(ele.tagName)]){ 274 ele.object=new GLGE[this.classString(ele.tagName)](); 275 this.setProperties(ele); 276 this.addChildren(ele); 277 } 278 else 279 { 280 GLGE.error("XML Parse Error: GLGE Object not found"); 281 } 282 } 283 return ele.object; 284 } 285 /** 286 * Parses the dom element and creates a texture 287 * @param {domelement} ele the element to create the objects from 288 * @private 289 */ 290 GLGE.Document.prototype.getTexture=function(ele){ 291 if(!ele.object){ 292 var rel=this.getAbsolutePath(this.rootURL,null); 293 ele.object=new GLGE.Texture(this.getAbsolutePath(ele.getAttribute("src"),rel)); 294 } 295 return ele.object; 296 } 297 /** 298 * Parses a document node into an array 299 * @param {node} the node to parse 300 * @private 301 */ 302 GLGE.Document.prototype.parseArray=function(node){ 303 var child=node.firstChild; 304 var prev=""; 305 var output=[]; 306 var currentArray; 307 while(child){ 308 currentArray=(prev+child.nodeValue).split(","); 309 child=child.nextSibling; 310 if(currentArray[0]=="") currentArray.unshift(); 311 if(child) prev=currentArray.pop(); 312 output=output.concat(currentArray); 313 } 314 return output; 315 } 316 /** 317 * Parses the skeleton to create the object 318 * @param {domelement} ele the element to create the skeleton 319 * @private 320 */ 321 GLGE.Document.prototype.getSkeleton=function(ele){ 322 if(!ele.object){ 323 ele.object=new GLGE.Skeleton(); 324 this.setProperties(ele); 325 var child=ele.firstChild; 326 while(child){ 327 switch(child.tagName){ 328 case "bone": 329 ele.object.addBone(new GLGE.Bone(child.getAttribute("channel"),child.getAttribute("x"),child.getAttribute("y"),child.getAttribute("z")),child.getAttribute("parent")); 330 break; 331 } 332 child=child.nextSibling; 333 } 334 } 335 return ele.object; 336 } 337 /** 338 * Parses the skeletal animation to create the object 339 * @param {domelement} ele the element to create the skeletal animation from 340 * @private 341 */ 342 GLGE.Document.prototype.getSkeletalAction=function(ele){ 343 if(!ele.object){ 344 ele.object=new GLGE.SkeletalAction(ele.getAttribute("frames")); 345 this.setProperties(ele); 346 var child=ele.firstChild; 347 while(child){ 348 switch(child.tagName){ 349 case "animation": 350 ele.object.addAnimationVector(child.getAttribute("channel"),this.getElement(child.getAttribute("vector").substr(1))); 351 break; 352 } 353 child=child.nextSibling; 354 } 355 } 356 return ele.object; 357 } 358 /** 359 * Parses the mesh dom to create the mesh object 360 * @param {domelement} ele the element to create the mesh from 361 * @private 362 */ 363 GLGE.Document.prototype.getMesh=function(ele){ 364 if(!ele.object){ 365 ele.object=new GLGE.Mesh(); 366 this.setProperties(ele); 367 child=ele.firstChild; 368 while(child){ 369 switch(child.tagName){ 370 case "positions": 371 ele.object.setPositions(this.parseArray(child)); 372 break; 373 case "normals": 374 ele.object.setNormals(this.parseArray(child)); 375 break; 376 case "uv1": 377 ele.object.setUV(this.parseArray(child)); 378 break; 379 case "faces": 380 ele.object.setFaces(this.parseArray(child)); 381 break; 382 case "weights": 383 ele.object.addBoneWeights(child.getAttribute("channel"),this.parseArray(child)); 384 break; 385 } 386 child=child.nextSibling; 387 } 388 } 389 return ele.object; 390 } 391 /** 392 * Parese the animation vector dom to create the mesh object 393 * @param {domelement} ele the element to create the animation vector from 394 * @private 395 */ 396 GLGE.Document.prototype.getAnimationVector=function(ele){ 397 if(!ele.object){ 398 ele.object=new GLGE.AnimationVector(); 399 this.setProperties(ele); 400 child=ele.firstChild; 401 var point; 402 var curve; 403 while(child){ 404 switch(child.tagName){ 405 case "animation_curve": 406 curve=new GLGE.AnimationCurve(); 407 bezs=child.getElementsByTagName("bez_point"); 408 for(var i=0; i<bezs.length;i++){ 409 point=bezs[i].firstChild.nodeValue.split(","); 410 curve.addPoint(new GLGE.BezTriple(point[0],point[1],point[2],point[3],point[4],point[5],point[6])); 411 } 412 ele.object.addCurve(child.getAttribute("channel"),curve); 413 414 break; 415 } 416 child=child.nextSibling; 417 } 418 } 419 return ele.object; 420 } 421 422 /** 423 * Adds a listener to be called when all documents have finished loading 424 * @param {function} listener the function to call when all loading in complete 425 */ 426 GLGE.Document.prototype.addLoadListener=function(listener){ 427 this.listeners.append(listener); 428 } 429 /** 430 * Removes a load listener 431 * @param {function} listener Listener to remove 432 */ 433 GLGE.Document.prototype.removeLoadListener=function(listener){ 434 for(var i=0; i<this.listeners.length; i++){ 435 if(this.listeners[i]===listener) this.listeners.splice(i,1); 436 } 437 } 438 439 440 441 442 /** 443 * @class Abstract class to agument objects that requires position, rotation and scale. 444 */ 445 GLGE.Placeable=function(){ 446 this.matrix=$M.I(4); 447 } 448 GLGE.Placeable.prototype.locX=0; 449 GLGE.Placeable.prototype.locY=0; 450 GLGE.Placeable.prototype.locZ=0; 451 GLGE.Placeable.prototype.dLocX=0; 452 GLGE.Placeable.prototype.dLocY=0; 453 GLGE.Placeable.prototype.dLocZ=0; 454 GLGE.Placeable.prototype.rotX=0; 455 GLGE.Placeable.prototype.rotY=0; 456 GLGE.Placeable.prototype.rotZ=0; 457 GLGE.Placeable.prototype.dRotX=0; 458 GLGE.Placeable.prototype.dRotY=0; 459 GLGE.Placeable.prototype.dRotZ=0; 460 GLGE.Placeable.prototype.scaleX=1; 461 GLGE.Placeable.prototype.scaleY=1; 462 GLGE.Placeable.prototype.scaleZ=1; 463 GLGE.Placeable.prototype.dScaleX=0; 464 GLGE.Placeable.prototype.dScaleY=0; 465 GLGE.Placeable.prototype.dScaleZ=0; 466 GLGE.Placeable.prototype.matrix=null; 467 /** 468 * Gets the rotaion matrix 469 * @returns {matrix} the objects rotation matrix 470 */ 471 GLGE.Placeable.prototype.getRotMatrix=function(){ 472 return $M([ 473 [this.matrix.e(1,1),this.matrix.e(1,2),this.matrix.e(1,3)], 474 [this.matrix.e(2,1),this.matrix.e(2,2),this.matrix.e(2,3)], 475 [this.matrix.e(3,1),this.matrix.e(3,2),this.matrix.e(3,3)]]); 476 } 477 /** 478 * Sets the x location of the object 479 * @param {number} value The value to assign to the x position 480 */ 481 GLGE.Placeable.prototype.setLocX=function(value){this.locX=value; this.updateMatrix();} 482 /** 483 * Sets the y location of the object 484 * @param {number} value The value to assign to the y position 485 */ 486 GLGE.Placeable.prototype.setLocY=function(value){this.locY=value;this.updateMatrix();} 487 /** 488 * Sets the z location of the object 489 * @param {number} value The value to assign to the z position 490 */ 491 GLGE.Placeable.prototype.setLocZ=function(value){this.locZ=value;this.updateMatrix();} 492 /** 493 * Sets the location of the object 494 * @param {number} x The value to assign to the x position 495 * @param {number} y The value to assign to the y position 496 * @param {number} z The value to assign to the z position 497 */ 498 GLGE.Placeable.prototype.setLoc=function(x,y,z){this.locX=x;this.locY=y;this.locZ=z;this.updateMatrix();} 499 /** 500 * Sets the x location displacement of the object, usefull for animation 501 * @param {number} value The value to assign to the x displacement 502 */ 503 GLGE.Placeable.prototype.setDLocX=function(value){this.dLocX=value;this.updateMatrix();} 504 /** 505 * Sets the y location displacement of the object, usefull for animation 506 * @param {number} value The value to assign to the y displacement 507 */ 508 GLGE.Placeable.prototype.setDLocY=function(value){this.dLocY=value;this.updateMatrix();} 509 /** 510 * Sets the z location displacement of the object, usefull for animation 511 * @param {number} value The value to assign to the z displacement 512 */ 513 GLGE.Placeable.prototype.setDLocZ=function(value){this.dLocZ=value;this.updateMatrix();} 514 /** 515 * Sets the location displacement of the object, useful for animation 516 * @param {number} x The value to assign to the x position 517 * @param {number} y The value to assign to the y position 518 * @param {number} z The value to assign to the z position 519 */ 520 GLGE.Placeable.prototype.setDLoc=function(x,y,z){this.dLocX=x;this.dLocY=y;this.dLocZ=z;this.updateMatrix();} 521 /** 522 * Sets the x rotation of the object 523 * @param {number} value The value to assign to the x rotation 524 */ 525 GLGE.Placeable.prototype.setRotX=function(value){this.rotX=value;this.updateMatrix();} 526 /** 527 * Sets the y rotation of the object 528 * @param {number} value The value to assign to the y rotation 529 */ 530 GLGE.Placeable.prototype.setRotY=function(value){this.rotY=value;this.updateMatrix();} 531 /** 532 * Sets the z rotation of the object 533 * @param {number} value The value to assign to the z rotation 534 */ 535 GLGE.Placeable.prototype.setRotZ=function(value){this.rotZ=value;this.updateMatrix();} 536 /** 537 * Sets the rotation of the object 538 * @param {number} x The value to assign to the x rotation 539 * @param {number} y The value to assign to the y rotation 540 * @param {number} z The value to assign to the z rotation 541 */ 542 GLGE.Placeable.prototype.setRot=function(x,y,z){this.rotX=x;this.rotY=y;this.rotZ=z;this.updateMatrix();} 543 /** 544 * Sets the x rotation displacement of the object, usefull for animation 545 * @param {number} value The value to assign to the x displacement 546 */ 547 GLGE.Placeable.prototype.setDRotX=function(value){this.dRotX=value;this.updateMatrix();} 548 /** 549 * Sets the y rotation displacement of the object, usefull for animation 550 * @param {number} value The value to assign to the y displacement 551 */ 552 GLGE.Placeable.prototype.setDRotY=function(value){this.dRotY=value;this.updateMatrix();} 553 /** 554 * Sets the z rotation displacement of the object, usefull for animation 555 * @param {number} value The value to assign to the z displacement 556 */ 557 GLGE.Placeable.prototype.setDRotZ=function(value){this.dRotZ=value;this.updateMatrix();} 558 /** 559 * Sets the rotation displacement of the object, useful for animation 560 * @param {number} x The value to assign to the x rotation 561 * @param {number} y The value to assign to the y rotation 562 * @param {number} z The value to assign to the z rotation 563 */ 564 GLGE.Placeable.prototype.setDRot=function(x,y,z){this.dRotX=x;this.dRotY=y;this.dRotZ=z;this.updateMatrix();} 565 /** 566 * Sets the x scale of the object 567 * @param {number} value The value to assign to the x scale 568 */ 569 GLGE.Placeable.prototype.setScaleX=function(value){this.scaleX=value;this.updateMatrix();} 570 /** 571 * Sets the y scale of the object 572 * @param {number} value The value to assign to the y scale 573 */ 574 GLGE.Placeable.prototype.setScaleY=function(value){this.scaleY=value;this.updateMatrix();} 575 /** 576 * Sets the z scale of the object 577 * @param {number} value The value to assign to the z scale 578 */ 579 GLGE.Placeable.prototype.setScaleZ=function(value){this.scaleZ=value;this.updateMatrix();} 580 /** 581 * Sets the scale of the object 582 * @param {number} x The value to assign to the x scale 583 * @param {number} y The value to assign to the y scale 584 * @param {number} z The value to assign to the z scale 585 */ 586 GLGE.Placeable.prototype.setScale=function(x,y,z){this.scaleX=x;this.scaleY=y;this.scaleZ=z;this.updateMatrix();} 587 /** 588 * Sets the x scale displacement of the object, usefull for animation 589 * @param {number} value The value to assign to the x displacement 590 */ 591 GLGE.Placeable.prototype.setDScaleX=function(value){this.dScaleX=value;this.updateMatrix();} 592 /** 593 * Sets the y scale displacement of the object, usefull for animation 594 * @param {number} value The value to assign to the y displacement 595 */ 596 GLGE.Placeable.prototype.setDScaleY=function(value){this.dScaleY=value;this.updateMatrix();} 597 /** 598 * Sets the z scale displacement of the object, usefull for animation 599 * @param {number} value The value to assign to the z displacement 600 */ 601 GLGE.Placeable.prototype.setDScaleZ=function(value){this.dScaleZ=value;this.updateMatrix();} 602 /** 603 * Sets the scale displacement of the object, useful for animation 604 * @param {number} x The value to assign to the x scale 605 * @param {number} y The value to assign to the y scale 606 * @param {number} z The value to assign to the z scale 607 */ 608 GLGE.Placeable.prototype.setDScale=function(x,y,z){this.dScaleX=x;this.dScaleY=y;this.dScaleZ=z;this.updateMatrix();} 609 /** 610 * Gets the x location of the object 611 * @returns {number} 612 */ 613 GLGE.Placeable.prototype.getLocX=function(){return this.locX;} 614 /** 615 * Gets the y location of the object 616 * @returns {number} 617 */ 618 GLGE.Placeable.prototype.getLocY=function(){return this.locY;} 619 /** 620 * Gets the z location of the object 621 * @returns {number} 622 */ 623 GLGE.Placeable.prototype.getLocZ=function(){return this.locZ;} 624 /** 625 * Gets the x location displacement of the object 626 * @returns {number} 627 */ 628 GLGE.Placeable.prototype.getDLocX=function(){return this.dLocX;} 629 /** 630 * Gets the y location displacement of the object 631 * @returns {number} 632 */ 633 GLGE.Placeable.prototype.getDLocY=function(){return this.dLocY;} 634 /** 635 * Gets the z location displacement of the object 636 * @returns {number} 637 */ 638 GLGE.Placeable.prototype.getDLocZ=function(){return this.dLocZ;} 639 /** 640 * Gets the x rotation of the object 641 * @returns {number} 642 */ 643 GLGE.Placeable.prototype.getRotX=function(){return this.rotX;} 644 /** 645 * Gets the y rotation of the object 646 * @returns {number} 647 */ 648 GLGE.Placeable.prototype.getRotY=function(){return this.rotY;} 649 /** 650 * Gets the z rotation of the object 651 * @returns {number} 652 */ 653 GLGE.Placeable.prototype.getRotZ=function(){return this.rotZ;} 654 /** 655 * Gets the x rotaional displacement of the object 656 * @returns {number} 657 */ 658 GLGE.Placeable.prototype.getDRotX=function(){return this.dRotX;} 659 /** 660 * Gets the y rotaional displacement of the object 661 * @returns {number} 662 */ 663 GLGE.Placeable.prototype.getDRotY=function(){return this.dRotY;} 664 /** 665 * Gets the z rotaional displacement of the object 666 * @returns {number} 667 */ 668 GLGE.Placeable.prototype.getDRotZ=function(){return this.dRotZ;} 669 /** 670 * Gets the x scale of the object 671 * @returns {number} 672 */ 673 GLGE.Placeable.prototype.getScaleX=function(){return this.scaleX;} 674 /** 675 * Gets the y scale of the object 676 * @returns {number} 677 */ 678 GLGE.Placeable.prototype.getSacleY=function(){return this.scaleY;} 679 /** 680 * Gets the z scale of the object 681 * @returns {number} 682 */ 683 GLGE.Placeable.prototype.getScaleZ=function(){return this.scaleZ;} 684 /** 685 * Gets the x scale displacement of the object 686 * @returns {number} 687 */ 688 GLGE.Placeable.prototype.getDScaleX=function(){return this.dScaleX;} 689 /** 690 * Gets the y scale displacement of the object 691 * @returns {number} 692 */ 693 GLGE.Placeable.prototype.getDScaleY=function(){return this.dScaleY;} 694 /** 695 * Gets the z scale displacement of the object 696 * @returns {number} 697 */ 698 GLGE.Placeable.prototype.getDScaleZ=function(){return this.dScaleZ;} 699 /** 700 * Gets the position of the object 701 * @returns {object} 702 */ 703 GLGE.Placeable.prototype.getPosition=function(){ 704 var position={}; 705 position.x=parseFloat(this.locX)+parseFloat(this.dLocX); 706 position.y=parseFloat(this.locY)+parseFloat(this.dLocY); 707 position.z=parseFloat(this.locZ)+parseFloat(this.dLocZ); 708 return position; 709 } 710 /** 711 * Gets the rotation of the object 712 * @returns {object} 713 */ 714 GLGE.Placeable.prototype.getRotation=function(){ 715 var rotation={}; 716 rotation.x=parseFloat(this.rotX)+parseFloat(this.dRotX); 717 rotation.y=parseFloat(this.rotY)+parseFloat(this.dRotY); 718 rotation.z=parseFloat(this.rotZ)+parseFloat(this.dRotZ); 719 return rotation; 720 } 721 /** 722 * Gets the scale of the object 723 * @returns {object} 724 */ 725 GLGE.Placeable.prototype.getScale=function(){ 726 var scale={}; 727 scale.x=parseFloat(this.scaleX)+parseFloat(this.dScaleX); 728 scale.y=parseFloat(this.scaleY)+parseFloat(this.dScaleY); 729 scale.z=parseFloat(this.scaleZ)+parseFloat(this.dScaleZ); 730 return scale; 731 } 732 /** 733 * Updates the model matrix 734 * @private 735 */ 736 GLGE.Placeable.prototype.updateMatrix=function(){ 737 this.matrix=null; 738 } 739 /** 740 * Gets the model matrix to transform the model within the world 741 */ 742 GLGE.Placeable.prototype.getModelMatrix=function(){ 743 if(!this.matrix){ 744 var position=this.getPosition(); 745 var rotation=this.getRotation(); 746 var scale=this.getScale(); 747 this.matrix=Matrix.transMat(position.x,position.y,position.z).x(Matrix.scaleMat(scale.x,scale.y,scale.z).x(Matrix.rotMat(rotation.x,rotation.y,rotation.z))); 748 } 749 return this.matrix; 750 } 751 752 /** 753 * @class Animation class to agument animatiable objects 754 */ 755 GLGE.Animatable=function(){ 756 } 757 GLGE.Animatable.prototype.animationStart=null; 758 GLGE.Animatable.prototype.animation=null; 759 GLGE.Animatable.prototype.lastFrame=null; 760 GLGE.Animatable.prototype.frameRate=25; 761 /** 762 * update animated properties on this object 763 */ 764 GLGE.Animatable.prototype.animate=function(){ 765 var now=parseInt(new Date().getTime()); 766 if(this.animation.frames>1){ 767 frame=((now-this.animationStart)/1000*this.frameRate)%(this.animation.frames-1)+1; 768 }else{ 769 frame=1; 770 } 771 if(frame!=this.lastFrame){ 772 this.lastFrame=frame; 773 for(property in this.animation.curves){ 774 if(this["set"+property]) this["set"+property](this.animation.curves[property].getValue(frame)); 775 } 776 } 777 } 778 /** 779 * Sets the animation vector of this object 780 * @param {GLGE.AnimationVector} animationVector the animation to apply to this object 781 */ 782 GLGE.Animatable.prototype.setAnimation=function(animationVector){ 783 this.animationStart=parseInt(new Date().getTime()); 784 this.animation=animationVector; 785 } 786 /** 787 * Gets the animation vector of this object 788 * @returns {AnimationVector} 789 */ 790 GLGE.Animatable.prototype.getAnimation=function(){ 791 return this.animation; 792 } 793 /** 794 * Sets the frame rate of the animation 795 * @param {number} value the frame rate to set 796 */ 797 GLGE.Animatable.prototype.setFrameRate=function(value){ 798 this.frameRate=value; 799 } 800 /** 801 * Gets the frame rate of the animation 802 * @return {number} the current frame rate 803 */ 804 GLGE.Animatable.prototype.getFrameRate=function(){ 805 return this.frameRate; 806 } 807 808 /** 809 * @class A bezier class to add points to the Animation Curve 810 * @param {number} x1 x-coord of the first control point 811 * @param {number} y1 y-coord of the first control point 812 * @param {number} x2 x-coord of the second control point 813 * @param {number} y2 y-coord of the second control point 814 * @param {number} x3 x-coord of the third control point 815 * @param {number} y3 y-coord of the third control point 816 */ 817 GLGE.BezTriple=function(x1,y1,x2,y2,x3,y3){ 818 this.x1=parseFloat(x1); 819 this.y1=parseFloat(y1); 820 this.x2=parseFloat(x2); 821 this.y2=parseFloat(y2); 822 this.x3=parseFloat(x3); 823 this.y3=parseFloat(y3); 824 }; 825 826 /** 827 * @class A curve which interpolates between control points 828 */ 829 GLGE.AnimationCurve=function(){ 830 this.keyFrames=[]; 831 this.solutions={}; 832 }; 833 GLGE.AnimationCurve.prototype.keyFrames=null; 834 /** 835 * Adds a point to the curve 836 * @param {BezPoint} bezPoint The bezier point to add 837 * @returns {Number} Index of the newly added point 838 */ 839 GLGE.AnimationCurve.prototype.addPoint=function(bezPoint){ 840 this.keyFrames.push(bezPoint); 841 return this.keyFrames.length-1; 842 }; 843 /** 844 * Get the value of the curve at any point 845 * @param {Number} frame The frame(x-coord) to return the value for 846 * @returns {Number} The value of the curve at the given point 847 */ 848 GLGE.AnimationCurve.prototype.coord=function(x,y){ 849 return {x:x,y:y} 850 } 851 GLGE.AnimationCurve.prototype.getValue=function(frame){ 852 var startKey=0; 853 var endKey=0; 854 //find the key frame bounds 855 for(var i=0; i<this.keyFrames.length;i++){ 856 if(this.keyFrames[i].x2<frame && (this.keyFrames[i].x2>this.keyFrames[startKey].x2 || this.keyFrames[startKey].x2>frame)) startKey=i; 857 if(this.keyFrames[i].x2>frame && (this.keyFrames[i].x2<this.keyFrames[endKey].x2 || this.keyFrames[endKey].x2<frame)) endKey=i; 858 } 859 var C1=this.coord(this.keyFrames[startKey].x2,this.keyFrames[startKey].y2); 860 var C2=this.coord(this.keyFrames[startKey].x3,this.keyFrames[startKey].y3); 861 var C3=this.coord(this.keyFrames[endKey].x1,this.keyFrames[endKey].y1); 862 var C4=this.coord(this.keyFrames[endKey].x2,this.keyFrames[endKey].y2); 863 return this.atX(frame,C1,C2,C3,C4).y; 864 }; 865 /** 866 * Function used to calculate bezier curve 867 * @private 868 */ 869 GLGE.AnimationCurve.prototype.B1=function(t) { return t*t*t }; 870 /** 871 * Function used to calculate bezier curve 872 * @private 873 */ 874 GLGE.AnimationCurve.prototype.B2=function(t) { return 3*t*t*(1-t) }; 875 /** 876 * Function used to calculate bezier curve 877 * @private 878 */ 879 GLGE.AnimationCurve.prototype.B3=function(t) { return 3*t*(1-t)*(1-t) }; 880 /** 881 * Function used to calculate bezier curve 882 * @private 883 */ 884 GLGE.AnimationCurve.prototype.B4=function(t) { return (1-t)*(1-t)*(1-t) }; 885 /** 886 * Gets the value of a bezier curve at a given point 887 * @private 888 */ 889 GLGE.AnimationCurve.prototype.getBezier=function(t,C1,C2,C3,C4) { 890 var pos = {}; 891 pos.x = C1.x*this.B1(t) + C2.x*this.B2(t) + C3.x*this.B3(t) + C4.x*this.B4(t); 892 pos.y = C1.y*this.B1(t) + C2.y*this.B2(t) + C3.y*this.B3(t) + C4.y*this.B4(t); 893 return pos; 894 }; 895 /** 896 * Solves cubic equation to get the parametic value of the curve at a specified point 897 * @private 898 */ 899 GLGE.AnimationCurve.prototype.Quad3Solve=function(a,b,c,d){ 900 ref=a+"-"+b+"-"+"-"+c+"-"+d; 901 if(this.solutions[ref]){ 902 return this.solutions[ref]; 903 } 904 else 905 { 906 b /= a;c /= a;d /= a; 907 var q, r, d1, s, t, t1, r13; 908 q = (3.0*c - (b*b))/9.0; 909 r = -(27.0*d) + b*(9.0*c - 2.0*(b*b)); 910 r /= 54.0; 911 t1 = (b/3.0); 912 discrim = q*q*q + r*r; 913 result=[]; 914 915 if (discrim > 0) { 916 // one real, two complex 917 s = r + Math.sqrt(discrim); 918 s = ((s < 0) ? -Math.pow(-s, (1.0/3.0)) : Math.pow(s, (1.0/3.0))); 919 t = r - Math.sqrt(discrim); 920 t = ((t < 0) ? -Math.pow(-t, (1.0/3.0)) : Math.pow(t, (1.0/3.0))); 921 result[0] = -t1 + s + t; 922 t1 = t1 + (s + t)/2.0; 923 result[1] = result[2] = -t1; 924 t1 = Math.sqrt(3.0)*(-t + s)/2; 925 } 926 else if (discrim == 0){ 927 // All roots real 928 r13 = ((r < 0) ? -Math.pow(-r,(1.0/3.0)) : Math.pow(r,(1.0/3.0))); 929 result[1] = -t1 + 2.0*r13; 930 result[1] = result[2] = -(r13 + t1); 931 } 932 else 933 { 934 q = -q; 935 d1 = q*q*q; 936 d1 = Math.acos(r/Math.sqrt(1)); 937 r13 = 2.0*Math.sqrt(q); 938 939 940 result[0] = -t1 + r13*Math.cos(d1/3.0); 941 result[1] = -t1 + r13*Math.cos((d1 + 2.0*Math.PI)/3.0); 942 result[2] = -t1 + r13*Math.cos((d1 + 4.0*Math.PI)/3.0); 943 } 944 var toreturn=false; 945 //determine which is the correct result 946 if(result[0]>=0 && result[0]<=1) toreturn=result[0]; 947 if(!toreturn && result[1]>=0 && result[1]<=1) toreturn=result[1]; 948 if(!toreturn && result[2]>=0 && result[2]<=1) toreturn=result[2]; 949 //cache result for next time 950 this.solutions[ref]=toreturn; 951 952 return toreturn; 953 } 954 }; 955 /** 956 * Get the value of the a single bezier curve 957 * @param {Number} x xcoord of point to get 958 * @param {Number} C1 First bezier control point 959 * @param {Number} C2 Second bezier control point 960 * @param {Number} C3 Third bezier control point 961 * @param {Number} C4 Forth bezier control point 962 * @returns {Number} The value of the curve at the given x 963 */ 964 GLGE.AnimationCurve.prototype.atX=function(x,C1,C2,C3,C4){ 965 a=C1.x-C2.x*3+C3.x*3-C4.x; 966 b=C2.x*3-C3.x*6+C4.x*3; 967 c=C3.x*3-C4.x*3; 968 d=C4.x-x; 969 return this.getBezier(this.Quad3Solve(a,b,c,d),C1,C2,C3,C4); 970 }; 971 972 /** 973 * @class The AnimationVectors class allows you to specify the 2D Animation curves that define specific channels of animation within the engine. 974 */ 975 GLGE.AnimationVector=function(){ 976 this.curves=[]; 977 } 978 GLGE.AnimationVector.prototype.curves=[]; 979 GLGE.AnimationVector.prototype.frames=250; 980 /** 981 * Adds an Animation Curve to a channel 982 * @param {String} channel The name of the curve to be added 983 * @param {GLGE.AnimationCurve} curve The animation curve to add 984 */ 985 GLGE.AnimationVector.prototype.addCurve=function(name,curve){ 986 this.curves[name]=curve; 987 } 988 /** 989 * Removes an Animation Curve form a channel 990 * @param {String} channel The name of the curve to be removed 991 */ 992 GLGE.AnimationVector.prototype.removeCurve=function(name){ 993 delete(this.curves[name]); 994 } 995 /** 996 * Sets the number of frames in the animation 997 * @param {number} value The number of frames in the animation 998 */ 999 GLGE.AnimationVector.prototype.setFrames=function(value){ 1000 this.frames=value; 1001 } 1002 /** 1003 * Sets the number of frames in the animation 1004 * @returns {number} The number of frames in the animation 1005 */ 1006 GLGE.AnimationVector.prototype.getFrames=function(){ 1007 return this.frames; 1008 } 1009 1010 1011 /** 1012 * Function to augment one object with another 1013 * @param {object} obj1 Source Object 1014 * @param {object} obj2 Destination Object 1015 */ 1016 GLGE.augment=function(obj1,obj2){ 1017 for(proto in obj1.prototype){ 1018 obj2.prototype[proto]=obj1.prototype[proto]; 1019 } 1020 } 1021 1022 1023 /** 1024 * @class Class defining a bones name and position in a skeleton 1025 * @param {string} name the name of the bone 1026 * @param {number} x the x co-ordinate of the bone 1027 * @param {number} y the y co-ordinate of the bone 1028 * @param {number} z the z co-ordinate of the bone 1029 */ 1030 GLGE.Bone=function(name,x,y,z){ 1031 this.name=name; 1032 this.x=x; 1033 this.y=y; 1034 this.z=z; 1035 } 1036 1037 GLGE.error=function(message){ 1038 alert(message) 1039 } 1040 1041 /** 1042 * @class Class specifing bones,locations and relationships 1043 */ 1044 GLGE.Skeleton=function(){ 1045 this.bones=[]; 1046 }; 1047 GLGE.Skeleton.prototype.bones=[]; 1048 /** 1049 * Adds a bone to the skeleton 1050 * @param {GLGE.Bone} bone the bone to add 1051 * NOTE why don't I just add the parent into the bone object???? 1052 */ 1053 GLGE.Skeleton.prototype.addBone=function(bone,parent){ 1054 if(parent) bone.parent=parent; 1055 this.bones.push(bone); 1056 } 1057 /** 1058 * Gets the transform of a bone for a given action at a specified frame 1059 * @param {string} bone the bone to get the matrix for 1060 * @param {GLGE.SkeletalAction} action the action to the the matrix for 1061 * @param {number} frame The frame number to get the matrix for 1062 * @returns Matrix 1063 */ 1064 GLGE.Skeleton.prototype.getBoneTransforms=function(bone,action,frame){ 1065 var TRANS1=Matrix.transMat(bone.x*-1,bone.y*-1,bone.z*-1); 1066 var TRANS2=Matrix.transMat(bone.x,bone.y,bone.z); 1067 1068 var result=Matrix.I(4); 1069 if(action && action.cache[frame][bone.name]) result=TRANS2.x(action.cache[frame][bone.name]).x(TRANS1); 1070 return result; 1071 } 1072 /** 1073 * Gets the bone object from it's name 1074 * @param {string} name the name of the bone to get 1075 * @returns GLGE.Bone 1076 */ 1077 GLGE.Skeleton.prototype.boneFromName=function(name){ 1078 for(var i=0; i<this.bones.length;i++){ 1079 if(this.bones[i].name==name){ 1080 return i; 1081 break; 1082 } 1083 } 1084 return false; 1085 } 1086 /** 1087 * Gets and array containing the transforms of each of the bones 1088 * @param {GLGE.SkeletalAction} action the action to get the transforms for 1089 * @param {number} frame the frame number 1090 * @returns Matrix[] 1091 */ 1092 GLGE.Skeleton.prototype.getTransforms=function(action,frame){ 1093 if(!action) alert(frame); 1094 var transforms={} 1095 for(var i=0; i<this.bones.length;i++){ 1096 bone=this.bones[i]; 1097 base=this.getBoneTransforms(bone,action,frame); 1098 while(bone.parent){ 1099 if(!bone.parentIdx) bone.parentIdx=this.boneFromName(bone.parent); 1100 bone=this.bones[bone.parentIdx]; 1101 base=this.getBoneTransforms(bone,action,frame).x(base); 1102 } 1103 transforms[this.bones[i].name]=({name:this.bones[i].name,matrix:base}); 1104 } 1105 return transforms; 1106 } 1107 1108 1109 1110 1111 /** 1112 * @class Class to perform an action on a skeleton 1113 */ 1114 GLGE.SkeletalAction=function(frames){ 1115 this.frames=frames; 1116 this.AnimationVectors=[]; 1117 } 1118 GLGE.SkeletalAction.prototype.frames=0; 1119 GLGE.SkeletalAction.prototype.frameRate=60; 1120 GLGE.SkeletalAction.prototype.cache=null; 1121 GLGE.SkeletalAction.prototype.AnimationVectors=null; 1122 /** 1123 * Adds an animation to one of the bone 1124 * @param {string} boneName The name of the bone 1125 * @param {GLGE.AnimationVector} AnimationVector The animation to associate with the bone 1126 */ 1127 GLGE.SkeletalAction.prototype.addAnimationVector=function(boneName,AnimationVector){ 1128 this.AnimationVectors[boneName]=AnimationVector; 1129 } 1130 /** 1131 * Removed an animation for a bone 1132 * @param {string} boneName The name of the bone 1133 */ 1134 GLGE.SkeletalAction.prototype.removeCurve=function(boneName){ 1135 delete(this.AnimationVectors[boneName]); 1136 } 1137 /** 1138 * Get the values of the animation vector for a given bone on a given channel at a given frame 1139 * @param {string} boneName The name of the bone 1140 * @param {string} channel The animation vector channel 1141 * @param {number} frame The frame to get the value for 1142 * @returns {object} 1143 */ 1144 GLGE.SkeletalAction.prototype.boneValue=function(boneName,channel,frame){ 1145 var result; 1146 var result=0; 1147 if(channel=="ScaleX" || channel=="ScaleY" || channel=="ScaleZ") result=1; 1148 if(this.AnimationVectors[boneName] && this.AnimationVectors[boneName].curves[channel]){ 1149 result=this.AnimationVectors[boneName].curves[channel].getValue(frame); 1150 } 1151 return result; 1152 } 1153 /** 1154 * Get the transformation matrix for the bone at a given frame 1155 * @param {string} boneName The name of the bone 1156 * @param {number} frame The frame to get the value for 1157 * @returns {Matrix} 1158 */ 1159 GLGE.SkeletalAction.prototype.getBoneTransform=function(boneName,frame){ 1160 var LOCX=this.boneValue(boneName,"LocX",frame); 1161 var LOCY=this.boneValue(boneName,"LocY",frame); 1162 var LOCZ=this.boneValue(boneName,"LocZ",frame); 1163 var SCALEX=this.boneValue(boneName,"ScaleX",frame); 1164 var SCALEY=this.boneValue(boneName,"ScaleY",frame); 1165 var SCALEZ=this.boneValue(boneName,"ScaleZ",frame); 1166 var QUATX=this.boneValue(boneName,"QuatX",frame); 1167 var QUATY=this.boneValue(boneName,"QuatY",frame); 1168 var QUATZ=this.boneValue(boneName,"QuatZ",frame); 1169 var QUATW=this.boneValue(boneName,"QuatW",frame); 1170 1171 1172 var QUAT=Matrix.quat2rot(QUATX,QUATY,QUATZ,QUATW); 1173 var LOC=Matrix.transMat(LOCX,LOCY,LOCZ); 1174 var SCALE=Matrix.scaleMat(SCALEX,SCALEY,SCALEZ); 1175 return LOC.x(QUAT).x(SCALE); 1176 } 1177 /** 1178 * Cache all the transforms for this action 1179 */ 1180 GLGE.SkeletalAction.prototype.cacheTransforms=function(){ 1181 this.cache=[]; 1182 var transforms; 1183 for(var frame=1; frame<=this.frames;frame++){ 1184 transforms={}; 1185 for(bone in this.AnimationVectors){ 1186 if(this.AnimationVectors[bone] instanceof GLGE.AnimationVector){ 1187 transforms[bone]=this.getBoneTransform(bone,frame+0.5); 1188 } 1189 } 1190 this.cache[frame]=transforms; 1191 } 1192 } 1193 1194 1195 /** 1196 * @class An object that can be rendered in a scene 1197 * @augments GLGE.Animatable 1198 * @augments GLGE.Placeable 1199 */ 1200 GLGE.Object=function(){ 1201 } 1202 GLGE.augment(GLGE.Placeable,GLGE.Object); 1203 GLGE.augment(GLGE.Animatable,GLGE.Object); 1204 GLGE.Object.prototype.action=null; 1205 GLGE.Object.prototype.mesh=null; 1206 GLGE.Object.prototype.skeleton=null; 1207 GLGE.Object.prototype.scene=null; 1208 GLGE.Object.prototype.transformMatrix=Matrix.I(4); 1209 GLGE.Object.prototype.material=null; 1210 GLGE.Object.prototype.gl=null; 1211 GLGE.Object.prototype.actionStart=null; 1212 GLGE.Object.prototype.blendState=null; 1213 GLGE.Object.prototype.actionCache=null; 1214 GLGE.Object.prototype.zTrans=false; 1215 /** 1216 * Blend from current skeletal action to another 1217 * @param {GLGE.SkeletalAction} action The action to be blended to 1218 * @param {Number} duration Number of millisecons the blend should last for 1219 */ 1220 GLGE.Object.prototype.blendAction=function(action,duration){ 1221 this.blendState=this.getBoneTransforms(); 1222 this.setAction(action); 1223 this.blendDuration=duration; 1224 this.actionCache=[]; 1225 } 1226 /** 1227 * Sets the skeletal action of this object 1228 * @param {GLGE.SkeletalAction} action The action to be blended to 1229 */ 1230 GLGE.Object.prototype.setAction=function(action){ 1231 this.action=action; 1232 this.actionCache=[]; 1233 if(!this.action.cache) this.action.cacheTransforms(); 1234 this.actionStart=parseInt(new Date().getTime()); 1235 } 1236 /** 1237 * Gets the current skeletal action of this object 1238 * @returns GLGE.SkeletalAction 1239 */ 1240 GLGE.Object.prototype.getAction=function(){ 1241 return this.action 1242 } 1243 /** 1244 * Gets the current transfroms for each of the bones 1245 * @returns Matrix[] 1246 * @private 1247 */ 1248 GLGE.Object.prototype.getBoneTransforms=function(){ 1249 var now=parseInt(new Date().getTime()); 1250 var frame; 1251 if(this.action.frames>1){ 1252 frame=((now-this.actionStart)/1000*this.action.frameRate)%(this.action.frames-1)+1; 1253 }else{ 1254 frame=1; 1255 } 1256 frame=Math.round(frame); 1257 if(this.actionCache[frame]){ 1258 var transforms=this.actionCache[frame]; 1259 } 1260 else 1261 { 1262 var transforms=this.skeleton.getTransforms(this.action,frame); 1263 if(this.blendState){ 1264 var blendframe; 1265 var blendpoint=(now-this.actionStart)/this.blendDuration; 1266 if(blendpoint>=1){ 1267 this.blendState=null; 1268 this.actionCache=[]; 1269 } 1270 else 1271 { 1272 //combine the two sets of transforms 1273 var newtransforms={}; 1274 for(bone in transforms){ 1275 if(transforms[bone].matrix){ 1276 newtransforms[bone]={matrix:this.blendState[bone].matrix.x(1-blendpoint).add(transforms[bone].matrix.x(blendpoint))}; 1277 } 1278 } 1279 transforms=newtransforms; 1280 } 1281 } 1282 else 1283 { 1284 this.actionCache[frame]=transforms; 1285 } 1286 } 1287 return transforms; 1288 } 1289 /** 1290 * Sets the Z Transparency of this object 1291 * @param {boolean} value Does this object need blending? 1292 */ 1293 GLGE.Object.prototype.setZtransparent=function(value){ 1294 this.zTrans=value; 1295 } 1296 /** 1297 * Gets the z transparency 1298 * @returns boolean 1299 */ 1300 GLGE.Object.prototype.isZtransparent=function(){ 1301 return this.zTrans; 1302 } 1303 1304 /** 1305 * Sets the skeletal action of this object 1306 * @param {GLGE.SkeletalAction} action The action to be blended to 1307 */ 1308 GLGE.Object.prototype.setSkeleton=function(skeleton){ 1309 this.skeleton=skeleton; 1310 } 1311 /** 1312 * Gets the current skeletal action of this object 1313 * @returns GLGE.SkeletalAction 1314 */ 1315 GLGE.Object.prototype.getSkeleton=function(){ 1316 return this.skeleton; 1317 } 1318 /** 1319 * Sets the material associated with the object 1320 * @param GLGE.Material 1321 */ 1322 GLGE.Object.prototype.setMaterial=function(material){ 1323 this.material=material; 1324 } 1325 /** 1326 * Gets the material associated with the object 1327 * @returns GLGE.Material 1328 */ 1329 GLGE.Object.prototype.getMaterial=function(){ 1330 return this.material; 1331 } 1332 GLGE.Object.prototype.setScene=function(scene){ 1333 this.scene=scene; 1334 } 1335 GLGE.Object.prototype.getScene=function(){ 1336 return this.scene; 1337 } 1338 /** 1339 * Sets the mesh associated with the object 1340 * @param GLGE.Mesh 1341 */ 1342 GLGE.Object.prototype.setMesh=function(mesh){ 1343 if(this.mesh) this.mesh.removeObject(this); 1344 this.mesh=mesh; 1345 mesh.addObject(this); 1346 } 1347 /** 1348 * Gets the mesh associated with the object 1349 * @returns GLGE.Mesh 1350 */ 1351 GLGE.Object.prototype.getMesh=function(){ 1352 return this.mesh; 1353 } 1354 /** 1355 * Initiallize all the GL stuff needed to render to screen 1356 * @private 1357 */ 1358 GLGE.Object.prototype.GLInit=function(gl){ 1359 this.gl=gl; 1360 this.GLGenerateShader(gl); 1361 } 1362 /** 1363 * Cleans up all the GL stuff we sets 1364 * @private 1365 */ 1366 GLGE.Object.prototype.GLDestory=function(gl){ 1367 } 1368 /** 1369 * Updates the GL shader program for the object 1370 * @private 1371 */ 1372 GLGE.Object.prototype.updateProgram=function(){ 1373 if(this.gl) this.GLGenerateShader(this.gl); 1374 } 1375 /** 1376 * Creates the shader program for the object 1377 * @private 1378 */ 1379 GLGE.Object.prototype.GLGenerateShader=function(gl){ 1380 if(this.GLShaderProgram) gl.deleteProgram(this.GLShaderProgram); 1381 //create the programs strings 1382 //Vertex Shader 1383 var vertexStr=""; 1384 for(var i=0;i<this.mesh.buffers.length;i++){ 1385 if(this.mesh.buffers[i].size>1) 1386 vertexStr=vertexStr+"attribute vec"+this.mesh.buffers[i].size+" "+this.mesh.buffers[i].name+";\n"; 1387 else 1388 vertexStr=vertexStr+"attribute float "+this.mesh.buffers[i].name+";\n"; 1389 } 1390 1391 vertexStr=vertexStr+"uniform mat4 MVMatrix;\n"; 1392 vertexStr=vertexStr+"uniform mat4 PMatrix;\n"; 1393 //normals needed for lighting 1394 vertexStr=vertexStr+"uniform mat4 uNMatrix;\n"; 1395 1396 for(var i=0; i<this.scene.lights.length;i++){ 1397 vertexStr=vertexStr+"uniform vec3 lightpos"+i+";\n"; 1398 vertexStr=vertexStr+"uniform vec3 lightdir"+i+";\n"; 1399 } 1400 1401 for(var i=0; i<this.mesh.boneWeights.length; i++){ 1402 vertexStr=vertexStr+"uniform mat4 "+this.mesh.boneWeights[i].boneName+"Matrix;\n"; 1403 vertexStr=vertexStr+"uniform mat4 "+this.mesh.boneWeights[i].boneName+"nMatrix;\n"; 1404 } 1405 1406 vertexStr=vertexStr+"varying vec3 eyevec;\n"; 1407 for(var i=0; i<this.scene.lights.length;i++){ 1408 vertexStr=vertexStr+"varying vec3 lightvec"+i+";\n"; 1409 vertexStr=vertexStr+"varying float lightdist"+i+";\n"; 1410 } 1411 1412 vertexStr=vertexStr+"varying vec3 n;\n"; 1413 vertexStr=vertexStr+"varying vec4 UVCoord;\n"; 1414 1415 vertexStr=vertexStr+"void main(void)\n"; 1416 vertexStr=vertexStr+"{\n"; 1417 vertexStr=vertexStr+"UVCoord=UV;\n"; 1418 vertexStr=vertexStr+"vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n"; 1419 vertexStr=vertexStr+"vec4 norm = vec4(0.0, 0.0, 0.0, 1.0);\n"; 1420 var cnt=0; 1421 //calculate the total bone weight 1422 var totalWeight=0; 1423 vertexStr=vertexStr+"float totalWeight=0.0"; 1424 for(var i=0; i<this.mesh.boneWeights.length; i=i+4){ 1425 if(!this.mesh.boneWeights[i+1]){ 1426 vertexStr=vertexStr+"+bones"+cnt; 1427 }else{ 1428 vertexStr=vertexStr+"+bones"+cnt+"["+(i%4)+"]"; 1429 } 1430 if(this.mesh.boneWeights[i+1]) vertexStr=vertexStr+"+bones"+cnt+"["+(i%4+1)+"]"; 1431 if(this.mesh.boneWeights[i+2]) vertexStr=vertexStr+"+bones"+cnt+"["+(i%4+2)+"]"; 1432 if(this.mesh.boneWeights[i+3]) vertexStr=vertexStr+"+bones"+cnt+"["+(i%4+3)+"]"; 1433 cnt++; 1434 } 1435 vertexStr=vertexStr+";\n"; 1436 vertexStr=vertexStr+"if(totalWeight>0.0){\n"; 1437 cnt=0; 1438 for(var i=0; i<this.mesh.boneWeights.length; i=i+4){ 1439 if(!this.mesh.boneWeights[i+1]){ 1440 vertexStr=vertexStr+"pos += ("+this.mesh.boneWeights[i].boneName+"Matrix * vec4(position, 1.0))*(bones"+cnt+"/totalWeight);\n"; 1441 vertexStr=vertexStr+"norm += ("+this.mesh.boneWeights[i].boneName+"nMatrix * vec4(normal, 1.0))*(bones"+cnt+"/totalWeight);\n"; 1442 }else{ 1443 vertexStr=vertexStr+"pos += ("+this.mesh.boneWeights[i].boneName+"Matrix * vec4(position, 1.0))*(bones"+cnt+"["+(i%4)+"]/totalWeight);\n"; 1444 vertexStr=vertexStr+"norm += ("+this.mesh.boneWeights[i].boneName+"nMatrix * vec4(normal, 1.0))*(bones"+cnt+"["+(i%4)+"]/totalWeight);\n"; 1445 } 1446 if(this.mesh.boneWeights[i+1]) vertexStr=vertexStr+"pos += ("+this.mesh.boneWeights[i+1].boneName+"Matrix * vec4(position, 1.0))*(bones"+cnt+"["+(i%4+1)+"]/totalWeight);\n"; 1447 if(this.mesh.boneWeights[i+2]) vertexStr=vertexStr+"pos += ("+this.mesh.boneWeights[i+2].boneName+"Matrix * vec4(position, 1.0))*(bones"+cnt+"["+(i%4+2)+"]/totalWeight);\n"; 1448 if(this.mesh.boneWeights[i+3]) vertexStr=vertexStr+"pos += ("+this.mesh.boneWeights[i+3].boneName+"Matrix * vec4(position, 1.0))*(bones"+cnt+"["+(i%4+3)+"]/totalWeight);\n"; 1449 if(this.mesh.boneWeights[i+1]) vertexStr=vertexStr+"norm += ("+this.mesh.boneWeights[i+1].boneName+"nMatrix * vec4(normal, 1.0))*(bones"+cnt+"["+(i%4+1)+"]/totalWeight);\n"; 1450 if(this.mesh.boneWeights[i+2]) vertexStr=vertexStr+"norm += ("+this.mesh.boneWeights[i+2].boneName+"nMatrix * vec4(normal, 1.0))*(bones"+cnt+"["+(i%4+2)+"]/totalWeight);\n"; 1451 if(this.mesh.boneWeights[i+3]) vertexStr=vertexStr+"norm += ("+this.mesh.boneWeights[i+3].boneName+"nMatrix * vec4(normal, 1.0))*(bones"+cnt+"["+(i%4+3)+"]/totalWeight);\n"; 1452 cnt++; 1453 } 1454 vertexStr=vertexStr+"pos = MVMatrix * vec4(pos.xyz, 1.0);\n"; 1455 vertexStr=vertexStr+"norm = uNMatrix * vec4(norm.xyz, 1.0);\n"; 1456 vertexStr=vertexStr+"}else{\n"; 1457 vertexStr=vertexStr+"pos = MVMatrix * vec4(position, 1.0);\n"; 1458 vertexStr=vertexStr+"norm = uNMatrix * vec4(normal, 1.0);\n"; 1459 vertexStr=vertexStr+"}\n"; 1460 1461 1462 vertexStr=vertexStr+"gl_Position = PMatrix * pos;\n"; 1463 vertexStr=vertexStr+"eyevec = -pos.xyz;\n"; 1464 for(var i=0; i<this.scene.lights.length;i++){ 1465 vertexStr=vertexStr+"lightvec"+i+" = (lightpos"+i+"-pos.xyz);\n"; 1466 vertexStr=vertexStr+"lightdist"+i+" = length(lightpos"+i+".xyz-pos.xyz);\n"; 1467 } 1468 vertexStr=vertexStr+"n = norm.rgb;\n"; 1469 vertexStr=vertexStr+"}\n"; 1470 1471 //Fragment Shader 1472 if(!this.material){ 1473 var fragStr=""; 1474 fragStr=fragStr+"void main(void)\n"; 1475 fragStr=fragStr+"{\n"; 1476 fragStr=fragStr+"gl_FragColor = vec4(1.0,1.0,1.0,1);\n"; 1477 fragStr=fragStr+"}\n"; 1478 } 1479 else 1480 { 1481 fragStr=this.material.getFragmentShader(this.scene.lights); 1482 } 1483 1484 if(!this.GLFragmentShader) this.GLFragmentShader=gl.createShader(gl.FRAGMENT_SHADER); 1485 if(!this.GLVertexShader) this.GLVertexShader=gl.createShader(gl.VERTEX_SHADER); 1486 1487 //set and compile the fragment shader 1488 //need to set str 1489 gl.shaderSource(this.GLFragmentShader, fragStr); 1490 gl.compileShader(this.GLFragmentShader); 1491 1492 /* temp remove for webkit 1493 if (!gl.getShaderi(this.GLFragmentShader, gl.COMPILE_STATUS)) 1494 { 1495 GLGE.error(gl.getShaderInfoLog(this.GLFragmentShader)); 1496 return null; 1497 }*/ 1498 //set and compile the vertex shader 1499 //need to set str 1500 gl.shaderSource(this.GLVertexShader, vertexStr); 1501 gl.compileShader(this.GLVertexShader); 1502 /* temp remove for webkit 1503 if (!gl.getShaderi(this.GLVertexShader, gl.COMPILE_STATUS)) 1504 { 1505 GLGE.error(gl.getShaderInfoLog(this.GLVertexShader)); 1506 return null; 1507 } 1508 */ 1509 1510 if(!this.GLShaderProgram) this.GLShaderProgram = gl.createProgram(); 1511 gl.attachShader(this.GLShaderProgram, this.GLVertexShader); 1512 gl.attachShader(this.GLShaderProgram, this.GLFragmentShader); 1513 gl.linkProgram(this.GLShaderProgram); 1514 } 1515 /** 1516 * Sets the shader program uniforms ready for rendering 1517 * @private 1518 */ 1519 GLGE.Object.prototype.GLUniforms=function(gl){ 1520 var camMat=this.scene.camera.getViewMatrix(); 1521 //generate and set the modelView matrix 1522 mvMatrix=camMat.x(this.getModelMatrix()); 1523 1524 var mvUniform = gl.getUniformLocation(this.GLShaderProgram, "MVMatrix"); 1525 gl.uniformMatrix4fv(mvUniform, false, new WebGLFloatArray(mvMatrix.flatten())); 1526 1527 var pUniform = gl.getUniformLocation(this.GLShaderProgram, "PMatrix"); 1528 gl.uniformMatrix4fv(pUniform, false, new WebGLFloatArray(this.scene.camera.pMatrix.flatten())); 1529 1530 //normalising matrix 1531 var normalMatrix = mvMatrix.inverse(); 1532 normalMatrix = normalMatrix.transpose(); 1533 var nUniform = gl.getUniformLocation(this.GLShaderProgram, "uNMatrix"); 1534 gl.uniformMatrix4fv(nUniform, false, new WebGLFloatArray(normalMatrix.flatten())); 1535 1536 //light 1537 var pos,lpos; 1538 for(var i=0; i<this.scene.lights.length;i++){ 1539 pos=camMat.x(this.scene.lights[i].getModelMatrix()).x($V([0,0,0,1])).flatten(); 1540 lpos=camMat.x(this.scene.lights[i].getModelMatrix()).x($V([0,0,-1,1])).flatten(); 1541 gl.uniform3f(gl.getUniformLocation(this.GLShaderProgram, "lightpos"+i), pos[0],pos[1],pos[2]); 1542 gl.uniform3f(gl.getUniformLocation(this.GLShaderProgram, "lightdir"+i),lpos[0]-pos[0],lpos[1]-pos[1],lpos[2]-pos[2]); 1543 } 1544 1545 //set bone transforms 1546 var boneUniform; 1547 var transforms={}; 1548 if(this.action && this.skeleton){ 1549 transforms=this.getBoneTransforms(); 1550 } 1551 for(var i=0; i<this.mesh.boneWeights.length; i++){ 1552 if(!transforms[this.mesh.boneWeights[i].boneName]) transforms[this.mesh.boneWeights[i].boneName]={matrix:Matrix.I(4)}; 1553 1554 boneUniform = gl.getUniformLocation(this.GLShaderProgram, this.mesh.boneWeights[i].boneName+"Matrix"); 1555 gl.uniformMatrix4fv(boneUniform, false, new WebGLFloatArray(transforms[this.mesh.boneWeights[i].boneName].matrix.flatten())); 1556 1557 boneUniform = gl.getUniformLocation(this.GLShaderProgram, this.mesh.boneWeights[i].boneName+"nMatrix"); 1558 gl.uniformMatrix4fv(boneUniform, false, new WebGLFloatArray(transforms[this.mesh.boneWeights[i].boneName].matrix.inverse().transpose().flatten())); 1559 } 1560 1561 if(this.material) this.material.textureUniforms(gl,this.GLShaderProgram,this.scene.lights); 1562 } 1563 /** 1564 * Renders the object to the screen 1565 * @private 1566 */ 1567 GLGE.Object.prototype.GLRender=function(gl){ 1568 //animate this object 1569 if(this.animation) this.animate(); 1570 1571 var attribslot; 1572 gl.useProgram(this.GLShaderProgram); 1573 1574 this.mesh.GLAttributes(gl,this.GLShaderProgram); 1575 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mesh.GLfaces); 1576 1577 this.GLUniforms(gl); 1578 //gl.drawArrays(gl.LINE_LOOP, 0, this.GLbuffers["position"].numItems); 1579 gl.drawElements(gl.TRIANGLES, this.mesh.GLfaces.numItems, gl.UNSIGNED_SHORT, 0); 1580 } 1581 1582 1583 1584 /** 1585 * @class Creates a new mesh to associate with a mesh 1586 * @see GLGE.Object 1587 */ 1588 GLGE.Mesh=function(){ 1589 this.GLbuffers=[]; 1590 this.buffers=[]; 1591 this.UV=[]; 1592 this.boneWeights=[]; 1593 this.setBuffers=[]; 1594 this.faces={}; 1595 this.objects=[]; 1596 } 1597 GLGE.Mesh.prototype.gl=null; 1598 GLGE.Mesh.prototype.GLbuffers=null; 1599 GLGE.Mesh.prototype.buffers=null; 1600 GLGE.Mesh.prototype.setBuffers=null; 1601 GLGE.Mesh.prototype.GLfaces=null; 1602 GLGE.Mesh.prototype.faces=null; 1603 GLGE.Mesh.prototype.boneWeights=null; 1604 GLGE.Mesh.prototype.UV=null; 1605 GLGE.Mesh.prototype.objects=null; 1606 /** 1607 * Set the UV coord for the first UV layer 1608 * @param {Number[]} jsArray the UV coords in a 1 dimentional array 1609 */ 1610 GLGE.Mesh.prototype.setUV=function(jsArray){ 1611 var idx=0; 1612 for(var i=0; i<jsArray.length;i=i+2){ 1613 this.UV[idx]=jsArray[i]; 1614 this.UV[idx+1]=jsArray[i+1]; 1615 if(!this.UV[idx+2]) this.UV[idx+2]=0; 1616 if(!this.UV[idx+3]) this.UV[idx+3]=0; 1617 idx=idx+4; 1618 } 1619 this.setBuffer("UV",this.UV,4); 1620 } 1621 /** 1622 * Set the UV coord for the second UV layer 1623 * @param {Number[]} jsArray the UV coords in a 1 dimentional array 1624 */ 1625 GLGE.Mesh.prototype.setUV2=function(jsArray){ 1626 var idx=0; 1627 for(var i=0; i<jsArray.length;i=i+2){ 1628 if(!this.UV[idx]) this.UV[idx]=0; 1629 if(!this.UV[idx+1]) this.UV[idx+1]=0; 1630 this.UV[idx+2]=jsArray[i]; 1631 this.UV[idx+3]=jsArray[i+1]; 1632 idx=idx+4; 1633 } 1634 this.setBuffer("UV",this.UV,4); 1635 } 1636 /** 1637 * Sets the bone weights for a perticular bone 1638 * @param {String} boneName The name of the bone 1639 * @param {Number[]} jsArray The 1 dimentional array of weights 1640 */ 1641 GLGE.Mesh.prototype.addBoneWeights=function(boneName,jsArray){ 1642 var bone={}; 1643 bone.boneName=boneName; 1644 bone.weights=jsArray; 1645 this.boneWeights.push(bone); 1646 1647 var weights; 1648 var cnt=0; 1649 for(var i=0; i<this.boneWeights.length; i=i+4){ 1650 weights=[]; 1651 size=1; 1652 for(var n=0; n<this.boneWeights[i].weights.length;n++){ 1653 weights.push(this.boneWeights[i].weights[n]); 1654 if(this.boneWeights[i+1]){ 1655 size=2; 1656 weights.push(this.boneWeights[i+1].weights[n]); 1657 } 1658 if(this.boneWeights[i+2]){ 1659 size=3; 1660 weights.push(this.boneWeights[i+2].weights[n]); 1661 } 1662 if(this.boneWeights[i+3]){ 1663 size=4; 1664 weights.push(this.boneWeights[i+3].weights[n]); 1665 } 1666 } 1667 this.setBuffer("bones"+cnt,weights,size); 1668 cnt++; 1669 } 1670 } 1671 /** 1672 * Sets the positions of the verticies 1673 * @param {Number[]} jsArray The 1 dimentional array of positions 1674 */ 1675 GLGE.Mesh.prototype.setPositions=function(jsArray){ 1676 this.setBuffer("position",jsArray,3); 1677 } 1678 /** 1679 * Sets the normals of the verticies 1680 * @param {Number[]} jsArray The 1 dimentional array of normals 1681 */ 1682 GLGE.Mesh.prototype.setNormals=function(jsArray){ 1683 this.setBuffer("normal",jsArray,3); 1684 } 1685 /** 1686 * Sets a buffer for the 1687 * @param {String} boneName The name of the bone 1688 * @param {Number[]} jsArray The 1 dimentional array of weights 1689 * @private 1690 */ 1691 GLGE.Mesh.prototype.setBuffer=function(bufferName,jsArray,size){ 1692 var buffer; 1693 for(var i=0;i<this.buffers.length;i++){ 1694 if(this.buffers[i].name==bufferName) buffer=i; 1695 } 1696 if(!buffer){ 1697 this.buffers.push({name:bufferName,data:jsArray,size:size,GL:false}); 1698 this.updatePrograms(); 1699 } 1700 else 1701 { 1702 this.buffers[buffer]={name:bufferName,data:jsArray,size:size,GL:false}; 1703 } 1704 } 1705 /** 1706 * Sets the faces for this mesh 1707 * @param {Number[]} jsArray The 1 dimentional array of normals 1708 */ 1709 GLGE.Mesh.prototype.setFaces=function(jsArray){ 1710 this.faces={data:jsArray,GL:false}; 1711 1712 } 1713 /** 1714 * Sets the faces for this mesh 1715 * @param {Number[]} jsArray The 1 dimentional array of normals 1716 * @private 1717 */ 1718 GLGE.Mesh.prototype.GLSetFaceBuffer=function(gl){ 1719 if(!this.GLfaces) this.GLfaces = gl.createBuffer(); 1720 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces); 1721 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(this.faces.data), gl.STATIC_DRAW); 1722 this.GLfaces.itemSize = 1; 1723 this.GLfaces.numItems = this.faces.data.length; 1724 } 1725 /** 1726 * Sets up a GL Buffer 1727 * @param {WebGLContext} gl The context being drawn on 1728 * @param {String} bufferName The name of the buffer to create 1729 * @param {Number[]} jsArray The data to add to the buffer 1730 * @param {Number} size Size of a single element within the array 1731 * @private 1732 */ 1733 GLGE.Mesh.prototype.GLSetBuffer=function(gl,bufferName,jsArray,size){ 1734 if(!this.GLbuffers[bufferName]) this.GLbuffers[bufferName] = gl.createBuffer(); 1735 gl.bindBuffer(gl.ARRAY_BUFFER, this.GLbuffers[bufferName]); 1736 gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(jsArray), gl.STATIC_DRAW); 1737 this.GLbuffers[bufferName].itemSize = size; 1738 this.GLbuffers[bufferName].numItems = jsArray.length/size; 1739 } 1740 /** 1741 * Sets the Attributes for this mesh 1742 * @param {WebGLContext} gl The context being drawn on 1743 * @private 1744 */ 1745 GLGE.Mesh.prototype.GLAttributes=function(gl,shaderProgram){ 1746 //disable all the attribute initially arrays - do I really need this? 1747 for(var i=0; i<8; i++) gl.disableVertexAttribArray(i); 1748 //check if the faces have been updated 1749 if(!this.faces.GL){ 1750 this.GLSetFaceBuffer(gl); 1751 this.faces.GL=true; 1752 } 1753 //loop though the buffers 1754 for(i=0; i<this.buffers.length;i++){ 1755 if(!this.buffers[i].GL){ 1756 this.GLSetBuffer(gl,this.buffers[i].name,this.buffers[i].data,this.buffers[i].size); 1757 this.buffers[i].GL=true; 1758 } 1759 attribslot=gl.getAttribLocation(shaderProgram, this.buffers[i].name); 1760 if(attribslot>-1){ 1761 gl.bindBuffer(gl.ARRAY_BUFFER, this.GLbuffers[this.buffers[i].name]); 1762 gl.enableVertexAttribArray(attribslot); 1763 gl.vertexAttribPointer(attribslot, this.GLbuffers[this.buffers[i].name].itemSize, gl.FLOAT, false, 0, 0); 1764 } 1765 } 1766 } 1767 /** 1768 * updates the programs for the objects when buffers are added/removed 1769 * @private 1770 */ 1771 GLGE.Mesh.prototype.updatePrograms=function(){ 1772 for(var i=0;i<this.objects.length;i++){ 1773 this.objects[i].updateProgram(); 1774 } 1775 } 1776 /** 1777 * Adds a object to this mesh to be notified when a buffer is added/removed 1778 * @param {GLGE.Object} object the object this mesh has been added to 1779 * @private 1780 */ 1781 GLGE.Mesh.prototype.addObject=function(object){ 1782 this.objects.push(object); 1783 } 1784 /** 1785 * Removes the association with an object 1786 * @param {GLGE.Object} object the object this mesh has been added to 1787 * @private 1788 */ 1789 GLGE.Mesh.prototype.removeObject=function(object){ 1790 //TODO: add remove code 1791 } 1792 1793 1794 /** 1795 * @class Creates a new light source to be added to a scene 1796 * @property {Boolean} diffuse Dose this light source effect diffuse shading 1797 * @property {Boolean} specular Dose this light source effect specular shading 1798 * @augments GLGE.Animatable 1799 * @augments GLGE.Placeable 1800 */ 1801 GLGE.Light=function(type){ 1802 this.color={r:1,g:1,b:1}; 1803 this.type=type; 1804 } 1805 GLGE.augment(GLGE.Placeable,GLGE.Light); 1806 GLGE.augment(GLGE.Animatable,GLGE.Light); 1807 /** 1808 * @constant 1809 * @description Enumeration for an point light source 1810 */ 1811 GLGE.L_POINT=1; 1812 /** 1813 * @constant 1814 * @description Enumeration for an directional light source 1815 */ 1816 GLGE.L_DIR=2; 1817 /** 1818 * @constant 1819 * @description Enumeration for an spot light source 1820 */ 1821 GLGE.L_SPOT=3; 1822 1823 GLGE.Light.prototype.constantAttenuation=1; 1824 GLGE.Light.prototype.linearAttenuation=0.002; 1825 GLGE.Light.prototype.quadraticAttenuation=0.0008; 1826 GLGE.Light.prototype.spotCosCutOff=0.95; 1827 GLGE.Light.prototype.spotExponent=10; 1828 GLGE.Light.prototype.color=null; 1829 GLGE.Light.prototype.diffuse=true; 1830 GLGE.Light.prototype.specular=true; 1831 GLGE.Light.type=GLGE.L_POINT; 1832 /** 1833 * Sets the spot light cut off 1834 * @param {number} value The cos of the angle to limit 1835 */ 1836 GLGE.Light.prototype.setSpotCosCutOff=function(value){ 1837 this.spotCosCutOff=value; 1838 } 1839 /** 1840 * Gets the spot light cut off 1841 * @returns {number} The cos of the limiting angle 1842 */ 1843 GLGE.Light.prototype.getSpotCosCutOff=function(){ 1844 return this.spotCosCutOff=value; 1845 } 1846 /** 1847 * Sets the spot light exponent 1848 * @param {number} value The spot lights exponent 1849 */ 1850 GLGE.Light.prototype.setSpotExponent=function(value){ 1851 this.spotExponent=value; 1852 } 1853 /** 1854 * Gets the spot light exponent 1855 * @returns {number} The exponent of the spot light 1856 */ 1857 GLGE.Light.prototype.getSpotExponent=function(){ 1858 return this.spotExponentf=value; 1859 } 1860 /** 1861 * Sets the light sources Attenuation 1862 * @returns {Object} The components of the light sources attenuation 1863 */ 1864 GLGE.Light.prototype.getAttenuation=function(constant,linear,quadratic){ 1865 var attenuation={}; 1866 attenuation.constant=this.constantAttenuation; 1867 attenuation.linear=this.linearAttenuation; 1868 attenuation.quadratic=this.quadraticAttenuation; 1869 return attenuation; 1870 } 1871 /** 1872 * Sets the light sources Attenuation 1873 * @param {Number} constant The constant part of the attenuation 1874 * @param {Number} linear The linear part of the attenuation 1875 * @param {Number} quadratic The quadratic part of the attenuation 1876 */ 1877 GLGE.Light.prototype.setAttenuation=function(constant,linear,quadratic){ 1878 this.constantAttenuation=constant; 1879 this.linearAttenuation=linear; 1880 this.quadraticAttenuation=quadratic; 1881 } 1882 /** 1883 * Sets the light sources constant attenuation 1884 * @param {Number} value The constant part of the attenuation 1885 */ 1886 GLGE.Light.prototype.setAttenuationConstant=function(value){ 1887 this.constantAttenuation=value; 1888 } 1889 /** 1890 * Sets the light sources linear attenuation 1891 * @param {Number} value The linear part of the attenuation 1892 */ 1893 GLGE.Light.prototype.setAttenuationLinear=function(value){ 1894 this.linearAttenuation=value; 1895 } 1896 /** 1897 * Sets the light sources quadratic attenuation 1898 * @param {Number} value The quadratic part of the attenuation 1899 */ 1900 GLGE.Light.prototype.setAttenuationQuadratic=function(value){ 1901 this.quadraticAttenuation=value; 1902 } 1903 1904 /** 1905 * Sets the color of the light source 1906 * @param {Number} r The new red level 0-1 1907 * @param {Number} g The new green level 0-1 1908 * @param {Number} b The new blue level 0-1 1909 */ 1910 GLGE.Light.prototype.setColor=function(r,g,b){ 1911 this.color={r:r,g:g,b:b}; 1912 } 1913 /** 1914 * Sets the red color of the light source 1915 * @param {Number} value The new red level 0-1 1916 */ 1917 GLGE.Light.prototype.setColorR=function(value){ 1918 this.color.r=value 1919 } 1920 /** 1921 * Sets the green color of the light source 1922 * @param {Number} value The new green level 0-1 1923 */ 1924 GLGE.Light.prototype.setColorG=function(value){ 1925 this.color.g=value 1926 } 1927 /** 1928 * Sets the blue color of the light source 1929 * @param {Number} value The new blue level 0-1 1930 */ 1931 GLGE.Light.prototype.setColorB=function(value){ 1932 this.color.b=value 1933 } 1934 /** 1935 * Gets the current color of the light source 1936 * @return {[r,g,b]} The current position 1937 */ 1938 GLGE.Light.prototype.getColor=function(){ 1939 return this.color; 1940 } 1941 /** 1942 * Gets the type of the light 1943 * @return {Number} The type of the light source eg GLGE.L_POINT 1944 */ 1945 GLGE.Light.prototype.getType=function(){ 1946 return this.type; 1947 } 1948 /** 1949 * Sets the type of the light 1950 * @param {Number} type The type of the light source eg GLGE.L_POINT 1951 */ 1952 GLGE.Light.prototype.setType=function(type){ 1953 this.type=type; 1954 } 1955 1956 1957 /** 1958 * @class Creates a new camera object 1959 * @augments GLGE.Animatable 1960 * @augments GLGE.Placeable 1961 */ 1962 GLGE.Camera=function(){ 1963 this.pMatrix=makePerspective(45, 1.0, 0.1, 300.0); 1964 }; 1965 GLGE.augment(GLGE.Placeable,GLGE.Camera); 1966 GLGE.augment(GLGE.Animatable,GLGE.Camera); 1967 GLGE.Camera.prototype.pMatrix=null; 1968 /** 1969 * Method gets the current projection matrix of this camera 1970 * @return {Matrix} Returns the camera projection matrix 1971 */ 1972 GLGE.Camera.prototype.getProjectionMatrix=function(){ 1973 return this.pMatrix; 1974 }; 1975 /** 1976 * Method generates the projection matrix based on the 1977 * camera paramaters 1978 * @param {Matrix} projection The new projection matrix 1979 */ 1980 GLGE.Camera.prototype.setProjectionMatrix=function(projection){ 1981 this.pMatrix=projection; 1982 }; 1983 /** 1984 * Method generates the cameras view matrix 1985 * @return Returns the view matrix based on this camera 1986 * @type Matrix 1987 */ 1988 GLGE.Camera.prototype.updateMatrix=function(){ 1989 var position=this.getPosition(); 1990 var rotation=this.getRotation(); 1991 var vMatrix=Matrix.transMat(position.x,position.y,position.z); 1992 vMatrix=vMatrix.x(Matrix.rotMat(rotation.x,rotation.y,rotation.z)); 1993 this.matrix=vMatrix.inverse(); 1994 }; 1995 /** 1996 * Method generates the cameras view matrix 1997 * @return Returns the view matrix based on this camera 1998 * @type Matrix 1999 */ 2000 GLGE.Camera.prototype.getViewMatrix=function(){ 2001 return this.matrix; 2002 }; 2003 2004 /** 2005 * @class Scene class containing the camera, lights and objects 2006 */ 2007 GLGE.Scene=function(){ 2008 this.objects=[]; 2009 this.lights=[]; 2010 this.camera=new GLGE.Camera(); 2011 this.backgroundColor={r:1,g:1,b:1}; 2012 this.ambientColor={r:0,g:0,b:0}; 2013 } 2014 GLGE.Scene.prototype.camera=null; 2015 GLGE.Scene.prototype.objects=null; 2016 GLGE.Scene.prototype.lights=null; 2017 GLGE.Scene.prototype.renderer=null; 2018 GLGE.Scene.prototype.backgroundColor=null; 2019 GLGE.Scene.prototype.ambientColor=null; 2020 /** 2021 * Gets the scenes background color 2022 * @returns {object} An assoiative array r,g,b 2023 */ 2024 GLGE.Scene.prototype.getBackgroundColor=function(){ 2025 return this.backgroundColor; 2026 } 2027 /** 2028 * Sets the scenes background color 2029 * @param {number} r the red componenent of the background color 0-1 2030 * @param {number} g the green componenent of the background color 0-1 2031 * @param {number} b the blue componenent of the background color 0-1 2032 */ 2033 GLGE.Scene.prototype.setBackgroundColor=function(r,g,b){ 2034 this.backgroundColor={r:r,g:g,b:b}; 2035 if(this.renderer){ 2036 this.renderer.gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, 1.0); 2037 } 2038 } 2039 /** 2040 * Gets the scenes ambient light 2041 * @returns {object} An assoiative array r,g,b 2042 */ 2043 GLGE.Scene.prototype.getAmbientColor=function(){ 2044 return this.ambientColor; 2045 } 2046 /** 2047 * Sets the scenes ambient light 2048 * @param {number} r the red componenent of the ambient light 0-1 2049 * @param {number} g the green componenent of the ambient light 0-1 2050 * @param {number} b the blue componenent of the ambient light 0-1 2051 */ 2052 GLGE.Scene.prototype.setAmbientColor=function(r,g,b){ 2053 this.ambientColor={r:r,g:g,b:b}; 2054 if(this.renderer){ 2055 this.renderer.gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, 1.0); 2056 } 2057 } 2058 /** 2059 * Sets the scenes ambient light 2060 * @param {number} value the red componenent of the ambient light 0-1 2061 */ 2062 GLGE.Scene.prototype.setAmbientColorR=function(value){ 2063 this.ambientColor.r=value; 2064 } 2065 /** 2066 * Sets the scenes ambient light 2067 * @param {number} value the green componenent of the ambient light 0-1 2068 */ 2069 GLGE.Scene.prototype.setAmbientColorG=function(value){ 2070 this.ambientColor.g=value; 2071 } 2072 /** 2073 * Sets the scenes ambient light 2074 * @param {number} value the blue componenent of the ambient light 0-1 2075 */ 2076 GLGE.Scene.prototype.setAmbientColorB=function(value){ 2077 this.ambientColor.b=value; 2078 } 2079 2080 /** 2081 * Gets an array of all the object in the scene 2082 * @returns {GLGE.Object[]} An array of objects 2083 */ 2084 GLGE.Scene.prototype.getObjects=function(){ 2085 return this.objects; 2086 } 2087 /** 2088 * Gets an array of all the light sources in the scene 2089 * @returns {GLGE.Lights[]} An array of lights 2090 */ 2091 GLGE.Scene.prototype.getLights=function(){ 2092 return this.lights; 2093 } 2094 /** 2095 * Sets the active camera for this scene 2096 * @property {GLGE.Camera} object The object to be added 2097 */ 2098 GLGE.Scene.prototype.setCamera=function(camera){ 2099 this.camera=camera; 2100 } 2101 /** 2102 * Gets the scenes active camera 2103 * @returns {GLGE.Camera} The current camera 2104 */ 2105 GLGE.Scene.prototype.getCamera=function(){ 2106 return this.camera; 2107 } 2108 /** 2109 * Adds an object to the scene 2110 * @property {GLGE.Object} object The object to be added 2111 * @returns {Number} The index of the added object 2112 */ 2113 GLGE.Scene.prototype.addObject=function(object){ 2114 object.scene=this; 2115 this.objects.push(object); 2116 if(this.renderer) object.GLInit(this.renderer.gl); 2117 return this.objects.length-1; 2118 } 2119 /** 2120 * Adds a light source to the scene 2121 * @property {GLGE.Light} light The light to be added 2122 * @returns {Number} The index of the added light 2123 */ 2124 GLGE.Scene.prototype.addLight=function(light){ 2125 light.scene=this; 2126 this.lights.push(light); 2127 } 2128 /** 2129 * used to initialize all the WebGL buffers etc need for this scene 2130 * @private 2131 */ 2132 GLGE.Scene.prototype.init=function(){ 2133 this.renderer.gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, 1.0); 2134 for(var i=0;i<this.objects.length;i++){ 2135 this.objects[i].GLInit(this.renderer.gl); 2136 } 2137 } 2138 /** 2139 * used to clean up all the WebGL buffers etc need for this scene 2140 * @private 2141 */ 2142 GLGE.Scene.prototype.destory=function(gl){ 2143 } 2144 /** 2145 * renders the scene 2146 * @private 2147 */ 2148 GLGE.Scene.prototype.render=function(gl){ 2149 if(this.camera.animation) this.camera.animate(); 2150 for(var i=0;i<this.lights.length;i++){ 2151 if(this.lights[i].animation) this.lights[i].animate(); 2152 } 2153 this.renderer.gl.disable(this.renderer.gl.BLEND); 2154 for(var i=0; i<this.objects.length;i++){ 2155 if(!this.objects[i].zTrans) this.objects[i].GLRender(this.renderer.gl); 2156 } 2157 this.renderer.gl.enable(this.renderer.gl.BLEND); 2158 for(var i=0; i<this.objects.length;i++){ 2159 if(this.objects[i].zTrans) this.objects[i].GLRender(this.renderer.gl); 2160 } 2161 } 2162 2163 /** 2164 * @class Sets the scene to render 2165 * @param {GLGE.Scene} scene The scene to be rendered 2166 */ 2167 GLGE.Renderer=function(canvas){ 2168 try{ 2169 this.gl = canvas.getContext("webkit-3d"); 2170 }catch(e){} 2171 if (!this.gl){ 2172 try 2173 { 2174 this.gl = canvas.getContext("moz-webgl"); 2175 }catch(e){} 2176 } 2177 if (!this.gl) 2178 { 2179 alert("What, What Whaaat? No WebGL!"); 2180 return false; 2181 } 2182 //set up defaults 2183 this.gl.clearDepth(1.0); 2184 this.gl.enable(this.gl.DEPTH_TEST); 2185 //this.gl.enable(this.gl.SAMPLE_ALPHA_TO_COVERAGE); 2186 2187 this.gl.depthFunc(this.gl.LEQUAL); 2188 this.gl.blendFuncSeparate(this.gl.SRC_ALPHA,this.gl.ONE_MINUS_SRC_ALPHA,this.gl.ZERO,this.gl.ONE); 2189 2190 this.gl.enable(this.gl.CULL_FACE); 2191 2192 }; 2193 GLGE.Renderer.prototype.gl=null; 2194 GLGE.Renderer.prototype.scene=null; 2195 /** 2196 * Gets the scene which is set to be rendered 2197 * @returns the current render scene 2198 */ 2199 GLGE.Renderer.prototype.getScene=function(gcene){ 2200 return this.scene; 2201 }; 2202 /** 2203 * Sets the scene to render 2204 * @param {GLGE.Scene} scene The scene to be rendered 2205 */ 2206 GLGE.Renderer.prototype.setScene=function(scene){ 2207 scene.renderer=this; 2208 this.scene=scene; 2209 scene.init(); 2210 }; 2211 /** 2212 * Renders the current scene to the canvas 2213 */ 2214 GLGE.Renderer.prototype.render=function(){ 2215 this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); 2216 this.scene.render(); 2217 }; 2218 2219 2220 /** 2221 * @class A texture to be included in a material 2222 * @param {string} url the url of the image to use as the texture 2223 * @see GLGE.Material 2224 */ 2225 GLGE.Texture=function(url){ 2226 this.image=new Image(); 2227 this.image.texture=this; 2228 this.image.onload = function(){ 2229 this.texture.state=1; 2230 } 2231 this.image.src=url; 2232 this.state=0; 2233 this.glTexture=null; 2234 } 2235 GLGE.Texture.prototype.image=null; 2236 GLGE.Texture.prototype.texture=null; 2237 GLGE.Texture.prototype.glTexture=null; 2238 2239 2240 /** 2241 * @class The material layer describes how to apply this layer to the material 2242 * @param {number} texture the texture index to apply to the layer 2243 * @param {number} mapto how to map this layer on to the material see M_XXXXX constants 2244 * @param {number} mapinput the UV layer to map to, UV1 or UV2 2245 * @param {Object} scale how much scaling the texture eg {x: 10, y:10, z:1} 2246 * @param {Object} offset how much to offset the texture eg {x: 10, y:10, z:1} 2247 * @see GLGE.Material 2248 * @augments GLGE.Animatable 2249 */ 2250 GLGE.MaterialLayer=function(texture,mapto,mapinput,scale,offset){ 2251 this.texture=texture; 2252 this.mapinput=mapinput; 2253 this.uv=mapinput; 2254 this.mapto=mapto; 2255 if(scale){ 2256 this.setScaleX(scale.x); 2257 this.setScaleY(scale.y); 2258 this.setScaleZ(scale.z); 2259 } 2260 if(offset){ 2261 this.setOffsetX(offset.x); 2262 this.setOffsetY(offset.y); 2263 this.setOffsetZ(offset.z); 2264 } 2265 this.scale=scale; 2266 this.offset=offset; 2267 }; 2268 GLGE.augment(GLGE.Animatable,GLGE.MaterialLayer); 2269 GLGE.MaterialLayer.prototype.texture=null; 2270 GLGE.MaterialLayer.prototype.mapto=GLGE.M_COLOR; 2271 GLGE.MaterialLayer.prototype.mapinput=GLGE.UV1; 2272 GLGE.MaterialLayer.prototype.scaleX=1; 2273 GLGE.MaterialLayer.prototype.offsetX=0; 2274 GLGE.MaterialLayer.prototype.scaleY=1; 2275 GLGE.MaterialLayer.prototype.offsetY=0; 2276 GLGE.MaterialLayer.prototype.scaleZ=1; 2277 GLGE.MaterialLayer.prototype.offsetZ=0; 2278 GLGE.MaterialLayer.prototype.dScaleX=0; 2279 GLGE.MaterialLayer.prototype.dOffsetX=0; 2280 GLGE.MaterialLayer.prototype.dScaleY=0; 2281 GLGE.MaterialLayer.prototype.dOffsetY=0; 2282 GLGE.MaterialLayer.prototype.dScaleZ=0; 2283 GLGE.MaterialLayer.prototype.dOffsetZ=0; 2284 2285 /** 2286 * Sets the textures used by the layer 2287 * @param {GLGE.Texture} value the teture to associate with this layer 2288 */ 2289 GLGE.MaterialLayer.prototype.setTexture=function(value){ 2290 this.texture=value; 2291 }; 2292 /** 2293 * Gets the textures used by the layer 2294 * @return {GLGE.Texture} The current shininess of the material 2295 */ 2296 GLGE.MaterialLayer.prototype.getTexture=function(){ 2297 return this.texture; 2298 }; 2299 /** 2300 * Sets the flag for how this layer maps to the material 2301 * @param {Number} value the flags to set for this layer 2302 */ 2303 GLGE.MaterialLayer.prototype.setMapto=function(value){ 2304 this.mapto=value; 2305 }; 2306 /** 2307 * Gets the flag representing the way the layer maps to the material 2308 * @return {Number} The flags currently set for this layer 2309 */ 2310 GLGE.MaterialLayer.prototype.getMapto=function(){ 2311 return this.mapto; 2312 }; 2313 /** 2314 * Sets the texture coordinate system 2315 * @param {Number} value the mapping to use 2316 */ 2317 GLGE.MaterialLayer.prototype.setMapinput=function(value){ 2318 this.mapinput=value; 2319 }; 2320 /** 2321 * Gets the texture coordinate system 2322 * @return {Number} The current mapping 2323 */ 2324 GLGE.MaterialLayer.prototype.getMapinput=function(){ 2325 return this.mapinput; 2326 }; 2327 2328 /** 2329 * Gets the layers texture offset 2330 * @return {object} the current offset 2331 */ 2332 GLGE.MaterialLayer.prototype.getOffset=function(){ 2333 var offset={}; 2334 offset.x=parseFloat(this.getOffsetX())+parseFloat(this.getDOffsetX()); 2335 offset.y=parseFloat(this.getOffsetY())+parseFloat(this.getDOffsetY()); 2336 offset.z=parseFloat(this.getOffsetZ())+parseFloat(this.getDOffsetZ()); 2337 return offset; 2338 }; 2339 2340 /** 2341 * Gets the layers texture scale 2342 * @return {object} the current scale 2343 */ 2344 GLGE.MaterialLayer.prototype.getScale=function(){ 2345 var scale={}; 2346 scale.x=parseFloat(this.getScaleX())+parseFloat(this.getDScaleX()); 2347 scale.y=parseFloat(this.getScaleY())+parseFloat(this.getDScaleY()); 2348 scale.z=parseFloat(this.getScaleZ())+parseFloat(this.getDScaleZ()); 2349 return scale; 2350 }; 2351 2352 /** 2353 * Sets the layers texture X offset 2354 * @param {Number} value the amount to offset the texture 2355 */ 2356 GLGE.MaterialLayer.prototype.setOffsetX=function(value){ 2357 this.offsetX=value; 2358 }; 2359 /** 2360 * Gets the layers texture X offset 2361 * @return {Number} the current offset 2362 */ 2363 GLGE.MaterialLayer.prototype.getOffsetX=function(){ 2364 return this.offsetX; 2365 }; 2366 /** 2367 * Sets the layers texture Y offset 2368 * @param {Number} value the amount to offset the texture 2369 */ 2370 GLGE.MaterialLayer.prototype.setOffsetY=function(value){ 2371 this.offsetY=value; 2372 }; 2373 /** 2374 * Gets the layers texture Y offset 2375 * @return {Number} the current offset 2376 */ 2377 GLGE.MaterialLayer.prototype.getOffsetY=function(){ 2378 return this.offsetY; 2379 }; 2380 /** 2381 * Sets the layers texture Z offset 2382 * @param {Number} value the amount to offset the texture 2383 */ 2384 GLGE.MaterialLayer.prototype.setOffsetZ=function(value){ 2385 this.offsetZ=value; 2386 }; 2387 /** 2388 * Gets the layers texture Z offset 2389 * @return {Number} the current offset 2390 */ 2391 GLGE.MaterialLayer.prototype.getOffsetZ=function(){ 2392 return this.offsetZ; 2393 }; 2394 /** 2395 * Sets the layers texture X displacment offset, useful for animation 2396 * @param {Number} value the amount to offset the texture 2397 */ 2398 GLGE.MaterialLayer.prototype.setDOffsetX=function(value){ 2399 this.dOffsetX=value; 2400 }; 2401 /** 2402 * Gets the layers texture X displacment offset, useful for animation 2403 * @return {Number} the current offset 2404 */ 2405 GLGE.MaterialLayer.prototype.getDOffsetX=function(){ 2406 return this.dOffsetX; 2407 }; 2408 /** 2409 * Sets the layers texture Y displacment offset, useful for animation 2410 * @param {Number} value the amount to offset the texture 2411 */ 2412 GLGE.MaterialLayer.prototype.setDOffsetY=function(value){ 2413 this.dOffsetY=value; 2414 }; 2415 /** 2416 * Gets the layers texture Y displacment offset, useful for animation 2417 * @return {Number} the current offset 2418 */ 2419 GLGE.MaterialLayer.prototype.getDOffsetY=function(){ 2420 return this.dOffsetY; 2421 }; 2422 /** 2423 * Sets the layers texture Z displacment offset, useful for animation 2424 * @param {Number} value the amount to offset the texture 2425 */ 2426 GLGE.MaterialLayer.prototype.setDOffsetZ=function(value){ 2427 this.dOffsetZ=value; 2428 }; 2429 /** 2430 * Gets the layers texture X displacment offset, useful for animation 2431 * @return {Number} the current offset 2432 */ 2433 GLGE.MaterialLayer.prototype.getDOffsetZ=function(){ 2434 return this.dOffsetZ; 2435 }; 2436 /** 2437 * Sets the layers texture X scale 2438 * @param {Number} value the amount to scale the texture 2439 */ 2440 GLGE.MaterialLayer.prototype.setScaleX=function(value){ 2441 this.scaleX=value; 2442 }; 2443 /** 2444 * Gets the layers texture X scale 2445 * @return {Number} the current scale 2446 */ 2447 GLGE.MaterialLayer.prototype.getScaleX=function(){ 2448 return this.scaleX; 2449 }; 2450 /** 2451 * Sets the layers texture Y scale 2452 * @param {Number} value the amount to scale the texture 2453 */ 2454 GLGE.MaterialLayer.prototype.setScaleY=function(value){ 2455 this.scaleY=value; 2456 }; 2457 /** 2458 * Gets the layers texture Y scale 2459 * @return {Number} the current scale 2460 */ 2461 GLGE.MaterialLayer.prototype.getScaleY=function(){ 2462 return this.scaleY; 2463 }; 2464 /** 2465 * Sets the layers texture Z scale 2466 * @param {Number} value the amount to scale the texture 2467 */ 2468 GLGE.MaterialLayer.prototype.setScaleZ=function(value){ 2469 this.scaleZ=value; 2470 }; 2471 /** 2472 * Gets the layers texture Z offset 2473 * @return {Number} the current offset 2474 */ 2475 GLGE.MaterialLayer.prototype.getScaleZ=function(){ 2476 return this.scaleZ; 2477 }; 2478 /** 2479 * Sets the layers texture X displacment scale, useful for animation 2480 * @param {Number} value the amount to scale the texture 2481 */ 2482 GLGE.MaterialLayer.prototype.setDScaleX=function(value){ 2483 this.dScaleX=value; 2484 }; 2485 /** 2486 * Gets the layers texture X displacment scale, useful for animation 2487 * @return {Number} the current scale 2488 */ 2489 GLGE.MaterialLayer.prototype.getDScaleX=function(){ 2490 return this.dScaleX; 2491 }; 2492 /** 2493 * Sets the layers texture Y displacment scale, useful for animation 2494 * @param {Number} value the amount to scale the texture 2495 */ 2496 GLGE.MaterialLayer.prototype.setDScaleY=function(value){ 2497 this.dScaleY=value; 2498 }; 2499 /** 2500 * Gets the layers texture Y displacment scale, useful for animation 2501 * @return {Number} the current scale 2502 */ 2503 GLGE.MaterialLayer.prototype.getDScaleY=function(){ 2504 return this.dScaleY; 2505 }; 2506 /** 2507 * Sets the layers texture Z displacment scale, useful for animation 2508 * @param {Number} value the amount to scale the texture 2509 */ 2510 GLGE.MaterialLayer.prototype.setDScaleZ=function(value){ 2511 this.dScaleZ=value; 2512 }; 2513 /** 2514 * Gets the layers texture X displacment scale, useful for animation 2515 * @return {Number} the current scale 2516 */ 2517 GLGE.MaterialLayer.prototype.getDScaleZ=function(){ 2518 return this.dScaleZ; 2519 }; 2520 2521 2522 2523 /** 2524 * @class The Material class creates materials to be applied to objects in the graphics engine 2525 * @see GLGE.Object 2526 * @augments GLGE.Animatable 2527 */ 2528 GLGE.Material=function(){ 2529 this.layers=[]; 2530 this.textures=[]; 2531 this.lights=[]; 2532 this.color={r:1,g:1,b:1,a:1}; 2533 this.specColor={r:1,g:1,b:1}; 2534 this.reflect=0.8; 2535 this.shine=50; 2536 this.specular=1; 2537 this.emit=0; 2538 this.alpha=1; 2539 }; 2540 GLGE.augment(GLGE.Animatable,GLGE.Material); 2541 /** 2542 * @constant 2543 * @description Flag for material colour 2544 */ 2545 GLGE.M_COLOR=1; 2546 /** 2547 * @constant 2548 * @description Flag for material normal 2549 */ 2550 GLGE.M_NOR=2; 2551 /** 2552 * @constant 2553 * @description Flag for material alpha 2554 */ 2555 GLGE.M_ALPHA=4; 2556 /** 2557 * @constant 2558 * @description Flag for material specular color 2559 */ 2560 GLGE.M_SPECCOLOR=8; 2561 /** 2562 * @constant 2563 * @description Flag for material specular cvalue 2564 */ 2565 GLGE.M_SPECULAR=16; 2566 /** 2567 * @constant 2568 * @description Flag for material shineiness 2569 */ 2570 GLGE.M_SHINE=32; 2571 /** 2572 * @constant 2573 * @description Flag for material reflectivity 2574 */ 2575 GLGE.M_REFLECT=64; 2576 /** 2577 * @constant 2578 * @description Flag for material emision 2579 */ 2580 GLGE.M_EMIT=128; 2581 /** 2582 * @constant 2583 * @description Flag for material alpha 2584 */ 2585 GLGE.M_ALPHA=256; 2586 /** 2587 * @constant 2588 * @description Flag for masking with textures red value 2589 */ 2590 GLGE.M_MSKR=512; 2591 /** 2592 * @constant 2593 * @description Flag for masking with textures green value 2594 */ 2595 GLGE.M_MSKG=1024; 2596 /** 2597 * @constant 2598 * @description Flag for masking with textures blue value 2599 */ 2600 GLGE.M_MSKB=2048; 2601 /** 2602 * @constant 2603 * @description Flag for masking with textures alpha value 2604 */ 2605 GLGE.M_MSKA=4096; 2606 2607 /** 2608 * @constant 2609 * @description Enumeration for first UV layer 2610 */ 2611 GLGE.UV1=0; 2612 /** 2613 * @constant 2614 * @description Enumeration for second UV layer 2615 */ 2616 GLGE.UV2=1; 2617 2618 GLGE.Material.prototype.layers=null; 2619 GLGE.Material.prototype.textures=null; 2620 GLGE.Material.prototype.color=null; 2621 GLGE.Material.prototype.specColor=null; 2622 GLGE.Material.prototype.specular=null; 2623 GLGE.Material.prototype.emit=null; 2624 GLGE.Material.prototype.shine=null; 2625 GLGE.Material.prototype.reflect=null; 2626 GLGE.Material.prototype.lights=null; 2627 GLGE.Material.prototype.alpha=null; 2628 2629 /** 2630 * Sets the base colour of the material 2631 * @param {Number} r The new red level 0-1 2632 * @param {Number} g The new green level 0-1 2633 * @param {Number} b The new blue level 0-1 2634 */ 2635 GLGE.Material.prototype.setColor=function(r,g,b){ 2636 this.color={r:r,g:g,b:b}; 2637 }; 2638 /** 2639 * Gets the current base color of the material 2640 * @return {[r,g,b]} The current base color 2641 */ 2642 GLGE.Material.prototype.getColor=function(){ 2643 return this.color; 2644 }; 2645 /** 2646 * Sets the base specular colour of the material 2647 * @param {Number} r The new red level 0-1 2648 * @param {Number} g The new green level 0-1 2649 * @param {Number} b The new blue level 0-1 2650 */ 2651 GLGE.Material.prototype.setSpecularColor=function(r,g,b){ 2652 this.specColor={r:r,g:g,b:b}; 2653 }; 2654 /** 2655 * Gets the current base specular color of the material 2656 * @return {[r,g,b]} The current base specular color 2657 */ 2658 GLGE.Material.prototype.getSpecularColor=function(){ 2659 return this.specColor; 2660 }; 2661 /** 2662 * Sets the alpha of the material 2663 * @param {Number} value how much alpha 2664 */ 2665 GLGE.Material.prototype.setAlpha=function(value){ 2666 this.alpha=value; 2667 }; 2668 /** 2669 * Gets the alpha of the material 2670 * @return {Number} The current alpha of the material 2671 */ 2672 GLGE.Material.prototype.getAlpha=function(){ 2673 return this.alpha; 2674 }; 2675 /** 2676 * Sets the specular of the material 2677 * @param {Number} value how much specular 2678 */ 2679 GLGE.Material.prototype.setSpecular=function(value){ 2680 this.specular=value; 2681 }; 2682 /** 2683 * Gets the specular of the material 2684 * @return {Number} The current specular of the material 2685 */ 2686 GLGE.Material.prototype.getSpecular=function(){ 2687 return this.specular; 2688 }; 2689 /** 2690 * Sets the shininess of the material 2691 * @param {Number} value how much shine 2692 */ 2693 GLGE.Material.prototype.setShininess=function(value){ 2694 this.shine=value; 2695 }; 2696 /** 2697 * Gets the shininess of the material 2698 * @return {Number} The current shininess of the material 2699 */ 2700 GLGE.Material.prototype.getShininess=function(){ 2701 return this.shine; 2702 }; 2703 /** 2704 * Sets how much the material should emit 2705 * @param {Number} value how much to emit (0-1) 2706 */ 2707 GLGE.Material.prototype.setEmit=function(value){ 2708 this.emit=value; 2709 }; 2710 /** 2711 * Gets the amount this material emits 2712 * @return {Number} The emit value for the material 2713 */ 2714 GLGE.Material.prototype.getEmit=function(){ 2715 return this.emit; 2716 }; 2717 /** 2718 * Sets reflectivity of the material 2719 * @param {Number} value how much to reflect (0-1) 2720 */ 2721 GLGE.Material.prototype.setReflectivity=function(value){ 2722 this.reflect=value; 2723 }; 2724 /** 2725 * Gets the materials reflectivity 2726 * @return {Number} The reflectivity of the material 2727 */ 2728 GLGE.Material.prototype.getReflectivity=function(){ 2729 return this.reflect; 2730 }; 2731 2732 /** 2733 * Add a new layer to the material 2734 * @param {MaterialLayer} layer The material layer to add to the material 2735 * @returns {Number} index of the added layer 2736 */ 2737 GLGE.Material.prototype.addMaterialLayer=function(layer){ 2738 this.layers.push(layer); 2739 return this.layers.length-1; 2740 }; 2741 /** 2742 * Gets all the materials layers 2743 * @returns {GLGE.MaterialLayer[]} all of the layers contained within this material 2744 */ 2745 GLGE.Material.prototype.getLayers=function(){ 2746 return this.layers; 2747 }; 2748 /** 2749 * Generate the fragment shader program for this material 2750 * @private 2751 */ 2752 GLGE.Material.prototype.getFragmentShader=function(lights,ambiantColor){ 2753 var shader=""; 2754 2755 for(var i=0; i<lights.length;i++){ 2756 if(lights[i].type==GLGE.L_POINT || lights[i].type==GLGE.L_SPOT || lights[i].type==GLGE.L_DIR){ 2757 shader=shader+"varying vec3 lightvec"+i+";\n"; 2758 shader=shader+"varying float lightdist"+i+";\n"; 2759 } 2760 } 2761 shader=shader+"varying vec3 n;\n"; 2762 shader=shader+"varying vec4 UVCoord;\n"; 2763 shader=shader+"varying vec3 eyevec;\n"; 2764 2765 //texture uniforms 2766 for(var i=0; i<this.textures.length;i++){ 2767 shader=shader+"uniform sampler2D TEXTURE"+i+";\n"; 2768 } 2769 for(var i=0; i<lights.length;i++){ 2770 shader=shader+"uniform vec3 lightcolor"+i+";\n"; 2771 shader=shader+"uniform vec3 lightAttenuation"+i+";\n"; 2772 shader=shader+"uniform float spotCosCutOff"+i+";\n"; 2773 shader=shader+"uniform float spotExp"+i+";\n"; 2774 shader=shader+"uniform vec3 lightdir"+i+";\n"; 2775 } 2776 for(i=0; i<this.layers.length;i++){ 2777 shader=shader+"uniform vec3 layer"+i+"Scale;\n"; 2778 shader=shader+"uniform vec3 layer"+i+"Offset;\n"; 2779 } 2780 2781 shader=shader+"uniform vec4 baseColor;\n"; 2782 shader=shader+"uniform vec3 specColor;\n"; 2783 shader=shader+"uniform float shine;\n"; 2784 shader=shader+"uniform float specular;\n"; 2785 shader=shader+"uniform float reflect;\n"; 2786 shader=shader+"uniform float emit;\n"; 2787 shader=shader+"uniform float alpha;\n"; 2788 2789 shader=shader+"void main(void)\n"; 2790 shader=shader+"{\n"; 2791 shader=shader+"float att;\n"; 2792 shader=shader+"int texture;\n"; 2793 shader=shader+"float mask=1.0;\n"; 2794 shader=shader+"float spec=specular;\n"; 2795 shader=shader+"vec3 specC=specColor;\n"; 2796 shader=shader+"float ref=reflect;\n"; 2797 shader=shader+"float sh=shine;\n"; 2798 shader=shader+"float em=emit;\n"; 2799 shader=shader+"float al=alpha;\n"; 2800 shader=shader+"vec4 normalmap=vec4(0.5,0.5,0.5,0.5);\n" 2801 shader=shader+"vec4 color = baseColor;"; //set the initial color 2802 for(i=0; i<this.layers.length;i++){ 2803 if((this.layers[i].mapto & GLGE.M_COLOR) == GLGE.M_COLOR){ 2804 shader=shader+"color = color*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1]))*mask;\n"; 2805 } 2806 if((this.layers[i].mapto & GLGE.M_SPECCOLOR) == GLGE.M_SPECCOLOR){ 2807 shader=shader+"specC = specC*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).rgb*mask;\n"; 2808 } 2809 if((this.layers[i].mapto & GLGE.M_MSKR) == GLGE.M_MSKR){ 2810 shader=shader+"mask = texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).r;\n"; 2811 } 2812 if((this.layers[i].mapto & GLGE.M_MSKG) == GLGE.M_MSKG){ 2813 shader=shader+"mask = texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).g;\n"; 2814 } 2815 if((this.layers[i].mapto & GLGE.M_MSKG) == GLGE.M_MSKB){ 2816 shader=shader+"mask = texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).b;\n"; 2817 } 2818 if((this.layers[i].mapto & GLGE.M_MSKG) == GLGE.M_MSKA){ 2819 shader=shader+"mask = texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).a;\n"; 2820 } 2821 if((this.layers[i].mapto & GLGE.M_SPECULAR) == GLGE.M_SPECULAR){ 2822 shader=shader+"spec = spec*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).r*mask*10.0;\n"; 2823 } 2824 if((this.layers[i].mapto & GLGE.M_REFLECT) == GLGE.M_REFLECT){ 2825 shader=shader+"ref = ref*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).g*mask;\n"; 2826 } 2827 if((this.layers[i].mapto & GLGE.M_SHINE) == GLGE.M_SHINE){ 2828 shader=shader+"sh = sh*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).b*mask*512.0;\n"; 2829 } 2830 if((this.layers[i].mapto & GLGE.M_EMIT) == GLGE.M_EMIT){ 2831 shader=shader+"em = em*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).r*mask;\n"; 2832 } 2833 if((this.layers[i].mapto & GLGE.M_NOR) == GLGE.M_NOR){ 2834 shader=shader+"normalmap = normalmap*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1]))*mask;\n"; 2835 } 2836 if((this.layers[i].mapto & GLGE.M_ALPHA) == GLGE.M_ALPHA){ 2837 shader=shader+"al = al*(1.0-mask) + texture2D(TEXTURE"+this.layers[i].texture.idx+", vec2((UVCoord["+(this.layers[i].mapinput*2)+"]+layer"+i+"Offset[0])*layer"+i+"Scale[0],(1.0-UVCoord["+(this.layers[i].mapinput*2+1)+"]+layer"+i+"Offset[1])*layer"+i+"Scale[1])).a*mask;\n"; 2838 } 2839 } 2840 shader=shader+"normalmap=(normalmap-vec4(0.5,0.5,0.5,0.5))*vec4(2.0,2.0,0.0,0.0);\n"; 2841 shader=shader+"vec3 normal = normalize(n+normalmap.rgb);\n"; 2842 shader=shader+"vec3 lightvalue=vec3(0.0,0.0,0.0);\n"; 2843 shader=shader+"vec3 specvalue=vec3(0.0,0.0,0.0);\n"; 2844 shader=shader+"float dotN,spotEffect;"; 2845 for(var i=0; i<lights.length;i++){ 2846 if(lights[i].type==GLGE.L_POINT){ 2847 shader=shader+"dotN=max(dot(normal,normalize(lightvec"+i+")),0.0);\n"; 2848 //shader=shader+"if(dotN>0.0){\n"; 2849 shader=shader+"att = 1 / (lightAttenuation"+i+"[0] + lightAttenuation"+i+"[1] * lightdist"+i+" + lightAttenuation"+i+"[2] * lightdist"+i+" * lightdist"+i+");\n"; 2850 if(lights[i].diffuse){ 2851 shader=shader+"lightvalue += att * dotN * lightcolor"+i+";\n"; 2852 } 2853 if(lights[i].specular){ 2854 shader=shader+"specvalue += att * specC * lightcolor"+i+" * spec * pow(max(dot(normal,normalize(eyevec)),0.0), sh);\n"; 2855 } 2856 //shader=shader+"}\n"; 2857 } 2858 shader=shader+"spotEffect = 0.0;\n"; 2859 if(lights[i].type==GLGE.L_SPOT){ 2860 shader=shader+"spotEffect = dot(normalize(lightdir"+i+"), normalize(-lightvec"+i+"));"; 2861 shader=shader+"if (spotEffect > spotCosCutOff"+i+") {\n"; 2862 shader=shader+"spotEffect = pow(spotEffect, spotExp"+i+");"; 2863 shader=shader+"dotN=max(dot(normal,normalize(lightvec"+i+")),0.0);\n"; 2864 shader=shader+"if(dotN>0.0){\n"; 2865 shader=shader+"att = spotEffect / (lightAttenuation"+i+"[0] + lightAttenuation"+i+"[1] * lightdist"+i+" + lightAttenuation"+i+"[2] * lightdist"+i+" * lightdist"+i+");\n"; 2866 if(lights[i].diffuse){ 2867 shader=shader+"lightvalue += att * dotN * lightcolor"+i+";\n"; 2868 } 2869 if(lights[i].specular){ 2870 shader=shader+"specvalue += att * specC * lightcolor"+i+" * spec * pow(max(dot(normal,normalize(eyevec)),0.0), sh);\n"; 2871 } 2872 shader=shader+"}\n}\n"; 2873 } 2874 if(lights[i].type==GLGE.L_DIR){ 2875 shader=shader+"dotN=max(dot(normal,normalize(-lightdir"+i+")),0.0);\n"; 2876 if(lights[i].diffuse){ 2877 shader=shader+"lightvalue += dotN * lightcolor"+i+";\n"; 2878 } 2879 if(lights[i].specular){ 2880 shader=shader+"specvalue += specC * lightcolor"+i+" * spec * pow(max(dot(normal,normalize(eyevec)),0.0), sh);\n"; 2881 } 2882 } 2883 } 2884 2885 shader=shader+"lightvalue *= ref;\n" 2886 shader=shader+"gl_FragColor = vec4(specvalue,0.0)+vec4(color.r*em+(color.r*lightvalue.r*(1.0-em)),color.g*em+(color.g*lightvalue.g*(1.0-em)),color.b*em+(color.b*lightvalue.b*(1.0-em)),al);\n"; 2887 //shader=shader+"gl_FragColor = vec4(normal,al);\n"; 2888 shader=shader+"}\n"; 2889 return shader; 2890 }; 2891 /** 2892 * Set the uniforms needed to render this material 2893 * @private 2894 */ 2895 GLGE.Material.prototype.textureUniforms=function(gl,shaderProgram,lights){ 2896 if(this.animation) this.animate(); 2897 gl.uniform4f(gl.getUniformLocation(shaderProgram, "baseColor"), this.color.r,this.color.g,this.color.b,this.color.a); 2898 gl.uniform3f(gl.getUniformLocation(shaderProgram, "specColor"), this.specColor.r,this.specColor.g,this.specColor.b); 2899 gl.uniform1f(gl.getUniformLocation(shaderProgram, "specular"), this.specular); 2900 gl.uniform1f(gl.getUniformLocation(shaderProgram, "shine"), this.shine); 2901 gl.uniform1f(gl.getUniformLocation(shaderProgram, "reflect"), this.reflect); 2902 gl.uniform1f(gl.getUniformLocation(shaderProgram, "emit"), this.emit); 2903 gl.uniform1f(gl.getUniformLocation(shaderProgram, "alpha"), this.alpha); 2904 for(var i=0; i<lights.length;i++){ 2905 gl.uniform3f(gl.getUniformLocation(shaderProgram, "lightcolor"+i), lights[i].color.r,lights[i].color.g,lights[i].color.b); 2906 gl.uniform3f(gl.getUniformLocation(shaderProgram, "lightAttenuation"+i), lights[i].constantAttenuation,lights[i].linearAttenuation,lights[i].quadraticAttenuation); 2907 gl.uniform1f(gl.getUniformLocation(shaderProgram, "spotCosCutOff"+i), lights[i].spotCosCutOff); 2908 gl.uniform1f(gl.getUniformLocation(shaderProgram, "spotExp"+i), lights[i].spotExponent); 2909 } 2910 2911 var scale,offset; 2912 for(i=0; i<this.layers.length;i++){ 2913 if(this.layers[i].animation) this.layers[i].animate(); 2914 scale=this.layers[i].getScale(); 2915 offset=this.layers[i].getOffset(); 2916 gl.uniform3f(gl.getUniformLocation(shaderProgram, "layer"+i+"Scale"), scale.x,scale.y,scale.z); 2917 gl.uniform3f(gl.getUniformLocation(shaderProgram, "layer"+i+"Offset"), offset.x,offset.y,offset.z); 2918 } 2919 2920 for(var i=0; i<this.textures.length;i++){ 2921 gl.activeTexture(gl["TEXTURE"+i]); 2922 //create the texture if it's not already created 2923 if(!this.textures[i].glTexture) this.textures[i].glTexture=gl.createTexture(); 2924 //if the image is loaded then set in the texture data 2925 if(this.textures[i].state==1){ 2926 gl.bindTexture(gl.TEXTURE_2D, this.textures[i].glTexture); 2927 gl.texImage2D(gl.TEXTURE_2D, 0, this.textures[i].image); 2928 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 2929 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); 2930 gl.generateMipmap(gl.TEXTURE_2D); 2931 gl.bindTexture(gl.TEXTURE_2D, null); 2932 this.textures[i].state=2; 2933 } 2934 gl.bindTexture(gl.TEXTURE_2D, this.textures[i].glTexture); 2935 gl.uniform1i(gl.getUniformLocation(shaderProgram, "TEXTURE"+i), i); 2936 } 2937 }; 2938 /** 2939 * Adds a new texture to this material 2940 * @param {String} image URL of the image to be used by the texture 2941 * @return {Number} index of the new texture 2942 */ 2943 GLGE.Material.prototype.addTexture=function(texture){ 2944 this.textures.push(texture); 2945 texture.idx=this.textures.length-1; 2946 return texture; 2947 }; 2948 })(GLGE); 2949 2950 2951