- Edited
Bounding box - Unity c-sharp
Not sure if I did something wrong, but the bounding box MinX, MinY, etc.. get calculated and result seem to be in local positions rather than world positions.
This make method like AabbIntersectsSkeleton, and AabbContainsPoint to not working correctly.
when I do thing like
if(animationBound.AabbIntersectsSkeleton(targetBound))
it always return true.
Not sure if it's a bug or just wrong setup on Editor?
In Unity the bone world positions, bounding box world positions, etc are relative to the GameObject. This is because the GameObject positions the skeleton rather than using skeleton x/y. One way to fix this:
// Set skeleton position to gameobject position.
skeleton.x = 123;
skeleton.y = 456;
bounds.update(skeleton, true);
// Set skeleton position back to zero.
skeleton.x = 0;
skeleton.y = 0;
I've also noticed that the Scale in Unity's SkeletonData doesn't scale the bounding boxes. The vertices aren't being scaled when skeleton is read.
Just need to edit line 215 from SkeletonJson.cs:
vertices[i] = (float)values[i] * Scale;
Also, I'd like to know how do you check for intersection between a desired BoundingBox and a Skeleton? I tried to make an "AabbIntersectsBoundingBox", but it doesn't seems to work properly:
(updated, see edit)
public bool AabbIntersectsBoundingBox(BoundingBoxAttachment boundingbox)
{
if (!aabb) aabbCompute();
if (boundingbox == null) return false;
float[] vertices = boundingbox.BoundingBoxWorldVertices;
for (int i = 0; i < vertices.Length; i += 2)
{
float vx = vertices[i];
float vy = vertices[i + 1];
if (minX < vx && maxX > vx && minY < vy && maxY > vy)
return true;
}
return false;
}
@Edit:
After fiddling with the code, I found that the bounding box vertices didn't have a world position, so I've made some changes to include it. Bear in mind that I didn't tried to be efficient, but it seems to work in Unity now:
BoundingBoxAttachment.cs
namespace Spine {
/** Attachment that has a polygon for bounds checking. */
public class BoundingBoxAttachment : Attachment {
public float[] Vertices { get; set; }
public float[] BoundingBoxWorldVertices { get; set; }
public BoundingBoxAttachment (string name)
: base(name) {
}
/** @param worldVertices Must have at least the same length as this attachment's vertices. */
public void ComputeWorldVertices (float x, float y, Bone bone, float[] worldVertices) {
x += bone.worldX;
y += bone.worldY;
float m00 = bone.m00;
float m01 = bone.m01;
float m10 = bone.m10;
float m11 = bone.m11;
float[] vertices = Vertices;
for (int i = 0, n = vertices.Length; i < n; i += 2) {
float px = vertices[i];
float py = vertices[i + 1];
worldVertices[i] = px * m00 + py * m01 + x;
worldVertices[i + 1] = px * m10 + py * m11 + y;
BoundingBoxWorldVertices[i] = worldVertices[i];
BoundingBoxWorldVertices[i + 1] = worldVertices[i + 1];
}
}
}
}
SkeletonJson.cs
@216
boundingBox.Vertices = vertices;
boundingBox.BoundingBoxWorldVertices = (float[])vertices.Clone();
}
I've updated my AabbIntersectsBoundingBox above to use BoundingBoxWorldVertices.
Good catch on the bounding box scale, fixed.
Attachments are stateless and may be used in multiple Skeletons. This is why SkeletonBounds computes and holds the state of a bounding box for a particular skeleton. If you stored world vertices in the BoundingBoxAttachment for a particular skeleton, you'd have a problem once two skeletons used the same BoundingBoxAttachment.
The polygons supplied by SkeletonBounds are the world vertices of each BoundingBoxAttachment. They are relative to the skeleton GameObject. You can use the code I posted above to adjust the polygons to be relative to whatever you like, eg the skeleton GameObject's parent. It is sort of a hack, since the skeleton x/y is just added to computed world vertices of the bounding boxes. It may be clearer to loop through all the polygon vertices and adjust them to be relative to whatever you like. This would also be necessary if you need to rotate or scale them.
Thanks for the reply Nate, I'll change my code based on your info ;D