160 lines
4.4 KiB
C++
160 lines
4.4 KiB
C++
// 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
|