在 OpenGL 中执行多次反射
Performing multiple reflections in OpenGL
我的任务是对二维对象执行转换(反射)。
假设我的原始对象是一个圆圈:
o
例如,我想在 y = 5 线上反映它。
o | o
然后我想在 x = 5 的直线上反映两个对象。
oo
__
oo
然后最后我想反映横跨一条线 y = 10 的四个对象,例如。
oo | o o
oo | o o
所以最终我希望最终结果包括 8 个圆圈。
我的问题是,我将如何在我的代码中实现它?
这是我项目的代码:
#include <glut.h>
GLfloat square[4][3] = {{5, 0,0}, {5,20,0},{-5,20,0}, {-5,0,0}};
GLfloat square2[4][3] = { { 10, -5,0 },{ 10,25,0 },{ 0,25,0 },{ 0,-5,0 } };
GLfloat square3[4][3] = { { 0, -5,0 },{ 0,25,0 },{ -10,25,0 },{ -10,-5,0 } };
GLfloat colors[3][3] = {{0,0,1},{1,1,1},{0,0,0}};
void draw_square(void){
glBegin(GL_POLYGON);
for(int i = 0; i < 4; i++){
glVertex3fv(square[i]);
}
glEnd();
}
void draw_square2(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square2[i]);
}
glEnd();
}
void draw_square3(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square3[i]);
}
glEnd();
}
void draw_ring(void){
for(int r =0; r < 360;r+=45){
glPushMatrix();
glRotated(r, 0,0,1);
glTranslated(0,50,0);
draw_square();
glPopMatrix();
}
}
void draw_ring2(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square2();
glPopMatrix();
}
}
void draw_ring3(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square3();
glPopMatrix();
}
}
下面的显示函数创建了我想要反映的一组重叠环。现在的样子,我只在左下角得到一组重叠的环。我希望输出为 8 组重叠环。我一直在努力寻找一种方法来创建我需要的反射,但我似乎无法弄清楚。
void display(void){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
glFlush();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(1000,600);
glutInitWindowPosition(200,100);
glutCreateWindow("Project 2");
glClearColor(1.0,1.0,0.0,1.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-100.0, 1000.0, -100.0,600.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutDisplayFunc(display);
glutMainLoop();
}
如有任何帮助,我们将不胜感激。
请注意,几十年来不推荐使用 glBegin
/glEnd
序列和固定功能流水线矩阵堆栈进行绘制。
阅读 Fixed Function Pipeline and see Vertex Specification and Shader 了解最先进的渲染方式。
无论如何,如果你想平铺对象,那么你可以通过嵌套循环来实现:
void draw_object( void )
{
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int tile_x = 4;
int tile_y = 2;
float tile_dist = 200.0f;
for ( int x = 0; x < tile_x; ++ x )
{
for (int y = 0; y < tile_y; ++ y )
{
glPushMatrix();
glTranslatef( (float)x * tile_dist, (float)y * tile_dist, 0.0f );
draw_object();
glPopMatrix();
}
}
glFlush();
}
同样的tile效果可以通过递归函数实现:
void display_tiles_recursive( int level, float dist )
{
if ( level == 0 )
{
draw_object();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_tiles_recursive( level - 1, dist );
glTranslatef( offset_x, offset_y, 0.0f );
display_tiles_recursive( level - 1, dist );
glPopMatrix();
}
void display_mirror(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_tiles_recursive( 3, 200.0f );
glFlush();
}
如果要实现重复的镜像效果,则必须沿x轴和y轴镜像偶数块。镜像可以通过glScale
来实现。 glScalef( -1.0f, 1.0f, 1.0f );
沿 x 轴镜像,glScalef( 1.0f, -1.0f, 1.0f );
沿 y 轴镜像。您可以扩展递归平铺功能以获得此效果:
void display_mirror_recursive( int level, float dist, bool even_x, bool even_y )
{
if ( level == 0 )
{
glPushMatrix();
if ( even_x )
glScalef( -1.0f, 1.0f, 1.0f );
if ( even_y )
glScalef( 1.0f, -1.0f, 1.0f );
draw_object();
glPopMatrix();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_mirror_recursive( level - 1, dist, even_x, even_y );
glTranslatef( offset_x, offset_y, 0.0f );
if ( level == 1 )
even_y = !even_y;
if ( level == 2)
even_x = !even_x;
display_mirror_recursive( level - 1, dist, even_x, even_y );
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_mirror_recursive( 3, 200.0f, false, false );
glFlush();
}
我的任务是对二维对象执行转换(反射)。
假设我的原始对象是一个圆圈: o
例如,我想在 y = 5 线上反映它。 o | o
然后我想在 x = 5 的直线上反映两个对象。
oo
__
oo
然后最后我想反映横跨一条线 y = 10 的四个对象,例如。
oo | o o
oo | o o
所以最终我希望最终结果包括 8 个圆圈。
我的问题是,我将如何在我的代码中实现它?
这是我项目的代码:
#include <glut.h>
GLfloat square[4][3] = {{5, 0,0}, {5,20,0},{-5,20,0}, {-5,0,0}};
GLfloat square2[4][3] = { { 10, -5,0 },{ 10,25,0 },{ 0,25,0 },{ 0,-5,0 } };
GLfloat square3[4][3] = { { 0, -5,0 },{ 0,25,0 },{ -10,25,0 },{ -10,-5,0 } };
GLfloat colors[3][3] = {{0,0,1},{1,1,1},{0,0,0}};
void draw_square(void){
glBegin(GL_POLYGON);
for(int i = 0; i < 4; i++){
glVertex3fv(square[i]);
}
glEnd();
}
void draw_square2(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square2[i]);
}
glEnd();
}
void draw_square3(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square3[i]);
}
glEnd();
}
void draw_ring(void){
for(int r =0; r < 360;r+=45){
glPushMatrix();
glRotated(r, 0,0,1);
glTranslated(0,50,0);
draw_square();
glPopMatrix();
}
}
void draw_ring2(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square2();
glPopMatrix();
}
}
void draw_ring3(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square3();
glPopMatrix();
}
}
下面的显示函数创建了我想要反映的一组重叠环。现在的样子,我只在左下角得到一组重叠的环。我希望输出为 8 组重叠环。我一直在努力寻找一种方法来创建我需要的反射,但我似乎无法弄清楚。
void display(void){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
glFlush();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(1000,600);
glutInitWindowPosition(200,100);
glutCreateWindow("Project 2");
glClearColor(1.0,1.0,0.0,1.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-100.0, 1000.0, -100.0,600.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutDisplayFunc(display);
glutMainLoop();
}
如有任何帮助,我们将不胜感激。
请注意,几十年来不推荐使用 glBegin
/glEnd
序列和固定功能流水线矩阵堆栈进行绘制。
阅读 Fixed Function Pipeline and see Vertex Specification and Shader 了解最先进的渲染方式。
无论如何,如果你想平铺对象,那么你可以通过嵌套循环来实现:
void draw_object( void )
{
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int tile_x = 4;
int tile_y = 2;
float tile_dist = 200.0f;
for ( int x = 0; x < tile_x; ++ x )
{
for (int y = 0; y < tile_y; ++ y )
{
glPushMatrix();
glTranslatef( (float)x * tile_dist, (float)y * tile_dist, 0.0f );
draw_object();
glPopMatrix();
}
}
glFlush();
}
同样的tile效果可以通过递归函数实现:
void display_tiles_recursive( int level, float dist )
{
if ( level == 0 )
{
draw_object();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_tiles_recursive( level - 1, dist );
glTranslatef( offset_x, offset_y, 0.0f );
display_tiles_recursive( level - 1, dist );
glPopMatrix();
}
void display_mirror(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_tiles_recursive( 3, 200.0f );
glFlush();
}
如果要实现重复的镜像效果,则必须沿x轴和y轴镜像偶数块。镜像可以通过glScale
来实现。 glScalef( -1.0f, 1.0f, 1.0f );
沿 x 轴镜像,glScalef( 1.0f, -1.0f, 1.0f );
沿 y 轴镜像。您可以扩展递归平铺功能以获得此效果:
void display_mirror_recursive( int level, float dist, bool even_x, bool even_y )
{
if ( level == 0 )
{
glPushMatrix();
if ( even_x )
glScalef( -1.0f, 1.0f, 1.0f );
if ( even_y )
glScalef( 1.0f, -1.0f, 1.0f );
draw_object();
glPopMatrix();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_mirror_recursive( level - 1, dist, even_x, even_y );
glTranslatef( offset_x, offset_y, 0.0f );
if ( level == 1 )
even_y = !even_y;
if ( level == 2)
even_x = !even_x;
display_mirror_recursive( level - 1, dist, even_x, even_y );
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_mirror_recursive( 3, 200.0f, false, false );
glFlush();
}