之前做过一次细分,可是效果相当不好、也不是效果不好,就是效率特别低,之后我自学了半边数据结构,这篇博文就要对半边数据结构表示的正方体进行细分,希望可以在这篇博文搞定之后就可以实现对任意的立方体进行细分了。。期待已久了真是。。
经过接近一个星期、、终于完成了第一阶段的工作,顺利实现了细分一次曲面,代码如下
#include <windows.h>
#include <math.h>
#include <gl/GL.h>
#include <GL/glut.h>
//static const GLfloat vertex_list[][3] = {
// -0.5f, -0.5f, -0.5f,
// 0.5f, -0.5f, -0.5f,
// 0.5f, 0.5f, -0.5f,
// -0.5f, 0.5f, -0.5f,
// -0.5f, -0.5f, 0.5f,
// 0.5f, -0.5f, 0.5f,
// 0.5f, 0.5f, 0.5f,
// -0.5f, 0.5f, 0.5f,
//};
//static const GLint index_list[][4] = {
// 0, 1, 2, 3,//bottem
// 0, 3, 7, 4,//left
// 2, 3, 7, 6,//front
// 1, 2, 6, 5,//right
// 0, 1, 5, 4,//back
// 4, 5, 6, 7//top
//};
float M_PI = 3.14159265f;
static float c = M_PI / 180.0f; //弧度和角度转换参数
static int du = 90, oldmy = -1, oldmx = -1; //du是视点绕y轴的角度,opengl里默认y轴是上方向
static float r = 3.1f, h = 0.0f; //r是视点绕y轴的半径,h是视点高度即在y轴上的坐标
float zoom = 1.0f;
typedef struct HE_vert
{
float x;
float y;
float z;
struct HE_edge *edge; // one of the half-edges emantating from the vertex
}HE_vert;
typedef struct HE_edge
{
struct HE_vert *vert; // vertex at the end of the half-edge
struct HE_edge *pair; // oppositely oriented adjacent half-edge
struct HE_face *face; // face the half-edge borders
struct HE_edge *next; // next half-edge around the face
}HE_edge;
typedef struct HE_face
{
struct HE_edge *edge; // one of the half-edges bordering the face
}HE_face;
struct HE_vert *v[8];
struct HE_edge *e[6][4];
struct HE_face *f[6];
void idv()
{
for (int i = 0; i < 8; i++)
{
v[i] = (HE_vert*)malloc(sizeof(HE_vert));
}
}
void ide()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
e[i][j] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
}
void idf()
{
for (int i = 0; i < 6; i++)
{
f[i] = (HE_face*)malloc(sizeof(HE_face));
}
}
struct HE_edge *en = (HE_edge*)malloc(sizeof(HE_edge));
void id1()//初始化函数
{
//初始化点
v[0]->x = -0.5f; v[0]->y = -0.5f; v[0]->z = -0.5f; v[0]->edge = e[0][0];
v[1]->x = 0.5f; v[1]->y = -0.5f; v[1]->z = -0.5f; v[1]->edge = e[0][1];
v[2]->x = 0.5f; v[2]->y = 0.5f; v[2]->z = -0.5f; v[2]->edge = e[0][2];
v[3]->x = -0.5f; v[3]->y = 0.5f; v[3]->z = -0.5f; v[3]->edge = e[0][3];
v[4]->x = -0.5f; v[4]->y = -0.5f; v[4]->z = 0.5f; v[4]->edge = e[5][0];
v[5]->x = 0.5f; v[5]->y = -0.5f; v[5]->z = 0.5f; v[5]->edge = e[5][3];
v[6]->x = 0.5f; v[6]->y = 0.5f; v[6]->z = 0.5f; v[6]->edge = e[5][2];
v[7]->x = -0.5f; v[7]->y = 0.5f; v[7]->z = 0.5f; v[7]->edge = e[5][1];
//struct HE_edge
//{
// HE_vert* vert; // vertex at the end of the half-edge
// HE_edge* pair; // oppositely oriented adjacent half-edge
// HE_face* face; // face the half-edge borders
// HE_edge* next; // next half-edge around the face
//};
//初始化边
//初始化face
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
e[i][j]->face = f[i];
}
}
//初始化next
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
if (j != 3)
{
e[i][j]->next = e[i][j+1];
}
else
{
e[i][j]->next = e[i][0];
}
}
}
e[0][0]->vert = v[1]; e[0][1]->vert = v[2]; e[0][2]->vert = v[3]; e[0][3]->vert = v[0];
e[1][1]->vert = v[7]; e[1][2]->vert = v[4]; e[1][3]->vert = v[0]; e[1][0]->vert = v[3];
e[2][0]->vert = v[6]; e[2][1]->vert = v[7]; e[2][2]->vert = v[3]; e[2][3]->vert = v[2];
e[3][0]->vert = v[5]; e[3][1]->vert = v[6]; e[3][2]->vert = v[2]; e[3][3]->vert = v[1];
e[4][0]->vert = v[4]; e[4][1]->vert = v[5]; e[4][2]->vert = v[1]; e[4][3]->vert = v[0];
e[5][0]->vert = v[7]; e[5][1]->vert = v[6]; e[5][2]->vert = v[5]; e[5][3]->vert = v[4];
e[0][0]->pair = e[4][3]; e[0][1]->pair = e[3][3]; e[0][2]->pair = e[2][3]; e[0][3]->pair = e[1][0];
e[1][1]->pair = e[2][2]; e[1][2]->pair = e[5][0]; e[1][3]->pair = e[4][0]; e[1][0]->pair = e[0][3];
e[2][0]->pair = e[3][2]; e[2][1]->pair = e[5][1]; e[2][2]->pair = e[1][1]; e[2][3]->pair = e[0][2];
e[3][0]->pair = e[4][2]; e[3][1]->pair = e[5][2]; e[3][2]->pair = e[2][0]; e[3][3]->pair = e[0][1];
e[4][0]->pair = e[1][3]; e[4][1]->pair = e[5][3]; e[4][2]->pair = e[3][0]; e[4][3]->pair = e[0][0];
e[5][0]->pair = e[1][2]; e[5][1]->pair = e[2][1]; e[5][2]->pair = e[3][1]; e[5][3]->pair = e[4][1];
//struct HE_edge
//{
// HE_vert* vert; // vertex at the end of the half-edge
// HE_edge* pair; // oppositely oriented adjacent half-edge
// HE_face* face; // face the half-edge borders
// HE_edge* next; // next half-edge around the face
//};
f[0]->edge = e[0][0];
f[1]->edge = e[1][0];
f[2]->edge = e[2][0];
f[3]->edge = e[3][0];
f[4]->edge = e[4][0];
f[5]->edge = e[5][0];
}
struct HE_vert *v1[30];
struct HE_edge *e1[50][4];
struct HE_face *f1[30];
struct HE_edge *ep[3];
void idv1()
{
for (int i = 0; i < 30; i++)
{
v1[i] = (HE_vert*)malloc(sizeof(HE_vert));
}
}
void ide1()
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 4; j++)
{
e1[i][j] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
}
void idf1()
{
for (int i = 0; i < 30; i++)
{
f1[i] = (HE_face*)malloc(sizeof(HE_face));
}
}
void idep()
{
for (int i = 0; i < 3; i++)
{
ep[i] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
void id2()//一次细分函数
{
id1();//绘制初始化矩阵
//细分一次
int nf = 6;//表示上一次细分的面数
//以下部分计算点
int t = 0;
for (int i = 0; i < nf; i++)
{
en = f[i]->edge;
do {
v1[t]->x = (en->pair->vert->x) * 9 / 16 + (en->next->pair->vert->x + en->next->next->next->pair->vert->x) * 3 / 16 + (en->next->next->pair->vert->x) * 1 / 16;
v1[t]->y = (en->pair->vert->y) * 9 / 16 + (en->next->pair->vert->y + en->next->next->next->pair->vert->y) * 3 / 16 + (en->next->next->pair->vert->y) * 1 / 16;
v1[t]->z = (en->pair->vert->z) * 9 / 16 + (en->next->pair->vert->z + en->next->next->next->pair->vert->z) * 3 / 16 + (en->next->next->pair->vert->z) * 1 / 16;
en = en->next;
t = t + 1;
} while (en != f[i]->edge);
}
//点还没有最后的一个指标
t = 0;
for (int i = 0; i < nf; i++)
{
int t1 = 0;
en = f[i]->edge;
do {
e1[i][t1]->face = f1[i];
if (t1 != 3)
{
e1[i][t1]->next = e1[i][t1 + 1];
e1[i][t1]->vert = v1[t + 1];//因为是指向末尾点
}
else
{
e1[i][t1]->next = e1[i][0];
e1[i][t1]->vert = v1[t - 3];//指向开头
}
v1[t]->edge = e1[i][t1];//补充好点的最后一个信息
en = en->next;
t = t + 1;
t1++;
} while (en != f[i]->edge);
}
//面边还没有对边的信息
//面面已经确定好
for (int i = 0; i < nf; i++)
{
f1[i]->edge = e1[i][0];
}
////开始做边面
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
int sub = e[i][j]->pair - e[i][j];
for (int u = 0; u < 6; u++)
{
for (int v = 0; v < 4; v++)
{
if (e1[u][v] - e1[i][j] == sub)
{
e1[i][j]->pair = e1[u][v];
goto ss;
}
}
}
ss:;
}
}
//以上代码实现的作用和下面的赋值是一样的,可是看起来复杂度有点高
/*e1[0][0]->pair = e1[4][3]; e1[0][1]->pair = e1[3][3]; e1[0][2]->pair = e1[2][3]; e1[0][3]->pair = e1[1][0];
e1[1][1]->pair = e1[2][2]; e1[1][2]->pair = e1[5][0]; e1[1][3]->pair = e1[4][0]; e1[1][0]->pair = e1[0][3];
e1[2][0]->pair = e1[3][2]; e1[2][1]->pair = e1[5][1]; e1[2][2]->pair = e1[1][1]; e1[2][3]->pair = e1[0][2];
e1[3][0]->pair = e1[4][2]; e1[3][1]->pair = e1[5][2]; e1[3][2]->pair = e1[2][0]; e1[3][3]->pair = e1[0][1];
e1[4][0]->pair = e1[1][3]; e1[4][1]->pair = e1[5][3]; e1[4][2]->pair = e1[3][0]; e1[4][3]->pair = e1[0][0];
e1[5][0]->pair = e1[1][2]; e1[5][1]->pair = e1[2][1]; e1[5][2]->pair = e1[3][1]; e1[5][3]->pair = e1[4][1];*/
int a[6][4];//一条边和其对边只算一次
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
a[i][j] = 0;
}
}
int t2 = 6;//记录边表的数据
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)//每面上的四个边
{
if (a[i][j] == 1)//如果其对边已经用过了,那么直接跳过
{
continue;
}
else
{
e1[t2][0]->vert = e1[i][j]->next->next->next->vert;//边面的第一条边
e1[t2][0]->pair = e1[i][j];//补齐了一半的对边
a[i][j] = 1;
en = e1[i][j]->pair;
e1[t2][1]->vert = e1[i][j]->pair->vert;//边面的第二条边
e1[t2][2]->vert = en->next->next->next->vert;//边面的第三条边
e1[t2][2]->pair = en;
for (int u = i; u < 6; u++)
{
for (int v = 0; v < 4; v++)
{
if ((&a[u][v] - &a[i][j]) == (e1[i][j]->pair - e1[i][j]) / 5)
{
a[u][v] = 1;
goto sss;//跳出两重循环
}
}
}
sss:;
//为了测试数组间距离,实验证明距离是5
//int sub = (e[i][j]->pair - e[i][j]) / 5;
//int sub1 = (&a[1][0] - &a[0][3]) ;
//int sub2 = (e[4][3] - e[i][j]);
//int sub3 = (e[0][3] - e[i][j]);
//int sub4 = (e[1][0] - e[0][3]);
//int sub5 = (e[2][3] - e[i][j]);
e1[t2][3]->vert = e1[i][j]->vert;//边面的第四条边
e1[i][j]->pair = e1[t2][0];//补全对边
en->pair = e1[t2][2];//补全另一条对边
e1[t2][0]->next = e1[t2][1];
e1[t2][1]->next = e1[t2][2];
e1[t2][2]->next = e1[t2][3];
e1[t2][3]->next = e1[t2][0];
e1[t2][0]->face = f1[t2];
e1[t2][1]->face = f1[t2];
e1[t2][2]->face = f1[t2];
e1[t2][3]->face = f1[t2];
f1[t2]->edge = e1[t2][0];
t2++;
}
}
}
//最后的就是三角面以及对边
for (int i = 0; i < 8; i++)
{
int nn = 0;
for (int u = 0; u < 6; u++)
{
for (int s = 0; s < 4; s++)
{
if (v[i] != e[u][s]->vert)
{
continue;
}
else
{
ep[nn] = e1[u][s];
nn = nn + 1;
}
}
}
e1[t2][0]->vert = ep[0]->vert;
e1[t2][0]->pair = ep[0]->next->pair->next;
ep[0]->next->pair->next->pair = e1[t2][0];
if (ep[2]->vert == ep[0]->next->pair->next->vert)
{
e1[t2][2]->vert = ep[2]->vert;
e1[t2][2]->pair = ep[2]->next->pair->next;
e1[t2][1]->vert = ep[1]->vert;
e1[t2][1]->pair = ep[1]->next->pair->next;
ep[2]->next->pair->next->pair = e1[t2][2];
ep[1]->next->pair->next->pair = e1[t2][1];
}
else if (ep[1]->vert == ep[0]->next->pair->next->vert)
{
e1[t2][2]->vert = ep[1]->vert;
e1[t2][2]->pair = ep[1]->next->pair->next;
e1[t2][1]->vert = ep[2]->vert;
e1[t2][1]->pair = ep[2]->next->pair->next;
ep[1]->next->pair->next->pair = e1[t2][2];
ep[2]->next->pair->next->pair = e1[t2][1];
}
e1[t2][0]->next = e1[t2][1];
e1[t2][1]->next = e1[t2][2];
e1[t2][2]->next = e1[t2][0];
e1[t2][0]->face = f1[t2];
e1[t2][1]->face = f1[t2];
e1[t2][2]->face = f1[t2];
f1[t2]->edge = e1[t2][0];
t2++;
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
id1();
id2();
glLoadIdentity();
gluLookAt(r*cos(c*du)*cos(c*h)*zoom, r*sin(c*h)*zoom, r*sin(c*du)*cos(c*h)*zoom, 0, 0, 0, 0, 1, 0); //从视点看远点,y 轴方向(0, 1, 0)是上方向
glColor3f(1, 0, 0);
for (int i = 0; i < 6; i++)
{
en = f[i]->edge;
do {
glBegin(GL_LINES);
{
glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
glVertex3f(en->pair->vert->x, en->pair->vert->y, en->pair->vert->z);//其中每条边由两点组成
}
glEnd();
en = en->next;
} while (en != f[i]->edge);
}
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//只让多边形绘制边框
glColor3f(1, 1, 0);
//绘制面面
for (int i = 0; i < 26; i++)
{
en = f1[i]->edge;
glBegin(GL_POLYGON);
do {
{
glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
}
en = en->next;
} while (en != f1[i]->edge);
glEnd();
}
glColor3f(1, 0, 0);
for (int i = 0; i < 26; i++)
{
en = f1[i]->edge;
do {
glBegin(GL_LINES);
{
glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
glVertex3f(en->pair->vert->x, en->pair->vert->y, en->pair->vert->z);//其中每条边由两点组成
}
glEnd();
en = en->next;
} while (en != f1[i]->edge);
}
//绘制细分点
for (int i = 0; i < 24; i++)
{
glPointSize(2);
glColor3f(1, 1, 0);
glBegin(GL_POINTS);
{
glVertex3f(v1[i]->x, v1[i]->y, v1[i]->z);//绘制点
}
glEnd();
}
glFlush();
glutSwapBuffers();
}
void Mouse(int button, int state, int x, int y) //处理鼠标点击
{
if (state == GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标
oldmx = x, oldmy = y;
if (state == GLUT_UP && button == GLUT_WHEEL_UP)
{
zoom = zoom + 0.2;
if (zoom >= 2)zoom = 2;
//glutPostRedisplay();
}
if (state == GLUT_UP && button == GLUT_WHEEL_DOWN)
{
zoom = zoom - 0.2;
if (zoom <= 0.6) zoom = 0.6;
//glutPostRedisplay();
}
}
void onMouseMove(int x, int y) //处理鼠标拖动
{
//printf("%d\n",du);
du += x - oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了
h += (y - oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了
if (h > 90)
{
h = 90;
}
else if (h < -90)
{
h = -90;
}
//if (h>1.0f) h = 1.0f; //视点y坐标作一些限制,不会使视点太奇怪
//else if (h<-1.0f) h = -1.0f;
oldmx = x, oldmy = y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备
}
int main(int argc, char *argv[])
{
idv();
ide();
idf();
idv1();
ide1();
idf1();
idep();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("OpenGL");
glutDisplayFunc(display);
glutIdleFunc(display); //设置不断调用显示函数
glutMouseFunc(Mouse);
glutMotionFunc(onMouseMove);
glutMainLoop();
return 0;
}
之后就是努力实现多次的细分,上面的代码应该注释的地方我都有过注释了,如果有问题的请评论哈^^
gogo fighting!
上一发效果
过了一周终于研制成功了一半的两次细分。。真是觉得还需要学习的太多了。。
先放着吧。。还有一半的半边和面还没有做。。自己知道怎么做了。。实在是懒得动脑子了。。
#include <windows.h>
#include <math.h>
#include <gl/GL.h>
#include <GL/glut.h>
//static const GLfloat vertex_list[][3] = {
// -0.5f, -0.5f, -0.5f,
// 0.5f, -0.5f, -0.5f,
// 0.5f, 0.5f, -0.5f,
// -0.5f, 0.5f, -0.5f,
// -0.5f, -0.5f, 0.5f,
// 0.5f, -0.5f, 0.5f,
// 0.5f, 0.5f, 0.5f,
// -0.5f, 0.5f, 0.5f,
//};
//static const GLint index_list[][4] = {
// 0, 1, 2, 3,//bottem
// 0, 3, 7, 4,//left
// 2, 3, 7, 6,//front
// 1, 2, 6, 5,//right
// 0, 1, 5, 4,//back
// 4, 5, 6, 7//top
//};
float M_PI = 3.14159265f;
static float c = M_PI / 180.0f; //弧度和角度转换参数
static int du = 90, oldmy = -1, oldmx = -1; //du是视点绕y轴的角度,opengl里默认y轴是上方向
static float r = 3.1f, h = 0.0f; //r是视点绕y轴的半径,h是视点高度即在y轴上的坐标
float zoom = 1.0f;
int Nump;//记录当前点数
int Nume;//记录当前半边数
int Numf;//记录当前面数
typedef struct HE_vert
{
float x;
float y;
float z;
struct HE_edge *edge; // one of the half-edges emantating from the vertex
}HE_vert;
typedef struct HE_edge
{
struct HE_vert *vert; // vertex at the end of the half-edge
struct HE_edge *pair; // oppositely oriented adjacent half-edge
struct HE_face *face; // face the half-edge borders
struct HE_edge *next; // next half-edge around the face
}HE_edge;
typedef struct HE_face
{
struct HE_edge *edge; // one of the half-edges bordering the face
}HE_face;
struct HE_vert *v[8];
struct HE_edge *e[6][4];
struct HE_face *f[6];
void idv()
{
for (int i = 0; i < 8; i++)
{
v[i] = (HE_vert*)malloc(sizeof(HE_vert));
}
}
void ide()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
e[i][j] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
}
void idf()
{
for (int i = 0; i < 6; i++)
{
f[i] = (HE_face*)malloc(sizeof(HE_face));
}
}
struct HE_edge *en = (HE_edge*)malloc(sizeof(HE_edge));
struct HE_edge *en1 = (HE_edge*)malloc(sizeof(HE_edge));//用来表示临时边
void idd()//用于初始化矩阵
{
idv();
ide();
idf();
};
void id1()//初始化函数
{
//初始化点
v[0]->x = -0.5f; v[0]->y = -0.5f; v[0]->z = -0.5f; v[0]->edge = e[0][0];
v[1]->x = 0.5f; v[1]->y = -0.5f; v[1]->z = -0.5f; v[1]->edge = e[0][1];
v[2]->x = 0.5f; v[2]->y = 0.5f; v[2]->z = -0.5f; v[2]->edge = e[0][2];
v[3]->x = -0.5f; v[3]->y = 0.5f; v[3]->z = -0.5f; v[3]->edge = e[0][3];
v[4]->x = -0.5f; v[4]->y = -0.5f; v[4]->z = 0.5f; v[4]->edge = e[5][0];
v[5]->x = 0.5f; v[5]->y = -0.5f; v[5]->z = 0.5f; v[5]->edge = e[5][3];
v[6]->x = 0.5f; v[6]->y = 0.5f; v[6]->z = 0.5f; v[6]->edge = e[5][2];
v[7]->x = -0.5f; v[7]->y = 0.5f; v[7]->z = 0.5f; v[7]->edge = e[5][1];
//struct HE_edge
//{
// HE_vert* vert; // vertex at the end of the half-edge
// HE_edge* pair; // oppositely oriented adjacent half-edge
// HE_face* face; // face the half-edge borders
// HE_edge* next; // next half-edge around the face
//};
//初始化边
//初始化face
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
e[i][j]->face = f[i];
}
}
//初始化next
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
if (j != 3)
{
e[i][j]->next = e[i][j+1];
}
else
{
e[i][j]->next = e[i][0];
}
}
}
e[0][0]->vert = v[1]; e[0][1]->vert = v[2]; e[0][2]->vert = v[3]; e[0][3]->vert = v[0];
e[1][1]->vert = v[7]; e[1][2]->vert = v[4]; e[1][3]->vert = v[0]; e[1][0]->vert = v[3];
e[2][0]->vert = v[6]; e[2][1]->vert = v[7]; e[2][2]->vert = v[3]; e[2][3]->vert = v[2];
e[3][0]->vert = v[5]; e[3][1]->vert = v[6]; e[3][2]->vert = v[2]; e[3][3]->vert = v[1];
e[4][0]->vert = v[4]; e[4][1]->vert = v[5]; e[4][2]->vert = v[1]; e[4][3]->vert = v[0];
e[5][0]->vert = v[7]; e[5][1]->vert = v[6]; e[5][2]->vert = v[5]; e[5][3]->vert = v[4];
e[0][0]->pair = e[4][3]; e[0][1]->pair = e[3][3]; e[0][2]->pair = e[2][3]; e[0][3]->pair = e[1][0];
e[1][1]->pair = e[2][2]; e[1][2]->pair = e[5][0]; e[1][3]->pair = e[4][0]; e[1][0]->pair = e[0][3];
e[2][0]->pair = e[3][2]; e[2][1]->pair = e[5][1]; e[2][2]->pair = e[1][1]; e[2][3]->pair = e[0][2];
e[3][0]->pair = e[4][2]; e[3][1]->pair = e[5][2]; e[3][2]->pair = e[2][0]; e[3][3]->pair = e[0][1];
e[4][0]->pair = e[1][3]; e[4][1]->pair = e[5][3]; e[4][2]->pair = e[3][0]; e[4][3]->pair = e[0][0];
e[5][0]->pair = e[1][2]; e[5][1]->pair = e[2][1]; e[5][2]->pair = e[3][1]; e[5][3]->pair = e[4][1];
//struct HE_edge
//{
// HE_vert* vert; // vertex at the end of the half-edge
// HE_edge* pair; // oppositely oriented adjacent half-edge
// HE_face* face; // face the half-edge borders
// HE_edge* next; // next half-edge around the face
//};
f[0]->edge = e[0][0];
f[1]->edge = e[1][0];
f[2]->edge = e[2][0];
f[3]->edge = e[3][0];
f[4]->edge = e[4][0];
f[5]->edge = e[5][0];
}
//做第一次细分
struct HE_vert *v1[30];
struct HE_edge *e1[50][4];
struct HE_face *f1[30];
struct HE_edge *ep1[3];
void idv1()
{
for (int i = 0; i < 30; i++)
{
v1[i] = (HE_vert*)malloc(sizeof(HE_vert));
}
}
void ide1()
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 4; j++)
{
e1[i][j] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
}
void idf1()
{
for (int i = 0; i < 30; i++)
{
f1[i] = (HE_face*)malloc(sizeof(HE_face));
}
}
void idep1()
{
for (int i = 0; i < 3; i++)
{
ep1[i] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
void idd1()//用于初始化矩阵
{
idv1();
ide1();
idf1();
idep1();
};
void id2()//一次细分函数
{
id1();//绘制初始化矩阵
//细分一次
int nf = 6;//表示上一次细分的面数
//以下部分计算点
int t = 0;
for (int i = 0; i < nf; i++)
{
en = f[i]->edge;
do {
v1[t]->x = (en->pair->vert->x) * 9 / 16 + (en->next->pair->vert->x + en->next->next->next->pair->vert->x) * 3 / 16 + (en->next->next->pair->vert->x) * 1 / 16;
v1[t]->y = (en->pair->vert->y) * 9 / 16 + (en->next->pair->vert->y + en->next->next->next->pair->vert->y) * 3 / 16 + (en->next->next->pair->vert->y) * 1 / 16;
v1[t]->z = (en->pair->vert->z) * 9 / 16 + (en->next->pair->vert->z + en->next->next->next->pair->vert->z) * 3 / 16 + (en->next->next->pair->vert->z) * 1 / 16;
en = en->next;
t = t + 1;
} while (en != f[i]->edge);
}
//点还没有最后的一个指标
Nump = t ;
t = 0;
for (int i = 0; i < nf; i++)
{
int t1 = 0;
en = f[i]->edge;
do {
e1[i][t1]->face = f1[i];
if (t1 != 3)
{
e1[i][t1]->next = e1[i][t1 + 1];
e1[i][t1]->vert = v1[t + 1];//因为是指向末尾点
}
else
{
e1[i][t1]->next = e1[i][0];
e1[i][t1]->vert = v1[t - 3];//指向开头
}
v1[t]->edge = e1[i][t1];//补充好点的最后一个信息
en = en->next;
t = t + 1;
t1++;
} while (en != f[i]->edge);
}
//面边还没有对边的信息
//面面已经确定好
for (int i = 0; i < nf; i++)
{
f1[i]->edge = e1[i][0];
}
////开始做边面
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
int sub = e[i][j]->pair - e[i][j];
for (int u = 0; u < 6; u++)
{
for (int v = 0; v < 4; v++)
{
if (e1[u][v] - e1[i][j] == sub)
{
e1[i][j]->pair = e1[u][v];
goto ss;
}
}
}
ss:;
}
}
//以上代码实现的作用和下面的赋值是一样的,可是看起来复杂度有点高
/*e1[0][0]->pair = e1[4][3]; e1[0][1]->pair = e1[3][3]; e1[0][2]->pair = e1[2][3]; e1[0][3]->pair = e1[1][0];
e1[1][1]->pair = e1[2][2]; e1[1][2]->pair = e1[5][0]; e1[1][3]->pair = e1[4][0]; e1[1][0]->pair = e1[0][3];
e1[2][0]->pair = e1[3][2]; e1[2][1]->pair = e1[5][1]; e1[2][2]->pair = e1[1][1]; e1[2][3]->pair = e1[0][2];
e1[3][0]->pair = e1[4][2]; e1[3][1]->pair = e1[5][2]; e1[3][2]->pair = e1[2][0]; e1[3][3]->pair = e1[0][1];
e1[4][0]->pair = e1[1][3]; e1[4][1]->pair = e1[5][3]; e1[4][2]->pair = e1[3][0]; e1[4][3]->pair = e1[0][0];
e1[5][0]->pair = e1[1][2]; e1[5][1]->pair = e1[2][1]; e1[5][2]->pair = e1[3][1]; e1[5][3]->pair = e1[4][1];*/
int a[6][4];//一条边和其对边只算一次
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
a[i][j] = 0;
}
}
int t2 = 6;//记录边表的数据
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)//每面上的四个边
{
if (a[i][j] == 1)//如果其对边已经用过了,那么直接跳过
{
continue;
}
else
{
e1[t2][0]->vert = e1[i][j]->next->next->next->vert;//边面的第一条边
e1[t2][0]->pair = e1[i][j];//补齐了一半的对边
a[i][j] = 1;
en = e1[i][j]->pair;
e1[t2][1]->vert = e1[i][j]->pair->vert;//边面的第二条边
e1[t2][2]->vert = en->next->next->next->vert;//边面的第三条边
e1[t2][2]->pair = en;
for (int u = i; u < 6; u++)
{
for (int v = 0; v < 4; v++)
{
if ((&a[u][v] - &a[i][j]) == (e1[i][j]->pair - e1[i][j]) / 5)
{
a[u][v] = 1;
goto sss;//跳出两重循环
}
}
}
sss:;
//为了测试数组间距离,实验证明距离是5
//int sub = (e[i][j]->pair - e[i][j]) / 5;
//int sub1 = (&a[1][0] - &a[0][3]) ;
//int sub2 = (e[4][3] - e[i][j]);
//int sub3 = (e[0][3] - e[i][j]);
//int sub4 = (e[1][0] - e[0][3]);
//int sub5 = (e[2][3] - e[i][j]);
e1[t2][3]->vert = e1[i][j]->vert;//边面的第四条边
e1[i][j]->pair = e1[t2][0];//补全对边
en->pair = e1[t2][2];//补全另一条对边
e1[t2][0]->next = e1[t2][1];
e1[t2][1]->next = e1[t2][2];
e1[t2][2]->next = e1[t2][3];
e1[t2][3]->next = e1[t2][0];
e1[t2][0]->face = f1[t2];
e1[t2][1]->face = f1[t2];
e1[t2][2]->face = f1[t2];
e1[t2][3]->face = f1[t2];
f1[t2]->edge = e1[t2][0];
t2++;
}
}
}
//最后的就是三角面以及对边
for (int i = 0; i < 8; i++)
{
int nn = 0;
for (int u = 0; u < 6; u++)
{
for (int s = 0; s < 4; s++)
{
if (v[i] != e[u][s]->vert)
{
continue;
}
else
{
ep1[nn] = e1[u][s];
nn = nn + 1;
}
}
}
e1[t2][0]->vert = ep1[0]->vert;
e1[t2][0]->pair = ep1[0]->next->pair->next;
ep1[0]->next->pair->next->pair = e1[t2][0];
if (ep1[2]->vert == ep1[0]->next->pair->next->vert)
{
e1[t2][2]->vert = ep1[2]->vert;
e1[t2][2]->pair = ep1[2]->next->pair->next;
e1[t2][1]->vert = ep1[1]->vert;
e1[t2][1]->pair = ep1[1]->next->pair->next;
ep1[2]->next->pair->next->pair = e1[t2][2];
ep1[1]->next->pair->next->pair = e1[t2][1];
}
else if (ep1[1]->vert == ep1[0]->next->pair->next->vert)
{
e1[t2][2]->vert = ep1[1]->vert;
e1[t2][2]->pair = ep1[1]->next->pair->next;
e1[t2][1]->vert = ep1[2]->vert;
e1[t2][1]->pair = ep1[2]->next->pair->next;
ep1[1]->next->pair->next->pair = e1[t2][2];
ep1[2]->next->pair->next->pair = e1[t2][1];
}
e1[t2][0]->next = e1[t2][1];
e1[t2][1]->next = e1[t2][2];
e1[t2][2]->next = e1[t2][0];
e1[t2][0]->face = f1[t2];
e1[t2][1]->face = f1[t2];
e1[t2][2]->face = f1[t2];
f1[t2]->edge = e1[t2][0];
t2++;
}
Numf = t2;
Nume = Numf * 4;
}
//做第二次细分
struct HE_vert *v2[100];
struct HE_edge *e2[150][4];
struct HE_face *f2[100];
struct HE_edge *ep2[3];
void idv2()
{
for (int i = 0; i < 100; i++)
{
v2[i] = (HE_vert*)malloc(sizeof(HE_vert));
}
}
void ide2()
{
for (int i = 0; i < 150; i++)
{
for (int j = 0; j < 4; j++)
{
e2[i][j] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
}
void idf2()
{
for (int i = 0; i < 100; i++)
{
f2[i] = (HE_face*)malloc(sizeof(HE_face));
}
}
void idep2()
{
for (int i = 0; i < 3; i++)
{
ep2[i] = (HE_edge*)malloc(sizeof(HE_edge));
}
}
void idd2()//用于初始化矩阵
{
idv2();
ide2();
idf2();
idep2();
};
int Nump1;
int Nume1;
int Numf1;
void id3()//一次细分函数
{
id1();
id2();
//以下部分计算点
int t = 0;
for (int i = 0; i < Numf-8; i++)
{
en = f1[i]->edge;
do {
v2[t]->x = (en->pair->vert->x) * 9 / 16 + (en->next->pair->vert->x + en->next->next->next->pair->vert->x) * 3 / 16 + (en->next->next->pair->vert->x) * 1 / 16;
v2[t]->y = (en->pair->vert->y) * 9 / 16 + (en->next->pair->vert->y + en->next->next->next->pair->vert->y) * 3 / 16 + (en->next->next->pair->vert->y) * 1 / 16;
v2[t]->z = (en->pair->vert->z) * 9 / 16 + (en->next->pair->vert->z + en->next->next->next->pair->vert->z) * 3 / 16 + (en->next->next->pair->vert->z) * 1 / 16;
en = en->next;
t = t + 1;
} while (en != f1[i]->edge);
}
//点还没有最后的一个指标
for (int i = Numf - 8; i < Numf ; i++)
{
en = f1[i]->edge;
do {
v2[t]->x = (en->pair->vert->x) * 2 / 3 + (en->next->pair->vert->x + en->next->next->pair->vert->x) * 1 / 6 ;
v2[t]->y = (en->pair->vert->y) * 2 / 3 + (en->next->pair->vert->y + en->next->next->pair->vert->y) * 1 / 6;
v2[t]->z = (en->pair->vert->z) * 2 / 3 + (en->next->pair->vert->z + en->next->next->pair->vert->z) * 1 / 6;
en = en->next;
t = t + 1;
} while (en != f1[i]->edge);
}
Nump1 = t;
Numf1 = Nume / 2 + Nump + Numf;
t = 0;
for (int i = 0; i < Numf-8; i++)
{
int t1 = 0;
en = f1[i]->edge;
do {
e2[i][t1]->face = f1[i];
if (t1 != 3)
{
e2[i][t1]->next = e2[i][t1 + 1];
e2[i][t1]->vert = v2[t + 1];//因为是指向末尾点
}
else
{
e2[i][t1]->next = e2[i][0];
e2[i][t1]->vert = v2[t - 3];//指向开头
}
v2[t]->edge = e2[i][t1];//补充好点的最后一个信息
en = en->next;
t = t + 1;
t1++;
} while (en != f1[i]->edge);
}
//面边还没有对边的信息
//三角面另说
for (int i = Numf - 8; i < Numf ; i++)
{
int t1 = 0;
en = f1[i]->edge;
do {
e2[i][t1]->face = f1[i];
if (t1 != 2)
{
e2[i][t1]->next = e2[i][t1 + 1];
e2[i][t1]->vert = v2[t + 1];//因为是指向末尾点
}
else
{
e2[i][t1]->next = e2[i][0];
e2[i][t1]->vert = v2[t - 2];//指向开头
}
v2[t]->edge = e2[i][t1];//补充好点的最后一个信息
en = en->next;
t = t + 1;
t1++;
} while (en != f1[i]->edge);
}
//面面已经确定好
for (int i = 0; i < Numf; i++)
{
f2[i]->edge = e2[i][0];
}
//开始绘制边面
for (int i = 0; i < Numf; i++)
{
for (int j = 0; j < 4; j++)
{
int sub = e1[i][j]->pair - e1[i][j];
for (int u = 0; u < Numf; u++)
{
for (int v = 0; v < 4; v++)
{
if (e2[u][v] - e2[i][j] == sub)
{
e2[i][j]->pair = e2[u][v];
goto ss;
}
}
}
ss:;
}
}
////开始做边面
int a[18][4];//一条边和其对边只算一次
for (int i = 0; i < 18; i++)
{
for (int j = 0; j < 4; j++)
{
a[i][j] = 0;
}
}
int t2 = Numf;//记录边表的数据
for (int i = 0; i < 18; i++)
{
for (int j = 0; j < 4; j++)//每面上的四个边
{
if (a[i][j] == 1)//如果其对边已经用过了,那么直接跳过
{
continue;
}
else
{
e2[t2][0]->vert = e2[i][j]->next->next->next->vert;//边面的第一条边
e2[t2][0]->pair = e2[i][j];//补齐了一半的对边
a[i][j] = 1;
en = e2[i][j]->pair;
e2[t2][1]->vert = e2[i][j]->pair->vert;//边面的第二条边
do
{
en1 = en;
en = en->next;
} while (en != e2[i][j]->pair);//找到一条边的起始
e2[t2][2]->vert = en1->vert;//边面的第三条边
e2[t2][2]->pair = en;
for (int u = 0; u < 18; u++)
{
for (int v = 0; v < 4; v++)
{
if ((&a[u][v] - &a[i][j]) == (e2[i][j]->pair - e2[i][j]) / 5)
{
a[u][v] = 1;
goto sss;//跳出两重循环
}
}
}
sss:;
//为了测试数组间距离,实验证明距离是5
//int sub = (e[i][j]->pair - e[i][j]) / 5;
//int sub1 = (&a[1][0] - &a[0][3]) ;
//int sub2 = (e[4][3] - e[i][j]);
//int sub3 = (e[0][3] - e[i][j]);
//int sub4 = (e[1][0] - e[0][3]);
//int sub5 = (e[2][3] - e[i][j]);
e2[t2][3]->vert = e2[i][j]->vert;//边面的第四条边
e2[i][j]->pair = e2[t2][0];//补全对边
en->pair = e2[t2][2];//补全另一条对边
e2[t2][0]->next = e2[t2][1];
e2[t2][1]->next = e2[t2][2];
e2[t2][2]->next = e2[t2][3];
e2[t2][3]->next = e2[t2][0];
e2[t2][0]->face = f2[t2];
e2[t2][1]->face = f2[t2];
e2[t2][2]->face = f2[t2];
e2[t2][3]->face = f2[t2];
f2[t2]->edge = e2[t2][0];
t2++;
}
}
}
Nume1 = t2;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
id1();
id2();
id3();
glLoadIdentity();
gluLookAt(r*cos(c*du)*cos(c*h)*zoom, r*sin(c*h)*zoom, r*sin(c*du)*cos(c*h)*zoom, 0, 0, 0, 0, 1, 0); //从视点看远点,y 轴方向(0, 1, 0)是上方向
//glColor3f(1, 0, 0);
//for (int i = 0; i < 6; i++)
//{
// en = f[i]->edge;
// do {
// glBegin(GL_LINES);
// {
// glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
// glVertex3f(en->pair->vert->x, en->pair->vert->y, en->pair->vert->z);//其中每条边由两点组成
// }
// glEnd();
// en = en->next;
// } while (en != f[i]->edge);
//
//}
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//只让多边形绘制边框
//glColor3f(1, 0, 0);
////绘制面面
//for (int i = 0; i < 26; i++)
//{
// en = f1[i]->edge;
// glBegin(GL_POLYGON);
// do {
// {
// glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
// }
// en = en->next;
// } while (en != f1[i]->edge);
// glEnd();
//}
//glColor3f(1, 0, 0);
//for (int i = 0; i < 26; i++)
//{
// en = f1[i]->edge;
// do {
// glBegin(GL_LINES);
// {
// glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
// glVertex3f(en->pair->vert->x, en->pair->vert->y, en->pair->vert->z);//其中每条边由两点组成
// }
// glEnd();
// en = en->next;
// } while (en != f1[i]->edge);
//}
//绘制细分点
//for (int i = 0; i < 24; i++)
//{
// glPointSize(2);
// glColor3f(1, 1, 0);
// glBegin(GL_POINTS);
// {
// glVertex3f(v1[i]->x, v1[i]->y, v1[i]->z);//绘制点
// }
// glEnd();
//}
for (int i = 0; i < Nump1; i++)
{
glPointSize(2);
glColor3f(1, 1, 0);
glBegin(GL_POINTS);
{
glVertex3f(v2[i]->x, v2[i]->y, v2[i]->z);//绘制点
}
glEnd();
}
for (int i = 0; i <26; i++)
{
en = f2[i]->edge;
glBegin(GL_POLYGON);
do {
{
glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
}
en = en->next;
} while (en != f2[i]->edge);
glEnd();
}
glColor3f(0,1,1);
for (int i = 26; i <74; i++)
{
en = f2[i]->edge;
glBegin(GL_POLYGON);
do {
{
glVertex3f(en->vert->x, en->vert->y, en->vert->z);//其中每条边由两点组成
}
en = en->next;
} while (en != f2[i]->edge);
glEnd();
}
glFlush();
glutSwapBuffers();
}
void Mouse(int button, int state, int x, int y) //处理鼠标点击
{
if (state == GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标
oldmx = x, oldmy = y;
if (state == GLUT_UP && button == GLUT_WHEEL_UP)
{
zoom = zoom + 0.2;
if (zoom >= 2)zoom = 2;
//glutPostRedisplay();
}
if (state == GLUT_UP && button == GLUT_WHEEL_DOWN)
{
zoom = zoom - 0.2;
if (zoom <= 0.6) zoom = 0.6;
//glutPostRedisplay();
}
}
void onMouseMove(int x, int y) //处理鼠标拖动
{
//printf("%d\n",du);
du += x - oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了
h += (y - oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了
if (h > 90)
{
h = 90;
}
else if (h < -90)
{
h = -90;
}
//if (h>1.0f) h = 1.0f; //视点y坐标作一些限制,不会使视点太奇怪
//else if (h<-1.0f) h = -1.0f;
oldmx = x, oldmy = y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备
}
int main(int argc, char *argv[])
{
idd();
idd1();
idd2();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("OpenGL");
glutDisplayFunc(display);
glutIdleFunc(display); //设置不断调用显示函数
glutMouseFunc(Mouse);
glutMotionFunc(onMouseMove);
glutMainLoop();
return 0;
}
最后放上效果。。如果我有时间的话一定完善之