画个球

TheBooksofShaders ShaderToy
OpenGL Tutorial
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

画个球

帖子 523066680 »

图片
happy886rr
渐入佳境
渐入佳境
帖子: 45
注册时间: 2016年09月27日 16:11
联系:

Re: 画个球

帖子 happy886rr »

How do it?
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Re: 画个球

帖子 523066680 »

happy886rr 写了:How do it?
该球是通过 正二十面体, 细分逼近的。
细分方法是 - 对于每个面上的三角形,求出各个边的中点坐标(向量),然后将这些向量缩放至和正二十面体其他顶点距离中心的长度一致。
重新连结 - 一个三角形变为4个三角形。进一步细分2-3次,不断逼近圆球(我也是看教程学的)

但是光照部分就直接用的现成函数

给出代码,keypress 函数内定义了一些按键操作
#include <GL/freeglut.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <time.h>

#define SIZE_X 500
#define SIZE_Y 500

#define PI 3.1415926
#define PI2 PI*2
int winID;

static float rx = 0.0;
static float ry = 0.0;
static float rz = 0.0;
static float gloden = (1.0+sqrt(5.0))/2.0;
static float scale = 1.0;
static float len;
static float rlx = 0.0, rly = 0.0, rlz = 0.0;

void normalize(float v[3])
{
float d = sqrt(v[0]*v[0] + v[1]*v[1] +v[2]*v[2]);
v[0] /= d/len;
v[1] /= d/len;
v[2] /= d/len;
}

void drawTriangle(float *v1, float *v2, float *v3)
{
glBegin(GL_TRIANGLES);
glNormal3fv(v1);
glVertex3fv(v1);
glNormal3fv(v2);
glVertex3fv(v2);
glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}

void subdivide(int lv, float *v1, float *v2, float *v3)
{
float v12[3], v23[3], v31[3];
for (int i = 0; i < 3; i++)
{
v12[i] = (v1[i]+v2[i])/2.0;
v23[i] = (v2[i]+v3[i])/2.0;
v31[i] = (v3[i]+v1[i])/2.0;
}

normalize(v12);
normalize(v23);
normalize(v31);

if (lv >= 2)
{
//glColor3f(v1[0]/2.0, (float)(rand()%5/5.0), v1[2]/2.0 );
//glColor3f(v1[0]/2.0, v1[1]/2.0, v1[2]/2.0 );
drawTriangle(v1, v12, v31);

glColor3f(v2[0]/2.0,v23[1]/2.0,v12[2]/2.0 );
drawTriangle(v2, v23, v12);

glColor3f(v3[0]/2.0,v3[1]/2.0,v3[2]/2.0 );
drawTriangle(v3, v31, v23);

glColor3f(v12[0]/2.0,v12[1]/2.0,v12[2]/2.0 );
drawTriangle(v12, v23, v31);
}
else
{
subdivide(lv+1, v1, v12, v31);
subdivide(lv+1, v2, v23, v12);
subdivide(lv+1, v3, v31, v23);
subdivide(lv+1, v12, v23, v31 );
}
}

void drawCube(float size)
{
float half = size/2.0;
glBegin(GL_QUADS);
glColor3f(0.3, 0.3, 0.8);
glNormal3f(1.0, 1.0, 1.0);
glVertex3f(half, half, half);
glNormal3f(-1.0, 1.0, 1.0);
glVertex3f(-half, half, half);
glNormal3f(-1.0, -1.0, 1.0);
glVertex3f(-half, -half, half);
glNormal3f(1.0, -1.0, 1.0);
glVertex3f(half, -half, half);

glColor3f(0.8, 0.3, 0.8);
glNormal3f(1.0, 1.0, -1.0);
glVertex3f(half, half, -half);
glNormal3f(-1.0, 1.0, -1.0);
glVertex3f(-half, half, -half);
glNormal3f(-1.0, -1.0, -1.0);
glVertex3f(-half, -half, -half);
glNormal3f(1.0, -1.0, -1.0);
glVertex3f(half, -half, -half);

glColor3f(0.3, 0.8, 0.3);
glNormal3f(1.0, 1.0, 1.0);
glVertex3f(half, half, half);
glNormal3f(1.0, -1.0, 1.0);
glVertex3f(half, -half, half);
glNormal3f(1.0, -1.0, -1.0);
glVertex3f(half, -half, -half);
glNormal3f(1.0, 1.0, -1.0);
glVertex3f(half, half, -half);

glColor3f(0.8, 0.3, 0.3);
glNormal3f(-1.0, 1.0, 1.0);
glVertex3f(-half, half, half);
glNormal3f(-1.0, -1.0, 1.0);
glVertex3f(-half, -half, half);
glNormal3f(-1.0, -1.0, -1.0);
glVertex3f(-half, -half, -half);
glNormal3f(-1.0, 1.0, -1.0);
glVertex3f(-half, half, -half);

glColor3f(0.3, 0.6, 0.8);
glNormal3f(1.0, 1.0, 1.0);
glVertex3f(half, half, half);
glNormal3f(-1.0, 1.0, 1.0);
glVertex3f(-half, half, half);
glNormal3f(-1.0, 1.0, -1.0);
glVertex3f(-half, half, -half);
glNormal3f(1.0, 1.0, -1.0);
glVertex3f(half, half, -half);

glColor3f(0.8, 0.8, 0.3);
glNormal3f(1.0, -1.0, 1.0);
glVertex3f(half, -half, half);
glNormal3f(-1.0, -1.0, 1.0);
glVertex3f(-half, -half, half);
glNormal3f(-1.0, -1.0, -1.0);
glVertex3f(-half, -half, -half);
glNormal3f(1.0, -1.0, -1.0);
glVertex3f(half, -half, -half);
glEnd();
}

