Kompyuter grafikasi: OpenGL 2-qism
Salom. Bugun yana o'sha kompyuter grafikasi haqida gapirmoqchiman. Oldingiz maqolamni o'qigan bo'lsangiz u yerda faqat matematika haqida gapirganman. Endi shu matematikani haqiqiy dasturlashda ko'ramiz.
Buning uchun bizga yana OpenGL va SDL kerak bo'ladi.
Avvalo VS2010 da bitta Console Application (C/C++) yaratib, main.cpp ni ham qo'shamiz o'sha proyektga va ishni boshlaymiz.
Asosiy ishimiy matritsalar bilan ishlash bo'ladi.
Matritsani strukturasini yaratish
Endi yangi matritsani yaratadigan ya o'chirish funksiyani
Eng ko'p ishlatiladigan funksiyamiz ya'ni matritsalarni ko'paytirish
Asosiy funksiyalar transform va rotate (scaleni yozmadim)
Yana 2 ta funksiyami qoldi, ular kordinalatalar oqi va nuqtani chizish uchun ishlatiladi. Mani holatimda n — matritsani qatorlari soni, m — ustunlari soni sifatida ishlatilgan. Kodda izoh keltirmadim chunki bundan oldingi maqolamda hamma matritsalarni keltirganman. Shularni faqat kodga o'tkazdim. Qolga sizga notanish funksiyalar bilan asta sekin tanishamiz.
Shunaq qilib oxirgi natija:
Natija (EXE ko'chirish):

Sizga vaxima bo'lib ko'rinayotgan kodda aslida hech narsa yozilmagan desayam bo'ladi. Keyingi maqolamda huddi shu natijani OpenGL ni funksiyalaridan foydalanib qilamiz.
Buning uchun bizga yana OpenGL va SDL kerak bo'ladi.
Avvalo VS2010 da bitta Console Application (C/C++) yaratib, main.cpp ni ham qo'shamiz o'sha proyektga va ishni boshlaymiz.
Asosiy ishimiy matritsalar bilan ishlash bo'ladi.
Matritsani strukturasini yaratish
typedef struct _MATRIX
{
int n, m; /* Matritsani o'lchami */
double ** data; /* Matritsa qiymatlari */
} MATRIX, * PMATRIX;
Endi yangi matritsani yaratadigan ya o'chirish funksiyani
PMATRIX new_matrix(int n, int m)
{
PMATRIX pm = (PMATRIX)malloc(sizeof(_MATRIX));
pm->data = (double **)malloc(n * sizeof(double));
pm->n = n;
pm->m = m;
for(int i = 0; i < n; i++)
{
pm->data[i] = (double *)malloc(m * sizeof(double));
for(int j = 0; j < m; j++)
pm->data[i][j] = i == j ? 1 : 0;
}
return pm;
}
void free_matrix(PMATRIX pm)
{
free(pm->data);
pm->data = NULL;
free(pm);
pm = NULL;
}
Eng ko'p ishlatiladigan funksiyamiz ya'ni matritsalarni ko'paytirish
void mult(PMATRIX m1, PMATRIX *m2)
{
PMATRIX result = new_matrix((*m2)->n, (*m2)->m);
for(int nn = 0; nn < (*m2)->n; nn++)
{
for(int mm = 0; mm < (*m2)->m; mm++)
{
result->data[nn][mm] = 0;
for(int k = 0; k <(*m2)->n; k++)
result->data[nn][mm] += m1->data[nn][k] * (*m2)->data[k][mm];
}
}
free_matrix(*m2);
*m2 = result;
}
Asosiy funksiyalar transform va rotate (scaleni yozmadim)
void transform(PMATRIX *point, int dx, int dy, int dz)
{
PMATRIX m = new_matrix(4, 4);
m->data[0][3] = dx;
m->data[1][3] = dy;
m->data[2][3] = dz;
mult(m, point);
free_matrix(m);
}
void rotate(PMATRIX *point, double x, double y, double z, float angle)
{
angle = angle * 3.1415926 / 180.0;
PMATRIX rX = new_matrix(4, 4);
rX->data[1][1] = cos(angle * x);
rX->data[2][1] = sin(angle * x);
rX->data[1][2] = -sin(angle * x);
rX->data[2][2] = cos(angle * x);
PMATRIX rY = new_matrix(4, 4);
rY->data[0][0] = cos(-angle * y);
rY->data[2][0] = sin(-angle * y);
rY->data[0][2] = -sin(-angle * y);
rY->data[2][2] = cos(-angle * y);
PMATRIX rZ = new_matrix(4, 4);
rZ->data[0][0] = cos(angle * z);
rZ->data[1][0] = sin(angle * z);
rZ->data[0][1] = -sin(angle * z);
rZ->data[1][1] = cos(angle * z);
if (x != 0.0)
mult(rX, point);
if (y != 0.0)
mult(rY, point);
if (z != 0.0)
mult(rZ, point);
free_matrix(rX);
free_matrix(rY);
free_matrix(rZ);
}
Yana 2 ta funksiyami qoldi, ular kordinalatalar oqi va nuqtani chizish uchun ishlatiladi. Mani holatimda n — matritsani qatorlari soni, m — ustunlari soni sifatida ishlatilgan. Kodda izoh keltirmadim chunki bundan oldingi maqolamda hamma matritsalarni keltirganman. Shularni faqat kodga o'tkazdim. Qolga sizga notanish funksiyalar bilan asta sekin tanishamiz.
Shunaq qilib oxirgi natija:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SDL.h>
#define PROGRAM_NAME "Matritsalar"
typedef struct _MATRIX
{
int n, m; /* Matritsani o'lchami */
double ** data; /* Matritsa qiymatlari */
} MATRIX, * PMATRIX;
PMATRIX new_matrix(int n, int m)
{
PMATRIX pm = (PMATRIX)malloc(sizeof(_MATRIX));
pm->data = (double **)malloc(n * sizeof(double));
pm->n = n;
pm->m = m;
for(int i = 0; i < n; i++)
{
pm->data[i] = (double *)malloc(m * sizeof(double));
for(int j = 0; j < m; j++)
pm->data[i][j] = i == j ? 1 : 0;
}
return pm;
}
void free_matrix(PMATRIX pm)
{
free(pm->data);
pm->data = NULL;
free(pm);
pm = NULL;
}
void mult(PMATRIX m1, PMATRIX *m2)
{
PMATRIX result = new_matrix((*m2)->n, (*m2)->m);
for(int nn = 0; nn < (*m2)->n; nn++)
{
for(int mm = 0; mm < (*m2)->m; mm++)
{
result->data[nn][mm] = 0;
for(int k = 0; k <(*m2)->n; k++)
result->data[nn][mm] += m1->data[nn][k] * (*m2)->data[k][mm];
}
}
free_matrix(*m2);
*m2 = result;
}
void transform(PMATRIX *point, int dx, int dy, int dz)
{
PMATRIX m = new_matrix(4, 4);
m->data[0][3] = dx;
m->data[1][3] = dy;
m->data[2][3] = dz;
mult(m, point);
free_matrix(m);
}
void rotate(PMATRIX *point, double x, double y, double z, float angle)
{
angle = angle * 3.1415926 / 180.0;
PMATRIX rX = new_matrix(4, 4);
rX->data[1][1] = cos(angle * x);
rX->data[2][1] = sin(angle * x);
rX->data[1][2] = -sin(angle * x);
rX->data[2][2] = cos(angle * x);
PMATRIX rY = new_matrix(4, 4);
rY->data[0][0] = cos(-angle * y);
rY->data[2][0] = sin(-angle * y);
rY->data[0][2] = -sin(-angle * y);
rY->data[2][2] = cos(-angle * y);
PMATRIX rZ = new_matrix(4, 4);
rZ->data[0][0] = cos(angle * z);
rZ->data[1][0] = sin(angle * z);
rZ->data[0][1] = -sin(angle * z);
rZ->data[1][1] = cos(angle * z);
if (x != 0.0)
mult(rX, point);
if (y != 0.0)
mult(rY, point);
if (z != 0.0)
mult(rZ, point);
free_matrix(rX);
free_matrix(rY);
free_matrix(rZ);
}
void draw_coords()
{
glBegin(GL_LINES);
glColor3ub(255, 0, 0);
glVertex3i(-50, 0, 0);
glVertex3i(100, 0, 0);
glColor3ub(0, 255, 0);
glVertex3i(0, -50, 0);
glVertex3i(0, 100, 0);
glColor3ub(0, 0, 255);
glVertex3i(0, 0, -50);
glVertex3i(0, 0, 100);
glEnd();
}
void draw_matrix_point(PMATRIX m)
{
int x = m->data[0][0];
int y = m->data[1][0];
int z = m->data[2][0];
glBegin(GL_QUADS);
glColor3ub(255, 255, 0);
//past qismi
glVertex3i(x - 1, y - 1, z - 1);
glVertex3i(x + 1, y - 1, z - 1);
glVertex3i(x + 1, y + 1, z - 1);
glVertex3i(x - 1, y + 1, z - 1);
//yuqorisi
glVertex3i(x - 1, y - 1, z + 1);
glVertex3i(x + 1, y - 1, z + 1);
glVertex3i(x + 1, y + 1, z + 1);
glVertex3i(x - 1, y + 1, z + 1);
glVertex3i(x - 1, y - 1, z - 1);
glVertex3i(x + 1, y - 1, z - 1);
glVertex3i(x + 1, y - 1, z + 1);
glVertex3i(x - 1, y - 1, z + 1);
glVertex3i(x - 1, y + 1, z - 1);
glVertex3i(x + 1, y + 1, z - 1);
glVertex3i(x + 1, y + 1, z + 1);
glVertex3i(x - 1, y + 1, z + 1);
glVertex3i(x - 1, y - 1, z - 1);
glVertex3i(x - 1, y - 1, z + 1);
glVertex3i(x - 1, y + 1, z + 1);
glVertex3i(x - 1, y + 1, z - 1);
glVertex3i(x + 1, y - 1, z - 1);
glVertex3i(x + 1, y - 1, z + 1);
glVertex3i(x + 1, y + 1, z + 1);
glVertex3i(x + 1, y + 1, z - 1);
glEnd();
}
void sdldie(const char *msg)
{
printf("%s: %s\n", msg, SDL_GetError());
SDL_Quit();
exit(1);
}
int main(int argc, char *argv[])
{
//X=50, Y=0, Z=50 joydagi nuqta matritsasini yaratish
PMATRIX point = new_matrix(4, 1);
point->data[0][0] = 50;
point->data[1][0] = 0;
point->data[2][0] = 50;
point->data[3][0] = 1;
int windowWidth = 640, windowHeight = 480;
int isRunning = 1;
SDL_Window *mainwindow; /* Oynda o'zgaruvchisi */
SDL_GLContext maincontext; /* OpenGL konteksi o'zgaruvchisi */
if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initsalizatsiya SDL. Umuman tekshirish. */
sdldie("Initsalizatsiya SDL da xatolik"); /* Agar xatolik bo'lsa */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); /* Double buffer qo'shish */
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); /* Double buffer qo'shish */
//Oyna yaratish, o'lchami 300x450 bo'lgan
mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
windowWidth, windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!mainwindow) /* Agar yaratib bo'lmasa */
sdldie("Oynani yaratishda xatolik");
/* OpenGL oynasini yaratish */
maincontext = SDL_GL_CreateContext(mainwindow);
//oyna o'lchamini berish
//glOrtho(0, 10, 15, 0, -1, 1);
glViewport(0, 0, windowWidth, windowHeight);
glLoadIdentity();
gluPerspective(45.0f, windowWidth / (float)windowHeight, 0.01f, 900.0f);
gluLookAt(150, 150, 150, 0, 0, 10, 0, 0, 1);
/* Bufferni tozalash rangi */
glClearColor ( 0.0f, 0.0f, 0.0f, 1.0 );
SDL_Event e;
//game loop
while( isRunning )
{
//klaviatura bosilganligini tekshiradi
if (SDL_PollEvent(&e))
{
if (e.type == SDL_KEYDOWN)
{
switch(e.key.keysym.sym)
{
case SDLK_ESCAPE:
isRunning = false;
break;
}
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_coords();
draw_matrix_point(point);
rotate(&point, 1, 0, 0, 10);
SDL_Delay(10); //10 ms ga pausa qilish
SDL_GL_SwapWindow(mainwindow);
}
//tozalash va chiqish
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(mainwindow);
SDL_Quit();
return 0;
}
Natija (EXE ko'chirish):

Sizga vaxima bo'lib ko'rinayotgan kodda aslida hech narsa yozilmagan desayam bo'ladi. Keyingi maqolamda huddi shu natijani OpenGL ni funksiyalaridan foydalanib qilamiz.
Нет комментариев