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
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 data[i] = (double *)malloc(m * sizeof(double));
for(int j = 0; j 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 n; nn++)
{
for(int mm = 0; mm m; mm++)
{
result->data[nn][mm] = 0;
for(int k = 0; k 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
#include
#include
#include
#include
#include
#include
#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 data[i] = (double *)malloc(m * sizeof(double));
for(int j = 0; j 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 n; nn++)
{
for(int mm = 0; mm m; mm++)
{
result->data[nn][mm] = 0;
for(int k = 0; k 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: %sn", 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)
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.
Texnologiyalar
Kompyuter grafikasi: OpenGL 2-qism