Merge branch '3.6' into 3.7-beta

This commit is contained in:
badlogic 2018-01-22 16:13:22 +01:00
commit c24990a1c4
21 changed files with 436 additions and 175 deletions

View File

@ -257,6 +257,7 @@
* Fixed renderer to work with 3.6 changes. Two color tinting is not supported.
* Added clipping support
* Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`.
* Added support for multi-page atlases
### Widget backend
* Fixed WebGL context loss (see WebGL backend changes). Enabled automatically.

View File

@ -10,7 +10,7 @@
<groupId>com.esotericsoftware.spine</groupId>
<artifactId>spine-libgdx</artifactId>
<packaging>jar</packaging>
<version>3.7.0.1-SNAPSHOT</version>
<version>3.6.51.2-SNAPSHOT</version>
<name>spine-libgdx</name>
<description>Spine Runtime for libGDX</description>

View File

@ -20,11 +20,11 @@ The Spine Runtimes are developed with the intent to be used with data exported f
spine-ts works with data exported from Spine 3.6.xx.
spine-ts WebGL & Widget backends supports all Spine features.
spine-ts WebGL & Widget backends supports all Spine features.
spine-ts Canvas does not support color tinting, mesh attachments and clipping. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers.
spine-ts Canvas does not support color tinting, mesh attachments and clipping. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers.
spine-ts THREE.JS does not support color tinting, blend modes and clipping. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
spine-ts THREE.JS does not support two color tinting & blend modes. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
spine-ts does not yet support loading the binary format.
@ -115,7 +115,7 @@ You can disable two-color tinting like this:
// If you use SceneRenderer, disable two-color tinting via the last constructor argument
var sceneRenderer = new spine.SceneRenderer(canvas, gl, false);
// If you use SkeletonRenderer and PolygonBatcher directly,
// If you use SkeletonRenderer and PolygonBatcher directly,
// disable two-color tinting in the respective constructor
// and use the shader returned by Shader.newColoredTextured()
// instead of Shader.newTwoColoredTextured()

View File

@ -1703,22 +1703,26 @@ declare module spine.threejs {
}
}
declare module spine.threejs {
class MeshBatcher {
mesh: THREE.Mesh;
class MeshBatcher extends THREE.Mesh {
private static VERTEX_SIZE;
private vertexBuffer;
private vertices;
private verticesLength;
private indices;
private indicesLength;
constructor(mesh: THREE.Mesh, maxVertices?: number);
constructor(maxVertices?: number);
clear(): void;
begin(): void;
canBatch(verticesLength: number, indicesLength: number): boolean;
batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
end(): void;
}
}
declare module spine.threejs {
class SkeletonMesh extends THREE.Mesh {
class SkeletonMeshMaterial extends THREE.ShaderMaterial {
constructor();
}
class SkeletonMesh extends THREE.Object3D {
tempPos: Vector2;
tempUv: Vector2;
tempLight: Color;
@ -1727,7 +1731,8 @@ declare module spine.threejs {
state: AnimationState;
zOffset: number;
vertexEffect: VertexEffect;
private batcher;
private batches;
private nextBatchIndex;
private clipper;
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
@ -1735,6 +1740,8 @@ declare module spine.threejs {
private tempColor;
constructor(skeletonData: SkeletonData);
update(deltaTime: number): void;
private clearBatches();
private nextBatch();
private updateGeometry();
}
}

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
@ -9563,18 +9563,19 @@ var spine;
(function (spine) {
var threejs;
(function (threejs) {
var MeshBatcher = (function () {
function MeshBatcher(mesh, maxVertices) {
var MeshBatcher = (function (_super) {
__extends(MeshBatcher, _super);
function MeshBatcher(maxVertices) {
if (maxVertices === void 0) { maxVertices = 10920; }
this.verticesLength = 0;
this.indicesLength = 0;
var _this = _super.call(this) || this;
_this.verticesLength = 0;
_this.indicesLength = 0;
if (maxVertices > 10920)
throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
var vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
var indices = this.indices = new Uint16Array(maxVertices * 3);
this.mesh = mesh;
var vertices = _this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
var indices = _this.indices = new Uint16Array(maxVertices * 3);
var geo = new THREE.BufferGeometry();
var vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
var vertexBuffer = _this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
vertexBuffer.dynamic = true;
geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
@ -9583,12 +9584,27 @@ var spine;
geo.getIndex().dynamic = true;
geo.drawRange.start = 0;
geo.drawRange.count = 0;
mesh.geometry = geo;
_this.geometry = geo;
_this.material = new threejs.SkeletonMeshMaterial();
return _this;
}
MeshBatcher.prototype.clear = function () {
var geo = this.geometry;
geo.drawRange.start = 0;
geo.drawRange.count = 0;
this.material.uniforms.map.value = null;
};
MeshBatcher.prototype.begin = function () {
this.verticesLength = 0;
this.indicesLength = 0;
};
MeshBatcher.prototype.canBatch = function (verticesLength, indicesLength) {
if (this.indicesLength + indicesLength >= this.indices.byteLength / 2)
return false;
if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2)
return false;
return true;
};
MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
if (z === void 0) { z = 0; }
var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
@ -9616,7 +9632,7 @@ var spine;
this.vertexBuffer.needsUpdate = true;
this.vertexBuffer.updateRange.offset = 0;
this.vertexBuffer.updateRange.count = this.verticesLength;
var geo = this.mesh.geometry;
var geo = this.geometry;
geo.getIndex().needsUpdate = true;
geo.getIndex().updateRange.offset = 0;
geo.getIndex().updateRange.count = this.indicesLength;
@ -9624,7 +9640,7 @@ var spine;
geo.drawRange.count = this.indicesLength;
};
return MeshBatcher;
}());
}(THREE.Mesh));
MeshBatcher.VERTEX_SIZE = 9;
threejs.MeshBatcher = MeshBatcher;
})(threejs = spine.threejs || (spine.threejs = {}));
@ -9633,6 +9649,29 @@ var spine;
(function (spine) {
var threejs;
(function (threejs) {
var SkeletonMeshMaterial = (function (_super) {
__extends(SkeletonMeshMaterial, _super);
function SkeletonMeshMaterial() {
var _this = this;
var vertexShader = "\n\t\t\t\tattribute vec4 color;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvColor = color;\n\t\t\t\t\tgl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);\n\t\t\t\t}\n\t\t\t";
var fragmentShader = "\n\t\t\t\tuniform sampler2D map;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(map, vUv)*vColor;\n\t\t\t\t}\n\t\t\t";
var parameters = {
uniforms: {
map: { type: "t", value: null }
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
transparent: true,
alphaTest: 0.5
};
_this = _super.call(this, parameters) || this;
return _this;
}
;
return SkeletonMeshMaterial;
}(THREE.ShaderMaterial));
threejs.SkeletonMeshMaterial = SkeletonMeshMaterial;
var SkeletonMesh = (function (_super) {
__extends(SkeletonMesh, _super);
function SkeletonMesh(skeletonData) {
@ -9642,17 +9681,14 @@ var spine;
_this.tempLight = new spine.Color();
_this.tempDark = new spine.Color();
_this.zOffset = 0.1;
_this.batches = new Array();
_this.nextBatchIndex = 0;
_this.clipper = new spine.SkeletonClipping();
_this.vertices = spine.Utils.newFloatArray(1024);
_this.tempColor = new spine.Color();
_this.skeleton = new spine.Skeleton(skeletonData);
var animData = new spine.AnimationStateData(skeletonData);
_this.state = new spine.AnimationState(animData);
var material = _this.material = new THREE.MeshBasicMaterial();
material.side = THREE.DoubleSide;
material.transparent = true;
material.alphaTest = 0.5;
_this.batcher = new threejs.MeshBatcher(_this);
return _this;
}
SkeletonMesh.prototype.update = function (deltaTime) {
@ -9663,12 +9699,29 @@ var spine;
skeleton.updateWorldTransform();
this.updateGeometry();
};
SkeletonMesh.prototype.clearBatches = function () {
for (var i = 0; i < this.batches.length; i++) {
this.batches[i].clear();
this.batches[i].visible = false;
}
this.nextBatchIndex = 0;
};
SkeletonMesh.prototype.nextBatch = function () {
if (this.batches.length == this.nextBatchIndex) {
var batch_1 = new threejs.MeshBatcher();
this.add(batch_1);
this.batches.push(batch_1);
}
var batch = this.batches[this.nextBatchIndex++];
batch.visible = true;
return batch;
};
SkeletonMesh.prototype.updateGeometry = function () {
this.clearBatches();
var tempPos = this.tempPos;
var tempUv = this.tempUv;
var tempLight = this.tempLight;
var tempDark = this.tempDark;
var geometry = this.geometry;
var numVertices = 0;
var verticesLength = 0;
var indicesLength = 0;
@ -9678,8 +9731,8 @@ var spine;
var triangles = null;
var uvs = null;
var drawOrder = this.skeleton.drawOrder;
var batcher = this.batcher;
batcher.begin();
var batch = this.nextBatch();
batch.begin();
var z = 0;
var zOffset = this.zOffset;
for (var i = 0, n = drawOrder.length; i < n; i++) {
@ -9720,17 +9773,16 @@ var spine;
else
continue;
if (texture != null) {
if (!this.material.map) {
var mat = this.material;
mat.map = texture.texture;
mat.needsUpdate = true;
}
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
var finalVertices = void 0;
var finalVerticesLength = void 0;
var finalIndices = void 0;
var finalIndicesLength = void 0;
if (clipper.isClipping()) {
clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
var clippedVertices = clipper.clippedVertices;
@ -9756,7 +9808,10 @@ var spine;
verts[v + 7] = tempUv.y;
}
}
batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
finalVertices = clippedVertices;
finalVerticesLength = clippedVertices.length;
finalIndices = clippedTriangles;
finalIndicesLength = clippedTriangles.length;
}
else {
var verts = vertices;
@ -9790,15 +9845,40 @@ var spine;
verts[v + 5] = uvs[u + 1];
}
}
batcher.batch(vertices, numFloats, triangles, triangles.length, z);
finalVertices = vertices;
finalVerticesLength = numFloats;
finalIndices = triangles;
finalIndicesLength = triangles.length;
}
if (finalVerticesLength == 0 || finalIndicesLength == 0)
continue;
if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
batch.end();
batch = this.nextBatch();
batch.begin();
}
var batchMaterial = batch.material;
if (batchMaterial.uniforms.map.value == null) {
batchMaterial.uniforms.map.value = texture.texture;
}
if (batchMaterial.uniforms.map.value != texture.texture) {
batch.end();
batch = this.nextBatch();
batch.begin();
batchMaterial = batch.material;
batchMaterial.uniforms.map.value = texture.texture;
}
batchMaterial.needsUpdate = true;
batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
z += zOffset;
}
clipper.clipEndWithSlot(slot);
}
batcher.end();
clipper.clipEnd();
batch.end();
};
return SkeletonMesh;
}(THREE.Mesh));
}(THREE.Object3D));
SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
threejs.SkeletonMesh = SkeletonMesh;

File diff suppressed because one or more lines are too long

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

File diff suppressed because one or more lines are too long

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

File diff suppressed because one or more lines are too long

View File

@ -1237,22 +1237,26 @@ declare module spine.threejs {
}
}
declare module spine.threejs {
class MeshBatcher {
mesh: THREE.Mesh;
class MeshBatcher extends THREE.Mesh {
private static VERTEX_SIZE;
private vertexBuffer;
private vertices;
private verticesLength;
private indices;
private indicesLength;
constructor(mesh: THREE.Mesh, maxVertices?: number);
constructor(maxVertices?: number);
clear(): void;
begin(): void;
canBatch(verticesLength: number, indicesLength: number): boolean;
batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
end(): void;
}
}
declare module spine.threejs {
class SkeletonMesh extends THREE.Mesh {
class SkeletonMeshMaterial extends THREE.ShaderMaterial {
constructor();
}
class SkeletonMesh extends THREE.Object3D {
tempPos: Vector2;
tempUv: Vector2;
tempLight: Color;
@ -1261,7 +1265,8 @@ declare module spine.threejs {
state: AnimationState;
zOffset: number;
vertexEffect: VertexEffect;
private batcher;
private batches;
private nextBatchIndex;
private clipper;
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
@ -1269,6 +1274,8 @@ declare module spine.threejs {
private tempColor;
constructor(skeletonData: SkeletonData);
update(deltaTime: number): void;
private clearBatches();
private nextBatch();
private updateGeometry();
}
}

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
@ -6734,18 +6734,19 @@ var spine;
(function (spine) {
var threejs;
(function (threejs) {
var MeshBatcher = (function () {
function MeshBatcher(mesh, maxVertices) {
var MeshBatcher = (function (_super) {
__extends(MeshBatcher, _super);
function MeshBatcher(maxVertices) {
if (maxVertices === void 0) { maxVertices = 10920; }
this.verticesLength = 0;
this.indicesLength = 0;
var _this = _super.call(this) || this;
_this.verticesLength = 0;
_this.indicesLength = 0;
if (maxVertices > 10920)
throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
var vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
var indices = this.indices = new Uint16Array(maxVertices * 3);
this.mesh = mesh;
var vertices = _this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
var indices = _this.indices = new Uint16Array(maxVertices * 3);
var geo = new THREE.BufferGeometry();
var vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
var vertexBuffer = _this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
vertexBuffer.dynamic = true;
geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
@ -6754,12 +6755,27 @@ var spine;
geo.getIndex().dynamic = true;
geo.drawRange.start = 0;
geo.drawRange.count = 0;
mesh.geometry = geo;
_this.geometry = geo;
_this.material = new threejs.SkeletonMeshMaterial();
return _this;
}
MeshBatcher.prototype.clear = function () {
var geo = this.geometry;
geo.drawRange.start = 0;
geo.drawRange.count = 0;
this.material.uniforms.map.value = null;
};
MeshBatcher.prototype.begin = function () {
this.verticesLength = 0;
this.indicesLength = 0;
};
MeshBatcher.prototype.canBatch = function (verticesLength, indicesLength) {
if (this.indicesLength + indicesLength >= this.indices.byteLength / 2)
return false;
if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2)
return false;
return true;
};
MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
if (z === void 0) { z = 0; }
var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
@ -6787,7 +6803,7 @@ var spine;
this.vertexBuffer.needsUpdate = true;
this.vertexBuffer.updateRange.offset = 0;
this.vertexBuffer.updateRange.count = this.verticesLength;
var geo = this.mesh.geometry;
var geo = this.geometry;
geo.getIndex().needsUpdate = true;
geo.getIndex().updateRange.offset = 0;
geo.getIndex().updateRange.count = this.indicesLength;
@ -6795,7 +6811,7 @@ var spine;
geo.drawRange.count = this.indicesLength;
};
return MeshBatcher;
}());
}(THREE.Mesh));
MeshBatcher.VERTEX_SIZE = 9;
threejs.MeshBatcher = MeshBatcher;
})(threejs = spine.threejs || (spine.threejs = {}));
@ -6804,6 +6820,29 @@ var spine;
(function (spine) {
var threejs;
(function (threejs) {
var SkeletonMeshMaterial = (function (_super) {
__extends(SkeletonMeshMaterial, _super);
function SkeletonMeshMaterial() {
var _this = this;
var vertexShader = "\n\t\t\t\tattribute vec4 color;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvColor = color;\n\t\t\t\t\tgl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);\n\t\t\t\t}\n\t\t\t";
var fragmentShader = "\n\t\t\t\tuniform sampler2D map;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(map, vUv)*vColor;\n\t\t\t\t}\n\t\t\t";
var parameters = {
uniforms: {
map: { type: "t", value: null }
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
transparent: true,
alphaTest: 0.5
};
_this = _super.call(this, parameters) || this;
return _this;
}
;
return SkeletonMeshMaterial;
}(THREE.ShaderMaterial));
threejs.SkeletonMeshMaterial = SkeletonMeshMaterial;
var SkeletonMesh = (function (_super) {
__extends(SkeletonMesh, _super);
function SkeletonMesh(skeletonData) {
@ -6813,17 +6852,14 @@ var spine;
_this.tempLight = new spine.Color();
_this.tempDark = new spine.Color();
_this.zOffset = 0.1;
_this.batches = new Array();
_this.nextBatchIndex = 0;
_this.clipper = new spine.SkeletonClipping();
_this.vertices = spine.Utils.newFloatArray(1024);
_this.tempColor = new spine.Color();
_this.skeleton = new spine.Skeleton(skeletonData);
var animData = new spine.AnimationStateData(skeletonData);
_this.state = new spine.AnimationState(animData);
var material = _this.material = new THREE.MeshBasicMaterial();
material.side = THREE.DoubleSide;
material.transparent = true;
material.alphaTest = 0.5;
_this.batcher = new threejs.MeshBatcher(_this);
return _this;
}
SkeletonMesh.prototype.update = function (deltaTime) {
@ -6834,12 +6870,29 @@ var spine;
skeleton.updateWorldTransform();
this.updateGeometry();
};
SkeletonMesh.prototype.clearBatches = function () {
for (var i = 0; i < this.batches.length; i++) {
this.batches[i].clear();
this.batches[i].visible = false;
}
this.nextBatchIndex = 0;
};
SkeletonMesh.prototype.nextBatch = function () {
if (this.batches.length == this.nextBatchIndex) {
var batch_1 = new threejs.MeshBatcher();
this.add(batch_1);
this.batches.push(batch_1);
}
var batch = this.batches[this.nextBatchIndex++];
batch.visible = true;
return batch;
};
SkeletonMesh.prototype.updateGeometry = function () {
this.clearBatches();
var tempPos = this.tempPos;
var tempUv = this.tempUv;
var tempLight = this.tempLight;
var tempDark = this.tempDark;
var geometry = this.geometry;
var numVertices = 0;
var verticesLength = 0;
var indicesLength = 0;
@ -6849,8 +6902,8 @@ var spine;
var triangles = null;
var uvs = null;
var drawOrder = this.skeleton.drawOrder;
var batcher = this.batcher;
batcher.begin();
var batch = this.nextBatch();
batch.begin();
var z = 0;
var zOffset = this.zOffset;
for (var i = 0, n = drawOrder.length; i < n; i++) {
@ -6891,17 +6944,16 @@ var spine;
else
continue;
if (texture != null) {
if (!this.material.map) {
var mat = this.material;
mat.map = texture.texture;
mat.needsUpdate = true;
}
var skeleton = slot.bone.skeleton;
var skeletonColor = skeleton.color;
var slotColor = slot.color;
var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
var color = this.tempColor;
color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
var finalVertices = void 0;
var finalVerticesLength = void 0;
var finalIndices = void 0;
var finalIndicesLength = void 0;
if (clipper.isClipping()) {
clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
var clippedVertices = clipper.clippedVertices;
@ -6927,7 +6979,10 @@ var spine;
verts[v + 7] = tempUv.y;
}
}
batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
finalVertices = clippedVertices;
finalVerticesLength = clippedVertices.length;
finalIndices = clippedTriangles;
finalIndicesLength = clippedTriangles.length;
}
else {
var verts = vertices;
@ -6961,15 +7016,40 @@ var spine;
verts[v + 5] = uvs[u + 1];
}
}
batcher.batch(vertices, numFloats, triangles, triangles.length, z);
finalVertices = vertices;
finalVerticesLength = numFloats;
finalIndices = triangles;
finalIndicesLength = triangles.length;
}
if (finalVerticesLength == 0 || finalIndicesLength == 0)
continue;
if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
batch.end();
batch = this.nextBatch();
batch.begin();
}
var batchMaterial = batch.material;
if (batchMaterial.uniforms.map.value == null) {
batchMaterial.uniforms.map.value = texture.texture;
}
if (batchMaterial.uniforms.map.value != texture.texture) {
batch.end();
batch = this.nextBatch();
batch.begin();
batchMaterial = batch.material;
batchMaterial.uniforms.map.value = texture.texture;
}
batchMaterial.needsUpdate = true;
batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
z += zOffset;
}
clipper.clipEndWithSlot(slot);
}
batcher.end();
clipper.clipEnd();
batch.end();
};
return SkeletonMesh;
}(THREE.Mesh));
}(THREE.Object3D));
SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
threejs.SkeletonMesh = SkeletonMesh;

File diff suppressed because one or more lines are too long

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

File diff suppressed because one or more lines are too long

View File

@ -2131,6 +2131,7 @@ var spine;
path = this.pathPrefix + path;
this.toLoad++;
AssetManager.downloadText(path, function (atlasData) {
var pagesLoaded = { count: 0 };
var atlasPages = new Array();
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2151,11 +2152,10 @@ var spine;
return;
}
var _loop_1 = function (atlasPage) {
var pagesLoaded = 0;
var pageLoadError = false;
_this.loadTexture(atlasPage, function (imagePath, image) {
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
var atlas = new spine.TextureAtlas(atlasData, function (path) {
@ -2186,8 +2186,8 @@ var spine;
}
}, function (imagePath, errorMessage) {
pageLoadError = true;
pagesLoaded++;
if (pagesLoaded == atlasPages.length) {
pagesLoaded.count++;
if (pagesLoaded.count == atlasPages.length) {
_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
if (error)
error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

File diff suppressed because one or more lines are too long

View File

@ -147,6 +147,7 @@ module spine {
this.toLoad++;
AssetManager.downloadText(path, (atlasData: string): void => {
var pagesLoaded: any = { count: 0 };
var atlasPages = new Array<string>();
try {
let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
@ -166,12 +167,11 @@ module spine {
}
for (let atlasPage of atlasPages) {
let pagesLoaded = 0;
let pageLoadError = false;
this.loadTexture(atlasPage, (imagePath: string, image: HTMLImageElement) => {
pagesLoaded++;
pagesLoaded.count++;
if (pagesLoaded == atlasPages.length) {
if (pagesLoaded.count == atlasPages.length) {
if (!pageLoadError) {
try {
let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
@ -197,9 +197,9 @@ module spine {
}
}, (imagePath: string, errorMessage: string) => {
pageLoadError = true;
pagesLoaded++;
pagesLoaded.count++;
if (pagesLoaded == atlasPages.length) {
if (pagesLoaded.count == atlasPages.length) {
this.errors[path] = `Couldn't load texture atlas page ${imagePath}} of atlas ${path}`;
if (error) error(path, `Couldn't load texture atlas page ${imagePath} of atlas ${path}`);
this.toLoad--;

