mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
[ts] THREE.JS backend, revised batching using interleaved buffers, WIP
This commit is contained in:
parent
8536f210ce
commit
b9afff01fd
@ -11,7 +11,7 @@ module spine {
|
||||
}
|
||||
|
||||
abstract setFilters (minFilter: TextureFilter, magFilter: TextureFilter): void;
|
||||
abstract setWraps (uWrap: TextureWrap, vWrap: TextureWrap): void;
|
||||
abstract setWraps (uWrap: TextureWrap, vWrap: TextureWrap): void;
|
||||
abstract dispose (): void;
|
||||
|
||||
|
||||
|
||||
279
spine-ts/threejs/example/assets/raptor.atlas
Normal file
279
spine-ts/threejs/example/assets/raptor.atlas
Normal file
@ -0,0 +1,279 @@
|
||||
|
||||
raptor.png
|
||||
size: 1024,1024
|
||||
format: RGBA8888
|
||||
filter: Linear,Linear
|
||||
repeat: none
|
||||
back_arm
|
||||
rotate: true
|
||||
xy: 140, 191
|
||||
size: 46, 29
|
||||
orig: 46, 29
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
back_bracer
|
||||
rotate: true
|
||||
xy: 167, 317
|
||||
size: 39, 28
|
||||
orig: 39, 28
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
back_hand
|
||||
rotate: false
|
||||
xy: 167, 358
|
||||
size: 36, 34
|
||||
orig: 36, 34
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
back_knee
|
||||
rotate: false
|
||||
xy: 299, 478
|
||||
size: 49, 67
|
||||
orig: 49, 67
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
back_thigh
|
||||
rotate: true
|
||||
xy: 167, 437
|
||||
size: 39, 24
|
||||
orig: 39, 24
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
eyes_closed
|
||||
rotate: true
|
||||
xy: 2, 2
|
||||
size: 47, 45
|
||||
orig: 47, 45
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
eyes_open
|
||||
rotate: true
|
||||
xy: 49, 2
|
||||
size: 47, 45
|
||||
orig: 47, 45
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
eyes_surprised
|
||||
rotate: true
|
||||
xy: 96, 2
|
||||
size: 47, 45
|
||||
orig: 47, 45
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
front_arm
|
||||
rotate: false
|
||||
xy: 419, 544
|
||||
size: 48, 30
|
||||
orig: 48, 30
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
front_bracer
|
||||
rotate: false
|
||||
xy: 880, 695
|
||||
size: 41, 29
|
||||
orig: 41, 29
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
front_hand
|
||||
rotate: true
|
||||
xy: 167, 394
|
||||
size: 41, 38
|
||||
orig: 41, 38
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
front_open_hand
|
||||
rotate: false
|
||||
xy: 880, 726
|
||||
size: 43, 44
|
||||
orig: 43, 44
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
front_thigh
|
||||
rotate: false
|
||||
xy: 360, 545
|
||||
size: 57, 29
|
||||
orig: 57, 29
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
gun
|
||||
rotate: false
|
||||
xy: 785, 774
|
||||
size: 107, 103
|
||||
orig: 107, 103
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
gun_nohand
|
||||
rotate: false
|
||||
xy: 614, 703
|
||||
size: 105, 102
|
||||
orig: 105, 102
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
head
|
||||
rotate: false
|
||||
xy: 2, 137
|
||||
size: 136, 149
|
||||
orig: 136, 149
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
lower_leg
|
||||
rotate: true
|
||||
xy: 780, 699
|
||||
size: 73, 98
|
||||
orig: 73, 98
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
mouth_grind
|
||||
rotate: false
|
||||
xy: 469, 544
|
||||
size: 47, 30
|
||||
orig: 47, 30
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
mouth_oooo
|
||||
rotate: true
|
||||
xy: 894, 772
|
||||
size: 105, 30
|
||||
orig: 105, 30
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
mouth_smile
|
||||
rotate: true
|
||||
xy: 140, 239
|
||||
size: 47, 30
|
||||
orig: 47, 30
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
neck
|
||||
rotate: true
|
||||
xy: 538, 577
|
||||
size: 18, 21
|
||||
orig: 18, 21
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_arm_back
|
||||
rotate: false
|
||||
xy: 940, 936
|
||||
size: 82, 86
|
||||
orig: 82, 86
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_body
|
||||
rotate: false
|
||||
xy: 2, 737
|
||||
size: 610, 285
|
||||
orig: 610, 285
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_front_arm
|
||||
rotate: true
|
||||
xy: 195, 464
|
||||
size: 81, 102
|
||||
orig: 81, 102
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_front_leg
|
||||
rotate: false
|
||||
xy: 2, 478
|
||||
size: 191, 257
|
||||
orig: 191, 257
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_hindleg_back
|
||||
rotate: false
|
||||
xy: 614, 807
|
||||
size: 169, 215
|
||||
orig: 169, 215
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_horn
|
||||
rotate: false
|
||||
xy: 360, 655
|
||||
size: 182, 80
|
||||
orig: 182, 80
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_horn_back
|
||||
rotate: false
|
||||
xy: 360, 576
|
||||
size: 176, 77
|
||||
orig: 176, 77
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_jaw
|
||||
rotate: false
|
||||
xy: 785, 879
|
||||
size: 153, 143
|
||||
orig: 153, 143
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_saddle_noshadow
|
||||
rotate: false
|
||||
xy: 2, 288
|
||||
size: 163, 188
|
||||
orig: 163, 188
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_saddle_strap_front
|
||||
rotate: false
|
||||
xy: 721, 710
|
||||
size: 57, 95
|
||||
orig: 57, 95
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_saddle_strap_rear
|
||||
rotate: true
|
||||
xy: 940, 880
|
||||
size: 54, 74
|
||||
orig: 54, 74
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_saddle_w_shadow
|
||||
rotate: false
|
||||
xy: 195, 547
|
||||
size: 163, 188
|
||||
orig: 163, 188
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
raptor_tongue
|
||||
rotate: true
|
||||
xy: 544, 649
|
||||
size: 86, 64
|
||||
orig: 86, 64
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
stirrup_back
|
||||
rotate: true
|
||||
xy: 140, 145
|
||||
size: 44, 35
|
||||
orig: 44, 35
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
stirrup_front
|
||||
rotate: false
|
||||
xy: 538, 597
|
||||
size: 45, 50
|
||||
orig: 45, 50
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
stirrup_strap
|
||||
rotate: false
|
||||
xy: 350, 497
|
||||
size: 49, 46
|
||||
orig: 49, 46
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
torso
|
||||
rotate: true
|
||||
xy: 610, 647
|
||||
size: 54, 91
|
||||
orig: 54, 91
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
visor
|
||||
rotate: false
|
||||
xy: 2, 51
|
||||
size: 131, 84
|
||||
orig: 131, 84
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
2621
spine-ts/threejs/example/assets/raptor.json
Normal file
2621
spine-ts/threejs/example/assets/raptor.json
Normal file
File diff suppressed because one or more lines are too long
BIN
spine-ts/threejs/example/assets/raptor.png
Normal file
BIN
spine-ts/threejs/example/assets/raptor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 495 KiB |
102
spine-ts/threejs/example/index.html
Normal file
102
spine-ts/threejs/example/index.html
Normal file
@ -0,0 +1,102 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>spine-threejs</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.js"></script>
|
||||
<script src="../../build/spine-threejs.js"></script>
|
||||
|
||||
<style>body, input { font-family: tahoma; font-size: 11pt }</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
|
||||
var scene, camera, renderer;
|
||||
var geometry, material, mesh, skeletonMesh;
|
||||
var assetManager;
|
||||
var lastFrameTime = Date.now();
|
||||
|
||||
function init () {
|
||||
scene = new THREE.Scene();
|
||||
|
||||
var width = 640, height = 480;
|
||||
camera = new THREE.PerspectiveCamera(75, width / height, 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);
|
||||
|
||||
renderer = new THREE.WebGLRenderer();
|
||||
renderer.setSize(width, height);
|
||||
|
||||
document.body.appendChild(renderer.domElement);
|
||||
|
||||
assetManager = new spine.threejs.AssetManager();
|
||||
assetManager.loadText("assets/raptor.json");
|
||||
assetManager.loadText("assets/raptor.atlas");
|
||||
assetManager.loadTexture("assets/raptor.png");
|
||||
|
||||
requestAnimationFrame(load);
|
||||
}
|
||||
|
||||
function load (name, scale) {
|
||||
if (assetManager.isLoadingComplete()) {
|
||||
// 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", 0.4);
|
||||
skeletonMesh = new spine.threejs.SkeletonMesh(skeletonData);
|
||||
skeletonMesh.state.setAnimation(0, "walk", 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 + ".atlas"), function(path) {
|
||||
return assetManager.get("assets/" + path);
|
||||
});
|
||||
|
||||
// Create a TextureAtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
|
||||
atlasLoader = new spine.TextureAtlasAttachmentLoader(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() {
|
||||
var now = Date.now() / 1000;
|
||||
var delta = now - lastFrameTime;
|
||||
lastFrameTime = now;
|
||||
|
||||
var a = Math.sin(now);
|
||||
var b = Math.cos(now);
|
||||
|
||||
mesh.rotation.x = a * Math.PI * 0.2;
|
||||
mesh.rotation.y = b * Math.PI * 0.4;
|
||||
|
||||
skeletonMesh.update(delta);
|
||||
renderer.render(scene, camera);
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
(function() {
|
||||
init();
|
||||
}());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
9
spine-ts/threejs/src/AssetManager.ts
Normal file
9
spine-ts/threejs/src/AssetManager.ts
Normal file
@ -0,0 +1,9 @@
|
||||
module spine.threejs {
|
||||
export class AssetManager extends spine.AssetManager {
|
||||
constructor () {
|
||||
super((image: HTMLImageElement) => {
|
||||
return new ThreeJsTexture(image);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
51
spine-ts/threejs/src/SkeletonMesh.ts
Normal file
51
spine-ts/threejs/src/SkeletonMesh.ts
Normal file
@ -0,0 +1,51 @@
|
||||
module spine.threejs {
|
||||
export class SkeletonMesh extends THREE.Mesh {
|
||||
|
||||
skeleton: Skeleton;
|
||||
state: AnimationState;
|
||||
|
||||
private _vertexBuffer: THREE.InterleavedBuffer;
|
||||
|
||||
constructor (skeletonData: SkeletonData) {
|
||||
super();
|
||||
|
||||
this.skeleton = new Skeleton(skeletonData);
|
||||
let animData = new AnimationStateData(skeletonData);
|
||||
this.state = new AnimationState(animData);
|
||||
|
||||
this.material = new THREE.MeshBasicMaterial();
|
||||
this.material.vertexColors = THREE.VertexColors;
|
||||
|
||||
let geometry: THREE.BufferGeometry = this.geometry = new THREE.BufferGeometry();
|
||||
let vertexBuffer = this._vertexBuffer = new THREE.InterleavedBuffer(new Float32Array(8 * 3 * 10920), 8);
|
||||
vertexBuffer.setDynamic(true);
|
||||
geometry.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 2, 0, false));
|
||||
geometry.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 2, false));
|
||||
geometry.addAttribute("uv", new THREE.InterleavedBufferAttribute(vertexBuffer, 2, 6, false));
|
||||
|
||||
let indexBuffer = new Uint16Array(3 * 10920);
|
||||
geometry.setIndex(new THREE.BufferAttribute(indexBuffer, 1));
|
||||
geometry.getIndex().dynamic = true;
|
||||
this.update(0);
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
let state = this.state;
|
||||
let skeleton = this.skeleton;
|
||||
|
||||
state.update(deltaTime);
|
||||
state.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
|
||||
this.updateGeometry();
|
||||
}
|
||||
|
||||
private updateGeometry() {
|
||||
let geometry = <THREE.BufferGeometry>this.geometry;
|
||||
geometry.drawRange.start = 0;
|
||||
geometry.drawRange.count = 0;
|
||||
this._vertexBuffer.needsUpdate = true;
|
||||
geometry.getIndex().needsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
spine-ts/threejs/src/ThreeJsTexture.ts
Normal file
42
spine-ts/threejs/src/ThreeJsTexture.ts
Normal file
@ -0,0 +1,42 @@
|
||||
module spine.threejs {
|
||||
export class ThreeJsTexture extends Texture {
|
||||
texture: THREE.Texture;
|
||||
|
||||
constructor (image: HTMLImageElement) {
|
||||
super(image);
|
||||
this.texture = new THREE.Texture(image);
|
||||
}
|
||||
|
||||
setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
|
||||
this.texture.minFilter = ThreeJsTexture.toThreeJsTextureFilter(minFilter);
|
||||
this.texture.magFilter = ThreeJsTexture.toThreeJsTextureFilter(magFilter);
|
||||
}
|
||||
|
||||
setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
|
||||
this.texture.wrapS = ThreeJsTexture.toThreeJsTextureWrap(uWrap);
|
||||
this.texture.wrapT = ThreeJsTexture.toThreeJsTextureWrap(vWrap);
|
||||
}
|
||||
|
||||
dispose () {
|
||||
this.texture.dispose();
|
||||
}
|
||||
|
||||
static toThreeJsTextureFilter(filter: TextureFilter) {
|
||||
if (filter === TextureFilter.Linear) return THREE.LinearFilter;
|
||||
else if (filter === TextureFilter.MipMap) return THREE.LinearMipMapLinearFilter;
|
||||
else if (filter === TextureFilter.MipMapLinearLinear) return THREE.LinearMipMapLinearFilter;
|
||||
else if (filter === TextureFilter.MipMapLinearNearest) return THREE.LinearMipMapNearestFilter;
|
||||
else if (filter === TextureFilter.MipMapNearestLinear) return THREE.NearestMipMapLinearFilter;
|
||||
else if (filter === TextureFilter.MipMapNearestNearest) return THREE.NearestMipMapNearestFilter;
|
||||
else if (filter === TextureFilter.Nearest) return THREE.NearestFilter;
|
||||
else throw new Error("Unknown texture filter: " + filter);
|
||||
}
|
||||
|
||||
static toThreeJsTextureWrap(wrap: TextureWrap) {
|
||||
if (wrap === TextureWrap.ClampToEdge) return THREE.ClampToEdgeWrapping;
|
||||
else if (wrap === TextureWrap.MirroredRepeat) return THREE.MirroredRepeatWrapping;
|
||||
else if (wrap === TextureWrap.Repeat) return THREE.RepeatWrapping;
|
||||
else throw new Error("Unknown texture wrap: " + wrap);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user