还是作业的一部分……
loop借鉴了http://2n1.org/opengl/proj2/里面的算法, 感谢!
butterfly则是根据ppt的算法。
一下是loop。h
#ifndef LOOP_H_
#define LOOP_H_
#include "halfedge_vector.h"
#define PI 3.14159265359
#include <assert.h>
halfegde_point getMiddlePoint(halfegde_point a, halfegde_point b)
{
halfegde_point newp1;
newp1.x = (a.x+b.x)/2;
newp1.y = (a.y+b.y)/2;
newp1.z = (a.z+b.z)/2;
newp1.isnew = true;
newp1.edge_index = -1;
newp1.beighbour.clear();
return newp1;
}
void addEdge(int p1, int p2, int p3, vector<halfegde_point> &p, vector<halfegde> &e, vector<halfedge_face> &f)
{
halfedge_face f1;
f.push_back(f1);
int fi = f.size()-1;
halfegde e1, e2, e3;
e.push_back(e1);
e.push_back(e2);
e.push_back(e3);
int ei1, ei2, ei3;
ei3 = e.size()-1;
ei2 = ei3-1;
ei1 = ei2-1;
e[ei1].original_point_index = p1;
e[ei1].next_edge_index = ei2;
e[ei1].previous_edge_index = ei3;
e[ei1].twin_edge_index = -1;
e[ei1].face_index = fi;
e[ei1].split_point_index = -1;
e[ei1].issplited = false;
p[p1].edge_index = ei1;
e[ei2].original_point_index = p2;
e[ei2].next_edge_index = ei3;
e[ei2].previous_edge_index = ei1;
e[ei2].twin_edge_index = -1;
e[ei2].face_index = fi;
e[ei2].split_point_index = -1;
e[ei2].issplited = false;
p[p2].edge_index = ei2;
e[ei3].original_point_index = p3;
e[ei3].next_edge_index = ei1;
e[ei3].previous_edge_index = ei2;
e[ei3].twin_edge_index = -1;
e[ei3].face_index = fi;
e[ei3].split_point_index = -1;
e[ei3].issplited = false;
p[p3].edge_index = ei3;
f[fi].one_edge_index = ei1;
}
void update_newpoint(vector<halfegde_point>&p, vector<halfedge_face>f, vector<halfegde>e, vector<halfegde_point> &p2)
{
// points initial
for (int i = 0; i< p.size(); i++)
{
// is it right?
// address or data?
halfegde_point tmp;
tmp.x = p[i].x;
tmp.y = p[i].y;
tmp.z = p[i].z;
tmp.isnew = p[i].isnew;
tmp.edge_index = p[i].edge_index;
for (int j = 0; j< p[i].beighbour.size(); j++)
{
tmp.beighbour.push_back(p[i].beighbour[j]);
}
p2.push_back(tmp);
}
for (int i = 0; i< p.size(); i++)
{
vector<int> neigh = p[i].beighbour;
int n = neigh.size();
float bn = 1.25-(3+2*cos(2*PI/n))*(3+2*cos(2*PI/n))/32;
float an = n*(1-bn)/bn;
float x = 0, y = 0, z = 0;
for (int j = 0; j< n; j++)
{
x+= p[neigh[j]].x;
y+= p[neigh[j]].y;
z+= p[neigh[j]].z;
}
p2[i].x = (p[i].x*an+x)/(an+n);
p2[i].y = (p[i].y*an+y)/(an+n);
p2[i].z = (p[i].z*an+z)/(an+n);
}
}
void getloop(vector<halfegde_point>p, vector<halfedge_face>f, vector<halfegde>e,
vector<halfegde_point> &p2, vector<halfedge_face> &f2, vector<halfegde> &e2)
{
// points initial
for (int i = 0; i< p.size(); i++)
{
// is it right?
// address or data?
halfegde_point tmp;
tmp.x = p[i].x;
tmp.y = p[i].y;
tmp.z = p[i].z;
tmp.isnew = p[i].isnew;
tmp.edge_index = p[i].edge_index;
for (int j = 0; j< p[i].beighbour.size(); j++)
{
tmp.beighbour.push_back(p[i].beighbour[j]);
}
p2.push_back(tmp);
}
// face
for (int i = 0; i< f.size(); i++)
{
int edge1 = f[i].one_edge_index;
int edge2 = e[edge1].next_edge_index;
int edge3 = e[edge2].next_edge_index;
assert(e[edge3].next_edge_index == edge1);
int point1 = e[edge1].original_point_index;
int point2 = e[edge2].original_point_index;
int point3 = e[edge3].original_point_index;
int newpindex1, newpindex2, newpindex3;
// e1
if (e[edge1].issplited)
{
newpindex1 = e[edge1].split_point_index;
}
else
{
halfegde_point newp1 = getMiddlePoint(p[point1], p[point2]);
p2.push_back(newp1);
newpindex1 = p2.size()-1;
e[edge1].issplited = true;
e[edge1].split_point_index = newpindex1;
int etwin = e[edge1].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex1;
}
}
// e2
if (e[edge2].issplited)
{
newpindex2 = e[edge2].split_point_index;
}
else
{
halfegde_point newp2 = getMiddlePoint(p[point2], p[point3]);
p2.push_back(newp2);
newpindex2 = p2.size()-1;
e[edge2].issplited = true;
e[edge2].split_point_index = newpindex2;
int etwin = e[edge2].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex2;
}
}
// e3
if (e[edge3].issplited)
{
newpindex3 = e[edge3].split_point_index;
}
else
{
halfegde_point newp3 = getMiddlePoint(p[point3], p[point1]);
p2.push_back(newp3);
newpindex3 = p2.size()-1;
e[edge3].issplited = true;
e[edge3].split_point_index = newpindex3;
int etwin = e[edge3].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex3;
}
}
// add face;
addEdge(point1, newpindex1, newpindex3,p2, e2, f2);
addEdge(newpindex1, point2, newpindex2,p2, e2, f2);
addEdge(newpindex3, newpindex2, point3,p2, e2, f2);
addEdge(newpindex1, newpindex2, newpindex3,p2, e2, f2);
}
// twins edge
for (int i = 0; i< e2.size(); i++)
{
for (int j = i+1; j< e2.size(); j++)
{
int abegin = e2[i].original_point_index;
int aend = e2[e2[i].next_edge_index].original_point_index;
int bbegin = e2[j].original_point_index;
int bend = e2[e2[j].next_edge_index].original_point_index;
if (abegin == bend
&&aend == bbegin)
{
e2[i].twin_edge_index = j;
e2[j].twin_edge_index = i;
break;
}
/*
if (twins(e2, e2[i], e2[j]))
{
e2[i].twin_edge_index = j;
e2[j].twin_edge_index = i;
break;
}
*/
}
}
// update neighbour
update_neighbour(p2, f2, e2);
// update points
vector<halfegde_point> p3;
update_newpoint(p2, f2, e2, p3);
p2 = p3;
}
#endif
一下是butterfly
#ifndef BUTTERFLY_H_
#define BUTTERFLY_H_
#include "halfedge_vector.h"
#define PI 3.14159265359
#include <assert.h>
void calculate_points(halfegde_point a, int bindex, vector<halfegde_point> p, float &x, float &y, float &z)
{
int avaluence = a.beighbour.size();
if (avaluence == 3)
{
float aweight[] = {0.417, -0.083, -0.083};
// a
int ab = 0;
while (a.beighbour[ab] != bindex)
{
ab ++;
}
for (int i = 0; i< 3; i++)
{
int ai = a.beighbour[(ab+i)%3];
x += p[ai].x*aweight[i];
y += p[ai].y*aweight[i];
z += p[ai].z*aweight[i];
}
float aw2 = 0.75;
x += a.x * aw2;
y += a.y * aw2;
z += a.z * aw2;
}
else if (avaluence == 4)
{
float aweight[] = {0.375, 0, -0.125, 0};
// a
int ab = 0;
while (a.beighbour[ab] != bindex)
{
ab ++;
}
for (int i = 0; i< 4; i++)
{
int ai = a.beighbour[(ab+i)%4];
x += p[ai].x*aweight[i];
y += p[ai].y*aweight[i];
z += p[ai].z*aweight[i];
}
float aw2 = 0.75;
x += a.x * aw2;
y += a.y * aw2;
z += a.z * aw2;
}
else
{
float *aweight = new float[avaluence];
for (int i = 0; i< avaluence; i++)
{
aweight[i] = 1.0/avaluence*(0.25+0.5*cos(4*PI/avaluence*i)+cos(2*PI/avaluence*i));
}
// a
int ab = 0;
while (a.beighbour[ab] != bindex)
{
ab ++;
}
for (int i = 0; i< avaluence; i++)
{
int ai = a.beighbour[(ab+i)%avaluence];
x += p[ai].x*aweight[i];
y += p[ai].y*aweight[i];
z += p[ai].z*aweight[i];
}
float aw2 = 1;
for (int i = 0; i< avaluence; i++)
{
aw2 -= aweight[i];
}
// aw2 =0;
x += a.x * aw2;
y += a.y * aw2;
z += a.z * aw2;
delete [] aweight;
}
}
halfegde_point getMiddlePoint(halfegde_point a, int aindex, halfegde_point b, int bindex, vector<halfegde_point> p)
{
halfegde_point newp1;
int avaluence = a.beighbour.size();
int bvalance = b.beighbour.size();
float x = 0, y = 0, z = 0;
if (avaluence == 6
&&bvalance == 6)
{
float aweight[] = {0.5, 0.125, -0.0625, 0, -0.0625, 0.125};
float bweight[] = {0.5, 0, -0.0625, 0, -0.0625, 0};
// a
int ab = 0;
while (a.beighbour[ab] != bindex)
{
ab ++;
}
int bb = 0;
while (b.beighbour[bb] != aindex)
{
bb ++;
}
for (int i = 0; i< 6; i++)
{
int ai = a.beighbour[(ab+i)%6];
int bi = b.beighbour[(bb+i)%6];
x += p[ai].x*aweight[i] + p[bi].x*bweight[i];
y += p[ai].y*aweight[i] + p[bi].y*bweight[i];
z += p[ai].z*aweight[i] + p[bi].z*bweight[i];
}
}
else
{
calculate_points(a, bindex, p, x, y, z);
calculate_points(b, aindex, p, x, y, z);
x = x/2;
y = y/2;
z = z/2;
}
newp1.x = x;
newp1.y = y;
newp1.z = z;
newp1.isnew = true;
newp1.edge_index = -1;
newp1.beighbour.clear();
return newp1;
}
void addEdge(int p1, int p2, int p3, vector<halfegde_point> &p, vector<halfegde> &e, vector<halfedge_face> &f)
{
halfedge_face f1;
f.push_back(f1);
int fi = f.size()-1;
halfegde e1, e2, e3;
e.push_back(e1);
e.push_back(e2);
e.push_back(e3);
int ei1, ei2, ei3;
ei3 = e.size()-1;
ei2 = ei3-1;
ei1 = ei2-1;
e[ei1].original_point_index = p1;
e[ei1].next_edge_index = ei2;
e[ei1].previous_edge_index = ei3;
e[ei1].twin_edge_index = -1;
e[ei1].face_index = fi;
e[ei1].split_point_index = -1;
e[ei1].issplited = false;
p[p1].edge_index = ei1;
e[ei2].original_point_index = p2;
e[ei2].next_edge_index = ei3;
e[ei2].previous_edge_index = ei1;
e[ei2].twin_edge_index = -1;
e[ei2].face_index = fi;
e[ei2].split_point_index = -1;
e[ei2].issplited = false;
p[p2].edge_index = ei2;
e[ei3].original_point_index = p3;
e[ei3].next_edge_index = ei1;
e[ei3].previous_edge_index = ei2;
e[ei3].twin_edge_index = -1;
e[ei3].face_index = fi;
e[ei3].split_point_index = -1;
e[ei3].issplited = false;
p[p3].edge_index = ei3;
f[fi].one_edge_index = ei1;
}
void getbutterfly(vector<halfegde_point>p, vector<halfedge_face>f, vector<halfegde>e,
vector<halfegde_point> &p2, vector<halfedge_face> &f2, vector<halfegde> &e2)
{
// points initial
for (int i = 0; i< p.size(); i++)
{
// is it right?
halfegde_point tmp;
tmp.x = p[i].x;
tmp.y = p[i].y;
tmp.z = p[i].z;
tmp.isnew = p[i].isnew;
tmp.edge_index = p[i].edge_index;
for (int j = 0; j< p[i].beighbour.size(); j++)
{
tmp.beighbour.push_back(p[i].beighbour[j]);
}
p2.push_back(tmp);
}
// face
for (int i = 0; i< f.size(); i++)
{
int edge1 = f[i].one_edge_index;
int edge2 = e[edge1].next_edge_index;
int edge3 = e[edge2].next_edge_index;
assert(e[edge3].next_edge_index == edge1);
int point1 = e[edge1].original_point_index;
int point2 = e[edge2].original_point_index;
int point3 = e[edge3].original_point_index;
int newpindex1, newpindex2, newpindex3;
// e1
if (e[edge1].issplited)
{
newpindex1 = e[edge1].split_point_index;
}
else
{
halfegde_point newp1 = getMiddlePoint(p[point1], point1, p[point2], point2, p);
p2.push_back(newp1);
newpindex1 = p2.size()-1;
e[edge1].issplited = true;
e[edge1].split_point_index = newpindex1;
int etwin = e[edge1].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex1;
}
}
// e2
if (e[edge2].issplited)
{
newpindex2 = e[edge2].split_point_index;
}
else
{
halfegde_point newp2 = getMiddlePoint(p[point2], point2, p[point3], point3, p);
p2.push_back(newp2);
newpindex2 = p2.size()-1;
e[edge2].issplited = true;
e[edge2].split_point_index = newpindex2;
int etwin = e[edge2].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex2;
}
}
// e3
if (e[edge3].issplited)
{
newpindex3 = e[edge3].split_point_index;
}
else
{
halfegde_point newp3 = getMiddlePoint(p[point3], point3, p[point1], point1, p);
p2.push_back(newp3);
newpindex3 = p2.size()-1;
e[edge3].issplited = true;
e[edge3].split_point_index = newpindex3;
int etwin = e[edge3].twin_edge_index;
if (etwin != -1)
{
e[etwin].issplited = true;
e[etwin].split_point_index = newpindex3;
}
}
// add face;
addEdge(point1, newpindex1, newpindex3,p2, e2, f2);
addEdge(newpindex1, point2, newpindex2,p2, e2, f2);
addEdge(newpindex3, newpindex2, point3,p2, e2, f2);
addEdge(newpindex1, newpindex2, newpindex3,p2, e2, f2);
}
// twins edge
for (int i = 0; i< e2.size(); i++)
{
for (int j = i+1; j< e2.size(); j++)
{
int abegin = e2[i].original_point_index;
int aend = e2[e2[i].next_edge_index].original_point_index;
int bbegin = e2[j].original_point_index;
int bend = e2[e2[j].next_edge_index].original_point_index;
if (abegin == bend
&&aend == bbegin)
{
e2[i].twin_edge_index = j;
e2[j].twin_edge_index = i;
break;
}
/*
if (twins(e2, e2[i], e2[j]))
{
e2[i].twin_edge_index = j;
e2[j].twin_edge_index = i;
break;
}
*/
}
}
// update new point
update_neighbour(p2, f2, e2);
}
#endif