mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
Refactored attachments to fill an array rather than store vertices for rendering.
This commit is contained in:
parent
66b5f49f2e
commit
938db42016
@ -211,14 +211,14 @@ public class PathConstraint implements Constraint {
|
||||
} else if (p < 0) {
|
||||
if (prevCurve != BEFORE) {
|
||||
prevCurve = BEFORE;
|
||||
path.computeWorldVertices(target, 2, 4, world, 0);
|
||||
path.computeWorldVertices(target, 2, 4, world, 0, 2);
|
||||
}
|
||||
addBeforePosition(p, world, 0, out, o);
|
||||
continue;
|
||||
} else if (p > pathLength) {
|
||||
if (prevCurve != AFTER) {
|
||||
prevCurve = AFTER;
|
||||
path.computeWorldVertices(target, verticesLength - 6, 4, world, 0);
|
||||
path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
|
||||
}
|
||||
addAfterPosition(p - pathLength, world, 0, out, o);
|
||||
continue;
|
||||
@ -239,10 +239,10 @@ public class PathConstraint implements Constraint {
|
||||
if (curve != prevCurve) {
|
||||
prevCurve = curve;
|
||||
if (closed && curve == curveCount) {
|
||||
path.computeWorldVertices(target, verticesLength - 4, 4, world, 0);
|
||||
path.computeWorldVertices(target, 0, 4, world, 4);
|
||||
path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
|
||||
path.computeWorldVertices(target, 0, 4, world, 4, 2);
|
||||
} else
|
||||
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0);
|
||||
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
|
||||
}
|
||||
addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
|
||||
tangents || (i > 0 && space == 0));
|
||||
@ -254,15 +254,15 @@ public class PathConstraint implements Constraint {
|
||||
if (closed) {
|
||||
verticesLength += 2;
|
||||
world = this.world.setSize(verticesLength);
|
||||
path.computeWorldVertices(target, 2, verticesLength - 4, world, 0);
|
||||
path.computeWorldVertices(target, 0, 2, world, verticesLength - 4);
|
||||
path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
|
||||
path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
|
||||
world[verticesLength - 2] = world[0];
|
||||
world[verticesLength - 1] = world[1];
|
||||
} else {
|
||||
curveCount--;
|
||||
verticesLength -= 4;
|
||||
world = this.world.setSize(verticesLength);
|
||||
path.computeWorldVertices(target, 2, verticesLength, world, 0);
|
||||
path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
|
||||
}
|
||||
|
||||
// Curve lengths.
|
||||
|
||||
@ -33,6 +33,7 @@ package com.esotericsoftware.spine;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.ObjectMap.Entry;
|
||||
import com.esotericsoftware.spine.Skin.Key;
|
||||
import com.esotericsoftware.spine.attachments.Attachment;
|
||||
@ -565,22 +566,30 @@ public class Skeleton {
|
||||
|
||||
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
||||
* @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.
|
||||
* @param size An output value, the width and height of the AABB. */
|
||||
public void getBounds (Vector2 offset, Vector2 size) {
|
||||
* @param size An output value, the width and height of the AABB.
|
||||
* @param temp Working memory. */
|
||||
public void getBounds (Vector2 offset, Vector2 size, FloatArray temp) {
|
||||
if (offset == null) throw new IllegalArgumentException("offset cannot be null.");
|
||||
if (size == null) throw new IllegalArgumentException("size cannot be null.");
|
||||
Array<Slot> drawOrder = this.drawOrder;
|
||||
float minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
|
||||
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
||||
Slot slot = drawOrder.get(i);
|
||||
int verticesLength = 0;
|
||||
float[] vertices = null;
|
||||
Attachment attachment = slot.attachment;
|
||||
if (attachment instanceof RegionAttachment)
|
||||
vertices = ((RegionAttachment)attachment).updateWorldVertices(slot, false);
|
||||
else if (attachment instanceof MeshAttachment) //
|
||||
vertices = ((MeshAttachment)attachment).updateWorldVertices(slot, true);
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
verticesLength = 8;
|
||||
vertices = temp.setSize(8);
|
||||
((RegionAttachment)attachment).computeWorldVertices(slot, vertices, 0, 2);
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
MeshAttachment mesh = (MeshAttachment)attachment;
|
||||
verticesLength = mesh.getWorldVerticesLength();
|
||||
vertices = temp.setSize(verticesLength);
|
||||
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
|
||||
}
|
||||
if (vertices != null) {
|
||||
for (int ii = 0, nn = vertices.length; ii < nn; ii += 5) {
|
||||
for (int ii = 0; ii < verticesLength; ii += 2) {
|
||||
float x = vertices[ii], y = vertices[ii + 1];
|
||||
minX = Math.min(minX, x);
|
||||
minY = Math.min(minY, y);
|
||||
|
||||
@ -72,7 +72,8 @@ public class SkeletonBounds {
|
||||
|
||||
FloatArray polygon = polygonPool.obtain();
|
||||
polygons.add(polygon);
|
||||
boundingBox.computeWorldVertices(slot, polygon.setSize(boundingBox.getWorldVerticesLength()));
|
||||
boundingBox.computeWorldVertices(slot, 0, boundingBox.getWorldVerticesLength(),
|
||||
polygon.setSize(boundingBox.getWorldVerticesLength()), 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -30,9 +30,12 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.NumberUtils;
|
||||
import com.esotericsoftware.spine.attachments.Attachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||
@ -41,29 +44,41 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
public class SkeletonMeshRenderer extends SkeletonRenderer<PolygonSpriteBatch> {
|
||||
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
private final FloatArray vertices = new FloatArray(32);
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public void draw (PolygonSpriteBatch batch, Skeleton skeleton) {
|
||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||
BlendMode blendMode = null;
|
||||
|
||||
float[] vertices = null;
|
||||
int verticesLength = 0;
|
||||
float[] vertices = null, uvs = null;
|
||||
short[] triangles = null;
|
||||
Texture texture = null;
|
||||
Color color = null, skeletonColor = skeleton.color;
|
||||
Array<Slot> drawOrder = skeleton.drawOrder;
|
||||
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
||||
Slot slot = drawOrder.get(i);
|
||||
Attachment attachment = slot.attachment;
|
||||
Texture texture = null;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
RegionAttachment region = (RegionAttachment)attachment;
|
||||
vertices = region.updateWorldVertices(slot, premultipliedAlpha);
|
||||
verticesLength = 20;
|
||||
vertices = this.vertices.items;
|
||||
region.computeWorldVertices(slot, vertices, 0, 5);
|
||||
triangles = quadTriangles;
|
||||
texture = region.getRegion().getTexture();
|
||||
uvs = region.getUVs();
|
||||
color = region.getColor();
|
||||
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
MeshAttachment mesh = (MeshAttachment)attachment;
|
||||
vertices = mesh.updateWorldVertices(slot, premultipliedAlpha);
|
||||
verticesLength = (mesh.getWorldVerticesLength() >> 1) * 5;
|
||||
vertices = this.vertices.setSize(verticesLength);
|
||||
mesh.computeWorldVertices(slot, 0, mesh.getWorldVerticesLength(), vertices, 0, 5);
|
||||
triangles = mesh.getTriangles();
|
||||
texture = mesh.getRegion().getTexture();
|
||||
uvs = mesh.getUVs();
|
||||
color = mesh.getColor();
|
||||
|
||||
} else if (attachment instanceof SkeletonAttachment) {
|
||||
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
|
||||
@ -76,7 +91,7 @@ public class SkeletonMeshRenderer extends SkeletonRenderer<PolygonSpriteBatch> {
|
||||
attachmentSkeleton.setPosition(bone.getWorldX(), bone.getWorldY());
|
||||
// rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
|
||||
// rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
|
||||
// Set shear.
|
||||
// Also set shear.
|
||||
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
|
||||
attachmentSkeleton.updateWorldTransform();
|
||||
|
||||
@ -89,6 +104,18 @@ public class SkeletonMeshRenderer extends SkeletonRenderer<PolygonSpriteBatch> {
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
Color slotColor = slot.getColor();
|
||||
float alpha = skeletonColor.a * slotColor.a * color.a * 255;
|
||||
float c = NumberUtils.intToFloatColor(((int)alpha << 24) //
|
||||
| ((int)(skeletonColor.b * slotColor.b * color.b * alpha) << 16) //
|
||||
| ((int)(skeletonColor.g * slotColor.g * color.g * alpha) << 8) //
|
||||
| (int)(skeletonColor.r * slotColor.r * color.r * alpha));
|
||||
for (int v = 2, u = 0; v < verticesLength; v += 5, u += 2) {
|
||||
vertices[v] = c;
|
||||
vertices[v + 1] = uvs[u];
|
||||
vertices[v + 2] = uvs[u + 1];
|
||||
}
|
||||
|
||||
BlendMode slotBlendMode = slot.data.getBlendMode();
|
||||
if (slotBlendMode != blendMode) {
|
||||
blendMode = slotBlendMode;
|
||||
|
||||
@ -30,29 +30,47 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.NumberUtils;
|
||||
import com.esotericsoftware.spine.attachments.Attachment;
|
||||
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
|
||||
public class SkeletonRenderer<T extends Batch> {
|
||||
boolean premultipliedAlpha;
|
||||
private final float[] vertices = new float[20];
|
||||
|
||||
public void draw (T batch, Skeleton skeleton) {
|
||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||
|
||||
float[] vertices = this.vertices;
|
||||
Color skeletonColor = skeleton.color;
|
||||
Array<Slot> drawOrder = skeleton.drawOrder;
|
||||
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
||||
Slot slot = drawOrder.get(i);
|
||||
Attachment attachment = slot.attachment;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||
float[] vertices = regionAttachment.updateWorldVertices(slot, premultipliedAlpha);
|
||||
RegionAttachment region = (RegionAttachment)attachment;
|
||||
region.computeWorldVertices(slot, vertices, 0, 5);
|
||||
Color color = region.getColor(), slotColor = slot.getColor();
|
||||
float alpha = skeletonColor.a * slotColor.a * color.a * 255;
|
||||
float c = NumberUtils.intToFloatColor(((int)alpha << 24) //
|
||||
| ((int)(skeletonColor.b * slotColor.b * color.b * alpha) << 16) //
|
||||
| ((int)(skeletonColor.g * slotColor.g * color.g * alpha) << 8) //
|
||||
| (int)(skeletonColor.r * slotColor.r * color.r * alpha));
|
||||
float[] uvs = region.getUVs();
|
||||
for (int u = 0, v = 2; u < 8; u += 2, v += 5) {
|
||||
vertices[v] = c;
|
||||
vertices[v + 1] = uvs[u];
|
||||
vertices[v + 2] = uvs[u + 1];
|
||||
}
|
||||
|
||||
BlendMode blendMode = slot.data.getBlendMode();
|
||||
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
|
||||
batch.draw(regionAttachment.getRegion().getTexture(), vertices, 0, 20);
|
||||
batch.draw(region.getRegion().getTexture(), vertices, 0, 20);
|
||||
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
throw new RuntimeException("SkeletonMeshRenderer is required to render meshes.");
|
||||
|
||||
@ -30,8 +30,6 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import static com.badlogic.gdx.graphics.g2d.Batch.*;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
@ -56,7 +54,7 @@ public class SkeletonRendererDebug {
|
||||
private boolean drawBones = true, drawRegionAttachments = true, drawBoundingBoxes = true;
|
||||
private boolean drawMeshHull = true, drawMeshTriangles = true, drawPaths = true;
|
||||
private final SkeletonBounds bounds = new SkeletonBounds();
|
||||
private final FloatArray temp = new FloatArray();
|
||||
private final FloatArray vertices = new FloatArray(32);
|
||||
private float scale = 1;
|
||||
private float boneWidth = 2;
|
||||
private boolean premultipliedAlpha;
|
||||
@ -106,12 +104,13 @@ public class SkeletonRendererDebug {
|
||||
Slot slot = slots.get(i);
|
||||
Attachment attachment = slot.attachment;
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||
float[] vertices = regionAttachment.updateWorldVertices(slot, false);
|
||||
shapes.line(vertices[X1], vertices[Y1], vertices[X2], vertices[Y2]);
|
||||
shapes.line(vertices[X2], vertices[Y2], vertices[X3], vertices[Y3]);
|
||||
shapes.line(vertices[X3], vertices[Y3], vertices[X4], vertices[Y4]);
|
||||
shapes.line(vertices[X4], vertices[Y4], vertices[X1], vertices[Y1]);
|
||||
RegionAttachment region = (RegionAttachment)attachment;
|
||||
float[] vertices = this.vertices.items;
|
||||
region.computeWorldVertices(slot, vertices, 0, 2);
|
||||
shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]);
|
||||
shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]);
|
||||
shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]);
|
||||
shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,14 +122,14 @@ public class SkeletonRendererDebug {
|
||||
Attachment attachment = slot.attachment;
|
||||
if (!(attachment instanceof MeshAttachment)) continue;
|
||||
MeshAttachment mesh = (MeshAttachment)attachment;
|
||||
mesh.updateWorldVertices(slot, false);
|
||||
float[] vertices = mesh.getWorldVertices();
|
||||
float[] vertices = this.vertices.setSize(mesh.getWorldVerticesLength());
|
||||
mesh.computeWorldVertices(slot, 0, mesh.getWorldVerticesLength(), vertices, 0, 2);
|
||||
short[] triangles = mesh.getTriangles();
|
||||
int hullLength = mesh.getHullLength();
|
||||
if (drawMeshTriangles) {
|
||||
shapes.setColor(triangleLineColor);
|
||||
for (int ii = 0, nn = triangles.length; ii < nn; ii += 3) {
|
||||
int v1 = triangles[ii] * 5, v2 = triangles[ii + 1] * 5, v3 = triangles[ii + 2] * 5;
|
||||
int v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2;
|
||||
shapes.triangle(vertices[v1], vertices[v1 + 1], //
|
||||
vertices[v2], vertices[v2 + 1], //
|
||||
vertices[v3], vertices[v3 + 1] //
|
||||
@ -139,8 +138,7 @@ public class SkeletonRendererDebug {
|
||||
}
|
||||
if (drawMeshHull && hullLength > 0) {
|
||||
shapes.setColor(attachmentLineColor);
|
||||
hullLength = (hullLength >> 1) * 5;
|
||||
float lastX = vertices[hullLength - 5], lastY = vertices[hullLength - 4];
|
||||
float lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1];
|
||||
for (int ii = 0, nn = hullLength; ii < nn; ii += 5) {
|
||||
float x = vertices[ii], y = vertices[ii + 1];
|
||||
shapes.line(x, y, lastX, lastY);
|
||||
@ -173,15 +171,15 @@ public class SkeletonRendererDebug {
|
||||
if (!(attachment instanceof PathAttachment)) continue;
|
||||
PathAttachment path = (PathAttachment)attachment;
|
||||
int nn = path.getWorldVerticesLength();
|
||||
float[] world = temp.setSize(nn);
|
||||
path.computeWorldVertices(slot, world);
|
||||
float[] vertices = this.vertices.setSize(nn);
|
||||
path.computeWorldVertices(slot, 0, nn, vertices, 0, 2);
|
||||
Color color = path.getColor();
|
||||
float x1 = world[2], y1 = world[3], x2 = 0, y2 = 0;
|
||||
float x1 = vertices[2], y1 = vertices[3], x2 = 0, y2 = 0;
|
||||
if (path.getClosed()) {
|
||||
shapes.setColor(color);
|
||||
float cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1];
|
||||
x2 = world[nn - 4];
|
||||
y2 = world[nn - 3];
|
||||
float cx1 = vertices[0], cy1 = vertices[1], cx2 = vertices[nn - 2], cy2 = vertices[nn - 1];
|
||||
x2 = vertices[nn - 4];
|
||||
y2 = vertices[nn - 3];
|
||||
shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);
|
||||
shapes.setColor(Color.LIGHT_GRAY);
|
||||
shapes.line(x1, y1, cx1, cy1);
|
||||
@ -189,9 +187,9 @@ public class SkeletonRendererDebug {
|
||||
}
|
||||
nn -= 4;
|
||||
for (int ii = 4; ii < nn; ii += 6) {
|
||||
float cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3];
|
||||
x2 = world[ii + 4];
|
||||
y2 = world[ii + 5];
|
||||
float cx1 = vertices[ii], cy1 = vertices[ii + 1], cx2 = vertices[ii + 2], cy2 = vertices[ii + 3];
|
||||
x2 = vertices[ii + 4];
|
||||
y2 = vertices[ii + 5];
|
||||
shapes.setColor(color);
|
||||
shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);
|
||||
shapes.setColor(Color.LIGHT_GRAY);
|
||||
|
||||
@ -115,7 +115,7 @@ public class Slot {
|
||||
/** Vertices to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a
|
||||
* weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions.
|
||||
* <p>
|
||||
* See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int)} and {@link DeformTimeline}. */
|
||||
* See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int, int)} and {@link DeformTimeline}. */
|
||||
public FloatArray getAttachmentVertices () {
|
||||
return attachmentVertices;
|
||||
}
|
||||
|
||||
@ -33,12 +33,7 @@ package com.esotericsoftware.spine.attachments;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.NumberUtils;
|
||||
import com.esotericsoftware.spine.Animation.DeformTimeline;
|
||||
import com.esotericsoftware.spine.Bone;
|
||||
import com.esotericsoftware.spine.Skeleton;
|
||||
import com.esotericsoftware.spine.Slot;
|
||||
|
||||
/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not
|
||||
* supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh.
|
||||
@ -47,7 +42,7 @@ import com.esotericsoftware.spine.Slot;
|
||||
public class MeshAttachment extends VertexAttachment {
|
||||
private TextureRegion region;
|
||||
private String path;
|
||||
private float[] regionUVs, worldVertices;
|
||||
private float[] regionUVs, uvs;
|
||||
private short[] triangles;
|
||||
private final Color color = new Color(1, 1, 1, 1);
|
||||
private int hullLength;
|
||||
@ -72,14 +67,9 @@ public class MeshAttachment extends VertexAttachment {
|
||||
return region;
|
||||
}
|
||||
|
||||
/** Calculates {@link #worldVertices} UVs using {@link #regionUVs} and the {@link #region}. Must be called after changing the
|
||||
* region UVs or region. */
|
||||
/** Calculates {@link #uvs} using {@link #regionUVs} and the {@link #region}. Must be called after changing the region UVs or
|
||||
* region. */
|
||||
public void updateUVs () {
|
||||
float[] regionUVs = this.regionUVs;
|
||||
int verticesLength = regionUVs.length;
|
||||
int worldVerticesLength = (verticesLength >> 1) * 5;
|
||||
if (worldVertices == null || worldVertices.length != worldVerticesLength) worldVertices = new float[worldVerticesLength];
|
||||
|
||||
float u, v, width, height;
|
||||
if (region == null) {
|
||||
u = v = 0;
|
||||
@ -90,92 +80,28 @@ public class MeshAttachment extends VertexAttachment {
|
||||
width = region.getU2() - u;
|
||||
height = region.getV2() - v;
|
||||
}
|
||||
float[] regionUVs = this.regionUVs;
|
||||
if (this.uvs == null || this.uvs.length != regionUVs.length) this.uvs = new float[regionUVs.length];
|
||||
float[] uvs = this.uvs;
|
||||
if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) {
|
||||
for (int i = 0, w = 3; i < verticesLength; i += 2, w += 5) {
|
||||
worldVertices[w] = u + regionUVs[i + 1] * width;
|
||||
worldVertices[w + 1] = v + height - regionUVs[i] * height;
|
||||
for (int i = 0, n = uvs.length; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i + 1] * width;
|
||||
uvs[i + 1] = v + height - regionUVs[i] * height;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0, w = 3; i < verticesLength; i += 2, w += 5) {
|
||||
worldVertices[w] = u + regionUVs[i] * width;
|
||||
worldVertices[w + 1] = v + regionUVs[i + 1] * height;
|
||||
for (int i = 0, n = uvs.length; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i] * width;
|
||||
uvs[i + 1] = v + regionUVs[i + 1] * height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return The updated world vertices. */
|
||||
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||
Skeleton skeleton = slot.getSkeleton();
|
||||
Color skeletonColor = skeleton.getColor(), slotColor = slot.getColor(), meshColor = color;
|
||||
float alpha = skeletonColor.a * slotColor.a * meshColor.a * 255;
|
||||
float multiplier = premultipliedAlpha ? alpha : 255;
|
||||
float color = NumberUtils.intToFloatColor( //
|
||||
((int)alpha << 24) //
|
||||
| ((int)(skeletonColor.b * slotColor.b * meshColor.b * multiplier) << 16) //
|
||||
| ((int)(skeletonColor.g * slotColor.g * meshColor.g * multiplier) << 8) //
|
||||
| (int)(skeletonColor.r * slotColor.r * meshColor.r * multiplier));
|
||||
|
||||
FloatArray deformArray = slot.getAttachmentVertices();
|
||||
float[] vertices = this.vertices, worldVertices = this.worldVertices;
|
||||
int[] bones = this.bones;
|
||||
if (bones == null) {
|
||||
int verticesLength = vertices.length;
|
||||
if (deformArray.size > 0) vertices = deformArray.items;
|
||||
Bone bone = slot.getBone();
|
||||
float x = bone.getWorldX(), y = bone.getWorldY();
|
||||
float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD();
|
||||
for (int v = 0, w = 0; v < verticesLength; v += 2, w += 5) {
|
||||
float vx = vertices[v], vy = vertices[v + 1];
|
||||
worldVertices[w] = vx * a + vy * b + x;
|
||||
worldVertices[w + 1] = vx * c + vy * d + y;
|
||||
worldVertices[w + 2] = color;
|
||||
}
|
||||
return worldVertices;
|
||||
}
|
||||
Object[] skeletonBones = skeleton.getBones().items;
|
||||
if (deformArray.size == 0) {
|
||||
for (int w = 0, v = 0, b = 0, n = bones.length; v < n; w += 5) {
|
||||
float wx = 0, wy = 0;
|
||||
int nn = bones[v++] + v;
|
||||
for (; v < nn; v++, b += 3) {
|
||||
Bone bone = (Bone)skeletonBones[bones[v]];
|
||||
float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
worldVertices[w + 2] = color;
|
||||
}
|
||||
} else {
|
||||
float[] deform = deformArray.items;
|
||||
for (int w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 5) {
|
||||
float wx = 0, wy = 0;
|
||||
int nn = bones[v++] + v;
|
||||
for (; v < nn; v++, b += 3, f += 2) {
|
||||
Bone bone = (Bone)skeletonBones[bones[v]];
|
||||
float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
worldVertices[w + 2] = color;
|
||||
}
|
||||
}
|
||||
return worldVertices;
|
||||
}
|
||||
|
||||
/** Returns true if the <code>sourceAttachment</code> is this mesh, else returns true if {@link #inheritDeform} is true and the
|
||||
* the <code>sourceAttachment</code> is the {@link #parentMesh}. */
|
||||
public boolean applyDeform (VertexAttachment sourceAttachment) {
|
||||
return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment);
|
||||
}
|
||||
|
||||
public float[] getWorldVertices () {
|
||||
return worldVertices;
|
||||
}
|
||||
|
||||
/** Triplets of vertex indices which describe the mesh's triangulation. */
|
||||
public short[] getTriangles () {
|
||||
return triangles;
|
||||
@ -185,6 +111,7 @@ public class MeshAttachment extends VertexAttachment {
|
||||
this.triangles = triangles;
|
||||
}
|
||||
|
||||
/** The UV pair for each vertex, normalized within the texture region. */
|
||||
public float[] getRegionUVs () {
|
||||
return regionUVs;
|
||||
}
|
||||
@ -194,6 +121,17 @@ public class MeshAttachment extends VertexAttachment {
|
||||
this.regionUVs = regionUVs;
|
||||
}
|
||||
|
||||
/** The UV pair for each vertex, normalized within the entire texture.
|
||||
* <p>
|
||||
* See {@link #updateUVs}. */
|
||||
public float[] getUVs () {
|
||||
return uvs;
|
||||
}
|
||||
|
||||
public void setUVs (float[] uvs) {
|
||||
this.uvs = uvs;
|
||||
}
|
||||
|
||||
/** The color to tint the mesh. */
|
||||
public Color getColor () {
|
||||
return color;
|
||||
|
||||
@ -30,15 +30,11 @@
|
||||
|
||||
package com.esotericsoftware.spine.attachments;
|
||||
|
||||
import static com.badlogic.gdx.graphics.g2d.Batch.*;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.NumberUtils;
|
||||
import com.esotericsoftware.spine.Bone;
|
||||
import com.esotericsoftware.spine.Skeleton;
|
||||
import com.esotericsoftware.spine.Slot;
|
||||
|
||||
/** An attachment that displays a textured quadrilateral.
|
||||
@ -57,7 +53,7 @@ public class RegionAttachment extends Attachment {
|
||||
private TextureRegion region;
|
||||
private String path;
|
||||
private float x, y, scaleX = 1, scaleY = 1, rotation, width, height;
|
||||
private final float[] vertices = new float[20];
|
||||
private final float[] uvs = new float[8];
|
||||
private final float[] offset = new float[8];
|
||||
private final Color color = new Color(1, 1, 1, 1);
|
||||
|
||||
@ -120,25 +116,25 @@ public class RegionAttachment extends Attachment {
|
||||
public void setRegion (TextureRegion region) {
|
||||
if (region == null) throw new IllegalArgumentException("region cannot be null.");
|
||||
this.region = region;
|
||||
float[] vertices = this.vertices;
|
||||
float[] uvs = this.uvs;
|
||||
if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) {
|
||||
vertices[U3] = region.getU();
|
||||
vertices[V3] = region.getV2();
|
||||
vertices[U4] = region.getU();
|
||||
vertices[V4] = region.getV();
|
||||
vertices[U1] = region.getU2();
|
||||
vertices[V1] = region.getV();
|
||||
vertices[U2] = region.getU2();
|
||||
vertices[V2] = region.getV2();
|
||||
uvs[4] = region.getU();
|
||||
uvs[5] = region.getV2();
|
||||
uvs[6] = region.getU();
|
||||
uvs[7] = region.getV();
|
||||
uvs[0] = region.getU2();
|
||||
uvs[1] = region.getV();
|
||||
uvs[2] = region.getU2();
|
||||
uvs[3] = region.getV2();
|
||||
} else {
|
||||
vertices[U2] = region.getU();
|
||||
vertices[V2] = region.getV2();
|
||||
vertices[U3] = region.getU();
|
||||
vertices[V3] = region.getV();
|
||||
vertices[U4] = region.getU2();
|
||||
vertices[V4] = region.getV();
|
||||
vertices[U1] = region.getU2();
|
||||
vertices[V1] = region.getV2();
|
||||
uvs[2] = region.getU();
|
||||
uvs[3] = region.getV2();
|
||||
uvs[4] = region.getU();
|
||||
uvs[5] = region.getV();
|
||||
uvs[6] = region.getU2();
|
||||
uvs[7] = region.getV();
|
||||
uvs[0] = region.getU2();
|
||||
uvs[1] = region.getV2();
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,55 +143,42 @@ public class RegionAttachment extends Attachment {
|
||||
return region;
|
||||
}
|
||||
|
||||
/** @return The updated world vertices. */
|
||||
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||
Skeleton skeleton = slot.getSkeleton();
|
||||
Color skeletonColor = skeleton.getColor();
|
||||
Color slotColor = slot.getColor();
|
||||
Color regionColor = color;
|
||||
float alpha = skeletonColor.a * slotColor.a * regionColor.a * 255;
|
||||
float multiplier = premultipliedAlpha ? alpha : 255;
|
||||
float color = NumberUtils.intToFloatColor( //
|
||||
((int)alpha << 24) //
|
||||
| ((int)(skeletonColor.b * slotColor.b * regionColor.b * multiplier) << 16) //
|
||||
| ((int)(skeletonColor.g * slotColor.g * regionColor.g * multiplier) << 8) //
|
||||
| (int)(skeletonColor.r * slotColor.r * regionColor.r * multiplier));
|
||||
|
||||
float[] vertices = this.vertices;
|
||||
float[] offset = this.offset;
|
||||
/** Transforms the attachment's four vertices to world coordinates.
|
||||
* <p>
|
||||
* See <a href="http://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
||||
* Runtimes Guide.
|
||||
* @param worldVertices The output world vertices. Must have a length >= <code>offset</code> + 8.
|
||||
* @param offset The <code>worldVertices</code> index to begin writing values.
|
||||
* @param stride The number of <code>worldVertices</code> entries between the value pairs written. */
|
||||
public void computeWorldVertices (Slot slot, float[] worldVertices, int offset, int stride) {
|
||||
float[] vertexOffset = this.offset;
|
||||
Bone bone = slot.getBone();
|
||||
float x = bone.getWorldX(), y = bone.getWorldY();
|
||||
float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD();
|
||||
float offsetX, offsetY;
|
||||
|
||||
offsetX = offset[BRX];
|
||||
offsetY = offset[BRY];
|
||||
vertices[X1] = offsetX * a + offsetY * b + x; // br
|
||||
vertices[Y1] = offsetX * c + offsetY * d + y;
|
||||
vertices[C1] = color;
|
||||
offsetX = vertexOffset[BRX];
|
||||
offsetY = vertexOffset[BRY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // br
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[BLX];
|
||||
offsetY = offset[BLY];
|
||||
vertices[X2] = offsetX * a + offsetY * b + x; // bl
|
||||
vertices[Y2] = offsetX * c + offsetY * d + y;
|
||||
vertices[C2] = color;
|
||||
offsetX = vertexOffset[BLX];
|
||||
offsetY = vertexOffset[BLY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // bl
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[ULX];
|
||||
offsetY = offset[ULY];
|
||||
vertices[X3] = offsetX * a + offsetY * b + x; // ul
|
||||
vertices[Y3] = offsetX * c + offsetY * d + y;
|
||||
vertices[C3] = color;
|
||||
offsetX = vertexOffset[ULX];
|
||||
offsetY = vertexOffset[ULY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // ul
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = offset[URX];
|
||||
offsetY = offset[URY];
|
||||
vertices[X4] = offsetX * a + offsetY * b + x; // ur
|
||||
vertices[Y4] = offsetX * c + offsetY * d + y;
|
||||
vertices[C4] = color;
|
||||
return vertices;
|
||||
}
|
||||
|
||||
public float[] getWorldVertices () {
|
||||
return vertices;
|
||||
offsetX = vertexOffset[URX];
|
||||
offsetY = vertexOffset[URY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x; // ur
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
}
|
||||
|
||||
/** For each of the 4 vertices, a pair of <code>x,y</code> values that is the local position of the vertex.
|
||||
@ -205,6 +188,10 @@ public class RegionAttachment extends Attachment {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public float[] getUVs () {
|
||||
return uvs;
|
||||
}
|
||||
|
||||
/** The local x translation. */
|
||||
public float getX () {
|
||||
return x;
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License v2.5
|
||||
*
|
||||
* Copyright (c) 2013-2016, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable, and
|
||||
* non-transferable license to use, install, execute, and perform the Spine
|
||||
* Runtimes software and derivative works solely for personal or internal
|
||||
* use. Without the written permission of Esoteric Software (see Section 2 of
|
||||
* the Spine Software License Agreement), you may not (a) modify, translate,
|
||||
* adapt, or develop new applications using the Spine Runtimes or otherwise
|
||||
* create derivative works or improvements of the Spine Runtimes 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 SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
|
||||
* USE, DATA, OR PROFITS) 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.
|
||||
*****************************************************************************/
|
||||
|
||||
package com.esotericsoftware.spine.attachments;
|
||||
|
||||
import com.esotericsoftware.spine.Slot;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
|
||||
/** Attachment that displays various texture regions over time. */
|
||||
public class RegionSequenceAttachment extends RegionAttachment {
|
||||
private Mode mode;
|
||||
private float frameTime;
|
||||
private TextureRegion[] regions;
|
||||
|
||||
public RegionSequenceAttachment (String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||
if (regions == null) throw new IllegalStateException("Regions have not been set: " + this);
|
||||
|
||||
int frameIndex = (int)(slot.getAttachmentTime() / frameTime);
|
||||
switch (mode) {
|
||||
case forward:
|
||||
frameIndex = Math.min(regions.length - 1, frameIndex);
|
||||
break;
|
||||
case forwardLoop:
|
||||
frameIndex = frameIndex % regions.length;
|
||||
break;
|
||||
case pingPong:
|
||||
frameIndex = frameIndex % (regions.length << 1);
|
||||
if (frameIndex >= regions.length) frameIndex = regions.length - 1 - (frameIndex - regions.length);
|
||||
break;
|
||||
case random:
|
||||
frameIndex = MathUtils.random(regions.length - 1);
|
||||
break;
|
||||
case backward:
|
||||
frameIndex = Math.max(regions.length - frameIndex - 1, 0);
|
||||
break;
|
||||
case backwardLoop:
|
||||
frameIndex = frameIndex % regions.length;
|
||||
frameIndex = regions.length - frameIndex - 1;
|
||||
break;
|
||||
}
|
||||
setRegion(regions[frameIndex]);
|
||||
|
||||
return super.updateWorldVertices(slot, premultipliedAlpha);
|
||||
}
|
||||
|
||||
public TextureRegion[] getRegions () {
|
||||
if (regions == null) throw new IllegalStateException("Regions have not been set: " + this);
|
||||
return regions;
|
||||
}
|
||||
|
||||
public void setRegions (TextureRegion[] regions) {
|
||||
this.regions = regions;
|
||||
}
|
||||
|
||||
/** Sets the time in seconds each frame is shown. */
|
||||
public void setFrameTime (float frameTime) {
|
||||
this.frameTime = frameTime;
|
||||
}
|
||||
|
||||
public void setMode (Mode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
static public enum Mode {
|
||||
forward, backward, forwardLoop, backwardLoop, pingPong, random
|
||||
}
|
||||
}
|
||||
@ -46,14 +46,6 @@ public class VertexAttachment extends Attachment {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/** Transforms the attachment's local {@link #getVertices()} to world coordinates, using 0 for <code>start</code> and
|
||||
* <code>offset</code>.
|
||||
* <p>
|
||||
* See {@link #computeWorldVertices(Slot, int, int, float[], int)}. */
|
||||
public void computeWorldVertices (Slot slot, float[] worldVertices) {
|
||||
computeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0);
|
||||
}
|
||||
|
||||
/** Transforms the attachment's local {@link #getVertices()} to world coordinates. If the slot has
|
||||
* {@link Slot#getAttachmentVertices()}, they are used to deform the vertices.
|
||||
* <p>
|
||||
@ -62,9 +54,10 @@ public class VertexAttachment extends Attachment {
|
||||
* @param start The index of the first {@link #getVertices()} value to transform. Each vertex has 2 values, x and y.
|
||||
* @param count The number of world vertex values to output. Must be <= {@link #getWorldVerticesLength()} - <code>start</code>.
|
||||
* @param worldVertices The output world vertices. Must have a length >= <code>offset</code> + <code>count</code>.
|
||||
* @param offset The <code>worldVertices</code> index to begin writing values. */
|
||||
public void computeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset) {
|
||||
count += offset;
|
||||
* @param offset The <code>worldVertices</code> index to begin writing values.
|
||||
* @param stride The number of <code>worldVertices</code> entries between the value pairs written. */
|
||||
public void computeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride) {
|
||||
count = offset + (count >> 1) * stride;
|
||||
Skeleton skeleton = slot.getSkeleton();
|
||||
FloatArray deformArray = slot.getAttachmentVertices();
|
||||
float[] vertices = this.vertices;
|
||||
@ -74,7 +67,7 @@ public class VertexAttachment extends Attachment {
|
||||
Bone bone = slot.getBone();
|
||||
float x = bone.getWorldX(), y = bone.getWorldY();
|
||||
float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD();
|
||||
for (int v = start, w = offset; w < count; v += 2, w += 2) {
|
||||
for (int v = start, w = offset; w < count; v += 2, w += stride) {
|
||||
float vx = vertices[v], vy = vertices[v + 1];
|
||||
worldVertices[w] = vx * a + vy * b + x;
|
||||
worldVertices[w + 1] = vx * c + vy * d + y;
|
||||
@ -89,7 +82,7 @@ public class VertexAttachment extends Attachment {
|
||||
}
|
||||
Object[] skeletonBones = skeleton.getBones().items;
|
||||
if (deformArray.size == 0) {
|
||||
for (int w = offset, b = skip * 3; w < count; w += 2) {
|
||||
for (int w = offset, b = skip * 3; w < count; w += stride) {
|
||||
float wx = 0, wy = 0;
|
||||
int n = bones[v++];
|
||||
n += v;
|
||||
@ -104,7 +97,7 @@ public class VertexAttachment extends Attachment {
|
||||
}
|
||||
} else {
|
||||
float[] deform = deformArray.items;
|
||||
for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) {
|
||||
for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
|
||||
float wx = 0, wy = 0;
|
||||
int n = bones[v++];
|
||||
n += v;
|
||||
@ -150,7 +143,7 @@ public class VertexAttachment extends Attachment {
|
||||
}
|
||||
|
||||
/** The maximum length required of the <code>worldVertices</code> passed to
|
||||
* {@link #computeWorldVertices(Slot, int, int, float[], int)}. */
|
||||
* {@link #computeWorldVertices(Slot, int, int, float[], int, int)}. */
|
||||
public int getWorldVerticesLength () {
|
||||
return worldVerticesLength;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user