// Copyright NVIDIA Corporation 2007 -- Denis Kovacs <den.kovacs@gmail.com> #pragma once #ifndef NV_MESH_CLIPPEDTRIANGLE_H #define NV_MESH_CLIPPEDTRIANGLE_H #include <nvmath/Vector.h> namespace nv { class ClippedTriangle { public: ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) { m_numVertices = 3; m_activeVertexBuffer = 0; m_verticesA[0]=a; m_verticesA[1]=b; m_verticesA[2]=c; m_vertexBuffers[0] = m_verticesA; m_vertexBuffers[1] = m_verticesB; } uint vertexCount() { return m_numVertices; } const Vector2 * vertices() { return m_vertexBuffers[m_activeVertexBuffer]; } inline void clipHorizontalPlane(float offset, float clipdirection) { Vector2 * v = m_vertexBuffers[m_activeVertexBuffer]; m_activeVertexBuffer ^= 1; Vector2 * v2 = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; float dy2, dy1 = offset - v[0].y; int dy2in, dy1in = clipdirection*dy1 >= 0; uint p=0; for (uint k=0; k<m_numVertices; k++) { dy2 = offset - v[k+1].y; dy2in = clipdirection*dy2 >= 0; if (dy1in) v2[p++] = v[k]; if ( dy1in + dy2in == 1 ) // not both in/out { float dx = v[k+1].x - v[k].x; float dy = v[k+1].y - v[k].y; v2[p++] = Vector2(v[k].x + dy1*(dx/dy), offset); } dy1 = dy2; dy1in = dy2in; } m_numVertices = p; //for (uint k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n"); } inline void clipVerticalPlane(float offset, float clipdirection ) { Vector2 * v = m_vertexBuffers[m_activeVertexBuffer]; m_activeVertexBuffer ^= 1; Vector2 * v2 = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; float dx2, dx1 = offset - v[0].x; int dx2in, dx1in = clipdirection*dx1 >= 0; uint p=0; for (uint k=0; k<m_numVertices; k++) { dx2 = offset - v[k+1].x; dx2in = clipdirection*dx2 >= 0; if (dx1in) v2[p++] = v[k]; if ( dx1in + dx2in == 1 ) // not both in/out { float dx = v[k+1].x - v[k].x; float dy = v[k+1].y - v[k].y; v2[p++] = Vector2(offset, v[k].y + dx1*(dy/dx)); } dx1 = dx2; dx1in = dx2in; } m_numVertices = p; //for (uint k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n"); } void computeAreaCentroid() { Vector2 * v = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; m_area = 0; float centroidx=0, centroidy=0; for (uint k=0; k<m_numVertices; k++) { // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/ float f = v[k].x*v[k+1].y - v[k+1].x*v[k].y; m_area += f; centroidx += f * (v[k].x + v[k+1].x); centroidy += f * (v[k].y + v[k+1].y); } m_area = 0.5f * fabs(m_area); if (m_area==0) { m_centroid = Vector2(0.0f); } else { m_centroid = Vector2(centroidx/(6*m_area), centroidy/(6*m_area)); } } void clipAABox(float x0, float y0, float x1, float y1) { clipVerticalPlane ( x0, -1); clipHorizontalPlane( y0, -1); clipVerticalPlane ( x1, 1); clipHorizontalPlane( y1, 1); computeAreaCentroid(); } Vector2 centroid() { return m_centroid; } float area() { return m_area; } private: Vector2 m_verticesA[7+1]; Vector2 m_verticesB[7+1]; Vector2 * m_vertexBuffers[2]; uint m_numVertices; uint m_activeVertexBuffer; float m_area; Vector2 m_centroid; }; } // nv namespace #endif // NV_MESH_CLIPPEDTRIANGLE_H