# opengl self study record_ Keyboard control graphic translation

Self study objectives:
1. Master the mathematical principle of two-dimensional transformation
2. Learn to apply two-dimensional transformation

```#define GLUT_DISABLE_ATEXIT_HACK
#include "GLUT.H"
#include<math.h>
#include <string.h>
#define ZVALUE 20.0f

int w_width = 600;
int w_height = 600;
int lineWidth;

//Nonhomogeneous two-dimensional geometric transformation
struct my_v_inhomogenous
{
int x;
int y;
};

struct my_v_inhomogeneous rectangle;
///

///
///
//
//A little brother forgot
/
void init(void)
{
rectangle.x = 0;
rectangle.y = 0;

rectangle.x = 80;
rectangle.y = 0;

rectangle.x = 80;
rectangle.y = 40;

rectangle.x = 0;
rectangle.y = 40;
}

//DDA draw line
void DDA(int x0, int y0, int x1, int y1)
{
float dx = x1 - x0;
float dy = y1 - y0;
float k = dy / dx;
float x = x0;
float y = y0;
//y(i+1)=yi+k; The formula y=kx+b is used
//xi,yi,int(y(i+1)+0.5).
//The slope is too large to be discrete
//Generally speaking, k and y are integers, and y must be rounded in each operation, so the operation efficiency is relatively low
while (x <= x1)
{
glVertex2d(x, y);
x++;
y = floor(y + k + 0.5);
}

}

void Bresenham(int x0, int y0, int x1, int y1)
//Only int type addition, subtraction and comparison
//Draw the horizontal and vertical lines separately, and divide the others into eight parts
//Only the first quadrant is written here
//Traverse each abscissa and find the ordinate corresponding to the abscissa
{
int dy = y1 - y0;
int dx = x1 - x0;
int xf = x0;
int yf = y0;
int e = -dx;
while (xf < x1)
{
glColor3f(1.0, 0.0, 0.0);
glVertex2d(xf, yf);
e = e + 2 * dy;
if (e > 0)
{
yf++;
xf++;
e = e - 2 * dx;
}
else
{
xf++;
}
}
}

//Draw a circle
void draw_circle(int r)
{
int x, y;
x = 0, y = r;
int d = 3 - 2 * r;
while (x <= y)
{
glColor3f(0.0, 1.0, 0.0);
glVertex2d(x, y);
glVertex2d(-x, y);
glVertex2d(x, -y);
glVertex2d(y, x);
glVertex2d(-x, -y);
glVertex2d(-y, -x);
glVertex2d(y, -x);
glVertex2d(-y, x);
if (d > 0)
{
d += 4 * (x - y) + 10;
y--;
}
else
{
d += 4 * x + 6;
}
x++;
}
}

//Draw content
void display(void)
{
glClearColor(1.f, 1.f, 1.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);

glPushMatrix();

glColor3b(0, 0, 1);
glBegin(GL_POINTS); //GL_POINTS
DDA(0, 0, 300, 1200);
Bresenham(-100, -100, +200, 12200);
draw_circle(100);
glEnd();
glBegin(GL_POLYGON); //GL_LINE_LOOP
for (int vIndex = 0; vIndex < 3; vIndex++)
{
glVertex2i(rectangle[vIndex].x, rectangle[vIndex].y);
glVertex2i(rectangle[vIndex + 1].x, rectangle[vIndex + 1].y);
}
glEnd();
glutSwapBuffers();
glPopMatrix();
glFlush();
}

void my_traslate_inhomogeneous(struct my_v_inhomogeneous* polygon, int polygon_vertex_count, int tx, int ty)
{
for (int vIndex = 0; vIndex < polygon_vertex_count; vIndex++)
{
polygon[vIndex].x += tx;
polygon[vIndex].y += ty;
}
}

//Projection mode, modelview mode, etc
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w_width, (GLsizei)w_height);//Viewport size
glMatrixMode(GL_PROJECTION);//Set projection mode and Vista size
if (w <= h)
glOrtho(-0.5 * w_width, 0.5 * w_width, -0.5 * w_height * (GLfloat)w_height / (GLfloat)w_width, 0.5 * w_height * (GLfloat)w_height / (GLfloat)w_width,
-ZVALUE, ZVALUE);
else
glOrtho(-0.5 * w_width, 0.5 * w_width, -0.5 * w_height * (GLfloat)w_width / (GLfloat)w_height, 0.5 * w_height * (GLfloat)w_width / (GLfloat)w_height,
-ZVALUE, ZVALUE);
glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'w':
case 'W':
{
my_traslate_inhomogeneous(rectangle, 4, 0, 1);//Move 1 unit in the positive direction of Y axis

glutPostRedisplay();
break;
}
case 's':
case 'S':
{
my_traslate_inhomogeneous(rectangle, 4, 0, -1);//Move 1 unit in the negative direction of Y axis

glutPostRedisplay();
break;
}
case 'a':
case 'A':
{
my_traslate_inhomogeneous(rectangle, 4, -1, 0);//Move 1 unit in the negative direction of the X-axis

glutPostRedisplay();
break;
}
case 'd':
case 'D':
{
my_traslate_inhomogeneous(rectangle, 4, 1, 0);//Move 1 unit in the positive direction of X axis

glutPostRedisplay();
break;
}
case 27:
exit(0);
break;
}
}

//calling function
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(w_width, w_height);
glutInitWindowPosition(50, 50);
glutCreateWindow("2");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
```

