Fork me on GitHub

API Documentation


Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 593 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 593 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 606 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 606 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 691 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 691 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 695 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 695 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 709 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 709 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 716 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 716 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 832 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 833 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 834 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1085 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1133 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1133 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_object.js.html, line: 1143 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29

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