wip, forgot about SkeletonBounds and SkeletonClipping

This commit is contained in:
Stephen Gowen 2017-11-25 15:09:37 -05:00
parent 5411125c93
commit 19687d9957
8 changed files with 765 additions and 1 deletions

View File

@ -41,6 +41,8 @@ namespace Spine
{
SPINE_RTTI_DECL;
friend class SkeletonClipping;
public:
ClippingAttachment(std::string name);

View File

@ -87,7 +87,7 @@ namespace Spine
// }
// }
// for (; frame < frameCount && time >= frames[frame]; frame++)
// firedEvents.Add(events[frame]);
// firedEvents.push_back(events[frame]);
// }
};
}

View File

@ -0,0 +1,112 @@
/******************************************************************************
* 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.
*****************************************************************************/
#ifndef Spine_SkeletonBounds_h
#define Spine_SkeletonBounds_h
#include <spine/Vector.h>
namespace Spine
{
class Skeleton;
class BoundingBoxAttachment;
class Polygon;
///
/// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon.
/// The polygon vertices are provided along with convenience methods for doing hit detection.
///
class SkeletonBounds
{
public:
SkeletonBounds();
///
/// Clears any previous polygons, finds all visible bounding box attachments,
/// and computes the world vertices for each bounding box's polygon.
/// @param skeleton The skeleton.
/// @param updateAabb
/// If true, the axis aligned bounding box containing all the polygons is computed.
/// If false, the SkeletonBounds AABB methods will always return true.
///
void update(Skeleton& skeleton, bool updateAabb);
/// Returns true if the axis aligned bounding box contains the point.
bool aabbcontainsPoint(float x, float y);
/// Returns true if the axis aligned bounding box intersects the line segment.
bool aabbintersectsSegment(float x1, float y1, float x2, float y2);
/// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds.
bool aabbIntersectsSkeleton(SkeletonBounds bounds);
/// Returns true if the polygon contains the point.
bool containsPoint(Polygon polygon, float x, float y);
/// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more
/// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true.
BoundingBoxAttachment* containsPoint(float x, float y);
/// Returns the first bounding box attachment that contains the line segment, or NULL. When doing many checks, it is usually
/// more efficient to only call this method if {@link #aabbintersectsSegment(float, float, float, float)} returns true.
BoundingBoxAttachment* intersectsSegment(float x1, float y1, float x2, float y2);
/// Returns true if the polygon contains the line segment.
bool intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2);
Polygon* getPolygon(BoundingBoxAttachment* attachment);
float getWidth();
float getHeight();
private:
Vector<Polygon*> _polygonPool;
Vector<BoundingBoxAttachment*> _boundingBoxes;
Vector<Polygon*> _polygons;
float _minX, _minY, _maxX, _maxY;
void aabbCompute();
};
class Polygon
{
public:
Vector<float> _vertices;
int _count;
Polygon() : _count(0)
{
_vertices.reserve(16);
}
};
}
#endif /* Spine_SkeletonBounds_h */

View File

@ -0,0 +1,76 @@
/******************************************************************************
* 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.
*****************************************************************************/
#ifndef Spine_SkeletonClipping_h
#define Spine_SkeletonClipping_h
#include <spine/Vector.h>
#include <spine/Triangulator.h>
namespace Spine
{
class Slot;
class ClippingAttachment;
class SkeletonClipping
{
public:
SkeletonClipping();
int clipStart(Slot& slot, ClippingAttachment* clip);
void clipEnd(Slot& slot);
void clipEnd();
void clipTriangles(Vector<float>& vertices, int verticesLength, Vector<int>& triangles, int trianglesLength, Vector<float>& uvs);
bool isClipping();
private:
Triangulator _triangulator;
Vector<float> _clippingPolygon;
Vector<float> _clipOutput;
Vector<float> _clippedVertices;
Vector<int> _clippedTriangles;
Vector<float> _clippedUVs;
Vector<float> _scratch;
ClippingAttachment* _clipAttachment;
Vector< Vector<float> > _clippingPolygons;
/** 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. */
bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector<float>& clippingArea, Vector<float>& output);
static void makeClockwise(Vector<float>& polygon);
};
}
#endif /* Spine_SkeletonClipping_h */

View File

