Initial release circa 2015
This commit is contained in:
commit
6857de388e
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Marching Hedrons LUT generator
|
||||
author: andrei (c) 2015
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "mh.h"
|
||||
|
||||
#define OUTPUT_BIN
|
||||
|
||||
//#define OUTPUT_TEXT
|
||||
|
||||
const int deviceIdx = 0;
|
||||
//const Distribution dist = UniformDistribution;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void addFace(FaceHVec *faces, int v0, int v1, int v2, int skipVert)
|
||||
{
|
||||
if (v0 == skipVert || v1 == skipVert || v2 == skipVert)
|
||||
return;
|
||||
faces->push_back(Face::getFace(v0, v1, v2));
|
||||
}
|
||||
|
||||
|
||||
//void setPoints(Point3HVec *pointNum, int *idx, int mask)
|
||||
void setPoints(Vec3HVec *pointNum, int *idx, int mask, int inv, int index)
|
||||
{
|
||||
for (int i = 0, j = 0; i < 26; i++)
|
||||
{
|
||||
int e0 = mask & (1 << MH::cell_edges[i][0]);
|
||||
int e1 = mask & (1 << MH::cell_edges[i][1]);
|
||||
if (MH::cell_edges[i][0] == 14) // special case for central edges
|
||||
{
|
||||
if (!e0)
|
||||
continue;
|
||||
}
|
||||
if ((e0 && !e1) || (!e0 && e1))
|
||||
{
|
||||
Vec3 p;
|
||||
if (index >= 0 && i < 8)
|
||||
{
|
||||
float coeff;
|
||||
coeff = MH::edge_indices[index][i & 3] == 0 ? 0.2f : 0.8f;
|
||||
p = MH::cell_vertices[MH::cell_edges[i][0]].interp(MH::cell_vertices[MH::cell_edges[i][1]], coeff);
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
if (inv == 0)
|
||||
k = 0;
|
||||
else if (i >= 8)
|
||||
k = 1;
|
||||
else
|
||||
k = 0;
|
||||
if (i < 12)
|
||||
{
|
||||
if ((mask & (1 << MH::edgeFacesCentralVertices[i][0])) && (mask & (1 << MH::edgeFacesCentralVertices[i][1])))
|
||||
{
|
||||
if (inv == 0)
|
||||
k = 1;
|
||||
else if (i >= 8)
|
||||
k = 0;
|
||||
else
|
||||
k = 1;
|
||||
}
|
||||
}
|
||||
p.x = MH::cell_hedron_vertices[k][i][0];
|
||||
p.y = MH::cell_hedron_vertices[k][i][1];
|
||||
p.z = MH::cell_hedron_vertices[k][i][2];
|
||||
}
|
||||
|
||||
|
||||
idx[j++] = i;
|
||||
pointNum->push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
#ifdef OUTPUT_BIN
|
||||
FILE *fpi = fopen("mh_idx.bin", "wb");
|
||||
FILE *fpi0 = fopen("mh_offs.bin", "wb");
|
||||
FILE *fpih = fopen("mh_h_idx.bin", "wb");
|
||||
FILE *fp = fopen("mh.bin", "wb");
|
||||
int offs = 0;
|
||||
#endif
|
||||
|
||||
MH::initConvexHull();
|
||||
|
||||
std::vector<FaceRecord> faceGroupStore[7];
|
||||
int totalIdx = 0;
|
||||
|
||||
for (int inv = 0; inv < 2; inv++)
|
||||
{
|
||||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
if (inv == 0)
|
||||
std::cout << "Starting Hedrons #" << idx << "...\n";
|
||||
else
|
||||
std::cout << "Starting Holes #" << idx << "...\n";
|
||||
|
||||
for (int i = 0; i < (1 << 14); i++)
|
||||
{
|
||||
Vec3HVec pointVec;
|
||||
int indices[26];
|
||||
|
||||
if (i > 0 && (i % 1000) == 0)
|
||||
{
|
||||
std::cout << "// " << i << std::endl;
|
||||
}
|
||||
|
||||
int mask = i | (1 << 14);
|
||||
|
||||
setPoints(&pointVec, indices, mask, inv, idx);
|
||||
|
||||
FaceHVec faces;
|
||||
FaceHVec faceGroups[7];
|
||||
|
||||
if (pointVec.size() == 3)
|
||||
{
|
||||
addFace(&faces, 0, 1, 2, -1);
|
||||
faceGroups[0].push_back(faces[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
FaceHVec fac;
|
||||
MH::computeConvexHull(pointVec, fac);
|
||||
MH::removeSpecialFaces(indices, fac, faces);
|
||||
MH::FixNormals(pointVec, faces);
|
||||
MH::SortOutFaces(indices, faces, faceGroups);
|
||||
}
|
||||
|
||||
#ifdef OUTPUT_TEXT
|
||||
std::cout << " /*" << i << " (N=" << faces.size() << ") */ { ";
|
||||
for (int j = 0; j < faces.size(); j++)
|
||||
{
|
||||
std::cout << "{ " << indices[faces[j].v[0]] << " /*" << faces[j].v[0] << "*/, " << indices[faces[j].v[1]] << "/*" << faces[j].v[1] << "*/, " << indices[faces[j].v[2]] << " /*" << faces[j].v[2] << "*/ }, ";
|
||||
}
|
||||
|
||||
std::cout << "{ -1, -1, -1 } }, " << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef OUTPUT_BIN
|
||||
for (int f = 0; f < 7; f++)
|
||||
{
|
||||
IntHVec offsList;
|
||||
bool addedNew = false;
|
||||
int fidx = MH::AddUniqueFaceGroups(faceGroupStore[f], indices, faceGroups[f], &addedNew);
|
||||
|
||||
FaceRecord &fr = faceGroupStore[f][fidx];
|
||||
if (addedNew) // new record added
|
||||
{
|
||||
fr.totalIdx = totalIdx;
|
||||
fwrite(&offs, sizeof(offs), 1, fpi0);
|
||||
fputc(fr.faces.size(), fp);
|
||||
offs ++;
|
||||
for (size_t j = 0; j < fr.faces.size(); j++)
|
||||
{
|
||||
fputc(fr.faces[j].v[0], fp);
|
||||
fputc(fr.faces[j].v[1], fp);
|
||||
fputc(fr.faces[j].v[2], fp);
|
||||
offs += 3;
|
||||
}
|
||||
totalIdx++;
|
||||
}
|
||||
|
||||
fputc(fr.totalIdx & 0xff, inv == 0 ? fpi : fpih);
|
||||
fputc((fr.totalIdx >> 8) & 0xff, inv == 0 ? fpi : fpih);
|
||||
//fputc((fr.totalIdx >> 16) & 0xff, inv == 0 ? fpi : fpih);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OUTPUT_BIN
|
||||
fclose(fp);
|
||||
fclose(fpi);
|
||||
fclose(fpi0);
|
||||
fclose(fpih);
|
||||
#endif
|
||||
|
||||
std::cout << "NUM: " << faceGroupStore[0].size() << " " << faceGroupStore[1].size() << " " << faceGroupStore[2].size()
|
||||
<< " " << faceGroupStore[3].size() << " " << faceGroupStore[4].size() << " " << faceGroupStore[5].size()
|
||||
<< " " << faceGroupStore[6].size() << std::endl;
|
||||
std::cout << "TOTALIDX = " << totalIdx << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Marching Hedrons LUT generator
|
||||
author: andrei (c) 2015
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _MH_H_
|
||||
#define _MH_H_
|
||||
|
||||
#include <vector>
|
||||
#include "vec.h"
|
||||
|
||||
struct Face
|
||||
{
|
||||
int v[3];
|
||||
|
||||
static Face getFace(int v0, int v1, int v2)
|
||||
{
|
||||
Face f;
|
||||
// 012
|
||||
f.v[0] = v0; f.v[1] = v1; f.v[2] = v2;
|
||||
return f;
|
||||
}
|
||||
|
||||
static Face getSortedFace(int v0, int v1, int v2)
|
||||
{
|
||||
Face f;
|
||||
// 012
|
||||
if (v0 < v1 && v1 < v2)
|
||||
{
|
||||
f.v[0] = v0; f.v[1] = v1; f.v[2] = v2;
|
||||
}
|
||||
// 021
|
||||
if (v0 < v2 && v2 < v1)
|
||||
{
|
||||
f.v[0] = v0; f.v[1] = v2; f.v[2] = v1;
|
||||
}
|
||||
// 102
|
||||
if (v1 < v0 && v0 < v2)
|
||||
{
|
||||
f.v[0] = v1; f.v[1] = v0; f.v[2] = v2;
|
||||
}
|
||||
// 120
|
||||
if (v1 < v2 && v2 < v0)
|
||||
{
|
||||
f.v[0] = v1; f.v[1] = v2; f.v[2] = v0;
|
||||
}
|
||||
// 201
|
||||
if (v2 < v0 && v0 < v1)
|
||||
{
|
||||
f.v[0] = v2; f.v[1] = v0; f.v[2] = v1;
|
||||
}
|
||||
// 210
|
||||
if (v2 < v1 && v1 < v0)
|
||||
{
|
||||
f.v[0] = v2; f.v[1] = v1; f.v[2] = v0;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
friend bool operator== (const Face &n1, const Face &n2)
|
||||
{
|
||||
return Face::equal(n1, n2);
|
||||
}
|
||||
|
||||
friend bool operator!= (const Face &n1, const Face &n2)
|
||||
{
|
||||
return !Face::equal(n1, n2);
|
||||
};
|
||||
|
||||
private:
|
||||
static bool equal(const Face & f0, const Face & f1)
|
||||
{
|
||||
return (f0.v[0] == f1.v[0] && f0.v[1] == f1.v[1] && f0.v[2] == f1.v[2]) ||
|
||||
(f0.v[0] == f1.v[0] && f0.v[1] == f1.v[2] && f0.v[2] == f1.v[1]) ||
|
||||
(f0.v[0] == f1.v[1] && f0.v[1] == f1.v[0] && f0.v[2] == f1.v[2]) ||
|
||||
(f0.v[0] == f1.v[1] && f0.v[1] == f1.v[2] && f0.v[2] == f1.v[0]) ||
|
||||
(f0.v[0] == f1.v[2] && f0.v[1] == f1.v[1] && f0.v[2] == f1.v[0]) ||
|
||||
(f0.v[0] == f1.v[2] && f0.v[1] == f1.v[0] && f0.v[2] == f1.v[1]);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Face> FaceHVec;
|
||||
|
||||
typedef std::vector<Vec3> Vec3HVec;
|
||||
|
||||
typedef std::vector<int> IntHVec;
|
||||
|
||||
struct FaceRecord
|
||||
{
|
||||
FaceHVec faces;
|
||||
int idx;
|
||||
int totalIdx;
|
||||
};
|
||||
|
||||
class MH
|
||||
{
|
||||
public:
|
||||
static const int cell_edges[26][2];
|
||||
static const Vec3 cell_vertices[8];
|
||||
static const float cell_hedron_vertices[2][26][3];
|
||||
static const int faceVertices[6][9];
|
||||
static const int edgeFacesCentralVertices[12][2];
|
||||
static int edge_indices[16][4];
|
||||
|
||||
public:
|
||||
|
||||
static bool initConvexHull();
|
||||
static bool computeConvexHull(const Vec3HVec & pointVec, FaceHVec & faces);
|
||||
static bool removeSpecialFaces(int *idx, FaceHVec & faces, FaceHVec & outfaces);
|
||||
static void FixNormals(const Vec3HVec & pointVec, FaceHVec & outfaces);
|
||||
static void SortOutFaces(int *idx, FaceHVec & faces, FaceHVec faceGroups[7]);
|
||||
static int AddUniqueFaceGroups(std::vector<FaceRecord> &faceStore, int *idx, FaceHVec &faceGroups, bool *addedNew);
|
||||
|
||||
static int tr_tri_intersect3D(const Vec3 & C1, const Vec3 & P1, const Vec3 & P2, const Vec3 & D1, const Vec3 & Q1, const Vec3 & Q2);
|
||||
};
|
||||
|
||||
#endif // of _MH_H_
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Marching Hedrons LUT generator
|
||||
author: andrei (c) 2015
|
||||
|
||||
*/
|
||||
|
||||
#include "mh.h"
|
||||
|
||||
const int MH::cell_edges[26][2] =
|
||||
{
|
||||
// the first 12 edges are the same as in MC
|
||||
{ 0, 1 }, { 1, 5 }, { 5, 4 }, { 4, 0 },
|
||||
{ 3, 2 }, { 2, 6 }, { 6, 7 }, { 7, 3 },
|
||||
{ 0, 3 }, { 1, 2 }, { 5, 6 }, { 4, 7 },
|
||||
|
||||
// there are 14 more edges coming from the central point:
|
||||
// - 8 to corner
|
||||
{ 14, 0 }, { 14, 1 }, { 14, 2 }, { 14, 3 },
|
||||
{ 14, 4 }, { 14, 5 }, { 14, 6 }, { 14, 7 },
|
||||
// - and 6 to facenormal (center of each cube face)
|
||||
{ 14, 8 }, { 14, 9 }, { 14, 10 }, { 14, 11 }, { 14, 12 }, { 14, 13 },
|
||||
};
|
||||
|
||||
|
||||
#define E01 0.05
|
||||
#define E09 0.95
|
||||
#define V00 0.01
|
||||
#define V10 0.99
|
||||
|
||||
const Vec3 MH::cell_vertices[8] =
|
||||
{
|
||||
Vec3(V00, V00, V00), Vec3(V10, V00, V00), Vec3(V10, V10, V00), Vec3(V00, V10, V00),
|
||||
Vec3(V00, V00, V10), Vec3(V10, V00, V10), Vec3(V10, V10, V10), Vec3(V00, V10, V10),
|
||||
};
|
||||
|
||||
#define A05 0.2
|
||||
|
||||
const float MH::cell_hedron_vertices[2][26][3] =
|
||||
{
|
||||
// low
|
||||
{
|
||||
// 12 cube edges
|
||||
// ++--
|
||||
// ++--
|
||||
{ A05, V00, V00 }, { V10, V00, A05 }, { A05, V00, V10 }, { V00, V00, A05 },
|
||||
{ A05, V10, V00 }, { V10, V10, A05 }, { A05, V10, V10 }, { V00, V10, A05 },
|
||||
{ V00, A05, V00 }, { V10, A05, V00 }, { V10, A05, V10 }, { V00, A05, V10 },
|
||||
|
||||
// 8 center-to-corner edges
|
||||
{ E01, E01, E01 }, { E09, E01, E01 }, { E09, E09, E01 }, { E01, E09, E01 },
|
||||
{ E01, E01, E09 }, { E09, E01, E09 }, { E09, E09, E09 }, { E01, E09, E09 },
|
||||
|
||||
// 6 center-to-facenormal edges
|
||||
{ 0.5, 1.0, 0.5 }, { 0.5, 0.5, 0.0 }, { 1.0, 0.5, 0.5 }, { 0.5, 0.5, 1.0 }, { 0.0, 0.5, 0.5 }, { 0.5, 0.0, 0.5 },
|
||||
},
|
||||
|
||||
#undef A05
|
||||
#define A05 0.8
|
||||
// high
|
||||
{
|
||||
// 12 cube edges
|
||||
{ A05, V00, V00 }, { V10, V00, A05 }, { A05, V00, V10 }, { V00, V00, A05 },
|
||||
{ A05, V10, V00 }, { V10, V10, A05 }, { A05, V10, V10 }, { V00, V10, A05 },
|
||||
{ V00, A05, V00 }, { V10, A05, V00 }, { V10, A05, V10 }, { V00, A05, V10 },
|
||||
|
||||
// 8 center-to-corner edges
|
||||
{ E01, E01, E01 }, { E09, E01, E01 }, { E09, E09, E01 }, { E01, E09, E01 },
|
||||
{ E01, E01, E09 }, { E09, E01, E09 }, { E09, E09, E09 }, { E01, E09, E09 },
|
||||
|
||||
// 6 center-to-facenormal edges
|
||||
{ 0.5, 1.0, 0.5 }, { 0.5, 0.5, 0.0 }, { 1.0, 0.5, 0.5 }, { 0.5, 0.5, 1.0 }, { 0.0, 0.5, 0.5 }, { 0.5, 0.0, 0.5 },
|
||||
}
|
||||
};
|
||||
|
||||
const int MH::faceVertices[6][9] =
|
||||
{
|
||||
{ 4, 5, 6, 7, 14, 15, 18, 19, 20 },
|
||||
{ 0, 8, 4, 9, 12, 13, 14, 15, 21 },
|
||||
{ 1, 9, 5, 10, 13, 14, 18, 17, 22 },
|
||||
{ 2, 10, 6, 11, 16, 17, 18, 19, 23 },
|
||||
{ 3, 8, 7, 11, 12, 15, 19, 16, 24 },
|
||||
{ 0, 1, 2, 3, 12, 13, 17, 16, 25 },
|
||||
};
|
||||
|
||||
const int MH::edgeFacesCentralVertices[12][2] =
|
||||
{
|
||||
{ 13, 9 }, { 13, 10 }, { 13, 11 }, { 13, 12 },
|
||||
{ 8, 9 }, { 8, 10 }, { 8, 11 }, { 8, 12 },
|
||||
{ 9, 12 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
|
||||
};
|
||||
|
||||
int MH::edge_indices[16][4];
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
|
||||
Marching Hedrons LUT generator
|
||||
author: andrei (c) 2015
|
||||
|
||||
Come code taken from:
|
||||
|
||||
"A fast triangle to triangle intersection test for collision detection"
|
||||
Oren Tropp, Ayellet Tal, Ilan Shimshoni
|
||||
Computer Animation and Virtual Worlds 17(5) 2006, pp 527-535.
|
||||
|
||||
You are free to use the code but cite the paper.
|
||||
|
||||
|
||||
The following code tests for 3D triangle triangle intersection.
|
||||
Main procedures:
|
||||
|
||||
int tr_tri_intersect3D (float *C1, float *P1, float *P2,
|
||||
float *D1, float *Q1, float *Q2);
|
||||
|
||||
int coplanar_tri_tri(float N[3],float V0[3],float V1[3],float V2[3],
|
||||
float U0[3],float U1[3],float U2[3]);
|
||||
|
||||
|
||||
tr_tri_intersect3D - C1 is a vertex of triangle A. P1,P2 are the two edges originating from this vertex.
|
||||
D1 is a vertex of triangle B. P1,P2 are the two edges originating from this vertex.
|
||||
Returns zero for disjoint triangles and non-zero for intersection.
|
||||
|
||||
coplanar_tri_tri - This procedure for testing coplanar triangles for intersection is
|
||||
taken from Tomas Moller's algorithm.
|
||||
See article "A Fast Triangle-Triangle Intersection Test",
|
||||
Journal of Graphics Tools, 2(2), 1997
|
||||
V1,V2,V3 are vertices of one triangle with normal N. U1,U2,U3 are vertices of the other
|
||||
triangle.
|
||||
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
#include <time.h>
|
||||
#ifndef UNIX
|
||||
#define drand48() (rand()*1.0/RAND_MAX)
|
||||
#endif
|
||||
|
||||
|
||||
#include "vec.h"
|
||||
#include "mh.h"
|
||||
|
||||
int coplanar_tri_tri(float N[3], float V0[3], float V1[3], float V2[3],
|
||||
float U0[3], float U1[3], float U2[3]);
|
||||
|
||||
// some vector macros
|
||||
#define CROSS(dest,v1,v2) \
|
||||
dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
|
||||
dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
|
||||
dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
|
||||
|
||||
|
||||
|
||||
#define sVpsV_2( Vr, s1, V1,s2, V2);\
|
||||
{\
|
||||
Vr[0] = s1*V1[0] + s2*V2[0];\
|
||||
Vr[1] = s1*V1[1] + s2*V2[1];\
|
||||
}\
|
||||
|
||||
#define myVpV(g,v2,v1);\
|
||||
{\
|
||||
g[0] = v2[0]+v1[0];\
|
||||
g[1] = v2[1]+v1[1];\
|
||||
g[2] = v2[2]+v1[2];\
|
||||
}\
|
||||
|
||||
#define myVmV(g,v2,v1);\
|
||||
{\
|
||||
g[0] = v2[0]-v1[0];\
|
||||
g[1] = v2[1]-v1[1];\
|
||||
g[2] = v2[2]-v1[2];\
|
||||
}\
|
||||
|
||||
// 2D intersection of segment and triangle.
|
||||
#define seg_collide3( q, r)\
|
||||
{\
|
||||
p1[0]=SF*P1[0];\
|
||||
p1[1]=SF*P1[1];\
|
||||
p2[0]=SF*P2[0];\
|
||||
p2[1]=SF*P2[1];\
|
||||
det1 = p1[0]*q[1]-q[0]*p1[1];\
|
||||
gama1 = (p1[0]*r[1]-r[0]*p1[1])*det1;\
|
||||
alpha1 = (r[0]*q[1] - q[0]*r[1])*det1;\
|
||||
alpha1_legal = (alpha1>=0) && (alpha1<=(det1*det1) && (det1!=0));\
|
||||
det2 = p2[0]*q[1] - q[0]*p2[1];\
|
||||
alpha2 = (r[0]*q[1] - q[0]*r[1]) *det2;\
|
||||
gama2 = (p2[0]*r[1] - r[0]*p2[1]) * det2;\
|
||||
alpha2_legal = (alpha2>=0) && (alpha2<=(det2*det2) && (det2 !=0));\
|
||||
det3=det2-det1;\
|
||||
gama3=((p2[0]-p1[0])*(r[1]-p1[1]) - (r[0]-p1[0])*(p2[1]-p1[1]))*det3;\
|
||||
if (alpha1_legal)\
|
||||
{\
|
||||
if (alpha2_legal)\
|
||||
{\
|
||||
if ( ((gama1<=0) && (gama1>=-(det1*det1))) || ((gama2<=0) && (gama2>=-(det2*det2))) || (gama1*gama2<0)) return 12;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if ( ((gama1<=0) && (gama1>=-(det1*det1))) || ((gama3<=0) && (gama3>=-(det3*det3))) || (gama1*gama3<0)) return 13;\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
if (alpha2_legal)\
|
||||
{\
|
||||
if ( ((gama2<=0) && (gama2>=-(det2*det2))) || ((gama3<=0) && (gama3>=-(det3*det3))) || (gama2*gama3<0)) return 23;\
|
||||
}\
|
||||
return 0;\
|
||||
}
|
||||
|
||||
|
||||
#define FABS(x) ((x)>=0?(x):-(x)) /* implement as is fastest on your machine */
|
||||
|
||||
#define EQU(V0, V1) (FABS((V0) - (V1)) < 1e-6)
|
||||
#define ZERO(V) (FABS(V) < 1e-6)
|
||||
|
||||
//main procedure
|
||||
|
||||
int tr_tri_intersect3D(float *C1, float *P1, float *P2, float *D1, float *Q1, float *Q2)
|
||||
{
|
||||
float t[3], p1[3], p2[3], r[3], r4[3];
|
||||
float beta1, beta2, beta3;
|
||||
float gama1, gama2, gama3;
|
||||
float det1, det2, det3;
|
||||
float dp0, dp1, dp2;
|
||||
float dq1, dq2, dq3, dr, dr3;
|
||||
float alpha1, alpha2;
|
||||
bool alpha1_legal, alpha2_legal;
|
||||
float SF;
|
||||
bool beta1_legal, beta2_legal;
|
||||
|
||||
myVmV(r, D1, C1);
|
||||
// determinant computation
|
||||
dp0 = P1[1] * P2[2] - P2[1] * P1[2];
|
||||
dp1 = P1[0] * P2[2] - P2[0] * P1[2];
|
||||
dp2 = P1[0] * P2[1] - P2[0] * P1[1];
|
||||
dq1 = Q1[0] * dp0 - Q1[1] * dp1 + Q1[2] * dp2;
|
||||
dq2 = Q2[0] * dp0 - Q2[1] * dp1 + Q2[2] * dp2;
|
||||
dr = -r[0] * dp0 + r[1] * dp1 - r[2] * dp2;
|
||||
|
||||
|
||||
|
||||
beta1 = dr*dq2; // beta1, beta2 are scaled so that beta_i=beta_i*dq1*dq2
|
||||
beta2 = dr*dq1;
|
||||
beta1_legal = (beta2 >= 0) && (beta2 <= dq1*dq1) && (dq1 != 0);
|
||||
beta2_legal = (beta1 >= 0) && (beta1 <= dq2*dq2) && (dq2 != 0);
|
||||
|
||||
dq3 = dq2 - dq1;
|
||||
dr3 = +dr - dq1; // actually this is -dr3
|
||||
|
||||
|
||||
if (ZERO(dq1) && ZERO(dq2))
|
||||
{
|
||||
if (dr != 0) return 0; // triangles are on parallel planes
|
||||
else
|
||||
{ // triangles are on the same plane
|
||||
float C2[3], C3[3], D2[3], D3[3], N1[3];
|
||||
// We use the coplanar test of Moller which takes the 6 vertices and 2 normals
|
||||
//as input.
|
||||
myVpV(C2, C1, P1);
|
||||
myVpV(C3, C1, P2);
|
||||
myVpV(D2, D1, Q1);
|
||||
myVpV(D3, D1, Q2);
|
||||
CROSS(N1, P1, P2);
|
||||
return coplanar_tri_tri(N1, C1, C2, C3, D1, D2, D3);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!beta2_legal && !beta1_legal) return 0;// fast reject-all vertices are on
|
||||
// the same side of the triangle plane
|
||||
|
||||
else if (beta2_legal && beta1_legal) //beta1, beta2
|
||||
{
|
||||
SF = dq1*dq2;
|
||||
sVpsV_2(t, beta2, Q2, (-beta1), Q1);
|
||||
}
|
||||
|
||||
else if (beta1_legal && !beta2_legal) //beta1, beta3
|
||||
{
|
||||
SF = dq1*dq3;
|
||||
beta1 = beta1 - beta2; // all betas are multiplied by a positive SF
|
||||
beta3 = dr3*dq1;
|
||||
sVpsV_2(t, (SF - beta3 - beta1), Q1, beta3, Q2);
|
||||
}
|
||||
|
||||
else if (beta2_legal && !beta1_legal) //beta2, beta3
|
||||
{
|
||||
SF = dq2*dq3;
|
||||
beta2 = beta1 - beta2; // all betas are multiplied by a positive SF
|
||||
beta3 = dr3*dq2;
|
||||
sVpsV_2(t, (SF - beta3), Q1, (beta3 - beta2), Q2);
|
||||
Q1 = Q2;
|
||||
beta1 = beta2;
|
||||
}
|
||||
sVpsV_2(r4, SF, r, beta1, Q1);
|
||||
seg_collide3(t, r4); // calculates the 2D intersection
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* this edge to edge test is based on Franlin Antonio's gem:
|
||||
"Faster Line Segment Intersection", in Graphics Gems III,
|
||||
pp. 199-202 */
|
||||
|
||||
int EDGE_EDGE_TEST(float *V0, float *V1, float *U0, float *U1, int i0, int i1, float Ax, float Ay)
|
||||
{
|
||||
float Bx, By, Cx, Cy, e, d, f;
|
||||
Bx = U0[i0] - U1[i0];
|
||||
By = U0[i1] - U1[i1];
|
||||
Cx = V0[i0] - U0[i0];
|
||||
Cy = V0[i1] - U0[i1];
|
||||
|
||||
// if edges are adjacent
|
||||
if (EQU(V0[i0], U0[i0]) && EQU(V0[i1], U0[i1]))
|
||||
return 0;
|
||||
if (EQU(V0[i0], U1[i0]) && EQU(V0[i1], U1[i1]))
|
||||
return 0;
|
||||
if (EQU(V1[i0], U0[i0]) && EQU(V1[i1], U0[i1]))
|
||||
return 0;
|
||||
if (EQU(V1[i0], U1[i0]) && EQU(V1[i1], U1[i1]))
|
||||
return 0;
|
||||
|
||||
f = Ay*Bx - Ax*By;
|
||||
d = By*Cx - Bx*Cy;
|
||||
if ((f > 0 && d >= 0 && d <= f) || (f<0 && d <= 0 && d >= f))
|
||||
{
|
||||
e = Ax*Cy - Ay*Cx;
|
||||
if (f>0)
|
||||
{
|
||||
if (e >= 0 && e <= f) return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e <= 0 && e >= f) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EDGE_AGAINST_TRI_EDGES(float *V0, float *V1, float *U0, float *U1, float *U2, int i0, int i1)
|
||||
{
|
||||
float Ax,Ay;
|
||||
Ax=V1[i0]-V0[i0];
|
||||
Ay=V1[i1]-V0[i1];
|
||||
/* test edge U0,U1 against V0,V1 */
|
||||
if (EDGE_EDGE_TEST(V0, V1, U0, U1, i0, i1, Ax, Ay) != 0)
|
||||
return 1;
|
||||
/* test edge U1,U2 against V0,V1 */
|
||||
if (EDGE_EDGE_TEST(V0, V1, U1, U2, i0, i1, Ax, Ay) != 0)
|
||||
return 1;
|
||||
/* test edge U2,U1 against V0,V1 */
|
||||
if (EDGE_EDGE_TEST(V0, V1, U2, U0, i0, i1, Ax, Ay) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define POINT_IN_TRI(V0,U0,U1,U2) \
|
||||
{ \
|
||||
float a,b,c,d0,d1,d2; \
|
||||
/* is T1 completly inside T2? */ \
|
||||
/* check if V0 is inside tri(U0,U1,U2) */ \
|
||||
a=U1[i1]-U0[i1]; \
|
||||
b=-(U1[i0]-U0[i0]); \
|
||||
c=-a*U0[i0]-b*U0[i1]; \
|
||||
d0=a*V0[i0]+b*V0[i1]+c; \
|
||||
\
|
||||
a=U2[i1]-U1[i1]; \
|
||||
b=-(U2[i0]-U1[i0]); \
|
||||
c=-a*U1[i0]-b*U1[i1]; \
|
||||
d1=a*V0[i0]+b*V0[i1]+c; \
|
||||
\
|
||||
a=U0[i1]-U2[i1]; \
|
||||
b=-(U0[i0]-U2[i0]); \
|
||||
c=-a*U2[i0]-b*U2[i1]; \
|
||||
d2=a*V0[i0]+b*V0[i1]+c; \
|
||||
if(d0*d1>0.0) \
|
||||
{ \
|
||||
if(d0*d2>0.0) return 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
//This procedure testing for intersection between coplanar triangles is taken
|
||||
// from Tomas Moller's
|
||||
//"A Fast Triangle-Triangle Intersection Test",Journal of Graphics Tools, 2(2), 1997
|
||||
int coplanar_tri_tri(float N[3], float V0[3], float V1[3], float V2[3],
|
||||
float U0[3], float U1[3], float U2[3])
|
||||
{
|
||||
float A[3];
|
||||
short i0, i1;
|
||||
/* first project onto an axis-aligned plane, that maximizes the area */
|
||||
/* of the triangles, compute indices: i0,i1. */
|
||||
A[0] = FABS(N[0]);
|
||||
A[1] = FABS(N[1]);
|
||||
A[2] = FABS(N[2]);
|
||||
if (A[0]>A[1])
|
||||
{
|
||||
if (A[0]>A[2])
|
||||
{
|
||||
i0 = 1; /* A[0] is greatest */
|
||||
i1 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = 0; /* A[2] is greatest */
|
||||
i1 = 1;
|
||||
}
|
||||
}
|
||||
else /* A[0]<=A[1] */
|
||||
{
|
||||
if (A[2]>A[1])
|
||||
{
|
||||
i0 = 0; /* A[2] is greatest */
|
||||
i1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = 0; /* A[1] is greatest */
|
||||
i1 = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* test all edges of triangle 1 against the edges of triangle 2 */
|
||||
if (EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2, i0, i1) != 0)
|
||||
return 1;
|
||||
if (EDGE_AGAINST_TRI_EDGES(V1, V2, U0, U1, U2, i0, i1) != 0)
|
||||
return 1;
|
||||
if (EDGE_AGAINST_TRI_EDGES(V2, V0, U0, U1, U2, i0, i1) != 0)
|
||||
return 1;
|
||||
|
||||
/* finally, test if tri1 is totally contained in tri2 or vice versa */
|
||||
POINT_IN_TRI(V0, U0, U1, U2);
|
||||
POINT_IN_TRI(U0, V0, V1, V2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MH::tr_tri_intersect3D(const Vec3 & C1, const Vec3 & P1, const Vec3 & P2, const Vec3 & D1, const Vec3 & Q1, const Vec3 & Q2)
|
||||
{
|
||||
float *fC1 = (float *)(Vec3 *)&C1;
|
||||
float *fP1 = (float *)(Vec3 *)&P1;
|
||||
float *fP2 = (float *)(Vec3 *)&P2;
|
||||
float *fD1 = (float *)(Vec3 *)&D1;
|
||||
float *fQ1 = (float *)(Vec3 *)&Q1;
|
||||
float *fQ2 = (float *)(Vec3 *)&Q2;
|
||||
return ::tr_tri_intersect3D(fC1, fP1, fP2, fD1, fQ1, fQ2);
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
#ifndef VEC_H
|
||||
#define VEC_H
|
||||
|
||||
class Vec2
|
||||
{
|
||||
public:
|
||||
float x, y;
|
||||
|
||||
public:
|
||||
Vec2() : x(0.0f), y(0.0f) {}
|
||||
Vec2(float _x, float _y) : x(_x), y(_y) {}
|
||||
Vec2(const Vec2 & v) : x(v.x), y(v.y) {}
|
||||
};
|
||||
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
|
||||
public:
|
||||
Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||
Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
Vec3(const Vec3 & v) : x(v.x), y(v.y), z(v.z) {}
|
||||
|
||||
public:
|
||||
Vec3 normalize()
|
||||
{
|
||||
float l = sqrtf(x * x + y * y + z * z);
|
||||
if (l != 0.0f)
|
||||
{
|
||||
x /= l;
|
||||
y /= l;
|
||||
z /= l;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec3 cross(const Vec3 & vec) const
|
||||
{
|
||||
return Vec3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
|
||||
}
|
||||
|
||||
float dot(const Vec3 & vec) const
|
||||
{
|
||||
return x * vec.x + y * vec.y + z * vec.z;
|
||||
}
|
||||
|
||||
Vec3 interp(const Vec3 & vec, float coeff) const
|
||||
{
|
||||
float coeff_1 = 1.0f - coeff;
|
||||
return Vec3(x * coeff_1 + vec.x * coeff, y * coeff_1 + vec.y * coeff, z * coeff_1 + vec.z * coeff);
|
||||
}
|
||||
|
||||
float squaredDist() const
|
||||
{
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
friend Vec3 operator + (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return Vec3(u.x + v.x, u.y + v.y, u.z + v.z);
|
||||
}
|
||||
|
||||
friend Vec3 operator - (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return Vec3(u.x - v.x, u.y - v.y, u.z - v.z);
|
||||
}
|
||||
|
||||
friend Vec3 operator * (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return Vec3(u.x * v.x, u.y * v.y, u.z * v.z);
|
||||
}
|
||||
|
||||
friend Vec3 operator / (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return Vec3(u.x / v.x, u.y / v.y, u.z / v.z);
|
||||
}
|
||||
|
||||
friend bool operator == (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return u.x == v.x && u.y == v.y && u.z == v.z;
|
||||
}
|
||||
|
||||
friend bool operator != (const Vec3 & u, const Vec3 & v)
|
||||
{
|
||||
return u.x != v.x || u.y != v.y || u.z != v.z;
|
||||
}
|
||||
|
||||
public:
|
||||
static const Vec3 Zero()
|
||||
{
|
||||
return Vec3();
|
||||
}
|
||||
};
|
||||
|
||||
class Vec4
|
||||
{
|
||||
public:
|
||||
float x, y, z, w;
|
||||
|
||||
public:
|
||||
Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
|
||||
Vec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {}
|
||||
Vec4(const Vec4 & v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
|
||||
|
||||
public:
|
||||
float dot(const Vec4 & vec) const
|
||||
{
|
||||
return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
|
||||
}
|
||||
|
||||
Vec4 interp(const Vec4 & vec, float coeff) const
|
||||
{
|
||||
float coeff_1 = 1.0f - coeff;
|
||||
return Vec4(x * coeff_1 + vec.x * coeff, y * coeff_1 + vec.y * coeff, z * coeff_1 + vec.z * coeff, w * coeff_1 + vec.w * coeff);
|
||||
}
|
||||
|
||||
friend Vec4 operator + (const Vec4 & u, const Vec4 & v)
|
||||
{
|
||||
return Vec4(u.x + v.x, u.y + v.y, u.z + v.z, u.w + v.w);
|
||||
}
|
||||
|
||||
friend Vec4 operator - (const Vec4 & u, const Vec4 & v)
|
||||
{
|
||||
return Vec4(u.x - v.x, u.y - v.y, u.z - v.z, u.w - v.w);
|
||||
}
|
||||
|
||||
friend Vec4 operator * (const Vec4 & u, const Vec4 & v)
|
||||
{
|
||||
return Vec4(u.x * v.x, u.y * v.y, u.z * v.z, u.w * v.w);
|
||||
}
|
||||
|
||||
friend Vec4 operator / (const Vec4 & u, const Vec4 & v)
|
||||
{
|
||||
return Vec4(u.x / v.x, u.y / v.y, u.z / v.z, u.w / v.w);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // of VEC_H
|
Loading…
Reference in New Issue