rectangle keeps marking the red line, saying "the expression must be a pointer to the complete object type"
Compared with the code that can be run line by line, I didn't find anything wrong.
Defines a structure struct, which defines two variables int x and int y. Then there is another instance, rectangle, which requires X and y.
I reviewed the concepts of pointer and structure again. In short, I can't see any problems. Then I typed it again and found that I wrote an e less in the naming of my structure
... okay, it's okay

Now let's analyze the nonhomogeneous translation transformation
Nonhomogeneous translation transformation is a transformation that does not involve a matrix. Directly change the coordinate position of the graph to achieve the effect.
need:

1. Structure

```struct my_v_inhomogeneous
{float x;
foat y;
}
```

2.void()

```void my_translate_inhomogeneous(struct my_v_inhomogeneous*polygon,int polygon_vertex_count,int tx,int ty)
{
for (int vIndex=0;vIndex<polygon_vertex_count;vIndex++)
{
polygon[vIndex].x+=tx;
polygon[vIndex].y+=ty;
}
}
```

3. Keyboard or mouse interaction. (mouse is selected here)
When w is pressed, my_translate_inhomogeneous (rectangle, several vertices, x-axis distance, y-distance) will transform
my_traslate_inhomogeneous(rectangle, 4, 0, 1);// Move 1 unit in the positive direction of Y axis.
glutPostRedisplay(): marks that the current window needs to be redrawn
x and y of polygon[vIndex] will be affected, tx and ty will change, and then assigned to x and y with + =.

```void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'w':
case 'W':
{
my_traslate_inhomogeneous(rectangle, 4, 0, 1);//Move 1 unit in the positive direction of Y axis

glutPostRedisplay();
break;
}
case 's':
case 'S':
{
my_traslate_inhomogeneous(rectangle, 4, 0, -1);//Move 1 unit in the negative direction of Y axis

glutPostRedisplay();
break;
}
case 'a':
case 'A':
{
my_traslate_inhomogeneous(rectangle, 4, -1, 0);//Move 1 unit in the negative direction of the X-axis

glutPostRedisplay();
break;
}
case 'd':
case 'D':
{
my_traslate_inhomogeneous(rectangle, 4, 1, 0);//Move 1 unit in the positive direction of X axis

glutPostRedisplay();
break;
}
case 27:
exit(0);
break;
}
}
```

In fact, I'm not very clear about the struct my here_ v_ What does inhomogeneous * polygon mean. but
It's my short learning experience that tells me that I can't understand it... I can't understand it even more when I'm dead. I can always understand it at another time.

4.display function.
The previous operations are to re assign x and y, but they do not involve the display above. We can't see any change yet
The x and y of this structure rectangle (suddenly realized the role of struct... Can change the x and Y corresponding to each rectangle[i])
Therefore, in the display, the changes brought by the rectangle should be displayed.
glBegin~glend doesn't explain.
Traverse each vertex of the quadrilateral,
{draw the i vertex
Draw the next vertex}
glVertex2i is a function for drawing two-dimensional graphics.

```glBegin(GL_POLYGON); //GL_LINE_LOOP
for (int vIndex = 0; vIndex < 3; vIndex++)
{
glVertex2i(rectangle[vIndex].x, rectangle[vIndex].y);
glVertex2i(rectangle[vIndex + 1].x, rectangle[vIndex + 1].y);
}
glEnd();
```

Posted on Sat, 23 Oct 2021 09:23:43 -0400 by zedd2006