@ -46,6 +46,7 @@ namespace Spine
{
friend class VertexAttachment;
friend class Skeleton;
friend class SkeletonClipping;
friend class AttachmentTimeline;
friend class ColorTimeline;

View File

@ -79,6 +79,19 @@ namespace Spine
return false;
}
int indexOf(const T& inValue)
{
for (size_t i = 0; i < _size; ++i)
{
if (_buffer[i] == inValue)
{
return static_cast<int>(i);
}
}
return -1;
}
void push_back(const T& inValue)
{
if (_size == _capacity)

View File

@ -0,0 +1,267 @@
/******************************************************************************
* 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.
*****************************************************************************/
#include <spine/SkeletonBounds.h>
#include <spine/Skeleton.h>
#include <spine/BoundingBoxAttachment.h>
namespace Spine
{
SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0)
{
// Empty
}
void SkeletonBounds::update(Skeleton& skeleton, bool updateAabb)
{
// Vector<Slot> slots = skeleton._slots;
// int slotCount = slots.Count;
//
// _boundingBoxes.clear();
// for (int i = 0, n = _polygons.size(); i < n; ++i)
// {
// _polygonPool.push_back(_polygons[i]);
// }
//
// _polygons.clear();
//
// for (int i = 0; i < slotCount; i++)
// {
// Slot slot = slots.Items[i];
// BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment;
// if (boundingBox == NULL)
// {
// continue;
// }
// _boundingBoxes.push_back(boundingBox);
//
// Polygon* polygonP = NULL;
// int poolCount = _polygonPool.size();
// if (poolCount > 0)
// {
// polygonP = _polygonPool[poolCount - 1];
// _polygonPool.erase(poolCount - 1);
// }
// else
// {
// polygonP = new Polygon();
// }
//
// _polygons.push_back(polygonP);
//
// Polygon& polygon = *polygonP;
//
// int count = boundingBox.worldVerticesLength;
// polygon._count = count;
// if (polygon._vertices.size() < count)
// {
// polygon._vertices.reserve(count);
// }
// boundingBox.computeWorldVertices(slot, polygon._vertices);
// }
//
// if (updateAabb)
// {
// aabbCompute();
// }
// else
// {
// minX = int.MinValue;
// minY = int.MinValue;
// maxX = int.MaxValue;
// maxY = int.MaxValue;
// }
}
bool SkeletonBounds::aabbcontainsPoint(float x, float y)
{
return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY;
}
bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2)
{
float minX = _minX;
float minY = _minY;
float maxX = _maxX;
float maxY = _maxY;
if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
{
return false;
}
float m = (y2 - y1) / (x2 - x1);
float y = m * (minX - x1) + y1;
if (y > minY && y < maxY)
{
return true;
}
y = m * (maxX - x1) + y1;
if (y > minY && y < maxY)
{
return true;
}
float x = (minY - y1) / m + x1;
if (x > minX && x < maxX)
{
return true;
}
x = (maxY - y1) / m + x1;
if (x > minX && x < maxX)
{
return true;
}
return false;
}
bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds)
{
return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY;
}
bool SkeletonBounds::containsPoint(Polygon polygon, float x, float y)
{
// float[] vertices = polygon.Vertices;
// int nn = polygon.Count;
//
// int prevIndex = nn - 2;
bool inside = false;
// for (int ii = 0; ii < nn; ii += 2)
// {
// float vertexY = vertices[ii + 1];
// float prevY = vertices[prevIndex + 1];
// if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y))
// {
// float vertexX = vertices[ii];
// if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x)
// {
// inside = !inside;
// }
// }
// prevIndex = ii;
// }
return inside;
}
BoundingBoxAttachment* SkeletonBounds::containsPoint(float x, float y)
{
// for (int i = 0, n = _polygons.size(); i < n; ++i)
// {
// if (containsPoint(_polygons[i], x, y))
// {
// return _boundingBoxes[i];
// }
// }
return NULL;
}
BoundingBoxAttachment* SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2)
{
// for (int i = 0, n = _polygons.size(); i < n; ++i)
// {
// if (intersectsSegment(_polygons[i], x1, y1, x2, y2))
// {
// return _boundingBoxes[i];
// }
// }
return NULL;
}
bool SkeletonBounds::intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2)
{
// Vector<float>& vertices = polygon->_vertices;
// int nn = polygon.Count;
//
// float width12 = x1 - x2, height12 = y1 - y2;
// float det1 = x1 * y2 - y1 * x2;
// float x3 = vertices[nn - 2], y3 = vertices[nn - 1];
// for (int ii = 0; ii < nn; ii += 2)
// {
// float x4 = vertices[ii], y4 = vertices[ii + 1];
// float det2 = x3 * y4 - y3 * x4;
// float width34 = x3 - x4, height34 = y3 - y4;
// float det3 = width12 * height34 - height12 * width34;
// float x = (det1 * width34 - width12 * det2) / det3;
// if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1)))
// {
// float y = (det1 * height34 - height12 * det2) / det3;
// if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1)))
// {
// return true;
// }
// }
// x3 = x4;
// y3 = y4;
// }
return false;
}
Polygon* SkeletonBounds::getPolygon(BoundingBoxAttachment* attachment)
{
int index = _boundingBoxes.indexOf(attachment);
return index == -1 ? NULL : _polygons[index];
}
float SkeletonBounds::getWidth()
{
return _maxX - _minX;
}
float SkeletonBounds::getHeight()
{
return _maxY - _minY;
}
void SkeletonBounds::aabbCompute()
{
// float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;
// for (int i = 0, n = _polygons.size(); i < n; i++)
// {
// Polygon* polygon = _polygons[i];
// Vector<float>& vertices = polygon->_vertices;
// for (int ii = 0, nn = polygon.Count; ii < nn; ii += 2)
// {
// float x = vertices[ii];
// float y = vertices[ii + 1];
// minX = Math.Min(minX, x);
// minY = Math.Min(minY, y);
// maxX = Math.Max(maxX, x);
// maxY = Math.Max(maxY, y);
// }
// }
// _minX = minX;
// _minY = minY;
// _maxX = maxX;
// _maxY = maxY;
}
}

