godot/thirdparty/thekla_atlas/nvmesh/raster/ClippedTriangle.h
Hein-Pieter van Braam bf05309af7 Import thekla_atlas
As requested by reduz, an import of thekla_atlas into thirdparty/
2017-12-08 15:47:15 +01:00

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