void display(void)
{
char spk[20];
GLUquadricObj *quad;
quad = gluNewQuadric();
// 清理颜色缓冲区
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

//glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

float a = 0.9;
float b = a / gloden * scale;
len = sqrt( a*a + b*b);

float A[4][3] = {
a, b, 0.0,
-a, b, 0.0,
-a, -b, 0.0,
a, -b, 0.0
};
float B[4][3] = {
b, 0.0, a,
-b, 0.0, a,
-b, 0.0, -a,
b, 0.0, -a,
};

float C[4][3] = {
0.0, a, b,
0.0, -a, b,
0.0, -a, -b,
0.0, a, -b
};

float *ico[20][3] =
{
A[0], B[0], C[0],
A[0], B[3], C[3],
A[1], B[1], C[0],
A[1], B[2], C[3],

A[2], B[1], C[1],
A[2], B[2], C[2],
A[3], B[0], C[1],
A[3], B[3], C[2],

A[0], A[3], B[0],
A[0], A[3], B[3],

A[1], A[2], B[1],
A[1], A[2], B[2],

B[0], B[1], C[0],
B[0], B[1], C[1],

B[2], B[3], C[2],
B[2], B[3], C[3],

C[0], C[3], A[0],
C[0], C[3], A[1],

C[1], C[2], A[2],
C[1], C[2], A[3],
};



glPushMatrix();

glRotatef(ry, 0.0, 1.0, 0.0);
glRotatef(rx, 1.0, 0.0, 0.0);
glRotatef(rz, 0.0, 0.0, 1.0);

glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

glColor3f(1.0, 1.0, 1.0);
drawCube(6.0);

glColor4f(0.8, 0.8, 0.6, 0.8);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_TRIANGLES);

for (int i = 0; i<20; i++)
{
subdivide(0, ico[i][0], ico[i][1], ico[i][2]);
}

glEnd();

glPopMatrix();

glPushMatrix();
glRotatef(rly, 0.0, 1.0, 0.0);
glRotatef(rlx, 1.0, 0.0, 0.0);
glRotatef(rlz, 0.0, 0.0, 1.0);

glTranslatef(1.0, 1.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glutSolidSphere(0.1, 20, 20);
glPopMatrix();

glPushMatrix();
glRotatef(rly, 0.0, 1.0, 0.0);
glRotatef(rlx, 1.0, 0.0, 0.0);
glRotatef(rlz, 0.0, 0.0, 1.0);
GLfloat light_position[] = { 2.0, 2.0, 2.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPopMatrix();

glutSwapBuffers();
}

void init(void)
{
glClearColor(0.3, 0.3, 0.3, 0.8);
glEnable(GL_BLEND);
glLineWidth( 1.0 );
glPointSize( 1.0 );

GLfloat mat_ambient[] = { 0.2, 0.0, 0.0, 1.0 };
GLfloat mat_specular[] = { 0.3, 0.3, 0.7, 1.0 };
GLfloat mat_shininess[] = { 10.0 };
GLfloat mat_diffuse[] = {0.5, 0.5, 0.5, 1.0};
GLfloat light_position[] = { -2.0, -2.0, -2.0, 0.0 };
GLfloat light_specular[] = { 0.5, 0.5, 1.0, 0.1 };

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient );
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse );
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