View File

@ -0,0 +1,293 @@
/******************************************************************************
* 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.
*****************************************************************************/
#include <spine/SkeletonClipping.h>
#include <spine/Slot.h>
#include <spine/ClippingAttachment.h>
namespace Spine
{
SkeletonClipping::SkeletonClipping()
{
_clipOutput.reserve(128);
_clippedVertices.reserve(128);
_clippedTriangles.reserve(128);
_clippedUVs.reserve(128);
}
int SkeletonClipping::clipStart(Slot& slot, ClippingAttachment* clip)
{
// if (clipAttachment != NULL) return 0;
// clipAttachment = clip;
//
// int n = clip.worldVerticesLength;
// float[] vertices = clippingPolygon.Resize(n).Items;
// clip.ComputeWorldVertices(slot, 0, n, vertices, 0, 2);
// makeClockwise(clippingPolygon);
// clippingPolygons = triangulator.Decompose(clippingPolygon, triangulator.Triangulate(clippingPolygon));
// foreach (var polygon in clippingPolygons) {
// makeClockwise(polygon);
// polygon.push_back(polygon.Items[0]);
// polygon.push_back(polygon.Items[1]);
// }
return static_cast<int>(_clippingPolygons.size());
}
void SkeletonClipping::clipEnd(Slot& slot)
{
if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data)
{
clipEnd();
}
}
void SkeletonClipping::clipEnd()
{
if (_clipAttachment == NULL)
{
return;
}
_clipAttachment = NULL;
_clippingPolygons.clear();
_clippedVertices.clear();
_clippedTriangles.clear();
_clippingPolygon.clear();
}
void SkeletonClipping::clipTriangles(Vector<float>& vertices, int verticesLength, Vector<int>& triangles, int trianglesLength, Vector<float>& uvs)
{
// Vector<float> clipOutput = _clipOutput, clippedVertices = _clippedVertices;
// var clippedTriangles = _clippedTriangles;
// var polygons = clippingPolygons.Items;
// int polygonsCount = clippingPolygons.Count;
//
// int index = 0;
// clippedVertices.Clear();
// clippedUVs.Clear();
// clippedTriangles.Clear();
// //outer:
// for (int i = 0; i < trianglesLength; i += 3) {
// int vertexOffset = triangles[i] << 1;
// float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
// float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
//
// vertexOffset = triangles[i + 1] << 1;
// float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
// float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
//
// vertexOffset = triangles[i + 2] << 1;
// float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
// float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
//
// for (int p = 0; p < polygonsCount; p++) {
// int s = clippedVertices.Count;
// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
// int clipOutputLength = clipOutput.Count;
// if (clipOutputLength == 0) continue;
// float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
// float d = 1 / (d0 * d2 + d1 * (y1 - y3));
//
// int clipOutputCount = clipOutputLength >> 1;
// float[] clipOutputItems = clipOutput.Items;
// float[] clippedVerticesItems = clippedVertices.Resize(s + clipOutputCount * 2).Items;
// float[] clippedUVsItems = clippedUVs.Resize(s + clipOutputCount * 2).Items;
// for (int ii = 0; ii < clipOutputLength; ii += 2) {
// float x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
// clippedVerticesItems[s] = x;
// clippedVerticesItems[s + 1] = y;
// float c0 = x - x3, c1 = y - y3;
// float a = (d0 * c0 + d1 * c1) * d;
// float b = (d4 * c0 + d2 * c1) * d;
// float c = 1 - a - b;
// clippedUVsItems[s] = u1 * a + u2 * b + u3 * c;
// clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c;
// s += 2;
// }
//
// s = clippedTriangles.Count;
// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3 * (clipOutputCount - 2)).Items;
// clipOutputCount--;
// for (int ii = 1; ii < clipOutputCount; ii++) {
// clippedTrianglesItems[s] = index;
// clippedTrianglesItems[s + 1] = index + ii;
// clippedTrianglesItems[s + 2] = index + ii + 1;
// s += 3;
// }
// index += clipOutputCount + 1;
// }
// else {
// float[] clippedVerticesItems = clippedVertices.Resize(s + 3 * 2).Items;
// float[] clippedUVsItems = clippedUVs.Resize(s + 3 * 2).Items;
// clippedVerticesItems[s] = x1;
// clippedVerticesItems[s + 1] = y1;
// clippedVerticesItems[s + 2] = x2;
// clippedVerticesItems[s + 3] = y2;
// clippedVerticesItems[s + 4] = x3;
// clippedVerticesItems[s + 5] = y3;
//
// clippedUVsItems[s] = u1;
// clippedUVsItems[s + 1] = v1;
// clippedUVsItems[s + 2] = u2;
// clippedUVsItems[s + 3] = v2;
// clippedUVsItems[s + 4] = u3;
// clippedUVsItems[s + 5] = v3;
//
// s = clippedTriangles.Count;
// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items;
// clippedTrianglesItems[s] = index;
// clippedTrianglesItems[s + 1] = index + 1;
// clippedTrianglesItems[s + 2] = index + 2;
// index += 3;
// break; //continue outer;
// }
// }
// }
}
bool SkeletonClipping::isClipping()
{
return _clipAttachment != NULL;
}
bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector<float>& clippingArea, Vector<float>& output)
{
// var originalOutput = output;
bool clipped = false;
//
// // Avoid copy at the end.
// Vector<float> input = NULL;
// if (clippingArea.Count % 4 >= 2) {
// input = output;
// output = scratch;
// } else {
// input = scratch;
// }
//
// input.Clear();
// input.push_back(x1);
// input.push_back(y1);
// input.push_back(x2);
// input.push_back(y2);
// input.push_back(x3);
// input.push_back(y3);
// input.push_back(x1);
// input.push_back(y1);
// output.Clear();
//
// Vector<float> clippingVertices = clippingArea.Items;
// int clippingVerticesLast = clippingArea.Count - 4;
// for (int i = 0; ; i += 2) {
// float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
// float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
// float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
//
// Vector<float> inputVertices = input.Items;
// int inputVerticesLength = input.Count - 2, outputStart = output.Count;
// for (int ii = 0; ii < inputVerticesLength; ii += 2) {
// float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
// float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
// bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
// if (side2) { // v1 inside, v2 inside
// output.push_back(inputX2);
// output.push_back(inputY2);
// continue;
// }
// // v1 inside, v2 outside
// float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
// output.push_back(edgeX + (edgeX2 - edgeX) * ua);
// output.push_back(edgeY + (edgeY2 - edgeY) * ua);
// }
// else if (side2) { // v1 outside, v2 inside
// float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
// output.push_back(edgeX + (edgeX2 - edgeX) * ua);
// output.push_back(edgeY + (edgeY2 - edgeY) * ua);
// output.push_back(inputX2);
// output.push_back(inputY2);
// }
// clipped = true;
// }
//
// if (outputStart == output.Count) { // All edges outside.
// originalOutput.Clear();
// return true;
// }
//
// output.push_back(output.Items[0]);
// output.push_back(output.Items[1]);
//
// if (i == clippingVerticesLast) break;
// var temp = output;
// output = input;
// output.Clear();
// input = temp;
// }
//
// if (originalOutput != output) {
// originalOutput.Clear();
// for (int i = 0, n = output.Count - 2; i < n; i++) {
// originalOutput.push_back(output.Items[i]);
// }
// } else {
// originalOutput.Resize(originalOutput.Count - 2);
// }
return clipped;
}
void SkeletonClipping::makeClockwise(Vector<float>& polygon)
{
// Vector<float> vertices = polygon.Items;
// int verticeslength = polygon.Count;
//
// float area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x, p1y, p2x, p2y;
// for (int i = 0, n = verticeslength - 3; i < n; i += 2) {
// p1x = vertices[i];
// p1y = vertices[i + 1];
// p2x = vertices[i + 2];
// p2y = vertices[i + 3];
// area += p1x * p2y - p2x * p1y;
// }
// if (area < 0) return;
//
// for (int i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
// float x = vertices[i], y = vertices[i + 1];
// int other = lastX - i;
// vertices[i] = vertices[other];
// vertices[i + 1] = vertices[other + 1];
// vertices[other] = x;
// vertices[other + 1] = y;
// }
}
}