mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 09:08:42 +08:00
[ts] Port of commit 68d262b5: Improved rendering performance when an attachment is fully inside a clipping attachment.
Reuse the original vertices rather than clipping's triangle soup. Removed deprecated clipping methods.
This commit is contained in:
parent
8711e55672
commit
457be16385
@ -652,8 +652,7 @@ export class Skeleton {
|
||||
continue;
|
||||
}
|
||||
if (vertices && triangles) {
|
||||
if (clipper != null && clipper.isClipping()) {
|
||||
clipper.clipTriangles(vertices, triangles, triangles.length);
|
||||
if (clipper != null && clipper.isClipping() && clipper.clipTriangles(vertices, triangles, triangles.length)) {
|
||||
vertices = clipper.clippedVertices;
|
||||
verticesLength = clipper.clippedVertices.length;
|
||||
}
|
||||
|
||||
@ -81,59 +81,18 @@ export class SkeletonClipping {
|
||||
return this.clipAttachment != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.
|
||||
*/
|
||||
clipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number): void;
|
||||
clipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): boolean;
|
||||
clipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number,
|
||||
uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean, stride: number): boolean;
|
||||
clipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number,
|
||||
uvs?: NumberArrayLike, light?: Color, dark?: Color, twoColor?: boolean, stride?: number): boolean {
|
||||
|
||||
/**
|
||||
* @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.
|
||||
*/
|
||||
clipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;
|
||||
|
||||
clipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): void;
|
||||
clipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;
|
||||
clipTriangles (
|
||||
vertices: NumberArrayLike,
|
||||
verticesLengthOrTriangles: number | NumberArrayLike,
|
||||
trianglesOrTrianglesLength: NumberArrayLike | number,
|
||||
trianglesLengthOrUvs?: number | NumberArrayLike,
|
||||
uvsOrLight?: NumberArrayLike | Color,
|
||||
lightOrDark?: Color,
|
||||
darkOrTwoColor?: Color | boolean,
|
||||
twoColorParam?: boolean
|
||||
): void {
|
||||
// Determine which overload is being used
|
||||
let triangles: NumberArrayLike;
|
||||
let trianglesLength: number;
|
||||
let uvs: NumberArrayLike | undefined;
|
||||
let light: Color | undefined;
|
||||
let dark: Color | undefined;
|
||||
let twoColor: boolean | undefined;
|
||||
|
||||
if (typeof verticesLengthOrTriangles === 'number') {
|
||||
triangles = trianglesOrTrianglesLength as NumberArrayLike;
|
||||
trianglesLength = trianglesLengthOrUvs as number;
|
||||
uvs = uvsOrLight as NumberArrayLike;
|
||||
light = lightOrDark as Color | undefined;
|
||||
dark = darkOrTwoColor as Color | undefined;
|
||||
twoColor = twoColorParam;
|
||||
} else {
|
||||
triangles = verticesLengthOrTriangles;
|
||||
trianglesLength = trianglesOrTrianglesLength as number;
|
||||
uvs = trianglesLengthOrUvs as NumberArrayLike;
|
||||
light = uvsOrLight as Color | undefined;
|
||||
dark = lightOrDark as Color | undefined;
|
||||
twoColor = darkOrTwoColor as boolean;
|
||||
}
|
||||
|
||||
if (uvs && light && dark && typeof twoColor === 'boolean')
|
||||
this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor);
|
||||
else
|
||||
this.clipTrianglesNoRender(vertices, triangles, trianglesLength);
|
||||
return (uvs && light && dark && typeof twoColor === 'boolean' && typeof stride === 'number')
|
||||
? this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor, stride)
|
||||
: this.clipTrianglesNoRender(vertices, triangles, trianglesLength);
|
||||
}
|
||||
|
||||
private clipTrianglesNoRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number) {
|
||||
private clipTrianglesNoRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): boolean {
|
||||
|
||||
let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
||||
let clippedTriangles = this.clippedTriangles;
|
||||
@ -143,24 +102,25 @@ export class SkeletonClipping {
|
||||
let index = 0;
|
||||
clippedVertices.length = 0;
|
||||
clippedTriangles.length = 0;
|
||||
let clipOutputItems = null;
|
||||
for (let i = 0; i < trianglesLength; i += 3) {
|
||||
let vertexOffset = triangles[i] << 1;
|
||||
let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
||||
let v = triangles[i] << 1;
|
||||
let x1 = vertices[v], y1 = vertices[v + 1];
|
||||
|
||||
vertexOffset = triangles[i + 1] << 1;
|
||||
let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
||||
v = triangles[i + 1] << 1;
|
||||
let x2 = vertices[v], y2 = vertices[v + 1];
|
||||
|
||||
vertexOffset = triangles[i + 2] << 1;
|
||||
let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
||||
v = triangles[i + 2] << 1;
|
||||
let x3 = vertices[v], y3 = vertices[v + 1];
|
||||
|
||||
for (let p = 0; p < polygonsCount; p++) {
|
||||
let s = clippedVertices.length;
|
||||
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
||||
clipOutputItems = this.clipOutput;
|
||||
let clipOutputLength = clipOutput.length;
|
||||
if (clipOutputLength == 0) continue;
|
||||
|
||||
let clipOutputCount = clipOutputLength >> 1;
|
||||
let clipOutputItems = this.clipOutput;
|
||||
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2);
|
||||
for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) {
|
||||
let x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
|
||||
@ -199,45 +159,46 @@ export class SkeletonClipping {
|
||||
}
|
||||
}
|
||||
}
|
||||
return clipOutputItems != null;
|
||||
}
|
||||
|
||||
private clipTrianglesRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike,
|
||||
light: Color, dark: Color, twoColor: boolean) {
|
||||
light: Color, dark: Color, twoColor: boolean, stride: number): boolean {
|
||||
|
||||
let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
||||
let clippedTriangles = this.clippedTriangles;
|
||||
let polygons = this.clippingPolygons!;
|
||||
let polygonsCount = polygons.length;
|
||||
let vertexSize = twoColor ? 12 : 8;
|
||||
|
||||
let index = 0;
|
||||
clippedVertices.length = 0;
|
||||
clippedTriangles.length = 0;
|
||||
let clipOutputItems = null;
|
||||
for (let i = 0; i < trianglesLength; i += 3) {
|
||||
let vertexOffset = triangles[i] << 1;
|
||||
let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
||||
let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
|
||||
let t = triangles[i];
|
||||
let u1 = uvs[t << 1], v1 = uvs[(t << 1) + 1];
|
||||
let x1 = vertices[t * stride], y1 = vertices[t * stride + 1];
|
||||
|
||||
vertexOffset = triangles[i + 1] << 1;
|
||||
let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
||||
let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
|
||||
t = triangles[i + 1];
|
||||
let u2 = uvs[t << 1], v2 = uvs[(t << 1) + 1];
|
||||
let x2 = vertices[t * stride], y2 = vertices[t * stride + 1];
|
||||
|
||||
vertexOffset = triangles[i + 2] << 1;
|
||||
let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
||||
let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
|
||||
t = triangles[i + 2];
|
||||
let u3 = uvs[t << 1], v3 = uvs[(t << 1) + 1];
|
||||
let x3 = vertices[t * stride], y3 = vertices[t * stride + 1];
|
||||
|
||||
for (let p = 0; p < polygonsCount; p++) {
|
||||
let s = clippedVertices.length;
|
||||
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
||||
clipOutputItems = this.clipOutput;
|
||||
let clipOutputLength = clipOutput.length;
|
||||
if (clipOutputLength == 0) continue;
|
||||
let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
|
||||
let d = 1 / (d0 * d2 + d1 * (y1 - y3));
|
||||
|
||||
let clipOutputCount = clipOutputLength >> 1;
|
||||
let clipOutputItems = this.clipOutput;
|
||||
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
|
||||
for (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) {
|
||||
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * stride);
|
||||
for (let ii = 0; ii < clipOutputLength; ii += 2, s += stride) {
|
||||
let x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
|
||||
clippedVerticesItems[s] = x;
|
||||
clippedVerticesItems[s + 1] = y;
|
||||
@ -270,7 +231,7 @@ export class SkeletonClipping {
|
||||
index += clipOutputCount + 1;
|
||||
|
||||
} else {
|
||||
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
|
||||
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * stride);
|
||||
clippedVerticesItems[s] = x1;
|
||||
clippedVerticesItems[s + 1] = y1;
|
||||
clippedVerticesItems[s + 2] = light.r;
|
||||
@ -343,6 +304,7 @@ export class SkeletonClipping {
|
||||
}
|
||||
}
|
||||
}
|
||||
return clipOutputItems != null;
|
||||
}
|
||||
|
||||
public clipTrianglesUnpacked (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike) {
|
||||
@ -356,17 +318,17 @@ export class SkeletonClipping {
|
||||
clippedUVs.length = 0;
|
||||
clippedTriangles.length = 0;
|
||||
for (let i = 0; i < trianglesLength; i += 3) {
|
||||
let vertexOffset = triangles[i] << 1;
|
||||
let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
||||
let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
|
||||
let v = triangles[i] << 1;
|
||||
let x1 = vertices[v], y1 = vertices[v + 1];
|
||||
let u1 = uvs[v], v1 = uvs[v + 1];
|
||||
|
||||
vertexOffset = triangles[i + 1] << 1;
|
||||
let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
||||
let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
|
||||
v = triangles[i + 1] << 1;
|
||||
let x2 = vertices[v], y2 = vertices[v + 1];
|
||||
let u2 = uvs[v], v2 = uvs[v + 1];
|
||||
|
||||
vertexOffset = triangles[i + 2] << 1;
|
||||
let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
||||
let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
|
||||
v = triangles[i + 2] << 1;
|
||||
let x3 = vertices[v], y3 = vertices[v + 1];
|
||||
let u3 = uvs[v], v3 = uvs[v + 1];
|
||||
|
||||
for (let p = 0; p < polygonsCount; p++) {
|
||||
let s = clippedVertices.length;
|
||||
@ -433,7 +395,7 @@ export class SkeletonClipping {
|
||||
|
||||
/** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping
|
||||
* area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */
|
||||
clip (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>) {
|
||||
private clip (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array<number>, output: Array<number>) {
|
||||
let originalOutput = output;
|
||||
let clipped = false;
|
||||
|
||||
|
||||
@ -659,7 +659,7 @@ export class Spine extends Container {
|
||||
}
|
||||
|
||||
const useDarkColor = slot.darkColor != null;
|
||||
const vertexSize = Spine.clipper.isClipping() ? 2 : useDarkColor ? Spine.DARK_VERTEX_SIZE : Spine.VERTEX_SIZE;
|
||||
const vertexSize = useDarkColor ? Spine.DARK_VERTEX_SIZE : Spine.VERTEX_SIZE;
|
||||
if (!slot.bone.active) {
|
||||
Spine.clipper.clipEndWithSlot(slot);
|
||||
this.pixiMaskCleanup(slot);
|
||||
@ -728,9 +728,7 @@ export class Spine extends Container {
|
||||
let finalIndices: NumberArrayLike;
|
||||
let finalIndicesLength: number;
|
||||
|
||||
if (Spine.clipper.isClipping()) {
|
||||
Spine.clipper.clipTriangles(this.verticesCache, triangles, triangles.length, uvs, this.lightColor, this.darkColor, useDarkColor);
|
||||
|
||||
if (Spine.clipper.isClipping() && Spine.clipper.clipTriangles(this.verticesCache, triangles, triangles.length, uvs, this.lightColor, this.darkColor, useDarkColor, vertexSize)) {
|
||||
finalVertices = Spine.clipper.clippedVertices;
|
||||
finalVerticesLength = finalVertices.length;
|
||||
|
||||
|
||||
@ -101,7 +101,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
||||
static VERTEX_SIZE = 2 + 2 + 4;
|
||||
private vertexSize = 2 + 2 + 4;
|
||||
private twoColorTint;
|
||||
private twoColorTint: boolean;
|
||||
|
||||
private vertices = Utils.newFloatArray(1024);
|
||||
private tempColor = new Color();
|
||||
@ -231,8 +231,8 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
batch.begin();
|
||||
let z = 0;
|
||||
let zOffset = this.zOffset;
|
||||
let vertexSize = this.vertexSize;
|
||||
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
||||
let vertexSize = clipper.isClipping() ? 2 : this.vertexSize;
|
||||
let slot = drawOrder[i];
|
||||
if (!slot.bone.active) {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
@ -243,36 +243,33 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
let texture: ThreeJsTexture | null;
|
||||
let numFloats = 0;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
let region = <RegionAttachment>attachment;
|
||||
attachmentColor = region.color;
|
||||
attachmentColor = attachment.color;
|
||||
vertices = this.vertices;
|
||||
numFloats = vertexSize * 4;
|
||||
region.computeWorldVertices(slot, vertices, 0, vertexSize);
|
||||
attachment.computeWorldVertices(slot, vertices, 0, vertexSize);
|
||||
triangles = SkeletonMesh.QUAD_TRIANGLES;
|
||||
uvs = region.uvs;
|
||||
texture = <ThreeJsTexture>region.region!.texture;
|
||||
uvs = attachment.uvs;
|
||||
texture = <ThreeJsTexture>attachment.region!.texture;
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
attachmentColor = mesh.color;
|
||||
attachmentColor = attachment.color;
|
||||
vertices = this.vertices;
|
||||
numFloats = (mesh.worldVerticesLength >> 1) * vertexSize;
|
||||
numFloats = (attachment.worldVerticesLength >> 1) * vertexSize;
|
||||
if (numFloats > vertices.length) {
|
||||
vertices = this.vertices = Utils.newFloatArray(numFloats);
|
||||
}
|
||||
mesh.computeWorldVertices(
|
||||
attachment.computeWorldVertices(
|
||||
slot,
|
||||
0,
|
||||
mesh.worldVerticesLength,
|
||||
attachment.worldVerticesLength,
|
||||
vertices,
|
||||
0,
|
||||
vertexSize
|
||||
);
|
||||
triangles = mesh.triangles;
|
||||
uvs = mesh.uvs;
|
||||
texture = <ThreeJsTexture>mesh.region!.texture;
|
||||
triangles = attachment.triangles;
|
||||
uvs = attachment.uvs;
|
||||
texture = <ThreeJsTexture>attachment.region!.texture;
|
||||
} else if (attachment instanceof ClippingAttachment) {
|
||||
let clip = <ClippingAttachment>attachment;
|
||||
clipper.clipStart(slot, clip);
|
||||
clipper.clipStart(slot, attachment);
|
||||
continue;
|
||||
} else {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
@ -307,16 +304,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
let finalIndices: NumberArrayLike;
|
||||
let finalIndicesLength: number;
|
||||
|
||||
if (clipper.isClipping()) {
|
||||
clipper.clipTriangles(
|
||||
vertices,
|
||||
triangles,
|
||||
triangles.length,
|
||||
uvs,
|
||||
color,
|
||||
tempLight,
|
||||
this.twoColorTint,
|
||||
);
|
||||
if (clipper.isClipping() && clipper.clipTriangles( vertices, triangles, triangles.length, uvs, color, tempLight, this.twoColorTint, vertexSize)) {
|
||||
let clippedVertices = clipper.clippedVertices;
|
||||
let clippedTriangles = clipper.clippedTriangles;
|
||||
finalVertices = clippedVertices;
|
||||
|
||||
@ -78,7 +78,6 @@ export class SkeletonRenderer {
|
||||
let inRange = false;
|
||||
if (slotRangeStart == -1) inRange = true;
|
||||
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
||||
let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
|
||||
let slot = drawOrder[i];
|
||||
if (!slot.bone.active) {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
@ -101,31 +100,29 @@ export class SkeletonRenderer {
|
||||
let attachment = slot.getAttachment();
|
||||
let texture: GLTexture;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
let region = <RegionAttachment>attachment;
|
||||
renderable.vertices = this.vertices;
|
||||
renderable.numVertices = 4;
|
||||
renderable.numFloats = clippedVertexSize << 2;
|
||||
region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize);
|
||||
renderable.numFloats = vertexSize << 2;
|
||||
attachment.computeWorldVertices(slot, renderable.vertices, 0, vertexSize);
|
||||
triangles = SkeletonRenderer.QUAD_TRIANGLES;
|
||||
uvs = region.uvs;
|
||||
texture = <GLTexture>region.region!.texture;
|
||||
attachmentColor = region.color;
|
||||
uvs = attachment.uvs;
|
||||
texture = <GLTexture>attachment.region!.texture;
|
||||
attachmentColor = attachment.color;
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
renderable.vertices = this.vertices;
|
||||
renderable.numVertices = (mesh.worldVerticesLength >> 1);
|
||||
renderable.numFloats = renderable.numVertices * clippedVertexSize;
|
||||
renderable.numVertices = (attachment.worldVerticesLength >> 1);
|
||||
renderable.numFloats = renderable.numVertices * vertexSize;
|
||||
|
||||
if (renderable.numFloats > renderable.vertices.length) {
|
||||
renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats);
|
||||
}
|
||||
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
|
||||
triangles = mesh.triangles;
|
||||
texture = <GLTexture>mesh.region!.texture;
|
||||
uvs = mesh.uvs;
|
||||
attachmentColor = mesh.color;
|
||||
attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, renderable.vertices, 0, vertexSize);
|
||||
triangles = attachment.triangles;
|
||||
texture = <GLTexture>attachment.region!.texture;
|
||||
uvs = attachment.uvs;
|
||||
attachmentColor = attachment.color;
|
||||
} else if (attachment instanceof ClippingAttachment) {
|
||||
let clip = <ClippingAttachment>(attachment);
|
||||
clipper.clipStart(slot, clip);
|
||||
clipper.clipStart(slot, attachment);
|
||||
continue;
|
||||
} else {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
@ -164,8 +161,7 @@ export class SkeletonRenderer {
|
||||
batcher.setBlendMode(blendMode, premultipliedAlpha);
|
||||
}
|
||||
|
||||
if (clipper.isClipping()) {
|
||||
clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
|
||||
if (clipper.isClipping() && clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint, vertexSize)) {
|
||||
let clippedVertices = new Float32Array(clipper.clippedVertices);
|
||||
let clippedTriangles = clipper.clippedTriangles;
|
||||
if (transformer) transformer(clippedVertices, clippedVertices.length, vertexSize);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user