Загрузка данных
Да, лучше сделать **две отдельные программы**: одну для ЛР №4, вторую для ЛР №5.
---
# Лабораторная №4
4 куба без вращения:
* слева сверху — ортографическая
* слева снизу — диметрическая, `fz = 5/8`
* справа сверху — изометрическая
* справа снизу — перспективная
* каждый куб одного сплошного цвета
* цвета у кубов разные
```cpp
#include <GL/glut.h>
#pragma comment(lib, "freeglut.lib")
#include <stdlib.h>
GLfloat vertices[8][3] = {
{-1.0f, -1.0f, -1.0f},
{ 1.0f, -1.0f, -1.0f},
{ 1.0f, 1.0f, -1.0f},
{-1.0f, 1.0f, -1.0f},
{-1.0f, -1.0f, 1.0f},
{ 1.0f, -1.0f, 1.0f},
{ 1.0f, 1.0f, 1.0f},
{-1.0f, 1.0f, 1.0f}
};
GLfloat cubeColors[4][3] = {
{1.0f, 0.2f, 0.2f},
{0.2f, 1.0f, 0.2f},
{0.2f, 0.4f, 1.0f},
{1.0f, 0.8f, 0.2f}
};
int windowWidth = 800;
int windowHeight = 800;
const float ISO_THETA = 35.264f;
const float ISO_PHI = 45.0f;
const float DIM_THETA = 20.7f;
const float DIM_PHI = 32.0f;
float eyeX = 5.0f;
float eyeY = 5.0f;
float eyeZ = 5.0f;
void drawFace(int a, int b, int c, int d) {
glBegin(GL_POLYGON);
glVertex3fv(vertices[a]);
glVertex3fv(vertices[b]);
glVertex3fv(vertices[c]);
glVertex3fv(vertices[d]);
glEnd();
}
void drawCube(int colorIndex) {
glColor3fv(cubeColors[colorIndex]);
drawFace(0, 3, 2, 1);
drawFace(2, 3, 7, 6);
drawFace(0, 4, 7, 3);
drawFace(1, 2, 6, 5);
drawFace(4, 5, 6, 7);
drawFace(0, 1, 5, 4);
}
void renderCubeInViewport(int x, int y, int w, int h, int projectionType, int colorIndex) {
glViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (projectionType == 3) {
double aspect = (double)w / (double)h;
gluPerspective(45.0, aspect, 1.0, 20.0);
} else {
glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (projectionType == 3) {
gluLookAt(
eyeX, eyeY, eyeZ,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0
);
}
switch (projectionType) {
case 1:
glRotatef(ISO_PHI, 0.0f, 1.0f, 0.0f);
glRotatef(ISO_THETA, 1.0f, 0.0f, 0.0f);
break;
case 2:
glRotatef(DIM_PHI, 0.0f, 1.0f, 0.0f);
glRotatef(DIM_THETA, 1.0f, 0.0f, 0.0f);
break;
}
drawCube(colorIndex);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
int halfW = windowWidth / 2;
int halfH = windowHeight / 2;
renderCubeInViewport(0, halfH, halfW, halfH, 0, 0);
renderCubeInViewport(0, 0, halfW, halfH, 2, 1);
renderCubeInViewport(halfW, halfH, halfW, halfH, 1, 2);
renderCubeInViewport(halfW, 0, halfW, halfH, 3, 3);
glutSwapBuffers();
}
void reshape(int w, int h) {
if (h == 0) h = 1;
windowWidth = w;
windowHeight = h;
glViewport(0, 0, w, h);
}
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27:
exit(0);
break;
}
}
void init() {
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Laboratory Work 4");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
```
---
# Лабораторная №5
Нужно:
* загрузить изображение через `stb_image.h`
* вывести изображение через `glDrawPixels`
* наложить это изображение как текстуру на все грани куба
* куб вращается
Файл картинки положи рядом с `.cpp`, например:
```cpp
"texture.bmp"
```
Также добавь в проект файл `stb_image.h`.
```cpp
#include <GL/glut.h>
#pragma comment(lib, "freeglut.lib")
#include <stdlib.h>
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
GLfloat vertices[8][3] = {
{-1.0f, -1.0f, -1.0f},
{ 1.0f, -1.0f, -1.0f},
{ 1.0f, 1.0f, -1.0f},
{-1.0f, 1.0f, -1.0f},
{-1.0f, -1.0f, 1.0f},
{ 1.0f, -1.0f, 1.0f},
{ 1.0f, 1.0f, 1.0f},
{-1.0f, 1.0f, 1.0f}
};
GLuint textureID;
unsigned char* imageData = NULL;
int imageWidth = 0;
int imageHeight = 0;
int imageChannels = 0;
int windowWidth = 1000;
int windowHeight = 600;
float angleX = 25.0f;
float angleY = 30.0f;
void drawTexturedFace(int a, int b, int c, int d) {
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vertices[a]);
glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vertices[b]);
glTexCoord2f(1.0f, 1.0f);
glVertex3fv(vertices[c]);
glTexCoord2f(0.0f, 1.0f);
glVertex3fv(vertices[d]);
glEnd();
}
void drawTexturedCube() {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glColor3f(1.0f, 1.0f, 1.0f);
drawTexturedFace(0, 3, 2, 1);
drawTexturedFace(2, 3, 7, 6);
drawTexturedFace(0, 4, 7, 3);
drawTexturedFace(1, 2, 6, 5);
drawTexturedFace(4, 5, 6, 7);
drawTexturedFace(0, 1, 5, 4);
glDisable(GL_TEXTURE_2D);
}
void loadTexture(const char* filename) {
imageData = stbi_load(filename, &imageWidth, &imageHeight, &imageChannels, 3);
if (!imageData) {
printf("Image loading error: %s\n", filename);
exit(1);
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
imageWidth,
imageHeight,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
imageData
);
}
void drawImageLeftSide() {
glViewport(0, 0, windowWidth / 2, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, windowWidth / 2, 0, windowHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
float scaleX = (float)(windowWidth / 2) / imageWidth;
float scaleY = (float)windowHeight / imageHeight;
float scale = scaleX < scaleY ? scaleX : scaleY;
float drawW = imageWidth * scale;
float drawH = imageHeight * scale;
float posX = ((windowWidth / 2) - drawW) / 2.0f;
float posY = (windowHeight - drawH) / 2.0f;
glRasterPos2f(posX, posY);
glPixelZoom(scale, scale);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glDrawPixels(
imageWidth,
imageHeight,
GL_RGB,
GL_UNSIGNED_BYTE,
imageData
);
glPixelZoom(1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
void drawCubeRightSide() {
glViewport(windowWidth / 2, 0, windowWidth / 2, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspect = (double)(windowWidth / 2) / (double)windowHeight;
gluPerspective(45.0, aspect, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
4.0, 4.0, 6.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0
);
glRotatef(angleX, 1.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 1.0f, 0.0f);
drawTexturedCube();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawImageLeftSide();
drawCubeRightSide();
glutSwapBuffers();
}
void reshape(int w, int h) {
if (h == 0) h = 1;
windowWidth = w;
windowHeight = h;
glViewport(0, 0, w, h);
}
void idle() {
angleY += 0.3f;
if (angleY >= 360.0f) {
angleY -= 360.0f;
}
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'a':
angleY -= 5.0f;
break;
case 'd':
angleY += 5.0f;
break;
case 'w':
angleX -= 5.0f;
break;
case 's':
angleX += 5.0f;
break;
case 27:
if (imageData) {
stbi_image_free(imageData);
}
exit(0);
break;
}
glutPostRedisplay();
}
void init() {
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glEnable(GL_DEPTH_TEST);
loadTexture("texture.bmp");
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Laboratory Work 5");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
```
Для ЛР №5 в папке проекта должны быть:
```text
main.cpp
stb_image.h
texture.bmp
```
В ЛР №4 кубы **не вращаются**.
В ЛР №5 куб **вращается**, и текстура наложена на все его грани.