GLfloat spot_direction[] = { 0.0, 0.0, 0.0 };

glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 120.0);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);

GLfloat light_position2[] = { -2.0, -2.0, 1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT1, GL_POSITION, light_position2);
// glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 90.0);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);


// GLfloat mat_specular2[] = { 1.0, 1.0, 1.0, 1.0 };
// GLfloat mat_shininess2[] = { 50.0 };
// GLfloat light_position2[] = { 1.0, 1.0, 1.0, 0.0 };
// glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular2);
// glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess2);
// glLightfv(GL_LIGHT0, GL_POSITION, light_position2);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);

glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_DEPTH_TEST);
}

void idle(void)
{
//rx+=0.2;
usleep(50000);
glutPostRedisplay();
}

void reshape(int Width,int Height)
{
const float fa = 4.0;
const float half = 4.0;

glViewport(0, 0, Width, Height); //视口范围
glMatrixMode(GL_PROJECTION); // 投影视图矩阵
glLoadIdentity();
//glOrtho(-half, half, -half, half, 0.0, 100.0);
gluPerspective(60.0, 1.0, 2.0, 100.0); // 透视投影矩阵(立体视图
glMatrixMode(GL_MODELVIEW); // 模型视图矩阵
glLoadIdentity();
gluLookAt(0.0,0.0,fa, 0.0,0.0,0.0, 0.0,1.0,fa); //设置观察点
// 观察点, 朝向的坐标, 观察点向上坐标
}

void keypress(unsigned char key, int mousex, int mousey)
{
switch (key)
{
case 'q':
glutDestroyWindow(winID);
exit(0);
break;
case 'Q':
glutDestroyWindow(winID);
exit(0);
break;
case 'w':
rx += 2.0;
glutPostRedisplay();
break;
case 's':
rx -= 2.0;
glutPostRedisplay();
break;
case 'a':
ry += 2.0;
glutPostRedisplay();
break;
case 'd':
ry -= 2.0;
glutPostRedisplay();
break;
case '[':
scale += 0.02;
printf("width scale: %.2f\n", scale);
glutPostRedisplay();
break;
case ']':
scale -= 0.02;
printf("width scale: %.2f\n", scale);
glutPostRedisplay();
break;
case '8':
rly += 2.0;
glutPostRedisplay();
break;
case '2':
rly -= 2.0;
glutPostRedisplay();
break;
}
}

void main(int argc, char *argv[])
{
glutInit(&argc, argv);
//显示模式 双缓冲 RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE );
glutInitWindowSize(SIZE_X, SIZE_Y); //窗口大小
glutInitWindowPosition(200, 200); //位置
winID = glutCreateWindow("LIGHT_ICO"); //窗口句柄
init();
glutDisplayFunc(display); //显示
glutKeyboardFunc(keypress); //按键事件响应
glutReshapeFunc(reshape); //窗口事件响应
glutIdleFunc(idle); //闲时回调函数
glutMainLoop(); //开始主循环
}
编译示例
gcc -std=c11 "%1" -o "%~n1" ^ -ID:\Lib\freeglut-MinGW-3.0.0-1.mp\include ^ -LD:\Lib\freeglut-MinGW-3.0.0-1.mp\lib\x64 ^ -lfreeglut -lopengl32 -lglu32
正二十面体的构造和黄金比例的关系
MinGW+OpenGL+freeglut+glew+glfw 环境配置
happy886rr
渐入佳境
渐入佳境
帖子: 45
注册时间: 2016年09月27日 16:11
联系:

Re: 画个球

帖子 happy886rr »

523066680 写了:该球是通过 正二十面体, 细分逼近的。
十分不错,但是细分的太小了,看不到砖石面的闪耀,太像球体了就会失去棱角的闪耀。光照效果不太好,要能做成那种淡蓝色透明钻石面就好了。
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Re: 画个球

帖子 523066680 »

happy886rr 写了:
523066680 写了:该球是通过 正二十面体, 细分逼近的。
十分不错,但是细分的太小了,看不到砖石面的闪耀,太像球体了就会失去棱角的闪耀。光照效果不太好,要能做成那种淡蓝色透明钻石面就好了。
应该也是可以做的很璀璨的,知识不够了,继续学 :shy
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 0 访客