makc 3f37b58292 an attempt to fix goblins problem
this only addresses bad attachment.uvs, there are still more problems :(
2014-12-14 04:14:33 +01:00

392 lines
12 KiB
HTML

<!-----------------------------------------------------------------------------
-- Spine Runtimes Software License
-- Version 2.1
--
-- Copyright (c) 2013, Esoteric Software
-- All rights reserved.
--
-- You are granted a perpetual, non-exclusive, non-sublicensable and
-- non-transferable license to install, execute and perform the Spine Runtimes
-- Software (the "Software") solely for internal use. Without the written
-- permission of Esoteric Software (typically granted by licensing Spine), you
-- may not (a) modify, translate, adapt or otherwise create derivative works,
-- improvements of the Software or develop new applications using the Software
-- or (b) remove, delete, alter or obscure any trademarks or any copyright,
-- trademark, patent or other intellectual property or proprietary rights
-- notices on or in the Software, including any copy thereof. Redistributions
-- in binary or source form must include this license and terms.
--
-- THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-- EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------>
<html>
<head>
<meta charset="UTF-8">
<title>spine-js</title>
<script src="../spine-js/spine.js"></script>
<script src="../three.min.js"></script>
<style>body, input { font-family: tahoma; font-size: 11pt }</style>
</head>
<body>
<input type="button" value="Spineboy" onclick="load('spineboy', 0.6)">
<input type="button" value="Hero" onclick="load('hero', 1)">
<input type="button" value="Goblins" onclick="load('goblins', 1)">
<input type="button" value="Gipsy" onclick="load('skeleton', 1)">
&nbsp; &nbsp; Click to change the animation or skin.
<br>
<script>
(function () {
var loadText = function (url, callback) {
var req = new XMLHttpRequest ();
req.open ("GET", url, true);
req.responseType = 'text';
req.addEventListener ('error', function (event) {}, false);
req.addEventListener ('abort', function (event) {}, false);
req.addEventListener ('load', function (event) { callback (req.response); }, false);
req.send ();
return req;
};
var loadImage = function (url, callback) {
var image = new Image ();
image.addEventListener ('error', function (event) {}, false);
image.addEventListener ('abort', function (event) {}, false);
image.addEventListener ('load', function (event) { callback (image); }, false);
image.src = url;
return image;
};
SpineAnimation = function (animation, path, scale) {
THREE.Object3D.call (this);
this.name = animation;
path = path ? (path +
((path.substr(-1) != '/') ? '/' : '')
) : '';
var self = this;
loadText (path + animation + '.atlas', function (atlasText) {
self.atlas = new spine.Atlas(atlasText, {
load: function (page, image, atlas) {
loadImage (path + image, function (image) {
// calculate UVs in atlas regions
page.width = image.width;
page.height = image.height;
atlas.updateUVs (page);
// propagate new UVs to attachments, if they were already created
if (self.skeleton) {
var skins = self.skeleton.data.skins;
for (var s = 0, n = skins.length; s < n; s++) {
var attachments = skins[s].attachments;
for (var k in attachments) {
var attachment = attachments[k];
if (attachment instanceof spine.RegionAttachment) {
var region = attachment.rendererObject;
attachment.setUVs (region.u, region.v, region.u2, region.v2, region.rotate);
}
}
}
}
// create basic material for the page
var texture = new THREE.Texture (image);
texture.needsUpdate = true;
page.rendererObject = [
new THREE.MeshBasicMaterial ({
//color: 0xff00, wireframe: true,
map : texture, side : THREE.DoubleSide, transparent : true, alphaTest : 0.5
})
];
});
},
unload: function (materials) {
for (var i = 0, n = materials.length; i < n; i++) {
var material = materials[i];
if (material.meshes) {
for (var name in material.meshes) {
var mesh = material.meshes[name];
if (mesh.parent) {
mesh.parent.remove (mesh);
}
mesh.geometry.dispose();
}
}
material.map.dispose();
material.dispose();
}
// will be called multiple times
materials.length = 0;
}
});
loadText (path + animation + '.json', function (skeletonText) {
var json = new spine.SkeletonJson (new spine.AtlasAttachmentLoader (self.atlas));
json.scale = scale || 1;
var skeletonData = json.readSkeletonData (JSON.parse (skeletonText));
self.skeleton = new spine.Skeleton (skeletonData);
self.stateData = new spine.AnimationStateData (skeletonData);
self.state = new spine.AnimationState (self.stateData);
self.dispatchEvent({
type : SpineAnimation.SKELETON_DATA_LOADED
});
});
});
var matrix = new THREE.Matrix4 ();
// if given, dt must be in ms
this.update = function (dt, dz) {
if (!this.state) return;
this.state.update (dt || (1.0 / 60));
this.state.apply (this.skeleton);
this.skeleton.updateWorldTransform ();
var Z = 0;
var drawOrder = this.skeleton.drawOrder;
for (var i = 0, n = drawOrder.length; i < n; i++) {
var slot = drawOrder[i];
var attachment = slot.attachment;
if (!(attachment instanceof spine.RegionAttachment)) continue;
var materials = attachment.rendererObject.page.rendererObject;
if (!materials) {
// texture was not loaded yet
continue;
}
if (slot.data.additiveBlending && (materials.length == 1)) {
// create separate material for additive blending
materials.push (new THREE.MeshBasicMaterial ({
map : materials[0].map,
side : THREE.DoubleSide,
transparent : true,
blending : THREE.AdditiveBlending,
depthWrite : false
}));
}
var material = materials[ slot.data.additiveBlending ? 1 : 0 ];
material.meshes = material.meshes || {};
var mesh = material.meshes[slot.data.name];
if (!mesh) {
var geometry = new THREE.PlaneGeometry (
attachment.regionOriginalWidth,
attachment.regionOriginalHeight
);
// TODO can slot change these?
geometry.faceVertexUvs[0][0][0].set (attachment.uvs[6], 1- attachment.uvs[7]);
geometry.faceVertexUvs[0][0][1].set (attachment.uvs[4], 1- attachment.uvs[5]);
geometry.faceVertexUvs[0][0][2].set (attachment.uvs[0], 1- attachment.uvs[1]);
geometry.faceVertexUvs[0][1][0].set (attachment.uvs[4], 1- attachment.uvs[5]);
geometry.faceVertexUvs[0][1][1].set (attachment.uvs[2], 1- attachment.uvs[3]);
geometry.faceVertexUvs[0][1][2].set (attachment.uvs[0], 1- attachment.uvs[1]);
geometry.vertices[1].set (attachment.offset[0], attachment.offset[1], 0);
geometry.vertices[3].set (attachment.offset[2], attachment.offset[3], 0);
geometry.vertices[2].set (attachment.offset[4], attachment.offset[5], 0);
geometry.vertices[0].set (attachment.offset[6], attachment.offset[7], 0);
mesh = new THREE.Mesh (geometry, material);
material.meshes[slot.data.name] = mesh;
mesh.matrixAutoUpdate = false;
this.add (mesh);
}
matrix.makeTranslation (
this.skeleton.x + slot.bone.worldX,
this.skeleton.y + slot.bone.worldY,
(dz || 0.1) * Z++
);
matrix.elements[0] = slot.bone.m00; matrix.elements[4] = slot.bone.m01;
matrix.elements[1] = slot.bone.m10; matrix.elements[5] = slot.bone.m11;
mesh.matrix.copy (matrix);
/* TODO slot.r,g,b,a ?? turbulenz example code:
batch.add(
attachment.rendererObject.page.rendererObject,
vertices[0], vertices[1],
vertices[6], vertices[7],
vertices[2], vertices[3],
vertices[4], vertices[5],
skeleton.r * slot.r,
skeleton.g * slot.g,
skeleton.b * slot.b,
skeleton.a * slot.a,
attachment.uvs[0], attachment.uvs[1],
attachment.uvs[4], attachment.uvs[5]
);
*/
}
};
};
SpineAnimation.SKELETON_DATA_LOADED = 'skeletonDataLoaded';
SpineAnimation.prototype = Object.create (THREE.Object3D.prototype);
SpineAnimation.prototype.dispose = function () {
if (this.parent) this.parent.remove (this); this.atlas.dispose ();
};
}) ();
var scene, camera, renderer;
var geometry, material, mesh;
var test;
function load(animation, scale) {
if (test) {
test.dispose ();
}
test = new SpineAnimation (animation, 'data/', scale);
test.addEventListener( SpineAnimation.SKELETON_DATA_LOADED, function () {
var canvas = renderer.domElement;
switch (test.name) {
case 'spineboy':
test.stateData.setMixByName('walk', 'jump', 0.2);
test.stateData.setMixByName('run', 'jump', 0.2);
test.stateData.setMixByName('jump', 'run', 0.2);
test.state.setAnimationByName(0, 'walk', true);
canvas.onmousedown = function () {
test.state.setAnimationByName(0, 'jump', false);
test.state.addAnimationByName(0, 'run', true, 0);
}
break;
case 'hero':
test.stateData.defaultMix = 0.2;
test.stateData.setMixByName('Walk', 'Attack', 0);
test.stateData.setMixByName('Attack', 'Run', 0);
test.stateData.setMixByName('Run', 'Attack', 0);
test.state.setAnimationByName(0, 'Idle', true);
canvas.onmousedown = function () {
var name = test.state.getCurrent(0).animation.name;
if (name == 'Idle') {
test.state.setAnimationByName(0, 'Crouch', true);
} else if (name == 'Crouch') {
test.state.setAnimationByName(0, 'Walk', true);
} else {
test.state.setAnimationByName(0, 'Attack', false);
test.state.addAnimationByName(0, 'Run', true, 0);
}
}
break;
case 'goblins':
test.skeleton.setSkinByName('goblingirl'); // TODO find why spine.Skeleton.prototype.setSkin does not work
test.skeleton.setSlotsToSetupPose();
test.state.setAnimationByName(0, 'walk', true);
canvas.onmousedown = function () {
test.skeleton.setSkinByName(test.skeleton.skin.name == 'goblin' ? 'goblingirl' : 'goblin');
test.skeleton.setSlotsToSetupPose();
}
break;
case 'skeleton':
test.state.setAnimationByName(0, 'walk test', true);
canvas.onmousedown = function () {
var name = test.state.getCurrent(0).animation.name;
if (name == 'walk test') {
test.state.setAnimationByName(0, 'idle test', true);
} else {
test.state.setAnimationByName(0, 'walk test', true);
}
}
break;
}
//test.skeleton.y = -200;
});
mesh.add( test );
}
init();
animate();
function init() {
spine.Bone.yDown = false;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 400;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
load( 'spineboy', 0.4 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
var t = Date.now ();
var a = Math.sin (t * 6e-4);
var b = Math.cos (t * 3e-4);
mesh.rotation.x = a * Math.PI * 0.2;
mesh.rotation.y = b * Math.PI * 0.4;
test.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>