View File

@ -19,6 +19,11 @@ var assetManager;
var canvas;
var lastFrameTime = Date.now() / 1000;
var baseUrl = "assets/";
var skeletonFile = "raptor-pro.json";
var atlasFile = skeletonFile.replace("-pro", "").replace("-ess", "").replace(".json", ".atlas");
var animation = "walk";
function init () {
// create the THREE.JS camera, scene and renderer (WebGL)
var width = window.innerWidth, height = window.innerHeight;
@ -32,10 +37,9 @@ function init () {
canvas = renderer.domElement;
// load the assets required to display the Raptor model
assetManager = new spine.threejs.AssetManager();
assetManager.loadText("assets/raptor-pro.json");
assetManager.loadText("assets/raptor.atlas");
assetManager.loadTexture("assets/raptor.png");
assetManager = new spine.threejs.AssetManager(baseUrl);
assetManager.loadText(skeletonFile);
assetManager.loadTextureAtlas(atlasFile);
requestAnimationFrame(load);
}
@ -50,39 +54,27 @@ function load (name, scale) {
// Load the texture atlas using name.atlas and name.png from the AssetManager.
// The function passed to TextureAtlas is used to resolve relative paths.
atlas = new spine.TextureAtlas(assetManager.get("assets/raptor.atlas"), function(path) {
return assetManager.get("assets/" + path);
});
var skeletonData = loadSkeleton("raptor-pro", 0.4);
atlas = assetManager.get(atlasFile);
// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
atlasLoader = new spine.AtlasAttachmentLoader(atlas);
// Create a SkeletonJson instance for parsing the .json file.
var skeletonJson = new spine.SkeletonJson(atlasLoader);
// Set the scale to apply during parsing, parse the file, and create a new skeleton.
skeletonJson.scale = 0.4;
var skeletonData = skeletonJson.readSkeletonData(assetManager.get(skeletonFile));
// Create a SkeletonMesh from the data and attach it to the scene
skeletonMesh = new spine.threejs.SkeletonMesh(skeletonData);
skeletonMesh.state.setAnimation(0, "walk", true);
skeletonMesh.state.setAnimation(0, animation, true);
mesh.add(skeletonMesh);
requestAnimationFrame(render);
} else requestAnimationFrame(load);
}
function loadSkeleton (name, scale) {
// Load the texture atlas using name.atlas and name.png from the AssetManager.
// The function passed to TextureAtlas is used to resolve relative paths.
atlas = new spine.TextureAtlas(assetManager.get("assets/" + name.replace("-pro", "") + ".atlas"), function(path) {
return assetManager.get("assets/" + path);
});
// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
atlasLoader = new spine.AtlasAttachmentLoader(atlas);
// Create a SkeletonJson instance for parsing the .json file.
var skeletonJson = new spine.SkeletonJson(atlasLoader);
// Set the scale to apply during parsing, parse the file, and create a new skeleton.
skeletonJson.scale = scale;
var skeletonData = skeletonJson.readSkeletonData(assetManager.get("assets/" + name + ".json"));
return skeletonData;
}
var lastTime = Date.now();
function render() {
// calculate delta time for animation purposes

View File

@ -29,9 +29,7 @@
*****************************************************************************/
module spine.threejs {
export class MeshBatcher {
mesh: THREE.Mesh;
export class MeshBatcher extends THREE.Mesh {
private static VERTEX_SIZE = 9;
private vertexBuffer: THREE.InterleavedBuffer;
private vertices: Float32Array;
@ -39,12 +37,11 @@ module spine.threejs {
private indices: Uint16Array;
private indicesLength = 0;
constructor (mesh: THREE.Mesh, maxVertices: number = 10920) {
constructor (maxVertices: number = 10920) {
super();
if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
let vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
let indices = this.indices = new Uint16Array(maxVertices * 3);
this.mesh = mesh;
let geo = new THREE.BufferGeometry();
let vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
vertexBuffer.dynamic = true;
@ -55,7 +52,15 @@ module spine.threejs {
geo.getIndex().dynamic = true;
geo.drawRange.start = 0;
geo.drawRange.count = 0;
mesh.geometry = geo;
this.geometry = geo;
this.material = new SkeletonMeshMaterial();
}
clear () {
let geo = (<THREE.BufferGeometry>this.geometry);
geo.drawRange.start = 0;
geo.drawRange.count = 0;
(<SkeletonMeshMaterial>this.material).uniforms.map.value = null;
}
begin () {
@ -63,6 +68,12 @@ module spine.threejs {
this.indicesLength = 0;
}
canBatch(verticesLength: number, indicesLength: number) {
if (this.indicesLength + indicesLength >= this.indices.byteLength / 2) return false;
if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2) return false;
return true;
}
batch (vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z: number = 0) {
let indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
let vertexBuffer = this.vertices;
@ -91,7 +102,7 @@ module spine.threejs {
this.vertexBuffer.needsUpdate = true;
this.vertexBuffer.updateRange.offset = 0;
this.vertexBuffer.updateRange.count = this.verticesLength;
let geo = (<THREE.BufferGeometry>this.mesh.geometry);
let geo = (<THREE.BufferGeometry>this.geometry);
geo.getIndex().needsUpdate = true;
geo.getIndex().updateRange.offset = 0;
geo.getIndex().updateRange.count = this.indicesLength;

View File

@ -29,7 +29,42 @@
*****************************************************************************/
module spine.threejs {
export class SkeletonMesh extends THREE.Mesh {
export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
constructor () {
let vertexShader = `
attribute vec4 color;
varying vec2 vUv;
varying vec4 vColor;
void main() {
vUv = uv;
vColor = color;
gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
}
`;
let fragmentShader = `
uniform sampler2D map;
varying vec2 vUv;
varying vec4 vColor;
void main(void) {
gl_FragColor = texture2D(map, vUv)*vColor;
}
`;
let parameters: THREE.ShaderMaterialParameters = {
uniforms: {
map: { type: "t", value: null }
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
transparent: true,
alphaTest: 0.5
};
super(parameters);
};
}
export class SkeletonMesh extends THREE.Object3D {
tempPos: Vector2 = new Vector2();
tempUv: Vector2 = new Vector2();
tempLight = new Color();
@ -39,7 +74,8 @@ module spine.threejs {
zOffset: number = 0.1;
vertexEffect: VertexEffect;
private batcher: MeshBatcher;
private batches = new Array<MeshBatcher>();
private nextBatchIndex = 0;
private clipper: SkeletonClipping = new SkeletonClipping();
static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
@ -54,12 +90,6 @@ module spine.threejs {
this.skeleton = new Skeleton(skeletonData);
let animData = new AnimationStateData(skeletonData);
this.state = new AnimationState(animData);
let material = this.material = new THREE.MeshBasicMaterial();
material.side = THREE.DoubleSide;
material.transparent = true;
material.alphaTest = 0.5;
this.batcher = new MeshBatcher(this);
}
update(deltaTime: number) {
@ -73,13 +103,33 @@ module spine.threejs {
this.updateGeometry();
}
private clearBatches () {
for (var i = 0; i < this.batches.length; i++) {
this.batches[i].clear();
this.batches[i].visible = false;
}
this.nextBatchIndex = 0;
}
private nextBatch () {
if (this.batches.length == this.nextBatchIndex) {
let batch = new MeshBatcher();
this.add(batch);
this.batches.push(batch);
}
let batch = this.batches[this.nextBatchIndex++];
batch.visible = true;
return batch;
}
private updateGeometry() {
this.clearBatches();
let tempPos = this.tempPos;
let tempUv = this.tempUv;
let tempLight = this.tempLight;
let tempDark = this.tempDark;
let geometry = <THREE.BufferGeometry>this.geometry;
var numVertices = 0;
var verticesLength = 0;
var indicesLength = 0;
@ -91,8 +141,8 @@ module spine.threejs {
let triangles: Array<number> = null;
let uvs: ArrayLike<number> = null;
let drawOrder = this.skeleton.drawOrder;
let batcher = this.batcher;
batcher.begin();
let batch = this.nextBatch();
batch.begin();
let z = 0;
let zOffset = this.zOffset;
for (let i = 0, n = drawOrder.length; i < n; i++) {
@ -130,12 +180,6 @@ module spine.threejs {
} else continue;
if (texture != null) {
if (!(<THREE.MeshBasicMaterial>this.material).map) {
let mat = <THREE.MeshBasicMaterial>this.material;
mat.map = texture.texture;
mat.needsUpdate = true;
}
let skeleton = slot.bone.skeleton;
let skeletonColor = skeleton.color;
let slotColor = slot.color;
@ -145,12 +189,11 @@ module spine.threejs {
skeletonColor.g * slotColor.g * attachmentColor.g,
skeletonColor.b * slotColor.b * attachmentColor.b,
alpha);
// FIXME per slot blending would require multiple material support
//let slotBlendMode = slot.data.blendMode;
//if (slotBlendMode != blendMode) {
// blendMode = slotBlendMode;
// batcher.setBlendMode(getSourceGLBlendMode(this._gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this._gl, blendMode));
//}
let finalVertices: ArrayLike<number>;
let finalVerticesLength: number;
let finalIndices: ArrayLike<number>;
let finalIndicesLength: number;
if (clipper.isClipping()) {
clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
@ -177,7 +220,10 @@ module spine.threejs {
verts[v + 7] = tempUv.y;
}
}
batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
finalVertices = clippedVertices;
finalVerticesLength = clippedVertices.length;
finalIndices = clippedTriangles;
finalIndicesLength = clippedTriangles.length;
} else {
let verts = vertices;
if (this.vertexEffect != null) {
@ -209,13 +255,50 @@ module spine.threejs {
verts[v + 5] = uvs[u + 1];
}
}
batcher.batch(vertices, numFloats, triangles, triangles.length, z);
finalVertices = vertices;
finalVerticesLength = numFloats;
finalIndices = triangles;
finalIndicesLength = triangles.length;
}
if (finalVerticesLength == 0 || finalIndicesLength == 0)
continue;
// Start new batch if this one can't hold vertices/indices
if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
batch.end();
batch = this.nextBatch();
batch.begin();
}
// FIXME per slot blending would require multiple material support
//let slotBlendMode = slot.data.blendMode;
//if (slotBlendMode != blendMode) {
// blendMode = slotBlendMode;
// batcher.setBlendMode(getSourceGLBlendMode(this._gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this._gl, blendMode));
//}
let batchMaterial = <SkeletonMeshMaterial>batch.material;
if (batchMaterial.uniforms.map.value == null) {
batchMaterial.uniforms.map.value = texture.texture;
}
if (batchMaterial.uniforms.map.value != texture.texture) {
batch.end();
batch = this.nextBatch();
batch.begin();
batchMaterial = <SkeletonMeshMaterial>batch.material;
batchMaterial.uniforms.map.value = texture.texture;
}
batchMaterial.needsUpdate = true;
batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
z += zOffset;
}
}
batcher.end();
clipper.clipEndWithSlot(slot);
}
clipper.clipEnd();
batch.end();
}
}
}