1 /** 2 * @fileOverview 3 * mmd.gl.enchant.js 4 * @version 0.2.2 5 * @require enchant.js v0.6.3+ 6 * @require gl.enchant.js v0.3.7+ 7 * @author UEI Corporation 8 * 9 * @description 10 */ 11 12 // for MMD.js 13 var MMD = {}; 14 15 (function() { 16 17 var splitPath = function(path) { 18 var split = path.match(/(.{0,})\/([^\/\s]{1,}\.pmd)/); 19 if (split == null) { 20 split = [ '.' + path, '.', path ]; 21 } 22 return split; 23 }; 24 25 /** 26 * @type {Object} 27 */ 28 enchant.gl.mmd = {}; 29 30 enchant.Core._loadFuncs['pmd'] = function(src, ext, callback, onerror) { 31 return new enchant.gl.mmd.MSprite3D(src, callback, onerror); 32 }; 33 34 enchant.Core._loadFuncs['vmd'] = function(src, ext, callback, onerror) { 35 return new enchant.gl.mmd.MAnimation(src, callback, onerror); 36 }; 37 38 /** 39 * @scope enchant.gl.mmd.MMesh.prototype 40 */ 41 enchant.gl.mmd.MMesh = enchant.Class.create(enchant.gl.Mesh, { 42 /** 43 * @constructs 44 * @extends enchant.gl.Mesh 45 */ 46 initialize: function() { 47 enchant.gl.Mesh.call(this); 48 var vpos1Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 49 var vpos2Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 50 var bone1posBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 51 var bone2posBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.VERTICES); 52 var quats1Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.QUATS); 53 var quats2Buffer = new enchant.gl.Buffer(enchant.gl.Buffer.QUATS); 54 var morphsBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.MORPHS); 55 var weightsBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.WEIGHTS); 56 var edgesBuffer = new enchant.gl.Buffer(enchant.gl.Buffer.EDGES); 57 this._addAttribute(vpos1Buffer, 'vpos1'); 58 this._addAttribute(vpos2Buffer, 'vpos2'); 59 this._addAttribute(bone1posBuffer, 'bone1pos'); 60 this._addAttribute(bone2posBuffer, 'bone2pos'); 61 this._addAttribute(quats1Buffer, 'quats1'); 62 this._addAttribute(quats2Buffer, 'quats2'); 63 this._addAttribute(morphsBuffer, 'morphs'); 64 this._addAttribute(weightsBuffer, 'weights'); 65 this._addAttribute(edgesBuffer, 'edges'); 66 }, 67 _addAttribute: function(buffer, prop) { 68 this['_' + prop] = buffer; 69 Object.defineProperty(this, prop, { 70 get: function() { 71 return this['_' + prop]._array; 72 }, 73 set: function(array) { 74 this['_' + prop]._array = array; 75 if (this._appear) { 76 this['_' + prop]._bufferData(); 77 } 78 } 79 }); 80 } 81 }); 82 83 enchant.gl.mmd.MBone = enchant.Class.create(enchant.gl.Bone, { 84 initialize: function(param) { 85 var pos = vec3.create(); 86 var rot = quat4.identity(); 87 enchant.gl.Bone.call(this, param.name, param.head_pos, pos, rot); 88 }, 89 _applyPose: function() { 90 var parent = this.parentNode; 91 var local = vec3.create(); 92 vec3.subtract(this._origin, parent._origin, local); 93 vec3.add(local, this._position); 94 quat4.multiply(parent._globalrot, this._rotation, this._globalrot); 95 quat4.multiplyVec3(parent._globalrot, local, this._globalpos); 96 vec3.add(this._globalpos, parent._globalpos); 97 } 98 }); 99 100 enchant.gl.mmd.MSkeleton = enchant.Class.create(enchant.gl.Skeleton, { 101 initialize: function(bones) { 102 enchant.gl.Skeleton.call(this); 103 this.table = []; 104 if (bones) { 105 this.load(bones); 106 } 107 }, 108 load: function(bones) { 109 var bone; 110 for (var i = 0, l = bones.length; i < l; i++) { 111 bone = bones[i]; 112 this._add(bone); 113 } 114 }, 115 _add: function(param) { 116 var bone = new enchant.gl.mmd.MBone(param); 117 this.table.push(bone); 118 if (param.parent_bone_index === 0xFFFF) { 119 this.addChild(bone); 120 } else { 121 this.table[param.parent_bone_index].addChild(bone); 122 } 123 if (param.name.match(/ひざ/)) { 124 bone.constraint = function(q) { 125 return quat4.set([ Math.sqrt(1 - q[3] * q[3]), 0, 0, q[3] ], q); 126 }; 127 } 128 }, 129 _addIK: function(data) { 130 var bones = []; 131 var effector = this.table[data.bone_index]; 132 var target = this.table[data.target_bone_index]; 133 for (var i = 0, l = data.child_bones.length; i < l; i++) { 134 bones[i] = this.table[data.child_bones[i]]; 135 } 136 var maxangle = data.control_weight * 4; 137 var iteration = data.iterations; 138 this.addIKControl(effector, target, bones, maxangle, iteration); 139 } 140 }); 141 142 /** 143 * @scope enchant.gl.mmd.MSprite3D.prototype 144 */ 145 enchant.gl.mmd.MSprite3D = enchant.Class.create(enchant.gl.Sprite3D, { 146 /** 147 * @constructs 148 * @extends enchant.gl.Sprite3D 149 */ 150 initialize: function(path, callback, onerror) { 151 enchant.gl.Sprite3D.call(this); 152 this.program = enchant.gl.mmd.MMD_SHADER_PROGRAM; 153 this.animation = []; 154 this.uMVMatrix = mat4.create(); 155 this.uNMatrix = mat4.create(); 156 157 this.addEventListener('enterframe', function() { 158 var first; 159 var skeleton = this.skeleton; 160 var morph = this.morph; 161 if (this.animation.length === 0) { 162 } else { 163 first = this.animation[0]; 164 165 var data = first.animation._tick(first.frame); 166 first.frame++; 167 168 this._skinning(data.poses); 169 170 this._morphing(data.morphs); 171 172 if (first.frame > first.animation.length) { 173 first = this.animation.shift(); 174 if (this.loop) { 175 first.frame = 0; 176 this.animation.push(first); 177 } 178 } 179 } 180 }); 181 if (arguments.length >= 2) { 182 this.loadPmd(path, callback, onerror); 183 } 184 }, 185 /** 186 * @param {enchant.gl.mmd.MAnimation} animation 187 */ 188 pushAnimation: function(animation) { 189 this.animation.push({ frame: 0, animation: animation }); 190 }, 191 /** 192 */ 193 clearAnimation: function(animation) { 194 this.animation = []; 195 }, 196 _skinning: function(poses) { 197 var skeleton = this.skeleton; 198 skeleton.setPoses(poses); 199 skeleton.solveFKs(); 200 skeleton.solveIKs(); 201 this._applySkeleton(); 202 203 }, 204 _morphing: function(morphs) { 205 var target = this.mesh.morphs; 206 for (var i = 0, l = target.length; i < l; i++) { 207 target[i] = 0; 208 } 209 this.morph.morphing(morphs, target); 210 this.mesh._morphs._bufferDataFast(); 211 }, 212 _render: function() { 213 var core = enchant.Core.instance; 214 var scene = core.currentScene3D; 215 var light = scene.directionalLight; 216 var lvec = [ light._directionX, light._directionY, light._directionZ ]; 217 var uMVMatrix = mat4.identity(this.uMVMatrix); 218 mat4.multiply(scene._camera.mat, this.tmpMat, uMVMatrix); 219 var uNMatrix = mat4.identity(this.uNMatrix); 220 mat4.transpose(mat4.inverse(uMVMatrix, uNMatrix)); 221 var uLightDirection = vec3.normalize(lvec); 222 mat4.multiplyVec3(uNMatrix, uLightDirection); 223 core.GL.currentProgram.setAttributes({ 224 aVertexPosition: this.mesh._vertices, 225 aVertexNormal: this.mesh._normals, 226 aTextureCoord: this.mesh._texCoords, 227 aVectorFromBone1: this.mesh._vpos1, 228 aVectorFromBone2: this.mesh._vpos2, 229 aBone1Position: this.mesh._bone1pos, 230 aBone2Position: this.mesh._bone2pos, 231 aBone1Rotation: this.mesh._quats1, 232 aBone2Rotation: this.mesh._quats2, 233 aMultiPurposeVector: this.mesh._morphs, 234 aBoneWeight: this.mesh._weights, 235 aVertexEdge: this.mesh._edges 236 }); 237 core.GL.currentProgram.setUniforms({ 238 uLightDirection: uLightDirection, 239 uPMatrix: scene._camera.projMat, 240 uMVMatrix: uMVMatrix, 241 uNMatrix: uNMatrix 242 }); 243 var length; 244 var material; 245 var offset = 0; 246 for (var i = 0, l = this.mesh.materials.length; i < l; i++) { 247 material = this.mesh.materials[i]; 248 var u = { 249 uAmbientColor: material.ambient, 250 uDiffuseColor: material.diffuse, 251 uSpecularColor: material.specular, 252 uShininess: material.shininess, 253 uAlpha: material.alpha 254 }; 255 if (material.toon) { 256 u.uToon = material.toon; 257 } 258 if (material.texture) { 259 if (material.texture._image.src.match(/sph/)) { 260 u.uUseSphereMap = 1; 261 u.uUseTexture = 0; 262 u.uUseSphereMapAdditive = 0; 263 u.uSphereMap = material.texture; 264 } else { 265 u.uUseSphereMap = 0; 266 u.uUseTexture = 1; 267 u.uTexture = material.texture; 268 } 269 } else { 270 u.uUseTexture = 0; 271 u.uTexture = 0; 272 u.uUseSphereMap = 0; 273 } 274 core.GL.currentProgram.setUniforms(u); 275 276 277 length = material.face_vert_count; 278 enchant.Core.instance.GL.renderElements(this.mesh._indices, offset * 2, length); 279 280 if (material.edge_flag) { 281 enchant.gl.mmd.MMD_SHADER_PROGRAM.setUniforms({ uEdge: 1 }); 282 gl.cullFace(gl.FRONT); 283 enchant.Core.instance.GL.renderElements(this.mesh._indices, offset * 2, length); 284 gl.cullFace(gl.BACK); 285 enchant.gl.mmd.MMD_SHADER_PROGRAM.setUniforms({ uEdge: 0 }); 286 } 287 288 offset += material.face_vert_count; 289 } 290 }, 291 /** 292 */ 293 loadPmd: function(path, callback, onerror) { 294 var split = splitPath(path); 295 var model = new MMD.Model(split[1], split[2]); 296 var that = this; 297 this._data = model; 298 callback = callback || function() {}; 299 onerror = onerror || function() {}; 300 this.addEventListener('load', callback); 301 this.addEventListener('error', onerror); 302 model.load(function() { 303 var e; 304 try { 305 that._parse(model); 306 that.dispatchEvent(new enchant.Event(enchant.Event.LOAD)); 307 } catch (err) { 308 e = new enchant.Event(enchant.Event.ERROR); 309 e.message = err.message; 310 enchant.Core.instance.dispatchEvent(e); 311 that.dispatchEvent(e); 312 } 313 }); 314 }, 315 set: function(sp) { 316 this._parse(sp._data); 317 this._data = sp._data; 318 }, 319 clone: function() { 320 var sp = new enchant.gl.mmd.MSprite3D(); 321 sp._parse(this._data); 322 sp._data = this._data; 323 return sp; 324 }, 325 _parse: function(model) { 326 var data; 327 var original; 328 var params = [ 'ambient', 'diffuse', 'specular', 'shininess', 'alpha', 'face_vert_count', 'edge_flag' ]; 329 330 var mesh = new enchant.gl.mmd.MMesh(); 331 var length = model.vertices.length; 332 var v; 333 var b1, b2; 334 var ind; 335 var material; 336 var vertices = new Float32Array(length * 3); 337 var normals = new Float32Array(length * 3); 338 var texCoords = new Float32Array(length * 2); 339 var indices = new Uint16Array(model.triangles); 340 var vpos1 = new Float32Array(length * 3); 341 var vpos2 = new Float32Array(length * 3); 342 var bone1pos = new Float32Array(length * 3); 343 var bone2pos = new Float32Array(length * 3); 344 var quats1 = new Float32Array(length * 4); 345 var quats2 = new Float32Array(length * 4); 346 var morphs = new Float32Array(length * 3); 347 var weights = new Float32Array(length); 348 var edges = new Uint16Array(length); 349 var bindex1 = new Float32Array(length); 350 var bindex2 = new Float32Array(length); 351 var tmp = vec3.create(); 352 var tmp2 = vec3.create(); 353 for (var i = 0; i < length; i++) { 354 v = model.vertices[i]; 355 b1 = model.bones[v.bone_num1]; 356 b2 = model.bones[v.bone_num2]; 357 bindex1[i] = v.bone_num1; 358 bindex2[i] = v.bone_num2; 359 tmp.set([ v.x, v.y, v.z ]); 360 vertices.set(tmp, i * 3); 361 vec3.subtract(tmp, b1.head_pos, tmp2); 362 vpos1.set(tmp2, i * 3); 363 vec3.subtract(tmp, b2.head_pos, tmp2); 364 vpos2.set(tmp2, i * 3); 365 normals.set([ v.nx, v.ny, v.nz ], i * 3); 366 texCoords.set([ v.u, v.v ], i * 2); 367 bone1pos.set(b1.head_pos, i * 3); 368 bone2pos.set(b2.head_pos, i * 3); 369 quats1.set([ 0, 0, 0, 1 ], i * 4); 370 quats2.set([ 0, 0, 0, 1 ], i * 4); 371 morphs.set([ 0, 0, 0 ], i * 3); 372 weights[i] = v.bone_weight; 373 edges[i] = 1 - v.edge_flag; 374 } 375 376 377 mesh.vertices = vertices; 378 mesh.normals = normals; 379 mesh.texCoords = texCoords; 380 mesh.indices = indices; 381 mesh.vpos1 = vpos1; 382 mesh.vpos2 = vpos2; 383 mesh.bone1pos = bone1pos; 384 mesh.bone2pos = bone2pos; 385 mesh.quats1 = quats1; 386 mesh.quats2 = quats2; 387 mesh.weights = weights; 388 mesh.edges = edges; 389 mesh.morphs = morphs; 390 mesh.colors = new Float32Array(length * 4); 391 mesh.bindex1 = bindex1; 392 mesh.bindex2 = bindex2; 393 394 this.mesh = mesh; 395 396 this.mesh.materials = []; 397 398 this.skeleton = new enchant.gl.mmd.MSkeleton(model.bones); 399 var l; 400 for (i = 0, l = model.iks.length; i < l; i++) { 401 data = model.iks[i]; 402 this.skeleton._addIK(data); 403 } 404 405 this.morph = new enchant.gl.mmd.MMorph(model.morphs); 406 407 for (i = 0, l = model.materials.length; i < l; i++) { 408 original = model.materials[i]; 409 material = this.mesh.materials[i] = {}; 410 for (var prop in params) { 411 material[params[prop]] = original[params[prop]]; 412 } 413 if (typeof model.toon_file_names[i] !== 'undefined') { 414 material.toon = new enchant.gl.Texture(model.directory + '/' + model.toon_file_names[original.toon_index], {flipY: false}); 415 } 416 if (original.texture_file_name) { 417 material.texture = new enchant.gl.Texture(model.directory + '/' + original.texture_file_name); 418 } 419 } 420 }, 421 _applySkeleton: function() { 422 var sk = this.skeleton; 423 var mesh = this.mesh; 424 var b1pos, b2pos, b1rot, b2rot; 425 var i3 = 0, i4 = 0; 426 var length = this.mesh.vertices.length / 3; 427 for (var i = 0; i < length; i++) { 428 b1pos = sk.table[mesh.bindex1[i]]._globalpos; 429 b2pos = sk.table[mesh.bindex2[i]]._globalpos; 430 b1rot = sk.table[mesh.bindex1[i]]._globalrot; 431 b2rot = sk.table[mesh.bindex2[i]]._globalrot; 432 433 mesh._bone1pos._array[i3 + 0] = b1pos[0]; 434 mesh._bone1pos._array[i3 + 1] = b1pos[1]; 435 mesh._bone1pos._array[i3 + 2] = b1pos[2]; 436 mesh._bone2pos._array[i3 + 0] = b2pos[0]; 437 mesh._bone2pos._array[i3 + 1] = b2pos[1]; 438 mesh._bone2pos._array[i3 + 2] = b2pos[2]; 439 440 mesh._quats1._array[i4 + 0] = b1rot[0]; 441 mesh._quats1._array[i4 + 1] = b1rot[1]; 442 mesh._quats1._array[i4 + 2] = b1rot[2]; 443 mesh._quats1._array[i4 + 3] = b1rot[3]; 444 mesh._quats2._array[i4 + 0] = b2rot[0]; 445 mesh._quats2._array[i4 + 1] = b2rot[1]; 446 mesh._quats2._array[i4 + 2] = b2rot[2]; 447 mesh._quats2._array[i4 + 3] = b2rot[3]; 448 449 i3 += 3; 450 i4 += 4; 451 } 452 mesh._bone1pos._bufferDataFast(); 453 mesh._bone2pos._bufferDataFast(); 454 mesh._quats1._bufferDataFast(); 455 mesh._quats2._bufferDataFast(); 456 } 457 }); 458 459 460 enchant.gl.mmd.MPose = enchant.Class.create(enchant.gl.Pose, { 461 initialize: function(param) { 462 enchant.gl.Pose.call(this, param.location, param.rotation); 463 this._interpolation = param.interpolation; 464 }, 465 _internalInterpole: function(i, x) { 466 var x1 = this._interpolation[0 + i] / 127; 467 var y1 = this._interpolation[4 + i] / 127; 468 var x2 = this._interpolation[8 + i] / 127; 469 var y2 = this._interpolation[12 + i] / 127; 470 return this._bezierp(x1, y1, x2, y2, x); 471 }, 472 getInterpolation: function(another, ratio) { 473 var v = vec3.create(); 474 var q = quat4.create(); 475 var xt = this._internalInterpole(0, ratio); 476 var yt = this._internalInterpole(1, ratio); 477 var zt = this._internalInterpole(2, ratio); 478 var rt = this._internalInterpole(3, ratio); 479 v[0] = this._position[0] + (another._position[0] - this._position[0]) * xt; 480 v[1] = this._position[1] + (another._position[1] - this._position[1]) * yt; 481 v[2] = this._position[2] + (another._position[2] - this._position[2]) * zt; 482 var loc = v; 483 var rot = quat4.slerp(this._rotation, another._rotation, rt, q); 484 return new enchant.gl.Pose(loc, rot); 485 } 486 }); 487 488 enchant.gl.mmd.MMorph = enchant.Class.create({ 489 initialize: function(data) { 490 this._base = {}; 491 this._morphs = {}; 492 if (typeof data !== 'undefined') { 493 this._load(data); 494 } 495 }, 496 _load: function(data) { 497 this._base = data.slice(0, 1)[0]; 498 var m, name, vert, morph; 499 for (var i = 1, l = data.length; i < l; i++) { 500 m = data[i]; 501 name = m.name; 502 vert = m.vert_data; 503 morph = this._morphs[name] = {}; 504 morph.index = new Float32Array(vert.length); 505 morph.vert = new Float32Array(vert.length * 3); 506 for (var j = 0, ll = vert.length; j < ll; j++) { 507 morph.index[j] = this._base.vert_data[vert[j].index].index * 3; 508 morph.vert[j * 3] = vert[j].x; 509 morph.vert[j * 3 + 1] = vert[j].y; 510 morph.vert[j * 3 + 2] = vert[j].z; 511 } 512 } 513 }, 514 morphing: function(data, target) { 515 var weight, index; 516 for (var prop in data) { 517 weight = data[prop]._weight; 518 if (weight && this._morphs[prop]) { 519 this._morphing(prop, target, weight); 520 } 521 } 522 }, 523 _morphing: function(name, target, weight) { 524 var set = this._morphs[name]; 525 var index; 526 for (var i = 0, l = set.index.length; i < l; i++) { 527 index = set.index[i]; 528 target[index] += set.vert[i * 3] * weight; 529 target[index + 1] += set.vert[i * 3 + 1] * weight; 530 target[index + 2] += set.vert[i * 3 + 2] * weight; 531 } 532 } 533 }); 534 535 enchant.gl.mmd.MMorphPoint = enchant.Class.create({ 536 initialize: function(weight) { 537 this._weight = weight; 538 }, 539 getInterpolation: function(another, ratio) { 540 return new enchant.gl.mmd.MMorphPoint(lerp(this._weight, another._weight, ratio)); 541 } 542 }); 543 544 enchant.gl.mmd.MKeyFrameManager = enchant.Class.create(enchant.gl.KeyFrameManager, { 545 initialize: function() { 546 enchant.gl.KeyFrameManager.call(this); 547 } 548 }); 549 550 /** 551 * @scope enchant.gl.mmd.MAnimation.prototype 552 */ 553 enchant.gl.mmd.MAnimation = enchant.Class.create(enchant.EventTarget, { 554 /** 555 * @constructs 556 * @extends enchant.EventTarget 557 * @see enchant.gl.mmd.MAnimation#loadVmd 558 */ 559 initialize: function(path, callback, onerror) { 560 enchant.EventTarget.call(this); 561 this.length = -1; 562 if (arguments.length >= 2) { 563 this.loadVmd(path, callback, onerror); 564 } 565 }, 566 /** 567 */ 568 loadVmd: function(path, callback, onerror) { 569 var motion = new MMD.Motion(path); 570 var frame; 571 var that = this; 572 573 callback = callback || function() {}; 574 onerror = onerror || function() {}; 575 console.log(this); 576 this.addEventListener('load', callback); 577 this.addEventListener('error', onerror); 578 motion.load(function() { 579 var e; 580 try { 581 that.motions = parseMotion(motion.bone); 582 that.morphs = parseMorph(motion.morph); 583 that._calcLength(); 584 that.dispatchEvent(new enchant.Event(enchant.Event.LOAD)); 585 } catch (err) { 586 e = new enchant.Event(enchant.Event.ERROR); 587 e.message = err.message; 588 enchant.Core.instance.dispatchEvent(e); 589 that.dispatchEvent(e); 590 } 591 }); 592 }, 593 bake: function() { 594 var prop, manager; 595 for (prop in this.morphs) { 596 manager = this.morphs[prop]; 597 if (manager instanceof enchant.gl.mmd.MKeyFrameManager) { 598 manager.bake(); 599 } 600 } 601 for (prop in this.motions) { 602 manager = this.motions[prop]; 603 if (manager instanceof enchant.gl.mmd.MKeyFrameManager) { 604 manager.bake(); 605 } 606 } 607 }, 608 _tick: function(frame) { 609 var poses = this._getFrame(this.motions, frame); 610 var morphs = this._getFrame(this.morphs, frame); 611 return { 612 poses: poses, 613 morphs: morphs 614 }; 615 }, 616 _getFrame: function(data, frame) { 617 var ret = {}; 618 for (var prop in data) { 619 ret[prop] = data[prop].getFrame(frame); 620 } 621 return ret; 622 }, 623 _calcLength: function() { 624 var data, deta; 625 for (var prop in this) { 626 data = this[prop]; 627 if (data instanceof Object) { 628 for (var plop in data) { 629 deta = data[plop]; 630 if (deta instanceof enchant.gl.mmd.MKeyFrameManager) { 631 if (this.length < deta.length) { 632 this.length = deta.length; 633 } 634 } 635 } 636 } 637 } 638 } 639 }); 640 641 var parseMorph = function(data) { 642 var morphs = {}; 643 var morph, name, frame, weight; 644 for (var i = 0, l = data.length; i < l; i++) { 645 morph = data[i]; 646 name = morph.name; 647 frame = morph.frame; 648 weight = morph.weight; 649 if (typeof morphs[name] === 'undefined') { 650 morphs[name] = new enchant.gl.mmd.MKeyFrameManager(); 651 } 652 morphs[name].addFrame(new enchant.gl.mmd.MMorphPoint(weight), frame); 653 } 654 for (var prop in morphs) { 655 morphs[prop]._sort(); 656 } 657 return morphs; 658 }; 659 660 var parseMotion = function(data) { 661 var motions = {}; 662 var bone, name, frame; 663 for (var i = 0, l = data.length; i < l; i++) { 664 bone = data[i]; 665 name = bone.name; 666 frame = bone.frame; 667 if (typeof motions[name] === 'undefined') { 668 motions[name] = new enchant.gl.mmd.MKeyFrameManager(); 669 } 670 motions[name].addFrame(new enchant.gl.mmd.MPose(bone), frame); 671 } 672 for (var prop in motions) { 673 motions[prop]._sort(); 674 } 675 return motions; 676 }; 677 678 var bufferProto = Object.getPrototypeOf(enchant.gl.Buffer); 679 bufferProto.MORPHS = bufferProto.NORMALS; 680 bufferProto.QUATS = bufferProto.COLORS; 681 bufferProto.WEIGHTS = { 682 size: 1, 683 type: 5126, 684 norm: false, 685 stride: 0, 686 offset: 0, 687 btype: 34962, 688 usage: 35044, 689 Atype: Float32Array 690 }; 691 bufferProto.EDGES = { 692 size: 1, 693 type: 5123, 694 norm: false, 695 stride: 0, 696 offset: 0, 697 btype: 34962, 698 usage: 35044, 699 Atype: Uint16Array 700 }; 701 702 var _original_start = enchant.gl.Core.prototype.start; 703 enchant.gl.Core.prototype.start = function() { 704 enchant.gl.mmd.MMD_SHADER_PROGRAM = new enchant.gl.Shader(MMD_VERTEX_SHADER_SOURCE, MMD_FRAGMENT_SHADER_SOURCE); 705 this.GL.setProgram(enchant.gl.mmd.MMD_SHADER_PROGRAM); 706 enchant.gl.mmd.MMD_SHADER_PROGRAM.setUniforms({ 707 uLightMatrix: [ 708 1, 0, 0, 0, 709 0, 1, 0, 0, 710 0, 0, 1, 0, 711 0, 0, 0, 1 712 ], 713 uLightColor: [ 0.6, 0.6, 0.6 ], 714 uSelfShadow: 0, 715 uShadowMap: 0, 716 uGenerateShadowMap: 0, 717 uCenterPoint: 0, 718 uAxis: 0, 719 uAxisColor: [ 1, 0, 1 ], 720 uEdge: 0, 721 uEdgeColor: [ 0, 0, 0 ], 722 uEdgeThickness: 0.004 723 }); 724 this.GL.setDefaultProgram(); 725 _original_start.call(this); 726 }; 727 728 var lerp = function(n1, n2, r) { 729 return n1 + r * (n2 - n1); 730 }; 731 732 var MMD_VERTEX_SHADER_SOURCE = '\n\ 733 uniform mat4 uMVMatrix;\n\ 734 uniform mat4 uPMatrix;\n\ 735 uniform mat4 uNMatrix;\n\ 736 \n\ 737 uniform mat4 uLightMatrix;\n\ 738 \n\ 739 attribute vec3 aVertexNormal;\n\ 740 attribute vec2 aTextureCoord;\n\ 741 attribute float aVertexEdge;\n\ 742 \n\ 743 attribute float aBoneWeight;\n\ 744 attribute vec3 aVectorFromBone1;\n\ 745 attribute vec3 aVectorFromBone2;\n\ 746 attribute vec4 aBone1Rotation;\n\ 747 attribute vec4 aBone2Rotation;\n\ 748 attribute vec3 aBone1Position;\n\ 749 attribute vec3 aBone2Position;\n\ 750 \n\ 751 attribute vec3 aMultiPurposeVector;\n\ 752 \n\ 753 varying vec3 vPosition;\n\ 754 varying vec3 vNormal;\n\ 755 varying vec2 vTextureCoord;\n\ 756 varying vec4 vLightCoord;\n\ 757 \n\ 758 uniform float uEdgeThickness;\n\ 759 uniform bool uEdge;\n\ 760 \n\ 761 uniform bool uGenerateShadowMap;\n\ 762 \n\ 763 uniform bool uSelfShadow;\n\ 764 \n\ 765 uniform bool uAxis;\n\ 766 uniform bool uCenterPoint;\n\ 767 \n\ 768 vec3 qtransform(vec4 q, vec3 v) {\n\ 769 return v + 2.0 * cross(cross(v, q.xyz) - q.w*v, q.xyz);\n\ 770 }\n\ 771 \n\ 772 void main() {\n\ 773 vec3 position;\n\ 774 vec3 normal;\n\ 775 \n\ 776 if (uAxis || uCenterPoint) {\n\ 777 \n\ 778 position = aMultiPurposeVector;\n\ 779 \n\ 780 } else {\n\ 781 \n\ 782 float weight = aBoneWeight;\n\ 783 vec3 morph = aMultiPurposeVector;\n\ 784 \n\ 785 position = qtransform(aBone1Rotation, aVectorFromBone1 + morph) + aBone1Position;\n\ 786 normal = qtransform(aBone1Rotation, aVertexNormal);\n\ 787 \n\ 788 if (weight < 0.99) {\n\ 789 vec3 p2 = qtransform(aBone2Rotation, aVectorFromBone2 + morph) + aBone2Position;\n\ 790 vec3 n2 = qtransform(aBone2Rotation, normal);\n\ 791 \n\ 792 position = mix(p2, position, weight);\n\ 793 normal = normalize(mix(n2, normal, weight));\n\ 794 }\n\ 795 }\n\ 796 \n\ 797 \n\ 798 gl_Position = uPMatrix * uMVMatrix * vec4(position, 1.0);\n\ 799 \n\ 800 if (uCenterPoint) {\n\ 801 gl_Position.z = 0.0;\n\ 802 gl_PointSize = 16.0;\n\ 803 }\n\ 804 \n\ 805 if (uGenerateShadowMap || uAxis || uCenterPoint) return;\n\ 806 \n\ 807 \n\ 808 vTextureCoord = aTextureCoord;\n\ 809 vPosition = (uMVMatrix * vec4(position, 1.0)).xyz;\n\ 810 vNormal = (uNMatrix * vec4(normal, 1.0)).xyz;\n\ 811 \n\ 812 if (uSelfShadow) {\n\ 813 vLightCoord = uLightMatrix * vec4(position, 1.0);\n\ 814 }\n\ 815 \n\ 816 if (uEdge) {\n\ 817 vec4 pos = gl_Position;\n\ 818 vec4 pos2 = uPMatrix * uMVMatrix * vec4(position + normal, 1.0);\n\ 819 vec4 norm = normalize(pos2 - pos);\n\ 820 gl_Position = pos + norm * uEdgeThickness * aVertexEdge * pos.w;\n\ 821 return;\n\ 822 }\n\ 823 }\n\ 824 '; 825 826 var MMD_FRAGMENT_SHADER_SOURCE = '\n\ 827 #ifdef GL_ES\n\ 828 precision highp float;\n\ 829 #endif\n\ 830 \n\ 831 varying vec2 vTextureCoord;\n\ 832 varying vec3 vPosition;\n\ 833 varying vec3 vNormal;\n\ 834 varying vec4 vLightCoord;\n\ 835 \n\ 836 uniform vec3 uLightDirection;\n\ 837 uniform vec3 uLightColor;\n\ 838 \n\ 839 uniform vec3 uAmbientColor;\n\ 840 uniform vec3 uSpecularColor;\n\ 841 uniform vec3 uDiffuseColor;\n\ 842 uniform float uAlpha;\n\ 843 uniform float uShininess;\n\ 844 \n\ 845 uniform bool uUseTexture;\n\ 846 uniform bool uUseSphereMap;\n\ 847 uniform bool uIsSphereMapAdditive;\n\ 848 \n\ 849 uniform sampler2D uToon;\n\ 850 uniform sampler2D uTexture;\n\ 851 uniform sampler2D uSphereMap;\n\ 852 \n\ 853 uniform bool uEdge;\n\ 854 uniform float uEdgeThickness;\n\ 855 uniform vec3 uEdgeColor;\n\ 856 \n\ 857 uniform bool uGenerateShadowMap;\n\ 858 uniform bool uSelfShadow;\n\ 859 uniform sampler2D uShadowMap;\n\ 860 \n\ 861 uniform bool uAxis;\n\ 862 uniform vec3 uAxisColor;\n\ 863 uniform bool uCenterPoint;\n\ 864 \n\ 865 // from http://spidergl.org/example.php?id=6\n\ 866 vec4 pack_depth(const in float depth) {\n\ 867 const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n\ 868 const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n\ 869 vec4 res = fract(depth * bit_shift);\n\ 870 res -= res.xxyz * bit_mask;\n\ 871 return res;\n\ 872 }\n\ 873 float unpack_depth(const in vec4 rgba_depth)\n\ 874 {\n\ 875 const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\n\ 876 float depth = dot(rgba_depth, bit_shift);\n\ 877 return depth;\n\ 878 }\n\ 879 \n\ 880 void main() {\n\ 881 if (uGenerateShadowMap) {\n\ 882 \n\ 883 gl_FragColor = pack_depth(gl_FragCoord.z);\n\ 884 return;\n\ 885 }\n\ 886 if (uAxis) {\n\ 887 gl_FragColor = vec4(uAxisColor, 1.0);\n\ 888 return;\n\ 889 }\n\ 890 if (uCenterPoint) {\n\ 891 vec2 uv = gl_PointCoord * 2.0 - 1.0;\n\ 892 float w = dot(uv, uv);\n\ 893 if (w < 0.3 || (w > 0.5 && w < 1.0)) {\n\ 894 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\ 895 } else {\n\ 896 discard;\n\ 897 }\n\ 898 return;\n\ 899 }\n\ 900 \n\ 901 \n\ 902 vec3 norm = normalize(vNormal);\n\ 903 vec3 cameraDirection = normalize(-vPosition);\n\ 904 \n\ 905 vec3 color;\n\ 906 float alpha = uAlpha;\n\ 907 \n\ 908 if (uEdge) {\n\ 909 \n\ 910 color = uEdgeColor;\n\ 911 \n\ 912 } else {\n\ 913 \n\ 914 color = vec3(1.0, 1.0, 1.0);\n\ 915 if (uUseTexture) {\n\ 916 vec4 texColor = texture2D(uTexture, vTextureCoord);\n\ 917 color *= texColor.rgb;\n\ 918 alpha *= texColor.a;\n\ 919 }\n\ 920 if (uUseSphereMap) {\n\ 921 vec2 sphereCoord = 0.5 * (1.0 + vec2(1.0, -1.0) * norm.xy);\n\ 922 if (uIsSphereMapAdditive) {\n\ 923 color += texture2D(uSphereMap, sphereCoord).rgb;\n\ 924 } else {\n\ 925 color *= texture2D(uSphereMap, sphereCoord).rgb;\n\ 926 }\n\ 927 }\n\ 928 \n\ 929 \n\ 930 vec3 halfAngle = normalize(uLightDirection + cameraDirection);\n\ 931 float specularWeight = pow( max(0.001, dot(halfAngle, norm)) , uShininess );\n\ 932 \n\ 933 vec3 specular = specularWeight * uSpecularColor;\n\ 934 \n\ 935 vec2 toonCoord = vec2(0.0, 0.5 * (1.0 - dot( uLightDirection, norm )));\n\ 936 \n\ 937 if (uSelfShadow) {\n\ 938 vec3 lightCoord = vLightCoord.xyz / vLightCoord.w;\n\ 939 vec4 rgbaDepth = texture2D(uShadowMap, lightCoord.xy);\n\ 940 float depth = unpack_depth(rgbaDepth);\n\ 941 if (depth < lightCoord.z - 0.01) {\n\ 942 toonCoord = vec2(0.0, 0.55);\n\ 943 }\n\ 944 }\n\ 945 \n\ 946 color *= uAmbientColor + uLightColor * (uDiffuseColor + specular);\n\ 947 \n\ 948 color = clamp(color, 0.0, 1.0);\n\ 949 color *= texture2D(uToon, toonCoord).rgb;\n\ 950 \n\ 951 }\n\ 952 gl_FragColor = vec4(color, alpha);\n\ 953 \n\ 954 }\n\ 955 '; 956 }()); 957