256 lines
5.1 KiB
C++
256 lines
5.1 KiB
C++
/*
|
|
Marching Hedrons LUT generator
|
|
author: andrei (c) 2015
|
|
|
|
Marching hedron convex test
|
|
|
|
*/
|
|
|
|
#include <iostream>
|
|
|
|
#include "mh.h"
|
|
|
|
#define EPS 1e-6
|
|
|
|
|
|
bool MH::initConvexHull()
|
|
{
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
for (int j = 0; j < 4; j++)
|
|
edge_indices[i][j] = (i >> j) & 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MH::computeConvexHull(const Vec3HVec & pointVec, FaceHVec & faces)
|
|
{
|
|
int s = pointVec.size();
|
|
FaceHVec allfaces;
|
|
for (int i0 = 0; i0 < s; i0++)
|
|
{
|
|
for (int i1 = i0 + 1; i1 < s; i1++)
|
|
{
|
|
for (int i2 = i1 + 1; i2 < s; i2++)
|
|
{
|
|
allfaces.push_back(Face::getFace(i0, i1, i2));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < allfaces.size(); i++)
|
|
{
|
|
Face &f = allfaces[i];
|
|
Vec3 n = (pointVec[f.v[2]] - pointVec[f.v[0]]).cross(pointVec[f.v[1]] - pointVec[f.v[0]]);
|
|
bool pos = false;
|
|
bool neg = false;
|
|
for (int j = 0; j < s; j++)
|
|
{
|
|
if (j == f.v[0] || j == f.v[1] || j == f.v[2])
|
|
continue;
|
|
Vec3 p = pointVec[j] - pointVec[f.v[0]];
|
|
float d = p.dot(n);
|
|
if (d < -EPS)
|
|
neg = true;
|
|
else if (d > EPS)
|
|
pos = true;
|
|
}
|
|
// if there are vertices on both sides of a face plane
|
|
if (pos && neg)
|
|
continue;
|
|
|
|
// test if this face intersects with already added faces
|
|
bool intersect = false;
|
|
for (size_t k = 0; k < faces.size(); k++)
|
|
{
|
|
Face &f2 = faces[k];
|
|
|
|
int ret = tr_tri_intersect3D(pointVec[f.v[0]], pointVec[f.v[1]] - pointVec[f.v[0]], pointVec[f.v[2]] - pointVec[f.v[0]],
|
|
pointVec[f2.v[0]], pointVec[f2.v[1]] - pointVec[f2.v[0]], pointVec[f2.v[2]] - pointVec[f2.v[0]]);
|
|
if (ret == 1)
|
|
{
|
|
intersect = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!intersect)
|
|
faces.push_back(f);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MH::removeSpecialFaces(int *idx, FaceHVec & faces, FaceHVec & outfaces)
|
|
{
|
|
// if there are special faces (faces that have all 3 verts of 12 'mc' edges), then remove them all - IF there are any other (non-special faces)
|
|
size_t i;
|
|
for (i = 0; i < faces.size(); i++)
|
|
{
|
|
if (idx[faces[i].v[0]] >= 12 || idx[faces[i].v[1]] >= 12 || idx[faces[i].v[2]] >= 12)
|
|
{
|
|
// we found non-special face
|
|
for (i = 0; i < faces.size(); i++)
|
|
{
|
|
if (idx[faces[i].v[0]] >= 12 || idx[faces[i].v[1]] >= 12 || idx[faces[i].v[2]] >= 12)
|
|
{
|
|
outfaces.push_back(faces[i]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void MH::FixNormals(const Vec3HVec & pointVec, FaceHVec & faces)
|
|
{
|
|
static const Vec3 c(0.5f, 0.5f, 0.5f), one_third(0.333333333333f, 0.333333333333f, 0.333333333333f);
|
|
|
|
for (size_t i = 0; i < faces.size(); i++)
|
|
{
|
|
Face &f = faces[i];
|
|
Vec3 cf = (pointVec[f.v[0]] + pointVec[f.v[1]] + pointVec[f.v[2]]) * one_third;
|
|
Vec3 n = (pointVec[f.v[2]] - pointVec[f.v[0]]).cross(pointVec[f.v[1]] - pointVec[f.v[0]]);
|
|
if (n.dot(cf - c) > 0)
|
|
{
|
|
// swap
|
|
int v = f.v[1];
|
|
f.v[1] = f.v[0];
|
|
f.v[0] = v;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MH::SortOutFaces(int *idx, FaceHVec & faces, FaceHVec faceGroups[7])
|
|
{
|
|
for (size_t i = 0; i < faces.size(); i++)
|
|
{
|
|
Face &f = faces[i];
|
|
bool inGroup = false;
|
|
for (int j = 0; j < 6; j++)
|
|
{
|
|
bool fv[3] = { false, false, false };
|
|
for (int k = 0; k < 9; k++)
|
|
{
|
|
for (int vi = 0; vi < 3; vi++)
|
|
{
|
|
if (idx[f.v[vi]] == faceVertices[j][k])
|
|
fv[vi] = true;
|
|
}
|
|
}
|
|
// if all 3 face verts are from the same cube face, then put them into face group
|
|
if (fv[0] && fv[1] && fv[2])
|
|
{
|
|
faceGroups[j].push_back(f);
|
|
inGroup = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!inGroup)
|
|
faceGroups[6].push_back(f);
|
|
}
|
|
}
|
|
|
|
int MH::AddUniqueFaceGroups(std::vector<FaceRecord> &faceStore, int *idx, FaceHVec &faces, bool *addedNew)
|
|
{
|
|
for (size_t j = 0; j < faceStore.size(); j++)
|
|
{
|
|
FaceRecord & fsvec = faceStore[j];
|
|
if (fsvec.faces.size() != faces.size())
|
|
continue;
|
|
bool notFound = false;
|
|
for (size_t i = 0; i < faces.size(); i++)
|
|
{
|
|
int a0 = idx[faces[i].v[0]];
|
|
int a1 = idx[faces[i].v[1]];
|
|
int a2 = idx[faces[i].v[2]];
|
|
bool found = false;
|
|
for (size_t k = 0; k < fsvec.faces.size(); k++)
|
|
{
|
|
int b0 = fsvec.faces[k].v[0];
|
|
int b1 = fsvec.faces[k].v[1];
|
|
int b2 = fsvec.faces[k].v[2];
|
|
if (a0 == b0)
|
|
{
|
|
if (a1 == b1)
|
|
{
|
|
if (a2 == b2)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
else if (a1 == b2)
|
|
{
|
|
if (a2 == b1)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (a0 == b1)
|
|
{
|
|
if (a1 == b0)
|
|
{
|
|
if (a2 == b2)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
else if (a1 == b2)
|
|
{
|
|
if (a2 == b0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (a0 == b2)
|
|
{
|
|
if (a1 == b0)
|
|
{
|
|
if (a2 == b1)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
else if (a1 == b1)
|
|
{
|
|
if (a2 == b0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
notFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (notFound)
|
|
continue;
|
|
|
|
// ok, we found it
|
|
return j;
|
|
}
|
|
|
|
// not found, add it to the list
|
|
FaceRecord newrec;
|
|
for (size_t k = 0; k < faces.size(); k++)
|
|
{
|
|
newrec.faces.push_back(Face::getFace(idx[faces[k].v[0]], idx[faces[k].v[1]], idx[faces[k].v[2]]));
|
|
}
|
|
newrec.idx = faceStore.size();
|
|
faceStore.push_back(newrec);
|
|
*addedNew = true;
|
|
return newrec.idx;
|
|
}
|