1 /** 2 * @fileOverview 3 * collada.gl.enchant.js 4 * @version v0.4.1 5 * @require enchant.js v0.6.3+ 6 * @require gl.enchant.js v0.3.5+ 7 * @author UEI Corporation 8 * @description 9 * gl.enchant.jsでcolladaファイル(.dae)を読み込むためのプラグイン 10 * 11 * @detail 12 * ベクトル・行列演算にgl-matrix.jsを使用しています. 13 * gl-matrix.js: 14 * https://github.com/toji/gl-matrix/ 15 */ 16 if (enchant.gl !== undefined) { 17 enchant.Core._loadFuncs['dae'] = function(src, ext, callback, onerror) { 18 var s = enchant.gl.Sprite3D.loadCollada(src, callback, onerror); 19 return s; 20 }; 21 (function() { 22 /** 23 * ColladaデータからSprite3Dを作成する. 24 * 現在, ジョイント, アニメーションを含むデータに対応していません. 25 * また, 頂点属性がtrianglesである必要があります. 26 * @example 27 * var scene = new Scene3D(); 28 * Sprite3D.loadCollada('hoge.dae', function(model){ 29 * scene.addChild(model); 30 * }); 31 * @param {String} url コラーダモデルのURL 32 * @param {Function} onload ロード完了時のコールバック. 33 * @param {Function} onload ロード失敗時のコールバック. 34 * @static 35 */ 36 enchant.gl.Sprite3D.loadCollada = function(url, onload, onerror) { 37 if (typeof onload !== 'function') { 38 return; 39 } 40 41 var rootSprite = new enchant.gl.collada.RootColladaSprite3D(); 42 rootSprite.addEventListener('load', onload); 43 rootSprite.addEventListener('error', onerror); 44 var e = new enchant.Event(enchant.Event.ERROR); 45 46 var req = new XMLHttpRequest(); 47 req.open('GET', url, true); 48 req.onerror = function() { 49 e.message = 'Cannot load an asset: ' + url; 50 enchant.Core.instance.dispatchEvent(e); 51 rootSprite.dispatchEvent(e); 52 }; 53 req.onload = function() { 54 try { 55 var maxbonenum = 6; 56 var lib = {}; 57 var collada = req.responseXML.getElementsByTagName('COLLADA')[0]; 58 for (var i = 0, l = availableLibraryFeatures.length; i < l; i++) { 59 lib[availableLibraryFeatures[i].libraryName] = availableLibraryFeatures[i].loadLibraryFromXML(collada, url); 60 } 61 var scene = new Scene(collada.getElementsByTagName('scene')[0]); 62 var rootColladaSprite3D = new enchant.gl.collada.ColladaSprite3D(lib); 63 var rootColladaSkeletonSprite3D = new enchant.gl.collada.ColladaSkeletonSprite3D(lib); 64 if (scene.visualSceneUrl) { 65 var visualScene = lib['visual_scenes'][scene.visualSceneUrl]; 66 for (var nk in visualScene.nodes) { 67 visualScene.nodes[nk].resolveChildNodes(lib); 68 } 69 for (var k in visualScene.nodes) { 70 if (visualScene.nodes[k].controllerUrl) { 71 var skeletonContainer = new Node(visualScene.nodes[k].xml); 72 skeletonContainer.nodes = []; 73 var skin = lib['controllers'][visualScene.nodes[k].controllerUrl].skin.getProcessedSkinData(); 74 if (visualScene.nodes[k].skeletons.length === 0) { 75 for (var sk in skin.ids) { 76 visualScene.nodes[k].skeletons.push(lib['nodes'][sk]); 77 break; 78 } 79 } 80 for (var key in visualScene.nodes[k].skeletons) { 81 skeletonContainer.nodes[visualScene.nodes[k].skeletons[key].id] = (visualScene.nodes[k].skeletons[key]); 82 } 83 var bone = new enchant.gl.collada.ColladaBone(skeletonContainer, [0, 0, 0]); 84 var skeleton = new enchant.gl.collada.ColladaSkeleton(); 85 skeleton.addChild(bone); 86 skeleton.solveFKs(); 87 rootColladaSkeletonSprite3D.skeleton = skeleton; 88 skeleton.calculateTableForIds(skin.ids); 89 rootColladaSkeletonSprite3D.addColladaSkeletonSprite3DFromNode(skeletonContainer, skin, skeleton, maxbonenum); 90 } else { 91 rootColladaSprite3D.addColladaSprite3DFromNode(visualScene.nodes[k]); 92 } 93 } 94 } 95 rootSprite.addChild(rootColladaSprite3D); 96 rootSprite.addChild(rootColladaSkeletonSprite3D); 97 rootSprite.dispatchEvent(new enchant.Event(enchant.Event.LOAD)); 98 } catch (err) { 99 e.message = err.message; 100 rootSprite.dispatchEvent(e); 101 } 102 }; 103 req.send(null); 104 return rootSprite; 105 }; 106 var Unit = enchant.Class.create({ 107 initialize: function(xml) { 108 this.xml = xml; 109 this._datas = {}; 110 this.loadParams(); 111 }, 112 loadParams: function() { 113 for (var i = 0, l = this._childable.length; i < l; i++) { 114 var nodes = []; 115 var param = this._childable[i]; 116 if (this.xml !== undefined) { 117 for (var j = 0, k = this.xml.childNodes.length; j < k; j++) { 118 if (this.xml.childNodes[j].nodeName === param) { 119 nodes.push(this.xml.childNodes[j]); 120 } 121 } 122 } 123 this._datas[param] = nodes; 124 } 125 }, 126 parseFloatArray: function(element) { 127 var array = []; 128 var floatStrings = (element.textContent).split(/\s+/); 129 for (var k = 0; k < floatStrings.length; k++) { 130 var value = parseFloat(floatStrings[k]); 131 if (!isNaN(value)) { 132 array.push(value); 133 } 134 } 135 return array; 136 }, 137 getParentDirectory: function(path) { 138 return path.substring(0, path.lastIndexOf('/') + 1); 139 }, 140 getReferenceAttribute: function(element, attribute) { 141 return element.getAttribute(attribute).replace('#', ''); 142 }, 143 getReferenceTextContent: function(element) { 144 return element.textContent.replace('#', ''); 145 } 146 }); 147 Unit.prototype._childable = []; 148 var Scene = enchant.Class.create(Unit, { 149 initialize: function(xml) { 150 Unit.call(this, xml); 151 if (this._datas['instance_visual_scene']) { 152 this.visualSceneUrl = this.getReferenceAttribute(this._datas['instance_visual_scene'][0], 'url'); 153 } 154 } 155 }); 156 Scene.prototype._childable = ['instance_visual_scene']; 157 var Image = enchant.Class.create(Unit, { 158 initialize: function(xml, url) { 159 Unit.call(this, xml); 160 this.initFrom = ''; 161 if (this._datas['init_from']) { 162 this.initFrom = this._datas['init_from'][0].textContent; 163 if (this.initFrom.substr(0, 4) ==='file') { 164 var spl=this.initFrom.split('/'); 165 this.initFrom=spl[spl.length-1]; 166 } 167 if (this.initFrom.substr(0, 4) !== 'http') { 168 if (this.initFrom.substr(0, 2) === './') { 169 this.initFrom = this.initFrom.substr(2, this.initFrom.length - 2); 170 } 171 this.initFrom = this.getParentDirectory(url) + this.initFrom; 172 } 173 } 174 } 175 }); 176 Image.prototype._childable = ['renderable', 'init_from', 'create_2d', 'create_3d', 'create_map']; 177 var Geometry = enchant.Class.create(Unit, { 178 initialize: function(xml) { 179 Unit.call(this, xml); 180 if (this._datas['mesh']) { 181 this.Mesh = new GeometryMesh(this._datas['mesh'][0]); 182 } 183 } 184 }); 185 Geometry.prototype._childable = ['asset', 'convex_mesh', 'mesh', 'spline', 'extra']; 186 var GeometryMesh = enchant.Class.create(Unit, { 187 initialize: function(xml) { 188 Unit.call(this, xml); 189 this.srcs = []; 190 this.srcs.offset = null; 191 this.vertices = []; 192 this.triangles = []; 193 if (this._datas['source']) { 194 for (var i = 0, l = this._datas['source'].length; i < l; i++) { 195 this.srcs[this._datas['source'][i].getAttribute('id')] = this.parseFloatArray(this._datas['source'][i].getElementsByTagName('float_array')[0]); 196 } 197 } 198 if (this._datas['vertices']) { 199 this.vertices = new Vertices(this._datas['vertices'][0]); 200 } 201 if (this._datas['triangles'].length > 0) { 202 this.triangles = []; 203 for (var ti = 0; ti < this._datas['triangles'].length; ti++) { 204 this.triangles[ti] = new Triangle(this._datas['triangles'][ti], this.srcs, this.vertices); 205 } 206 } 207 if (this._datas['polylist'].length > 0) { 208 this.triangles = []; 209 for (var pi = 0; pi < this._datas['polylist'].length; pi++) { 210 this.triangles[pi] = new Polylist(this._datas['polylist'][pi], this.srcs, this.vertices); 211 } 212 } 213 } 214 }); 215 GeometryMesh.prototype._childable = ['source', 'vertices', 'lines', 'linestripes', 'polygons', 'polylist', 'triangles', 'trifans', 'tristrips', 'extra']; 216 var Vertices = enchant.Class.create(Unit, { 217 initialize: function(xml) { 218 Unit.call(this, xml); 219 this.source = {}; 220 for (var i = 0; i < this._datas['input'].length; i++) { 221 var input = this._datas['input'][i]; 222 this.source[input.getAttribute('semantic')] = this.getReferenceAttribute(input, 'source'); 223 } 224 this.id = xml.getAttribute('id'); 225 this.position = this.source['POSITION']; 226 } 227 }); 228 Vertices.prototype._childable = ['input', 'extras']; 229 var AbstractGeometryMeshTriangleData = enchant.Class.create(Unit, { 230 initialize: function(xml, srcs, vertices) { 231 Unit.call(this, xml); 232 this.inputs = []; 233 this.primitives = []; 234 this.stride = 0; 235 this.material = this.xml.getAttribute('material'); 236 if (this._datas['input']) { 237 for (var i = 0, l = this._datas['input'].length; i < l; i++) { 238 var sourceId = this.getReferenceAttribute(this._datas['input'][i], 'source'); 239 var offset = parseInt(this._datas['input'][i].getAttribute('offset'), 10); 240 var set = parseInt(this._datas['input'][i].getAttribute('set'), 10); 241 if (srcs[sourceId]) { 242 this._addSource(srcs, sourceId, this._datas['input'][i].getAttribute('semantic')); 243 this.inputs[this._datas['input'][i].getAttribute('semantic') + 'offset'] = offset; 244 if (!isNaN(set)) { 245 this.inputs[this._datas['input'][i].getAttribute('semantic') + 'set'] = set; 246 } else { 247 this.inputs[this._datas['input'][i].getAttribute('semantic') + 'set'] =0; 248 } 249 } else if (vertices.id === sourceId) { 250 for (var key in vertices.source) { 251 if (srcs[vertices.source[key]]) { 252 this._addSource(srcs, vertices.source[key], key); 253 this.inputs[key + 'offset'] = offset; 254 } 255 } 256 } 257 this.stride = Math.max(this.stride, (offset + 1)); 258 } 259 } 260 if (this._datas['p']) { 261 if (this._datas['p'][0]) { 262 this._calculatePrimitives(this.parseFloatArray(this._datas['p'][0])); 263 } 264 } 265 }, 266 _calculatePrimitives: function(pointArray) {}, 267 _addSource: function(sources, sourceId, inputId) { 268 var source = sources[sourceId]; 269 this.inputs[inputId] = source; 270 if (inputId === 'TEXCOORD') { 271 for (var sj = 1; sj < source.length; sj += 2) { 272 this.inputs[inputId][sj] = source[sj]; 273 } 274 } 275 } 276 }); 277 var Triangle = enchant.Class.create(AbstractGeometryMeshTriangleData, { 278 _calculatePrimitives: function(pointArray) { 279 this.primitives = pointArray; 280 } 281 }); 282 Triangle.prototype._childable = ['input', 'p']; 283 var Polylist = enchant.Class.create(AbstractGeometryMeshTriangleData, { 284 _calculatePrimitives: function(primitives) { 285 var vcount = this.parseFloatArray(this._datas['vcount'][0]); 286 var num = 0; 287 var last = 0; 288 var triangles = []; 289 var first = true; 290 for (var i = 0, l = primitives.length / this.stride; i < l; i++) { 291 if (first) { 292 for (var j = 0; j < this.stride; j++) { 293 triangles.push(primitives[i * this.stride + j]); 294 } 295 } else { 296 for (var lj = 0; lj < this.stride; lj++) { 297 triangles.push(primitives[last * this.stride + lj]); 298 } 299 for (var prej = 0; prej < this.stride; prej++) { 300 triangles.push(primitives[(i - 1) * this.stride + prej]); 301 } 302 for (var cj = 0; cj < this.stride; cj++) { 303 triangles.push(primitives[i * this.stride + cj]); 304 } 305 } 306 if (i - last === 2) { 307 first = false; 308 } 309 if (vcount[num] - 1 === i - last) { 310 this.primitives = this.primitives.concat(triangles); 311 last += vcount[num]; 312 num += 1; 313 triangles = []; 314 first = true; 315 } 316 } 317 } 318 }); 319 Polylist.prototype._childable = ['input', 'p', 'vcount']; 320 var VisualScene = enchant.Class.create(Unit, { 321 initialize: function(xml) { 322 Unit.call(this, xml); 323 this.nodes = []; 324 for (var i = 0, l = this._datas['node'].length; i < l; i++) { 325 this.nodes[this._datas['node'][i].getAttribute('id')] = new Node(this._datas['node'][i]); 326 } 327 } 328 }); 329 VisualScene.prototype._childable = ['asset', 'node', 'evaluate_scene', 'extra']; 330 var Node = enchant.Class.create(Unit, { 331 initialize: function(xml) { 332 this.nodes = []; 333 this.childNodeIds = []; 334 this.skeletons = []; 335 this.poses = []; 336 this.skeletonChildNodeIds = []; 337 this.translate = [0, 0, 0]; 338 this.rotate = []; 339 this.nMatrix = []; 340 Unit.call(this, xml); 341 if (xml) { 342 if (xml.getAttribute('sid')) { 343 this.sid = xml.getAttribute('sid'); 344 } else { 345 this.sid = xml.getAttribute('id'); 346 } 347 this.id = xml.getAttribute('id'); 348 this.type = xml.getAttribute('type'); 349 for (var i = 0, l = this._datas['node'].length; i < l; i++) { 350 this.nodes[this._datas['node'][i].getAttribute('id')] = new Node(this._datas['node'][i]); 351 } 352 if (this._datas['translate'].length > 0) { 353 this.translate = this.parseFloatArray(this._datas['translate'][0]); 354 } 355 for (var ri = 0, rl = this._datas['rotate'].length; ri < rl; ri++) { 356 this.rotate[this._datas['rotate'][ri].getAttribute('sid')] = this.parseFloatArray(this._datas['rotate'][ri]); 357 } 358 for (var mi = 0, ml = this._datas['matrix'].length; mi < ml; mi++) { 359 this.nMatrix[this._datas['matrix'][mi].getAttribute('sid')] = mat4.transpose(this.parseFloatArray(this._datas['matrix'][0])); 360 } 361 var materialNode = null; 362 if (this._datas['instance_geometry'].length > 0) { 363 materialNode = this._datas['instance_geometry'][0]; 364 this.geometryUrl = this.getReferenceAttribute(materialNode, 'url'); 365 } else if (this._datas['instance_controller'].length > 0) { 366 materialNode = this._datas['instance_controller'][0]; 367 this.controllerUrl = this.getReferenceAttribute(materialNode, 'url'); 368 var skels = this._datas['instance_controller'][0].getElementsByTagName('skeleton'); 369 for (i = 0, l = skels.length; i < l; i++) { 370 this.skeletonChildNodeIds[i] = this.getReferenceTextContent(skels[i]); 371 } 372 } 373 if (this._datas['instance_node']) { 374 for (i = 0, l = this._datas['instance_node'].length; i < l; i++) { 375 this.childNodeIds[i] = this.getReferenceAttribute(this._datas['instance_node'][i], 'url'); 376 } 377 } 378 if (materialNode != null) { 379 var material = materialNode.getElementsByTagName('instance_material'); 380 if (material) { 381 this.materialTarget = {}; 382 for (i = 0; i < material.length; i++) { 383 this.materialTarget[material[i].getAttribute('symbol')] = this.getReferenceAttribute(material[i], 'target'); 384 } 385 } 386 } 387 } 388 }, 389 resolveChildNodes: function(lib) { 390 this.__resolveChildNodes(lib, this.childNodeIds, this.nodes); 391 var libNodes = lib['nodes']; 392 var libVisualScene = lib['visual_scenes']; 393 for (var key in this.skeletonChildNodeIds) { 394 var element = null; 395 for (var nodeKey in libNodes) { 396 if (libNodes[nodeKey]._getNodeInHirachy(this.skeletonChildNodeIds[key])) { 397 element = libNodes[nodeKey]; 398 } 399 if (element != null) {break;} 400 } 401 for (nodeKey in libVisualScene) { 402 if (element != null) {break;} 403 if (libVisualScene[nodeKey]._getNodeInHirachy(this.skeletonChildNodeIds[key])) { 404 element = libNodes[nodeKey]; 405 } 406 } 407 if (element != null) { 408 element.resolveChildNodes(lib); 409 this.skeletons.push(element); 410 } 411 } 412 for (var i = 0; i < this.skeletons.length; i++) { 413 for (var j = i + 1; j < this.skeletons.length; j++) { 414 if (this.skeletons[i]._getNodeInHirachy(this.skeletons[j].id)) { 415 this.skeletons.splice(j, 1); 416 j--; 417 } else if (this.skeletons[j]._getNodeInHirachy(this.skeletons[i].id)) { 418 this.skeletons.splice(i, 1); 419 i--; 420 break; 421 } 422 } 423 } 424 }, 425 __resolveChildNodes: function(lib, childNodeIds, childArray) { 426 for (var key in childArray) { 427 childArray[key].resolveChildNodes(lib); 428 } 429 var libNodes = lib['nodes']; 430 var libVisualScene = lib['visual_scenes']; 431 for (var i = 0; i < childNodeIds.length;) { 432 var element = null; 433 for (key in libNodes) { 434 element = libNodes[key]._getNodeInHirachy(childNodeIds[i]); 435 if (element != null) {break;} 436 } 437 for (key in libVisualScene) { 438 if (element != null) {break;} 439 var nodes = libVisualScene[key].nodes; 440 for (var nodeKey in nodes) { 441 element = nodes[nodeKey]._getNodeInHirachy(childNodeIds[i]); 442 if (element != null) {break;} 443 } 444 } 445 if (element != null) { 446 childArray[element.id] = new Node(element.xml); 447 childArray[element.id].resolveChildNodes(lib); 448 childNodeIds.splice(i, 1); 449 } else { 450 i++; 451 } 452 } 453 }, 454 _getNodeInHirachy: function(id) { 455 if (this.id === id) {return this;} 456 var child = null; 457 for (var k in this.nodes) { 458 child = this.nodes[k]._getNodeInHirachy(id); 459 if (child != null) {break;} 460 } 461 return child; 462 }, 463 getRotationMatrix: function() { 464 var rotation = mat4.create(); 465 mat4.identity(rotation); 466 for (var rotationSid in this.rotate) { 467 var rotationVec = this.rotate[rotationSid]; 468 var mat = new enchant.gl.Quat(rotationVec[0], rotationVec[1], rotationVec[2], rotationVec[3] * Math.PI / 180); 469 mat4.multiply(rotation, mat.toMat4(mat4.create())); 470 } 471 return rotation; 472 }, 473 getTranslationMatrix: function() { 474 var translation = mat4.create(); 475 mat4.identity(translation); 476 var position = this.translate; 477 mat4.translate(translation, [position[0], position[1], position[2]]); 478 return translation; 479 }, 480 getnMatrix: function() { 481 var matrix = mat4.create(); 482 mat4.identity(matrix); 483 for (var matrixSid in this.nMatrix) { 484 mat4.multiply(matrix, this.nMatrix[matrixSid]); 485 } 486 return matrix; 487 }, 488 getNode: function() { 489 var table = this.nodes; 490 var child = []; 491 for (var key in table){ 492 child[key] = []; 493 child[key] = table[key].getNode(); 494 for(var ckey in child[key]){ 495 table[ckey] = child[key][ckey]; 496 } 497 } 498 return table; 499 }, 500 getAnimationMatrixFromOneAnimationNode: function(Animation, libAnimationClips, flag) { 501 var core = enchant.Core.instance; 502 var rotation = this.getRotationMatrix(); 503 var translation = this.getTranslationMatrix(); 504 var matrix = this.getnMatrix(); 505 var animationMatrixes = []; 506 var sid = this.sid; 507 animationMatrixes[sid] = []; 508 animationMatrixes[sid][0] = mat4.multiply(translation, rotation, mat4.create()); 509 mat4.multiply(animationMatrixes[sid][0], matrix); 510 var output = []; 511 var input = []; 512 var length = 0; 513 for (var ci = 0, cl = Animation.channels.length; ci < cl; ci++) { 514 if (this.id === Animation.channels[ci].target.split('/')[0]) { 515 var currentLength = Animation.samplers[Animation.channels[ci].samplerId].lerpedinput.length; 516 length = Math.max(currentLength, length); 517 if (Animation.samplers[Animation.channels[ci].samplerId].lerpedinput.length === length) { 518 input = Animation.samplers[Animation.channels[ci].samplerId].lerpedinput; 519 } 520 output[Animation.channels[ci].target.split('/')[1].split('.')[0]] = Animation.samplers[Animation.channels[ci].samplerId].lerpedoutput; 521 } 522 } 523 for (var i = 0, l = length; i < l; i++) { 524 var rot = mat4.create(); 525 var trans = mat4.create(); 526 var nMat = mat4.create(); 527 mat4.identity(rot); 528 mat4.identity(trans); 529 mat4.identity(nMat); 530 mat4.translate(trans, this.translate); 531 for (var rkey in this.rotate) { 532 var tmpf = false; 533 var mat; 534 for (var okey in output) { 535 if (rkey === okey) { 536 mat = new enchant.gl.Quat(this.rotate[rkey][0], this.rotate[rkey][1], this.rotate[rkey][2], output[okey][i] * Math.PI / 180); 537 mat4.multiply(rot, mat.toMat4(mat4.create())); 538 tmpf = true; 539 } 540 } 541 if (!tmpf) { 542 mat = new enchant.gl.Quat(this.rotate[rkey][0], this.rotate[rkey][1], this.rotate[rkey][2], this.rotate[rkey][3] * Math.PI / 180); 543 mat4.multiply(rot, mat.toMat4(mat4.create())); 544 } 545 } 546 for (var okey2 in output) { 547 if (okey2 === 'translation') { 548 mat4.identity(trans); 549 mat4.translate(trans, [output[okey2][i * 3], output[okey2][i * 3 + 1], output[okey2][i * 3 + 2]]); 550 } else if (okey2 === 'scale') { 551 //TODO ! 552 } else if (okey2 === 'matrix') { 553 var tmpMat = []; 554 for (var j = 0; j < 16; j++) { 555 tmpMat.push(output[okey2][i*16+j]); 556 } 557 mat4.transpose(tmpMat); 558 mat4.multiply(nMat,tmpMat); 559 } else { 560 for (var mkey in this.nMatrix) { 561 if (okey2.indexOf('(')!==-1) { 562 if (mkey === okey2.split('(')[0]) { 563 if (!isNaN(output[okey2][i])) { 564 nMat[parseInt(okey2.split('(')[1].split(')')[0], 10) * 4 + parseInt(okey2.split(')(')[1].split(')')[0], 10)] = output[okey2][i]; 565 } else { 566 nMat[parseInt(okey2.split('(')[1].split(')')[0], 10) * 4 + parseInt(okey2.split(')(')[1].split(')')[0], 10)] = output[okey2][0]; 567 } 568 } 569 } else { 570 var tmpMatrix = []; 571 for (var oj = 0; oj < 16; oj++) { 572 tmpMatrix.push(output[okey2][i * 16 + oj]); 573 } 574 mat4.transpose(tmpMatrix); 575 mat4.multiply(nMat, tmpMatrix); 576 } 577 } 578 } 579 } 580 animationMatrixes[sid][Math.round(core.fps * input[i])] = mat4.multiply(trans, rot, mat4.create()); 581 mat4.multiply(animationMatrixes[sid][Math.round(core.fps * input[i])],nMat); 582 } 583 if (Animation.animations.length > 0) { 584 var child = this.getAnimationMatrixesLocal(Animation.animations, libAnimationClips, true); 585 for (var ccl in child) { 586 animationMatrixes[ccl] = child[ccl]; 587 } 588 } 589 return animationMatrixes; 590 }, 591 getAnimationMatrixesLocal: function(libAnimations, libAnimationClips, flag) { 592 var core = enchant.Core.instance; 593 var rotation = this.getRotationMatrix(); 594 var translation = this.getTranslationMatrix(); 595 var matrix = this.getnMatrix(); 596 var animationMatrixes = []; 597 animationMatrixes[this.sid] = []; 598 animationMatrixes[this.sid][0] = mat4.multiply(translation, rotation, mat4.create()); 599 mat4.multiply(animationMatrixes[this.sid][0], matrix); 600 var output = []; 601 var input = []; 602 var length = 0; 603 for (var key in libAnimations) { 604 for (var ci = 0, cl = libAnimations[key].channels.length; ci < cl; ci++) { 605 if (this.id === libAnimations[key].channels[ci].target.split('/')[0]) { 606 var currentLength = libAnimations[key].samplers[libAnimations[key].channels[ci].samplerId].lerpedinput.length; 607 length = Math.max(currentLength, length); 608 if (libAnimations[key].samplers[libAnimations[key].channels[ci].samplerId].lerpedinput.length === length) { 609 input = libAnimations[key].samplers[libAnimations[key].channels[ci].samplerId].lerpedinput; 610 } 611 output[libAnimations[key].channels[ci].target.split('/')[1].split('.')[0]] = libAnimations[key].samplers[libAnimations[key].channels[ci].samplerId].lerpedoutput; 612 } 613 } 614 for (var ackey in libAnimationClips) { 615 if (libAnimationClips[ackey].urls.indexOf(key) > -1 && flag) { 616 length = 0; 617 } 618 } 619 if (libAnimations[key].animations.length > 0 && length > 0) { 620 var child = this.getAnimationMatrixesLocal(libAnimations[key].animations, libAnimationClips, true); 621 for (var ckey in child) { 622 animationMatrixes[ckey] = child[ckey]; 623 } 624 } 625 } 626 for (var i = 0, l = length; i < l; i++) { 627 var rot = mat4.create(); 628 var trans = mat4.create(); 629 var nMat = mat4.create(); 630 mat4.identity(rot); 631 mat4.identity(trans); 632 mat4.identity(nMat); 633 mat4.translate(trans, this.translate); 634 for (var rkey in this.rotate) { 635 var tmpf = false; 636 var mat; 637 for (var okey in output) { 638 if (rkey === okey) { 639 mat = new enchant.gl.Quat(this.rotate[rkey][0], this.rotate[rkey][1], this.rotate[rkey][2], output[okey][i] * Math.PI / 180); 640 mat4.multiply(rot, mat.toMat4(mat4.create())); 641 tmpf = true; 642 } 643 } 644 if (!tmpf) { 645 mat = new enchant.gl.Quat(this.rotate[rkey][0], this.rotate[rkey][1], this.rotate[rkey][2], this.rotate[rkey][3] * Math.PI / 180); 646 mat4.multiply(rot, mat.toMat4(mat4.create())); 647 } 648 } 649 for (var okey2 in output) { 650 if (okey2 === 'translation') { 651 mat4.identity(trans); 652 mat4.translate(trans, [output[okey2][i * 3], output[okey2][i * 3 + 1], output[okey2][i * 3 + 2]]); 653 } else if (okey2 === 'scale') { 654 //TODO ! 655 } else if (okey2 === 'matrix') { 656 var tmpMat = []; 657 for (var j = 0; j < 16; j++) { 658 tmpMat.push(output[okey2][i*16+j]); 659 } 660 mat4.transpose(tmpMat); 661 mat4.multiply(nMat,tmpMat); 662 } else { 663 for (var mkey in this.nMatrix) { 664 if (okey2.indexOf('(')!==-1) { 665 if (mkey === okey2.split('(')[0]) { 666 if (!isNaN(output[okey2][i])) { 667 nMat[parseInt(okey2.split('(')[1].split(')')[0], 10) * 4 + parseInt(okey2.split(')(')[1].split(')')[0], 10)] = output[okey2][i]; 668 } else { 669 nMat[parseInt(okey2.split('(')[1].split(')')[0], 10) * 4 + parseInt(okey2.split(')(')[1].split(')')[0], 10)] = output[okey2][0]; 670 } 671 } 672 } else { 673 var tmpMatrix = []; 674 for (var oj = 0; oj < 16; oj++) { 675 tmpMatrix.push(output[okey2][i * 16 + oj]); 676 } 677 mat4.transpose(tmpMatrix); 678 mat4.multiply(nMat, tmpMatrix); 679 } 680 } 681 } 682 } 683 animationMatrixes[this.sid][Math.round(core.fps * input[i])] = mat4.multiply(trans, rot, mat4.create()); 684 mat4.multiply(animationMatrixes[this.sid][Math.round(core.fps * input[i])],nMat); 685 } 686 for (var k in this.nodes) { 687 var childmat = this.nodes[k].getAnimationMatrixesLocal(libAnimations, libAnimationClips, true); 688 for (l in childmat) { 689 animationMatrixes[l] = childmat[l]; 690 } 691 } 692 return animationMatrixes; 693 }, 694 getAnimationMatrixesLocalFromAnimationClips: function(libAnimations, libAnimationClips) { 695 var animationMatrixClips = []; 696 for (var ackey in libAnimationClips) { 697 var urls = libAnimationClips[ackey].urls; 698 animationMatrixClips[ackey] = []; 699 for (var ui = 0, ul = urls.length; ui < ul; ui++) { 700 var child = []; 701 if (libAnimations[urls[ui]].channels[0]) { 702 child = this.getNode()[libAnimations[urls[ui]].channels[0].target.split('/')[0]].getAnimationMatrixFromOneAnimationNode(libAnimations[urls[ui]], libAnimationClips, true); 703 } 704 var child2 = []; 705 if (libAnimations[urls[ui]].animations[0]) { 706 child2 = this.getAnimationMatrixesLocal(libAnimations[urls[ui]].animations, libAnimationClips, true); 707 } 708 for (var l in child) { 709 animationMatrixClips[ackey][l] = child[l]; 710 } 711 for (l in child2) { 712 animationMatrixClips[ackey][l] = child2[l]; 713 } 714 } 715 } 716 return animationMatrixClips; 717 } 718 }); 719 Node.prototype._childable = ['node', 'Lookat', 'matrix', 'rotate', 'scale', 'skew', 'translate', 'instance_camera', 'instance_controller', 'instance_geometry', 'instance_light', 'instance_node', 'extra']; 720 var Material = enchant.Class.create(Unit, { 721 initialize: function(xml) { 722 Unit.call(this, xml); 723 this.effectUrl = this.getReferenceAttribute(this._datas['instance_effect'][0], 'url'); 724 } 725 }); 726 Material.prototype._childable = ['asset', 'instance_effect', 'extra']; 727 var Animation = enchant.Class.create(Unit, { 728 initialize: function(xml) { 729 Unit.call(this, xml); 730 this.srcs = []; 731 this.channels = []; 732 this.samplers = []; 733 this.animations = []; 734 for (var ai = 0, al = this._datas['animation'].length; ai < al; ai++) { 735 this.animations[ai] = new Animation(this._datas['animation'][ai]); 736 } 737 for (var ci = 0, cl = this._datas['channel'].length; ci < cl; ci++) { 738 this.channels[ci]={}; 739 this.channels[ci].target = this.getReferenceAttribute(this._datas['channel'][ci], 'target'); 740 this.channels[ci].samplerId = this.getReferenceAttribute(this._datas['channel'][ci], 'source'); 741 } 742 for (var i = 0, l = this._datas['source'].length; i < l; i++) { 743 if (this._datas['source'][i].getElementsByTagName('float_array')[0]) { 744 this.srcs[this._datas['source'][i].getAttribute('id')] = this.parseFloatArray(this._datas['source'][i].getElementsByTagName('float_array')[0]); 745 } 746 } 747 for (var si = 0, sl = this._datas['sampler'].length; si < sl; si++) { 748 this.samplers[this._datas['sampler'][si].getAttribute('id')] = new Sampler(this._datas['sampler'][si], this.srcs); 749 } 750 if (this._datas['sampler'].length > 0) { 751 this.sampler = new Sampler(this._datas['sampler'][0], this.srcs); 752 } 753 } 754 }); 755 Animation.prototype._childable = ['asset', 'animation', 'source', 'sampler', 'channel', 'extra']; 756 var AnimationClip = enchant.Class.create(Unit, { 757 initialize: function(xml) { 758 Unit.call(this, xml); 759 this.urls = []; 760 for (var i = 0, l = this._datas['instance_animation'].length; i < l; i++) { 761 this.urls.push(this._datas['instance_animation'][i].getAttribute('url').replace('#', '')); 762 } 763 } 764 }); 765 AnimationClip.prototype._childable = ['asset','instance_animation','instance_formula','extra']; 766 var Sampler = enchant.Class.create(Unit, { 767 initialize: function(xml, srcs) { 768 Unit.call(this, xml); 769 this.input = []; 770 this.output = []; 771 this.lerpedinput =[]; 772 this.lerpedoutput = []; 773 for (var i = 0, l = this._datas['input'].length; i < l; i++) { 774 if (this._datas['input'][i].getAttribute('semantic') === 'OUTPUT') { 775 this.output = srcs[this.getReferenceAttribute(this._datas['input'][i], 'source')]; 776 } 777 if (this._datas['input'][i].getAttribute('semantic') === 'INPUT') { 778 this.input = srcs[this.getReferenceAttribute(this._datas['input'][i], 'source')]; 779 } 780 } 781 var stride = this.output.length / this.input.length; 782 var ll = Math.floor(1 + this.input[this.input.length - 1] * enchant.Core.instance.fps); 783 for (var li = 0; li < ll; li++) { 784 this.lerpedinput.push(li / enchant.Core.instance.fps); 785 for (var j = 0; j < stride; j++) { 786 for (var post = 0, iil = this.input.length; post < iil; post++ ) { 787 if (li / enchant.Core.instance.fps < this.input[post]) { 788 break; 789 } 790 } 791 if (this.output[post * stride + j]) { 792 this.lerpedoutput.push(this.output[(post - 1) * stride + j] + 1 / (this.input[post] - this.input[post - 1]) * (li / enchant.Core.instance.fps - this.input[post - 1]) * (this.output[post * stride + j] - this.output[(post - 1) * stride + j])); 793 } else{ 794 this.lerpedoutput.push(this.output[(post - 1) * stride + j]); 795 } 796 } 797 } 798 } 799 }); 800 Sampler.prototype._childable = ['input']; 801 var Controller = enchant.Class.create(Unit, { 802 initialize: function(xml) { 803 Unit.call(this, xml); 804 for (var i = 0, l = this._datas['skin'].length; i < l; i++) { 805 this.skin = new Skin(this._datas['skin'][i]); 806 } 807 } 808 }); 809 Controller.prototype._childable = ['asset', 'skin', 'morph', 'extra']; 810 var Skin = enchant.Class.create(Unit, { 811 initialize: function(xml) { 812 Unit.call(this, xml); 813 this.source = this.getReferenceAttribute(xml, 'source'); 814 this.sources = []; 815 var child; 816 for (var i = 0, l = this._datas['source'].length; i < l; i++) { 817 var source = this._datas['source'][i]; 818 for (var j = 0, m = source.childNodes.length; j < m; j++) { 819 child = source.childNodes[j]; 820 if (child.nodeName === 'Name_array') { 821 this.sources[source.getAttribute('id')] = child.textContent.replace(/^\s+|\s+$/g, "").split(/[\s,]+/); 822 } 823 if (child.nodeName === 'float_array') { 824 this.sources[source.getAttribute('id')] = this.parseFloatArray(child); 825 } 826 } 827 } 828 this.joints = {}; 829 var joints = this._datas['joints'][0]; 830 for (i = 0, l = joints.childNodes.length; i < l; i++) { 831 child = joints.childNodes[i]; 832 if (child.nodeName === 'input') { 833 this.joints[child.getAttribute('semantic')] = this.sources[this.getReferenceAttribute(child, 'source')]; 834 } 835 } 836 this.vertex_weights = []; 837 var vweights = this._datas['vertex_weights'][0]; 838 for (i = 0, l = vweights.childNodes.length; i < l; i++) { 839 child = vweights.childNodes[i]; 840 if (child.nodeName === 'input') { 841 this.vertex_weights[child.getAttribute('semantic')] = this.sources[this.getReferenceAttribute(child, 'source')]; 842 this.vertex_weights[child.getAttribute('semantic') + '_offset'] = child.getAttribute('offset'); 843 } 844 if (child.nodeName === 'vcount' || child.nodeName === 'v') { 845 this.vertex_weights[child.nodeName] = this.parseFloatArray(child); 846 } 847 } 848 this.bind_shape_matrix = mat4.identity(); 849 if (this._datas['bind_shape_matrix'].length > 0) { 850 var bind_shape_matrix = this._datas['bind_shape_matrix'][0]; 851 this.bind_shape_matrix = mat4.transpose(this.parseFloatArray(bind_shape_matrix)); 852 } 853 }, 854 getProcessedSkinData: function() { 855 var resultSkin = {}; 856 resultSkin.bind_shape_matrix = this.bind_shape_matrix; 857 resultSkin.joints = {}; 858 var ids = {}; 859 for (var i = 0, l = this.vertex_weights.JOINT.length; i < l; i++) { 860 ids[this.vertex_weights.JOINT[i]] = i; 861 } 862 resultSkin.ids = ids; 863 resultSkin.source = this.source; 864 for (i = 0, l = this.joints['JOINT'].length; i < l; i++) { 865 resultSkin.joints[this.joints['JOINT'][i]] = []; 866 for (var j = 0; j < 16; j++) { 867 var retu = (j - j % 4) / 4; 868 var gyou = j % 4; 869 resultSkin.joints[this.joints['JOINT'][i]].push(this.joints['INV_BIND_MATRIX'][i * 16 + gyou * 4 + retu]); 870 } 871 } 872 resultSkin.vertex_weights = []; 873 var last = 0; 874 for (i = 0, l = this.vertex_weights['vcount'].length; i < l; i++) { 875 resultSkin.vertex_weights[i] = []; 876 for (var vj = 0, vl = this.vertex_weights['vcount'][i]; vj < vl; vj++) { 877 var weight = this.vertex_weights['WEIGHT'][this.vertex_weights['v'][(last + vj) * 2 + 1]]; 878 resultSkin.vertex_weights[i][this.vertex_weights['JOINT'][this.vertex_weights['v'][(last + vj) * 2]]] = weight; 879 } 880 last += this.vertex_weights['vcount'][i]; 881 } 882 return resultSkin; 883 } 884 }); 885 Skin.prototype._childable = ['bind_shape_matrix', 'source', 'joints', 'vertex_weights', 'extra']; 886 var Effect = enchant.Class.create(Unit, { 887 getFieldFromXMLWithDefaultValue: function(defaultValue, elementName, floatArrayName) { 888 var element = this._datas['profile_COMMON'][0].getElementsByTagName(elementName)[0]; 889 if (element) { 890 var array = element.getElementsByTagName(floatArrayName)[0]; 891 if (array) {return this.parseFloatArray(array);} 892 } 893 return defaultValue; 894 }, 895 initialize: function(xml) { 896 Unit.call(this, xml); 897 if (this._datas['profile_COMMON'][0].getElementsByTagName('newparam')[0]) { 898 this.imageSrc = this._datas['profile_COMMON'][0].getElementsByTagName('newparam')[0].getElementsByTagName('surface')[0].getElementsByTagName('init_from')[0].textContent; 899 } 900 this.emission = this.getFieldFromXMLWithDefaultValue([0, 0, 0, 1], 'emission', 'color'); 901 this.ambient = this.getFieldFromXMLWithDefaultValue([1, 1, 1, 1], 'ambient', 'color'); 902 this.diffuse = this.getFieldFromXMLWithDefaultValue([1.0, 1.0, 1.0, 1], 'diffuse', 'color'); 903 this.specular = this.getFieldFromXMLWithDefaultValue([1, 1, 1, 1], 'specular', 'color'); 904 this.shininess = this.getFieldFromXMLWithDefaultValue([20], 'shininess', 'float'); 905 this.reflective = this.getFieldFromXMLWithDefaultValue([0, 0, 0, 0], 'reflective', 'color'); 906 this.reflectivity = this.getFieldFromXMLWithDefaultValue([0], 'reflectivity', 'float'); 907 this.transparent = this.getFieldFromXMLWithDefaultValue([0, 0, 0, 0], 'transparent', 'color'); 908 this.transparency = this.getFieldFromXMLWithDefaultValue(0, 'transparency', 'float'); 909 } 910 }); 911 Effect.prototype._childable = ['asset', 'annotate', 'image', 'newparam', 'profile_CG', 'profile_GLSL', 'profile_COMMON', 'extra']; 912 913 /** 914 * enchantにcollada.gl.enchant.jsのクラスをエクスポートする. 915 */ 916 enchant.gl.collada = {}; 917 /** 918 * @scope enchant.gl.collada.ColladaBone.prototype 919 */ 920 enchant.gl.collada.ColladaBone = enchant.Class.create(enchant.gl.Bone, { 921 /** 922 * colladaのボーンの状態を表すクラス. 923 * @param {Node} node 924 * @param {vec3} parentpos 925 * @param {quat4} parentrot 926 * @constructs 927 * @extends enchant.gl.Bone 928 */ 929 initialize: function(node, parentpos, parentrot) { 930 var rotation = node.getRotationMatrix(); 931 var translation = node.getTranslationMatrix(); 932 var matrix = node.getnMatrix(); 933 var animationMatrixes = []; 934 animationMatrixes[0] = []; 935 animationMatrixes[0][node.sid] = mat4.multiply(translation, rotation, mat4.create()); 936 mat4.multiply(animationMatrixes[0][node.sid],matrix); 937 var pos = vec3.create([animationMatrixes[0][node.sid][12], animationMatrixes[0][node.sid][13], animationMatrixes[0][node.sid][14]]); 938 var rotation3x3 = mat4.toMat3(animationMatrixes[0][node.sid], mat3.create()); 939 mat3.transpose(rotation3x3); 940 var quatanion = mat3.toQuat4(rotation3x3, quat4.create()); 941 var wquatanion, local; 942 if (parentrot) { 943 wquatanion = quat4.multiply(parentrot, quatanion, quat4.create()); 944 local = quat4.multiplyVec3(parentrot, vec3.create(pos)); 945 } else { 946 wquatanion = quatanion; 947 local = vec3.create(pos); 948 } 949 var head = vec3.add(parentpos, local, vec3.create()); 950 enchant.gl.Bone.call(this, node.sid, head, pos, quatanion); 951 for (var k in node.nodes) { 952 var child = new enchant.gl.collada.ColladaBone(node.nodes[k], head, wquatanion); 953 this.addChild(child); 954 } 955 } 956 }); 957 /** 958 * @scope enchant.gl.collada.ColladaSkeleton.prototype 959 */ 960 enchant.gl.collada.ColladaSkeleton = enchant.Class.create(enchant.gl.Skeleton, { 961 /** 962 * colladaのボーンの構造のルートになるクラス. 963 * @constructs 964 * @extends enchant.gl.Skeleton 965 */ 966 initialize: function() { 967 enchant.gl.Skeleton.call(this); 968 }, 969 calculateTableForIds: function(ids) { 970 this.table = this._calculateFlatTableForIds(this, ids); 971 }, 972 _calculateFlatTableForIds: function(skelPart, ids) { 973 var table = {}; 974 table.pos = []; 975 table.rot = []; 976 for (var i = 0; i < 4; i++) { 977 if (i < 3) {table['pos'][ids[skelPart._name] * 3 + i] = skelPart._globalpos[i];} 978 table['rot'][ids[skelPart._name] * 4 + i] = skelPart._globalrot[i]; 979 } 980 for (var x = 0, l = skelPart.childNodes.length; x < l; x++) { 981 var child = this._calculateFlatTableForIds(skelPart.childNodes[x], ids); 982 for (var key in child) { 983 for (var k in child[key]) { 984 table[key][k] = child[key][k]; 985 } 986 } 987 } 988 return table; 989 } 990 }); 991 /** 992 * @scope enchant.gl.collada.ColladaMesh.prototype 993 */ 994 enchant.gl.collada.ColladaMesh = enchant.Class.create(enchant.gl.Mesh, { 995 /** 996 * 頂点配列やテクスチャを格納するクラス. 997 * enchant.gl.collada.ColladaSprite3Dのプロパティとして使用される. 998 * @param {Triangle} triangles 999 * @constructs 1000 * @extends enchant.gl.Mesh 1001 */ 1002 initialize: function(triangles) { 1003 enchant.gl.Mesh.call(this); 1004 this.parseMeshFromGeometryMesh(triangles); 1005 this.colors = []; 1006 for (var i = 0; i < (this.vertices.length / 3) * 4; i++) { 1007 this.colors[i] = 1.0; 1008 } 1009 }, 1010 parseMeshFromGeometryMesh: function(triangles) { 1011 var inputs = triangles.inputs; 1012 this.vertices = []; 1013 this.normals = []; 1014 this.texCoords = []; 1015 this.indices = []; 1016 var index; 1017 for (var k = 0; k < triangles.primitives.length; k += triangles.stride) { 1018 if (triangles.inputs['POSITIONoffset'] >= 0) { 1019 index = triangles.primitives[k + triangles.inputs['POSITIONoffset']] * 3; 1020 this.vertices.push(inputs['POSITION'][index], inputs['POSITION'][index + 1], inputs['POSITION'][index + 2]); 1021 } 1022 if (triangles.inputs['NORMALoffset'] >= 0) { 1023 index = triangles.primitives[k + triangles.inputs['NORMALoffset']] * 3; 1024 this.normals.push(inputs['NORMAL'][index], inputs['NORMAL'][index + 1], inputs['NORMAL'][index + 2]); 1025 } 1026 if (triangles.inputs['TEXCOORDoffset'] >= 0) { 1027 index = triangles.primitives[k + triangles.inputs['TEXCOORDoffset']] * (2+triangles.inputs['TEXCOORDset']); 1028 this.texCoords.push(inputs['TEXCOORD'][index], inputs['TEXCOORD'][index + 1]); 1029 } else { 1030 this.texCoords.push(0, 0); 1031 } 1032 } 1033 for (k = 0; k < triangles.primitives.length / (triangles.stride); k++) { 1034 this.indices.push(k); 1035 } 1036 } 1037 }); 1038 /** 1039 * @scope enchant.gl.collada.ColladaSkeletonSpriteMesh.prototype 1040 */ 1041 enchant.gl.collada.ColladaSkeletonSpriteMesh = enchant.Class.create(enchant.gl.collada.ColladaMesh, { 1042 /** 1043 * 頂点配列やテクスチャを格納するクラス. 1044 * enchant.gl.collada.ColladaSkeletonSprite3Dのプロパティとして使用される. 1045 * @param {Triangle} triangles 1046 * @constructs 1047 * @extends enchant.gl.collada.ColladaMesh 1048 */ 1049 initialize: function(triangles) { 1050 enchant.gl.collada.ColladaMesh.call(this, triangles); 1051 var vpos1Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 1052 var vpos2Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 1053 var vpos3Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 1054 var bindicesBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.BONE_INDICES); 1055 var weights1Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.WEIGHTS); 1056 var weights2Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.WEIGHTS); 1057 this._addAttribute(vpos1Buffer, 'vpos1'); 1058 this._addAttribute(vpos2Buffer, 'vpos2'); 1059 this._addAttribute(vpos3Buffer, 'vpos3'); 1060 this._addAttribute(bindicesBuffer, 'boneIndices'); 1061 this._addAttribute(weights1Buffer, 'weights1'); 1062 this._addAttribute(weights2Buffer, 'weights2'); 1063 }, 1064 _addAttribute: function(buffer, prop) { 1065 this['_' + prop] = buffer; 1066 Object.defineProperty(this, prop, { 1067 get: function() { 1068 return this['_' + prop]._array; 1069 }, 1070 set: function(array) { 1071 this['_' + prop]._array = array; 1072 if (this._appear) { 1073 this['_' + prop]._bufferData(); 1074 } 1075 } 1076 }); 1077 } 1078 }); 1079 /** 1080 * @scope enchant.gl.collada.AbstractColladaSprite3D.prototype 1081 */ 1082 enchant.gl.collada.AbstractColladaSprite3D = enchant.Class.create(enchant.gl.Sprite3D, { 1083 /** 1084 * colladaのSprite3Dのスーパークラス. 1085 * このクラスを使わないでください。 1086 * @param {Object} lib 1087 * @param {Node} node 1088 * @param {Triangle} triangles 1089 * @constructs 1090 * @extends enchant.gl.Sprite3D 1091 */ 1092 initialize: function(lib, node, triangles) { 1093 enchant.gl.Sprite3D.call(this); 1094 this.lib = lib; 1095 if (triangles) { 1096 this.mesh = this._getMesh(triangles); 1097 this.initSpriteTexture(node, lib, triangles); 1098 } 1099 }, 1100 _getMesh: function(triangles) { 1101 return null; 1102 }, 1103 getPose: function(poses, length, localframe) { 1104 var core = enchant.Core.instance; 1105 var frame = (core.frame) % length; 1106 if (localframe) { 1107 frame = localframe; 1108 } 1109 var pose = []; 1110 for (var k in poses) { 1111 pose[k] = poses[k].getFrame(frame); 1112 } 1113 return pose; 1114 }, 1115 createPoses: function(node, poses, lib) { 1116 var matrix = node.getAnimationMatrixesLocal(lib['animations'], lib['animation_clips'], true); 1117 var length = 0; 1118 for (var k in matrix) { 1119 poses[k] = new enchant.gl.KeyFrameManager(); 1120 for (var i in matrix[k]) { 1121 var pos = vec3.create([matrix[k][i][12], matrix[k][i][13], matrix[k][i][14]]); 1122 var rotation3x3 = mat4.toMat3(matrix[k][i], mat3.create()); 1123 mat3.transpose(rotation3x3); 1124 var quatanion = quat4.fromRotationMatrix(rotation3x3, quat4.create()); 1125 poses[k].addFrame(new enchant.gl.Pose(pos, quatanion), parseInt(i, 10)); 1126 } 1127 length = Math.max(poses[k].length, length); 1128 } 1129 return length; 1130 }, 1131 createPosesClips: function(node, poseclips, lib) { 1132 var matrixclips = node.getAnimationMatrixesLocalFromAnimationClips(lib['animations'],lib['animation_clips']); 1133 var length = []; 1134 var core = enchant.Core.instance; 1135 for (var pkey in matrixclips) { 1136 length[pkey] = 0; 1137 var matrix = matrixclips[pkey]; 1138 poseclips[pkey] = []; 1139 for (var mkey in matrix) { 1140 poseclips[pkey][mkey] = new enchant.gl.KeyFrameManager(); 1141 for (var i in matrix[mkey]) { 1142 var num = 0; 1143 if (matrix[mkey].length > parseInt(lib['animation_clips'][pkey].start * core.fps, 10)) { 1144 num = i - parseInt(lib['animation_clips'][pkey].start * core.fps, 10); 1145 } else { 1146 num = i; 1147 } 1148 var pos = vec3.create([matrix[mkey][i][12], matrix[mkey][i][13], matrix[mkey][i][14]]); 1149 var rotation3x3 = mat4.toMat3(matrix[mkey][i], mat3.create()); 1150 mat3.transpose(rotation3x3); 1151 var quatanion = quat4.fromRotationMatrix(rotation3x3, quat4.create()); 1152 if (num >= 0 && i <= parseInt(lib['animation_clips'][pkey].end * core.fps, 10)) { 1153 poseclips[pkey][mkey].addFrame(new enchant.gl.Pose(pos, quatanion), parseInt(num, 10)); 1154 } 1155 } 1156 length[pkey] = Math.max(poseclips[pkey][mkey].length, length[pkey]); 1157 } 1158 } 1159 return length; 1160 }, 1161 initSpriteTexture: function(node, lib, triangles) { 1162 var libMaterials = lib['materials']; 1163 var libEffects = lib['effects']; 1164 var libImages = lib['images']; 1165 if (node.materialTarget && this.mesh) { 1166 var material = node.materialTarget[triangles.material]; 1167 if (material) { 1168 var texture = this.mesh.texture; 1169 var effect = libEffects[libMaterials[material].effectUrl]; 1170 texture.emission = effect.emission; 1171 texture.ambient = effect.ambient; 1172 texture.diffuse = effect.diffuse; 1173 texture.specular = effect.specular; 1174 texture.shininess = effect.shininess[0]; 1175 if (effect.imageSrc) { 1176 texture.src=libImages[effect.imageSrc].initFrom; 1177 } 1178 } 1179 } 1180 }, 1181 _getTriangles: function(geometry, index) { 1182 if (geometry) { 1183 return geometry.Mesh.triangles[index]; 1184 } 1185 return null; 1186 }, 1187 _getTrianglesLength: function(geometry) { 1188 if (geometry) { 1189 return geometry.Mesh.triangles.length; 1190 } 1191 return 0; 1192 } 1193 }); 1194 /** 1195 * @scope enchant.gl.collada.RootColladaSprite3D.prototype 1196 */ 1197 enchant.gl.collada.RootColladaSprite3D = enchant.Class.create(enchant.gl.Sprite3D, { 1198 /** 1199 * アニメーションクリップを追加する. 1200 * アニメーションクリップは追加された順に再生されていく. 1201 * @param {String} clipId 1202 */ 1203 pushAnimationClip: function(clipId){ 1204 this.childNodes[1].pushAnimationClip(clipId); 1205 }, 1206 /** 1207 * 追加されたアニメーションクリップを削除する. 1208 */ 1209 clearAnimationClip: function(){ 1210 this.childNodes[1].clearAnimationClip(); 1211 }, 1212 getAnimationClip: function() { 1213 return this.childNodes[1].animationClips; 1214 }, 1215 loop: { 1216 set: function(flag) { 1217 this.childNodes[1].loop = flag; 1218 }, 1219 get: function() { 1220 return this.childNodes[1].loop; 1221 } 1222 } 1223 }); 1224 /** 1225 * @scope enchant.gl.collada.ColladaSprite3D.prototype 1226 */ 1227 enchant.gl.collada.ColladaSprite3D = enchant.Class.create(enchant.gl.collada.AbstractColladaSprite3D, { 1228 _getMesh: function(triangles) { 1229 return new enchant.gl.collada.ColladaMesh(triangles); 1230 }, 1231 /** 1232 * ColladaSprite3D表示機能を持ったクラス. 1233 * ColladaSprite3Dは{@link enchant.gl.Sprite3D}と同じクラス. 1234 * このメソッドはColladaSprite3Dのファクトリメソッド。 1235 * @param {Node} node 1236 * @constructs 1237 * @extends enchant.gl.collada.AbstractColladaSprite3D 1238 */ 1239 addColladaSprite3DFromNode: function(node) { 1240 var geometry = this.lib['geometries'][node.geometryUrl]; 1241 var trianglesLength = this._getTrianglesLength(geometry); 1242 var currentTriangle = 0; 1243 var makeEnterframe = function(poses, length, sid, obj) { 1244 return function() { 1245 var currentPose = obj.getPose(poses, length)[sid]; 1246 obj.rotation = quat4.toMat4(currentPose._rotation); 1247 }; 1248 }; 1249 do { 1250 var sprite = new enchant.gl.collada.ColladaSprite3D(this.lib, node, this._getTriangles(geometry, currentTriangle)); 1251 if (node._datas['translate'][0]) { 1252 var translate = node.parseFloatArray(node._datas['translate'][0]); 1253 sprite.x = translate[0]; 1254 sprite.y = translate[1]; 1255 sprite.z = translate[2]; 1256 } else { 1257 sprite.x = sprite.y = sprite.z = 0; 1258 } 1259 var rotation = []; 1260 var rotateX = [1, 0, 0]; 1261 var rotateY = [0, 1, 0]; 1262 var rotateZ = [0, 0, 1]; 1263 for (var i = 0, l = node._datas['rotate'].length; i < l; i++) { 1264 var rotate = node._datas['rotate'][i]; 1265 var sid = rotate.getAttribute('sid'); 1266 if (sid === 'rotateZ') { 1267 rotateZ = node.parseFloatArray(rotate); 1268 } else if (sid === 'rotateY') { 1269 rotateY = node.parseFloatArray(rotate); 1270 } else if (sid === 'rotateX') { 1271 rotateX = node.parseFloatArray(rotate); 1272 } 1273 } 1274 for (i = 0; i < 3; i++) { 1275 rotation.push(rotateX[i], rotateY[i], rotateZ[i], 0); 1276 } 1277 rotation.push(0, 0, 0, 1); 1278 sprite.rotation = rotation; 1279 if (node._datas['matrix'][0]) { 1280 var matrix = node.parseFloatArray(node._datas['matrix'][0]); 1281 var transposed = [matrix[0], matrix[4], matrix[8], matrix[12], matrix[1], matrix[5], matrix[9], matrix[13], matrix[2], matrix[6], matrix[10], matrix[14], matrix[3], matrix[7], matrix[11], matrix[15]]; 1282 sprite.matrix = transposed; 1283 } else { 1284 sprite.matrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; 1285 } 1286 if (node._datas['scale'][0]) { 1287 var scale = node.parseFloatArray(node._datas['scale'][0]); 1288 sprite.scaleX = scale[0]; 1289 sprite.scaleY = scale[1]; 1290 sprite.scaleZ = scale[2]; 1291 } else { 1292 sprite.scaleX = sprite.scaleY = sprite.scaleZ = 1; 1293 } 1294 if (node.nodes) { 1295 for (var k in node.nodes) { 1296 sprite.addColladaSprite3DFromNode(node.nodes[k]); 1297 } 1298 } 1299 var poses = []; 1300 var poselength = this.createPoses(node, poses, this.lib); 1301 if (poselength > 0) { 1302 sprite.addEventListener('enterframe', makeEnterframe(poses, poselength, node.sid, sprite)); 1303 } 1304 //var poselength = this.createPoses(node, poses, this.lib); 1305 //if (poselength > 0) { 1306 //sprite.addEventListener('enterframe', function() { 1307 //var currentPose = this.getPose(poses, poselength)[node.sid]; 1308 1309 // TODO : USE CURRENT POSE TO MODIFY SPRITE ROTATION / TRANSLATION 1310 //var mat = new Quat(); 1311 //mat._quat = currentPose._rotation; 1312 //console.log(currentPose._rotation); 1313 //sprite.rotationApply(mat); 1314 // var glMat = mat4.create(); 1315 // mat.toMat4(glMat); 1316 // mat4.multiply(sprite._rotation, glMat); 1317 //mat4.rotateX(sprite._rotation, currentPose._rotation[2]); 1318 //mat4.rotateY(sprite._rotation, currentPose._rotation[1]); 1319 //mat4.rotateZ(sprite._rotation, currentPose._rotation[0]); 1320 //sprite._changedRotation = true; 1321 //sprite.translate(currentPose._position[2],currentPose._position[1],currentPose._position[0]); 1322 //}); 1323 //} 1324 this.addChild(sprite); 1325 currentTriangle++; 1326 } while (currentTriangle < trianglesLength); 1327 } 1328 }); 1329 /** 1330 * @scope enchant.gl.collada.ColladaSprite3D.prototype 1331 */ 1332 enchant.gl.collada.ColladaSkeletonSprite3D = enchant.Class.create(enchant.gl.collada.ColladaSprite3D, { 1333 /** 1334 * ColladaSkeletonSprite3Dのクラス. 1335 * このメソッドを使わないでくださいが、 1336 * {@link enchant.gl.collada.ColladaSkeletonSprite3D#addColladaSkeletonSprite3DFromNode}を使ったほうがいい。 1337 * @param {Object} lib 1338 * @param {Node} node 1339 * @param {Triangle} triangles 1340 * @constructs 1341 * @extends enchant.gl.collada.ColladaSprite3D 1342 */ 1343 initialize: function(lib, node, triangles) { 1344 enchant.gl.collada.AbstractColladaSprite3D.call(this, lib, node, triangles); 1345 this.program = enchant.gl.collada.COLLADA_SHADER_PROGRAM; 1346 this.animation = []; 1347 this.defaultAnimation = function(){ 1348 }; 1349 this.animationClips = []; 1350 this.uMVMatrix = mat4.create(); 1351 this.uNMatrix = mat3.create(); 1352 this.applyAnimationChild = function() { 1353 for (var cni = 0, cnl = this.childNodes.length; cni < cnl; cni++) { 1354 this.childNodes[cni].defaultAnimation(this.childNodes[cni]); 1355 this.childNodes[cni].applyAnimationChild(); 1356 } 1357 }; 1358 this.addEventListener("enterframe", function() { 1359 this.applyAnimationChild(); 1360 if (this.animation.length === 0) { 1361 } else { 1362 var first = this.animation[0]; 1363 first.frame++; 1364 for(var i = 0, l = this.childNodes.length; i < l; i++) { 1365 first.animation.enterframe(this.childNodes[i], first.frame); 1366 } 1367 if (first.frame >= this.animation[0].animation.length) { 1368 first = this.animation.shift(); 1369 if (this.loop) { 1370 first.frame = 0; 1371 this.animation.push(first); 1372 } 1373 } 1374 } 1375 }); 1376 }, 1377 pushAnimationClip: function(clipId) { 1378 if(this.animationClips[clipId]){ 1379 this.animation.push({animation: this.animationClips[clipId], frame: 0}); 1380 } 1381 }, 1382 clearAnimationClip: function() { 1383 this.animation = []; 1384 }, 1385 _getMesh: function(triangles) { 1386 return new enchant.gl.collada.ColladaSkeletonSpriteMesh(triangles); 1387 }, 1388 /** 1389 * スケルタルアニメーション持っているColladaSkeletonSprite3D表示機能を持ったクラス. 1390 * ColladaSkeletonSprite3Dは{@link enchant.gl.Sprite3D}と同じクラス. 1391 * このメソッドはColladaSkeletonSprite3Dのファクトリメソッド。 1392 * @param {Node} node 1393 * @constructs 1394 * @extends enchant.gl.collada.ColladaSprite3D 1395 */ 1396 addColladaSkeletonSprite3DFromNode: function(node, skin, skeleton, maxbonenum) { 1397 var controller = this.lib['controllers'][node.controllerUrl]; 1398 var geometry = this.lib['geometries'][controller.skin.source]; 1399 var trianglesLength = this._getTrianglesLength(geometry); 1400 var currentTriangle = 0; 1401 var makeEnterframe = function(poses, length, skin, maxbonem) { 1402 return function(obj) { 1403 skeleton.setPoses(obj.getPose(poses, length)); 1404 skeleton.solveFKs(); 1405 skeleton.calculateTableForIds(skin.ids); 1406 obj.mesh.udBoneInfo = obj.calculateSkeletonTable(obj.divisioninfo.dividedIndices, skeleton.table, maxbonenum); 1407 }; 1408 }; 1409 var makeClipEnterframe = function(poses, length, skin, maxbonem, clipId) { 1410 return function(obj, frame) { 1411 skeleton.setPoses(obj.getPose(poses, length, frame)); 1412 skeleton.solveFKs(); 1413 skeleton.calculateTableForIds(skin.ids); 1414 obj.mesh.udBoneInfo = obj.calculateSkeletonTable(obj.divisioninfo.dividedIndices, skeleton.table, maxbonenum); 1415 }; 1416 }; 1417 do { 1418 var triangles = this._getTriangles(geometry, currentTriangle); 1419 var child = new enchant.gl.collada.ColladaSkeletonSprite3D(this.lib, node, triangles); 1420 var arrays = this.createStaticArrayForShader(triangles, skin, skeleton); 1421 child.divisioninfo = this.getDivisionInfo(arrays, skeleton.table, maxbonenum); 1422 this.addChild(child); 1423 1424 child.mesh.vpos1 = arrays.vectorFromBone1; 1425 child.mesh.vpos2 = arrays.vectorFromBone2; 1426 child.mesh.vpos3 = arrays.vectorFromBone3; 1427 1428 child.mesh.weights1 = arrays.weights1; 1429 child.mesh.weights2 = arrays.weights2; 1430 1431 child.mesh.dividedpoints = child.divisioninfo.dividedPoint; 1432 child.mesh.boneIndices = child.divisioninfo.boneIndices; 1433 child.mesh.udBoneInfo = child.divisioninfo.skeletontable; 1434 var poses = []; 1435 var length = this.createPoses(node, poses, this.lib); 1436 var posesclips = []; 1437 var cliplength = this.createPosesClips(node, posesclips, this.lib); 1438 for (var clk in cliplength) { 1439 if (cliplength[clk] > 0) { 1440 var clipenterframe = makeClipEnterframe(posesclips[clk], cliplength[clk], skin, maxbonenum, clk); 1441 this.animationClips[clk] = {enterframe: clipenterframe, length: cliplength[clk]}; 1442 } 1443 } 1444 if (length > 0) { 1445 child.defaultAnimation = makeEnterframe(poses, length, skin, maxbonenum); 1446 } 1447 currentTriangle++; 1448 } while (currentTriangle < trianglesLength); 1449 }, 1450 calculateSkeletonTable: function(dividedIndices, table, n) { 1451 var skeletontable = []; 1452 var indices, index, postable, rottable; 1453 for (var i = 0, l = dividedIndices.length; i < l; i++) { 1454 indices = dividedIndices[i]; 1455 postable = []; 1456 rottable = []; 1457 for (var j = 0, ll = indices.length; j < ll; j++) { 1458 index = indices[j]; 1459 postable.push( 1460 table.pos[index * 3], 1461 table.pos[index * 3 + 1], 1462 table.pos[index * 3 + 2] 1463 ); 1464 rottable.push( 1465 table.rot[index * 4], 1466 table.rot[index * 4 + 1], 1467 table.rot[index * 4 + 2], 1468 table.rot[index * 4 + 3] 1469 ); 1470 } 1471 skeletontable.push({ 1472 pos: new Float32Array(postable), 1473 rot: new Float32Array(rottable) 1474 }); 1475 } 1476 return skeletontable; 1477 }, 1478 /** 1479 * スキニングの分割描画を行う境界を計算する. 1480 * 1481 */ 1482 getDivisionInfo: function(arrays, table, n) { 1483 var dividedPoint = [0]; 1484 var dividedIndices = []; 1485 var indices = []; 1486 var packedIndices = []; 1487 var count = 0; 1488 var index, packedIndex, num; 1489 for (var i = 0, l = arrays.boneIndices.length; i < l; i += 9) { 1490 for (var j = 0; j < 9; j++) { 1491 index = arrays.boneIndices[i + j]; 1492 num = indices.indexOf(index); 1493 if (num === -1) { 1494 indices.push(index); 1495 packedIndex = indices.length - 1; 1496 } else { 1497 packedIndex = num; 1498 } 1499 packedIndices.push(packedIndex); 1500 if (j === 8) { 1501 if (indices.length > n) { 1502 dividedPoint.push(i + 9); 1503 dividedIndices.push(indices); 1504 count++; 1505 indices = []; 1506 } 1507 } 1508 } 1509 } 1510 dividedPoint.push(packedIndices.length); 1511 dividedIndices.push(indices); 1512 return { 1513 dividedPoint: dividedPoint, 1514 dividedIndices: dividedIndices, 1515 skeletontable: this.calculateSkeletonTable(dividedIndices, table, n), 1516 boneIndices: new Uint16Array(packedIndices) 1517 }; 1518 }, 1519 createStaticArrayForShader: function(triangles, skin, skeleton) { 1520 var arraysForShader = {}; 1521 var length = 0; 1522 var vectorForBones = [ 1523 [], 1524 [], 1525 [] 1526 ]; 1527 var weights = [ 1528 [], 1529 [] 1530 ]; 1531 var boneIndices = []; 1532 var keys = []; 1533 var index, vec, rvec; 1534 rvec = vec3.create(); 1535 for (var i = 0, l = triangles.primitives.length; i < l; i += triangles.stride) { 1536 if (triangles.inputs['POSITIONoffset'] >= 0) { 1537 length++; 1538 index = triangles.primitives[i + triangles.inputs['POSITIONoffset']]; 1539 vec = [ 1540 triangles.inputs['POSITION'][index * 3], 1541 triangles.inputs['POSITION'][index * 3 + 1], 1542 triangles.inputs['POSITION'][index * 3 + 2] 1543 ]; 1544 mat4.multiplyVec3(skin.bind_shape_matrix, vec); 1545 var count = -1; 1546 keys.push(skin.vertex_weights[index]); 1547 for (var key in skin.vertex_weights[index]) { 1548 count++; 1549 mat4.multiplyVec3(skin.joints[key], vec, rvec); 1550 vectorForBones[count].push(rvec[0], rvec[1], rvec[2]); 1551 boneIndices.push(skin.ids[key]); 1552 if (count < 2) { 1553 weights[count].push(skin.vertex_weights[index][key]); 1554 } else { 1555 break; 1556 } 1557 } 1558 for (var j = count + 1; j < 3; j++) { 1559 if (j < 2) { 1560 weights[j].push(0); 1561 } 1562 vectorForBones[j].push(0, 0, 0); 1563 boneIndices.push(0); 1564 } 1565 } 1566 } 1567 for (i = 0; i < 3; i++) { 1568 arraysForShader['vectorFromBone' + (i + 1)] = new Float32Array(vectorForBones[i]); 1569 if (i < 2) {arraysForShader['weights' + (i + 1)] = new Float32Array(weights[i]);} 1570 } 1571 arraysForShader.boneIndices = new Uint16Array(boneIndices); 1572 arraysForShader.keys = keys; 1573 return arraysForShader; 1574 }, 1575 _render: function(detectTouch) { 1576 var core = enchant.Core.instance; 1577 var scene = core.currentScene3D; 1578 var l = scene.directionalLight; 1579 var detect = (detectTouch === 'detect') ? 1.0 : 0.0; 1580 mat4.multiply(scene._camera.mat, this.tmpMat, this.uMVMatrix); 1581 mat4.toInverseMat3(this.tmpMat, this.uNMatrix); 1582 mat3.transpose(this.uNMatrix); 1583 core.GL.currentProgram.setAttributes({ 1584 aVertexPosition: this.mesh._vertices, 1585 aVertexNormal: this.mesh._normals, 1586 aTextureCoord: this.mesh._texCoords, 1587 aBoneIndices: this.mesh._boneIndices, 1588 aVectorFromBone1: this.mesh._vpos1, 1589 aVectorFromBone2: this.mesh._vpos2, 1590 aVectorFromBone3: this.mesh._vpos3, 1591 aBoneWeight1: this.mesh._weights1, 1592 aBoneWeight2: this.mesh._weights2 1593 }); 1594 core.GL.currentProgram.setUniforms({ 1595 uUseDirectionalLight: scene.useDirectionalLight, 1596 uLightColor: l.color, 1597 uDetectTouch: detect, 1598 uAmbientLightColor: scene.ambientLight.color, 1599 uPMatrix: scene._camera.projMat, 1600 uMVMatrix: this.uMVMatrix, 1601 uNMatrix: this.uNMatrix, 1602 uLightDirection: [ 1603 l.directionX, l.directionY, l.directionZ 1604 ], 1605 uLookVec: [ 1606 scene._camera._centerX - scene._camera._x, 1607 scene._camera._centerY - scene._camera._y, 1608 scene._camera._centerZ - scene._camera._z 1609 ] 1610 }); 1611 var u = { 1612 uDetectColor: this.detectColor, 1613 uSpecular: this.mesh.texture.specular, 1614 uDiffuse: this.mesh.texture.diffuse, 1615 uEmission: this.mesh.texture.emission, 1616 uAmbient: this.mesh.texture.ambient, 1617 uShininess: this.mesh.texture.shininess 1618 }; 1619 1620 if (this.mesh.texture._image) { 1621 u.uUseTexture = 1; 1622 u.uSampler = this.mesh.texture; 1623 } else { 1624 u.uUseTexture = 0; 1625 u.uSampler = 0; 1626 } 1627 core.GL.currentProgram.setUniforms(u); 1628 for (var i = 0; i < this.mesh.dividedpoints.length - 1; i++) { 1629 core.GL.currentProgram.setUniforms({ 1630 uBonePos: this.mesh.udBoneInfo[i]['pos'], 1631 uBoneRot: this.mesh.udBoneInfo[i]['rot'] 1632 }); 1633 enchant.Core.instance.GL.renderElements(this.mesh._indices, this.mesh.dividedpoints[i] / 3 * 2, this.mesh.dividedpoints[i + 1] / 3 - this.mesh.dividedpoints[i] / 3); 1634 } 1635 } 1636 }); 1637 var bufferProto = Object.getPrototypeOf(enchant.gl.Buffer); 1638 bufferProto.MORPHS = bufferProto.NORMALS; 1639 bufferProto.QUATS = bufferProto.COLORS; 1640 bufferProto.BONE_INDICES = { 1641 size: 3, 1642 type: 5123, 1643 normed: false, 1644 stride: 0, 1645 offset: 0, 1646 btype: 34962, 1647 usage: 35044, 1648 Atype: Uint16Array 1649 }; 1650 bufferProto.WEIGHTS = { 1651 size: 1, 1652 type: 5126, 1653 norm: false, 1654 stride: 0, 1655 offset: 0, 1656 btype: 34962, 1657 usage: 35044, 1658 Atype: Float32Array 1659 }; 1660 var COLLADA_VERTEX_SHADER_SOURCE = '\n\ 1661 uniform mat4 uMVMatrix;\n\ 1662 uniform mat4 uPMatrix;\n\ 1663 uniform mat3 uNMatrix;\n\ 1664 \n\ 1665 uniform vec3 uBonePos[55];\n\ 1666 uniform vec4 uBoneRot[55];\n\ 1667 \n\ 1668 attribute vec3 aBoneIndices;\n\ 1669 attribute vec3 aVertexNormal;\n\ 1670 attribute vec2 aTextureCoord;\n\ 1671 \n\ 1672 attribute float aBoneWeight1;\n\ 1673 attribute float aBoneWeight2;\n\ 1674 attribute vec3 aVectorFromBone1;\n\ 1675 attribute vec3 aVectorFromBone2;\n\ 1676 attribute vec3 aVectorFromBone3;\n\ 1677 \n\ 1678 varying vec3 vNormal;\n\ 1679 varying vec4 vColor;\n\ 1680 varying vec2 vTextureCoord;\n\ 1681 \n\ 1682 \n\ 1683 vec3 qtransform(vec4 q, vec3 v) {\n\ 1684 return v + 2.0 * cross(cross(v, q.xyz) - q.w*v, q.xyz);\n\ 1685 }\n\ 1686 \n\ 1687 void main() {\n\ 1688 int index[3];\n\ 1689 index[0] = int(aBoneIndices.x);\n\ 1690 index[1] = int(aBoneIndices.y);\n\ 1691 index[2] = int(aBoneIndices.z);\n\ 1692 \n\ 1693 float w3 = 1.0 - aBoneWeight1 - aBoneWeight2;\n\ 1694 \n\ 1695 vec3 position = (qtransform(uBoneRot[index[0]], aVectorFromBone1) + uBonePos[index[0]]) * aBoneWeight1\n\ 1696 + (qtransform(uBoneRot[index[1]], aVectorFromBone2) + uBonePos[index[1]]) * aBoneWeight2\n\ 1697 + (qtransform(uBoneRot[index[2]], aVectorFromBone3) + uBonePos[index[2]]) * w3;\n\ 1698 vec3 normal = qtransform(uBoneRot[index[0]], aVertexNormal) * aBoneWeight1\n\ 1699 + qtransform(uBoneRot[index[1]], aVertexNormal) * aBoneWeight2\n\ 1700 + qtransform(uBoneRot[index[2]], aVertexNormal) * w3;\n\ 1701 \n\ 1702 gl_Position = uPMatrix * uMVMatrix * vec4(position, 1.0);\n\ 1703 vColor = vec4(1,1,1,1);\n\ 1704 vTextureCoord = aTextureCoord;\n\ 1705 vNormal = normalize(uNMatrix * normal);\n\ 1706 vNormal = normalize(uNMatrix * aVertexNormal);\n\ 1707 }\n\ 1708 '; 1709 1710 enchant.gl.Core.prototype._original_start = enchant.gl.Core.prototype.start; 1711 enchant.gl.Core.prototype.start = function() { 1712 enchant.gl.collada.COLLADA_SHADER_PROGRAM = new enchant.gl.Shader(COLLADA_VERTEX_SHADER_SOURCE, enchant.Core.instance.GL.defaultProgram._fShaderSource); 1713 this._original_start(); 1714 }; 1715 var ColladaLibraryLoader = enchant.Class.create({ 1716 initialize: function(libraryName, libraryPropertyName, className) { 1717 this.libraryName = libraryName; 1718 this.libraryPropertyName = libraryPropertyName; 1719 this.className = className; 1720 this.library = {}; 1721 }, 1722 loadLibraryFromXML: function(colladaRootElement, url) { 1723 var libraries = colladaRootElement.getElementsByTagName('library_' + this.libraryName); 1724 this.library = {}; 1725 var props = []; 1726 if (libraries.length > 0) { 1727 for (var ci = 0, cl = libraries[0].childNodes.length; ci < cl; ci++) { 1728 if (libraries[0].childNodes[ci].nodeName === this.libraryPropertyName) { 1729 props.push(libraries[0].childNodes[ci]); 1730 } 1731 } 1732 } 1733 var childNodes=colladaRootElement.childNodes; 1734 if (this.libraryPropertyName === "node") { 1735 props = colladaRootElement.getElementsByTagName(this.libraryPropertyName); 1736 } 1737 for (var i = 0, l = props.length; i < l; i++) { 1738 var child = props[i]; 1739 this.library[child.getAttribute('id')] = new this.className(child, url); 1740 if (this.libraryPropertyName === "animation_clip") { 1741 this.library[child.getAttribute('id')].start=child.getAttribute('start'); 1742 this.library[child.getAttribute('id')].end=child.getAttribute('end'); 1743 } 1744 } 1745 return this.library; 1746 } 1747 }); 1748 var availableLibraryFeatures = [new ColladaLibraryLoader('images', 'image', Image), new ColladaLibraryLoader('geometries', 'geometry', Geometry), new ColladaLibraryLoader('nodes', 'node', Node), new ColladaLibraryLoader('visual_scenes', 'visual_scene', VisualScene), new ColladaLibraryLoader('materials', 'material', Material), new ColladaLibraryLoader('effects', 'effect', Effect), new ColladaLibraryLoader('controllers', 'controller', Controller), new ColladaLibraryLoader('animations', 'animation', Animation), new ColladaLibraryLoader('animation_clips', 'animation_clip', AnimationClip)]; 1749 }()); 1750 } 1751