Skip to content

Instantly share code, notes, and snippets.

@habibg1232191
Created May 3, 2024 22:57
Show Gist options
  • Save habibg1232191/80ee600e812a0ed75fd8e28cafa87df2 to your computer and use it in GitHub Desktop.
Save habibg1232191/80ee600e812a0ed75fd8e28cafa87df2 to your computer and use it in GitHub Desktop.
#include "Render.h"
#include <sstream>
#include <iostream>
#include <windows.h>
#include <GL\GL.h>
#include <GL\GLU.h>
#include "MyOGL.h"
#include "Camera.h"
#include "Light.h"
#include "Primitives.h"
#include "GUItextRectangle.h"
#define PI 3.14
bool textureMode = true;
bool lightMode = true;
bool textureReplace = true; // (Н) Эта переменная отвечает за смену текстур
//класс для настройки камеры
class CustomCamera : public Camera
{
public:
//дистанция камеры
double camDist;
//углы поворота камеры
double fi1, fi2;
//значния масеры по умолчанию
CustomCamera()
{
camDist = 15;
fi1 = 1;
fi2 = 1;
}
//считает позицию камеры, исходя из углов поворота, вызывается движком
void SetUpCamera()
{
//отвечает за поворот камеры мышкой
lookPoint.setCoords(0, 0, 0);
pos.setCoords(camDist*cos(fi2)*cos(fi1),
camDist*cos(fi2)*sin(fi1),
camDist*sin(fi2));
if (cos(fi2) <= 0)
normal.setCoords(0, 0, -1);
else
normal.setCoords(0, 0, 1);
LookAt();
}
void CustomCamera::LookAt()
{
//функция настройки камеры
gluLookAt(pos.X(), pos.Y(), pos.Z(), lookPoint.X(), lookPoint.Y(), lookPoint.Z(), normal.X(), normal.Y(), normal.Z());
}
} camera; //создаем объект камеры
//Класс для настройки света
class CustomLight : public Light
{
public:
CustomLight()
{
//начальная позиция света
pos = Vector3(1, 1, 3);
}
//рисует сферу и линии под источником света, вызывается движком
void DrawLightGhismo()
{
glDisable(GL_LIGHTING);
glColor3d(0.9, 0.8, 0);
Sphere s;
s.pos = pos;
s.scale = s.scale*0.08;
s.Show();
if (OpenGL::isKeyPressed('G'))
{
glColor3d(0, 0, 0);
//линия от источника света до окружности
glBegin(GL_LINES);
glVertex3d(pos.X(), pos.Y(), pos.Z());
glVertex3d(pos.X(), pos.Y(), 0);
glEnd();
//рисуем окруность
Circle c;
c.pos.setCoords(pos.X(), pos.Y(), 0);
c.scale = c.scale*1.5;
c.Show();
}
}
void SetUpLight()
{
GLfloat amb[] = { 0.2, 0.2, 0.2, 0 };
GLfloat dif[] = { 1.0, 1.0, 1.0, 0 };
GLfloat spec[] = { .7, .7, .7, 0 };
GLfloat position[] = { pos.X(), pos.Y(), pos.Z(), 1. };
// параметры источника света
glLightfv(GL_LIGHT0, GL_POSITION, position);
// характеристики излучаемого света
// фоновое освещение (рассеянный свет)
glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
// диффузная составляющая света
glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
// зеркально отражаемая составляющая света
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glEnable(GL_LIGHT0);
}
} light; //создаем источник света
//старые координаты мыши
int mouseX = 0, mouseY = 0;
void mouseEvent(OpenGL *ogl, int mX, int mY)
{
int dx = mouseX - mX;
int dy = mouseY - mY;
mouseX = mX;
mouseY = mY;
//меняем углы камеры при нажатой левой кнопке мыши
if (OpenGL::isKeyPressed(VK_RBUTTON))
{
camera.fi1 += 0.01*dx;
camera.fi2 += -0.01*dy;
}
//двигаем свет по плоскости, в точку где мышь
if (OpenGL::isKeyPressed('G') && !OpenGL::isKeyPressed(VK_LBUTTON))
{
LPPOINT POINT = new tagPOINT();
GetCursorPos(POINT);
ScreenToClient(ogl->getHwnd(), POINT);
POINT->y = ogl->getHeight() - POINT->y;
Ray r = camera.getLookRay(POINT->x, POINT->y);
double z = light.pos.Z();
double k = 0, x = 0, y = 0;
if (r.direction.Z() == 0)
k = 0;
else
k = (z - r.origin.Z()) / r.direction.Z();
x = k*r.direction.X() + r.origin.X();
y = k*r.direction.Y() + r.origin.Y();
light.pos = Vector3(x, y, z);
}
if (OpenGL::isKeyPressed('G') && OpenGL::isKeyPressed(VK_LBUTTON))
{
light.pos = light.pos + Vector3(0, 0, 0.02*dy);
}
}
void mouseWheelEvent(OpenGL *ogl, int delta)
{
if (delta < 0 && camera.camDist <= 1)
return;
if (delta > 0 && camera.camDist >= 100)
return;
camera.camDist += 0.01*delta;
}
void keyDownEvent(OpenGL *ogl, int key)
{
if (key == 'L')
{
lightMode = !lightMode;
}
if (key == 'T')
{
textureMode = !textureMode;
}
if (key == 'R')
{
camera.fi1 = 1;
camera.fi2 = 1;
camera.camDist = 15;
light.pos = Vector3(1, 1, 3);
}
if (key == 'F')
{
light.pos = camera.pos;
}
if (key == 'E') // (Н) Смена текстуры происходит по этой кнопке
{
textureReplace = !textureReplace;
}
}
void keyUpEvent(OpenGL *ogl, int key)
{
}
GLuint texId;
GLuint texId2; // (Н) Я хз как по другому делать, поэтому я просто скопировал часть кода, ко всем переменным в конце добавил "2", и всё работает
//выполняется перед первым рендером
void initRender(OpenGL *ogl)
{
//настройка текстур
//4 байта на хранение пикселя
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//настройка режима наложения текстур
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
//включаем текстуры
glEnable(GL_TEXTURE_2D);
//массив трехбайтных элементов (R G B) (Н) Код брался и копировался отсюда
RGBTRIPLE *texarray;
//массив символов, (высота*ширина*4 4, потомучто выше, мы указали использовать по 4 байта на пиксель текстуры - R G B A)
char *texCharArray;
int texW, texH;
OpenGL::LoadBMP("texture.bmp", &texW, &texH, &texarray); // (Н) Чтоб не мучаться с картинками, я коприовал старую и рисовал на ней
OpenGL::RGBtoChar(texarray, texW, texH, &texCharArray);
//генерируем ИД для текстуры
glGenTextures(1, &texId);
//биндим айдишник, все что будет происходить с текстурой, будте происходить по этому ИД
glBindTexture(GL_TEXTURE_2D, texId);
//загружаем текстуру в видеопямять, в оперативке нам больше она не нужна
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texW, texH, 0, GL_RGBA, GL_UNSIGNED_BYTE, texCharArray);
//отчистка памяти
free(texCharArray);
free(texarray);
//наводим шмон
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // (Н) И досюда
//массив трехбайтных элементов (R G B)
RGBTRIPLE* texarray2;
//массив символов, (высота*ширина*4 4, потомучто выше, мы указали использовать по 4 байта на пиксель текстуры - R G B A)
char* texCharArray2;
int texW2, texH2;
OpenGL::LoadBMP("texture1.bmp", &texW2, &texH2, &texarray2);
OpenGL::RGBtoChar(texarray2, texW2, texH2, &texCharArray2);
//генерируем ИД для текстуры
glGenTextures(1, &texId2);
//биндим айдишник, все что будет происходить с текстурой, будте происходить по этому ИД
glBindTexture(GL_TEXTURE_2D, texId2);
//загружаем текстуру в видеопямять, в оперативке нам больше она не нужна
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texW2, texH2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texCharArray2);
//отчистка памяти
free(texCharArray2);
free(texarray2);
//наводим шмон
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//камеру и свет привязываем к "движку"
ogl->mainCamera = &camera;
ogl->mainLight = &light;
// нормализация нормалей : их длины будет равна 1
glEnable(GL_NORMALIZE);
// устранение ступенчатости для линий
glEnable(GL_LINE_SMOOTH);
// задать параметры освещения
// параметр GL_LIGHT_MODEL_TWO_SIDE -
// 0 - лицевые и изнаночные рисуются одинаково(по умолчанию),
// 1 - лицевые и изнаночные обрабатываются разными режимами
// соответственно лицевым и изнаночным свойствам материалов.
// параметр GL_LIGHT_MODEL_AMBIENT - задать фоновое освещение,
// не зависящее от сточников
// по умолчанию (0.2, 0.2, 0.2, 1.0)
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
camera.fi1 = -1.3;
camera.fi2 = 0.8;
}
void crossProduct( double vec1[3], double vec2[3], double result[3]) {
result[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
result[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
result[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
}
// Функция для нормализации вектора
void normalize(double vec[3]) {
double length = std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
if (length != 0.0f) {
vec[0] /= length;
vec[1] /= length;
vec[2] /= length;
}
}
// Функция для вычисления нормали по трем векторам
void computeNormal(double vec1[3], double vec2[3], double vec3[3], double normal[3]) {
double vecA[3] = { vec2[0] - vec1[0], vec2[1] - vec1[1], vec2[2] - vec1[2] };
double vecB[3] = { vec3[0] - vec1[0], vec3[1] - vec1[1], vec3[2] - vec1[2] };
crossProduct(vecA, vecB, normal);
normalize(normal);
}
// Функция для вычисления нормали по четырем векторам
void computeQuadNormal( double A[3], const double B[3], double C[3], double D[3], double normal[3]) {
double vec1[3] = { B[0] - A[0], B[1] - A[1], B[2] - A[2] };
double vec2[3] = { D[0] - A[0], D[1] - A[1], D[2] - A[2] };
crossProduct(vec1, vec2, normal);
normalize(normal);
}
//Начало рисования квадратика станкина
double A[] = { 0.0, 0.0, 0.0 };
double B[] = { 7, -3, 0 };
double C[] = { 5, -7, 0 };
double D[] = { 8, -11, 0 };
double E[] = { 2, -13, 0 }; //polukrug dlya 40
double F[] = { 2, -8, 0 }; //polukrug dlya 40
double G[] = { -6, -7, 0 };
double H[] = { 0, -6, 0 };
double A1[] = { 0.0, 0.0, 5 };
double B1[] = { 7, -3, 5 };
double C1[] = { 5, -7, 5 };
double D1[] = { 8, -11, 5 };
double E1[] = { 2, -13, 5 }; //polukrug dlya 40
double F1[] = { 2, -8, 5 }; //polukrug dlya 40
double G1[] = { -6, -7, 5 };
double H1[] = { 0, -6, 5 };
double ED[] = { 4.95, -11.9, 0 }; //polukrug dlya 40
double AB[] = { 4.145, 0, 0 }; //polukrug dlya 40
void drawGreenCylinder()
{
glColor3d(0, 1, 0);
double step = 0.1;
double height = 5;
double radius = PI * 2.0 / 2;
glPushMatrix();
glTranslatef(ED[0], ED[1], ED[2]);
glRotatef(18, 0, 0, 1);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, 0);
glNormal3d(0, 0, -1);
for (double a = -PI; a <= 0; a += step)
{
glVertex3f(radius * cos(a), radius * sin(a), 0);
}
glVertex3f(radius * cos(0), radius * sin(0), 0);
glEnd();
/*glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, height);
glNormal3d(0, 0, 1);
for (double a = -PI; a <= 0; a += step)
{
glVertex3f(radius * cos(a), radius * sin(a), height);
}
glVertex3f(radius * cos(0), radius * sin(0), height);
glEnd();*/
double normal[3];
double Det[] = { 0,0,0 };
double Det1[] = { 0,0,5 };
double N[] = { 0,0,0 };
double Nl;
double x0 = radius * cos(PI);
double y0 = radius * sin(PI);
double tx0 = 0;
double ty0 = 0;
step = 0.0001;
for (double a = -PI; a <= 0; a += step)
{
double x = radius * cos(a);
double y = radius * sin(a);
double tx = tx0 + 1.0 / 8440.0;
double ty = tx0 + 1.0 / 8440.0;
glBegin(GL_QUADS);
Det[0] = { x - (16 + PI * cos((a - 0.0001) * 3.141593)) }; // (Н) Это нахождение нормалей
Det[1] = { y - (2 + PI * 2 * sin((a - 0.0001) * 3.141593)) };
N[0] = { Det[1] * Det1[2] - Det1[1] * Det[2] };
N[1] = { -Det[0] * Det1[2] + Det1[0] * Det[2] };
N[2] = { Det[0] * Det1[1] - Det1[0] * Det[1] };
Nl = sqrt(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
N[0] = { N[0] / Nl };
N[1] = { N[1] / Nl };
N[2] = { N[2] / Nl };
glNormal3d(N[0], -N[1], N[2]);
glTexCoord2d(tx0, 0); // (Н) Это пиздец, нигде нет нормального гайда наложения текстуры на выпулкую плоскость
glVertex3d(x0, y0, 0); // (Н) Для работы с текстурами существуют текстурные координаты от 0 до 1. Если мы хотим впихнуть в условный квадрат половину текстуры мы просто вводим дробь
glTexCoord2d(tx, 0); // (Н) Вот здесь это и используется, я, по сути, делю текстуру на 7000 частей, и на каждый квадрат(их 7000 штук) накладываю определённую часть текстуры
glVertex3d(x, y, 0); // (Н) Если что не понятно спрашивайте лично, правда объяснять я не умею :p
glTexCoord2d(ty, 1); // (Н) Если у вас будет текстура с зарисованным правым углом(у меня такая была, лучше края не закрашывать) будут артефакты!!!!!
glVertex3d(x, y, 5);
glTexCoord2d(ty0, 1);
glVertex3d(x0, y0, 5);
glEnd();
x0 = x;
y0 = y;
tx0 = tx;
ty0 = ty;
}
glPopMatrix();
}
void drawPurpleCylinder()
{
glColor3d(0.54, 0, 1);
double step = 0.1;
double height = 5;
double radius = PI * 2.64 / 2;
glPushMatrix();
glTranslatef(AB[0], AB[1], AB[2]);
// glRotatef(-23.19, 0, 0, 1); // x = 7, y = -3
double cut_angle = 2 * PI - 0.8;
const double finalAngle = 3 * PI / 2 + 0.05;
glColor3f(1, 0, 0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(-AB[0], H[1], 0);
glNormal3d(0, 0, -1);
for (double a = PI; a <= PI * 2; a += step)
{
double px = radius * cos(a);
double py = radius * sin(a);
if (a >= PI && a <= finalAngle)
{
glVertex3f(px, py, 0);
}
}
glVertex3f(radius * cos(finalAngle), radius * sin(finalAngle), 0);
glEnd();
double normal[3];
double Det[] = { 0,0,0 };
double Det1[] = { 0,0,5 };
double N[] = { 0,0,0 };
double Nl;
double x0 = radius * cos(PI);
double y0 = radius * sin(PI);
double tx0 = 0;
double ty0 = 0;
step = 0.0001;
for (double a = PI; a <= cut_angle; a += step) {
double x = radius * cos(a);
double y = radius * sin(a);
double tx = tx0 + 1.0 / 7000.0;
double ty = tx0 + 1.0 / 7000.0;
glBegin(GL_QUADS);
Det[0] = { x - (18 + PI * cos((a - 0.0001) * 3.141593)) }; // (Н) Это нахождение нормалей
Det[1] = { y - (2 + PI * sin((a - 0.0001) * 3.141593)) };
N[0] = { Det[1] * Det1[2] - Det1[1] * Det[2] };
N[1] = { -Det[0] * Det1[2] + Det1[0] * Det[2] };
N[2] = { Det[0] * Det1[1] - Det1[0] * Det[1] };
Nl = sqrt(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
N[0] = { N[0] / Nl };
N[1] = { N[1] / Nl };
N[2] = { N[2] / Nl };
glNormal3d(N[0], N[1], N[2]);
glTexCoord2d(tx0, 0); // (Н) Это пиздец, нигде нет нормального гайда наложения текстуры на выпулкую плоскость
glVertex3d(x0, y0, 0); // (Н) Для работы с текстурами существуют текстурные координаты от 0 до 1. Если мы хотим впихнуть в условный квадрат половину текстуры мы просто вводим дробь
glTexCoord2d(tx, 0); // (Н) Вот здесь это и используется, я, по сути, делю текстуру на 7000 частей, и на каждый квадрат(их 7000 штук) накладываю определённую часть текстуры
glVertex3d(x, y, 0); // (Н) Если что не понятно спрашивайте лично, правда объяснять я не умею :p
glTexCoord2d(ty, 1); // (Н) Если у вас будет текстура с зарисованным правым углом(у меня такая была, лучше края не закрашывать) будут артефакты!!!!!
glVertex3d(x, y, 5);
glTexCoord2d(ty0, 1);
glVertex3d(x0, y0, 5);
glEnd();
x0 = x;
y0 = y;
tx0 = tx;
ty0 = ty;
}
//glColor3d(0.54, 0, 1); // цвет стенки
//glBegin(GL_QUADS);
//glVertex3f(-AB[0], 0, 0);
//glVertex3f(-AB[0], 0, height);
//glVertex3f(radius * cos(cut_angle), radius * sin(cut_angle), height);
//glVertex3f(radius * cos(cut_angle), radius * sin(cut_angle), 0);
//glEnd();
glPopMatrix();
}
void Render(OpenGL *ogl)
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
if (textureMode)
glEnable(GL_TEXTURE_2D);
if (lightMode)
glEnable(GL_LIGHTING);
if (textureReplace) // (Н) Здесь переключаются текстуры: textureReplace - создаётся на 20 строчке
glBindTexture(GL_TEXTURE_2D, texId); // (Н) Назначение кнопки на 225
else
glBindTexture(GL_TEXTURE_2D, texId2);
//альфаналожение
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glDisable(GL_BLEND);
//настройка материала
GLfloat amb[] = { 0.2, 0.2, 0.1, 1. };
GLfloat dif[] = { 0.4, 0.65, 0.5, 1. };
GLfloat spec[] = { 0.9, 0.8, 0.3, 1. };
GLfloat sh = 0.1f * 256;
//фоновая
glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
//дифузная
glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
//зеркальная
glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
//размер блика
glMaterialf(GL_FRONT, GL_SHININESS, sh);
//чтоб было красиво, без квадратиков (сглаживание освещения)
glShadeModel(GL_SMOOTH);
//===================================
//Прогать тут (Н) это обман, пришлось прогать не только тут
glColor3d(0.7, 0.7, 0.7);
double normal[3];
//glBegin(GL_TRIANGLES);
//computeNormal(A, B, H, normal);
//glNormal3d(normal[0], normal[1], -0.01); // (Н) Это нормаль
//glColor3f(0.5f, 0.5f, 0.5f);
//glVertex3dv(A);
//glVertex3dv(B);
//glVertex3dv(H);
//glEnd();
glBegin(GL_TRIANGLES);
computeNormal(B, H, C, normal);
glNormal3d(normal[0], normal[1], -0.01);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(B);
glVertex3dv(H);
glVertex3dv(C);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(D, E, C, normal);
glNormal3d(normal[0], normal[1], -0.01);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(D);
glVertex3dv(E);
glVertex3dv(C);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(C, F, E, normal);
glNormal3d(normal[0], normal[1], -0.01);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(C);
glVertex3dv(F);
glVertex3dv(E);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(G, H, C, normal);
glNormal3d(normal[0], normal[1], -0.01);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(G);
glVertex3dv(H);
glVertex3dv(C);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(C, F, G, normal);
glNormal3d(normal[0], normal[1], -0.01);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(C);
glVertex3dv(F);
glVertex3dv(G);
glEnd();
/*glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(A, A1, B1, B, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0);
glVertex3dv(A);
glTexCoord2d(0, 1);
glVertex3dv(A1);
glTexCoord2d(1, 1);
glVertex3dv(B1);
glTexCoord2d(1, 0);
glVertex3dv(B);
glEnd();*/
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(B, B1, C1, C, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0); // (Н) Это накладывается текстура (x, y) это углы текстуры, пишутся поверх углов квадратов
glVertex3dv(B);
glTexCoord2d(0, 1);
glVertex3dv(B1);
glTexCoord2d(1, 1);
glVertex3dv(C1);
glTexCoord2d(1, 0);
glVertex3dv(C);
glEnd();
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(C1, C, D, D1, normal);
glNormal3d(-normal[0], -normal[1], normal[2]); // 2
glTexCoord2d(0, 0);
glVertex3dv(C1);
glTexCoord2d(1, 0);
glVertex3dv(C);
glTexCoord2d(1, 1);
glVertex3dv(D);
glTexCoord2d(0, 1);
glVertex3dv(D1);
glEnd();
//glBegin(GL_QUADS);
//glColor3f(0.3f, 0.3f, 0.3f);
//computeQuadNormal(D1, D, E, E1, normal);
//glNormal3d(-normal[0], -normal[1], normal[2]); // 1
//glTexCoord2d(0, 0);
//glVertex3dv(D1);
//glTexCoord2d(1, 0);
//glVertex3dv(D);
//glTexCoord2d(1, 1);
//glVertex3dv(E);
//glTexCoord2d(0, 1);
//glVertex3dv(E1);
//glEnd();
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(E, E1, F1, F, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0);
glVertex3dv(E);
glTexCoord2d(1, 0);
glVertex3dv(E1);
glTexCoord2d(1, 1);
glVertex3dv(F1);
glTexCoord2d(0, 1);
glVertex3dv(F);
glEnd();
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(F, F1, G1, G, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0);
glVertex3dv(F);
glTexCoord2d(0, 1);
glVertex3dv(F1);
glTexCoord2d(1, 1);
glVertex3dv(G1);
glTexCoord2d(1, 0);
glVertex3dv(G);
glEnd();
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(G, G1, H1, H, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0);
glVertex3dv(G);
glTexCoord2d(0, 1);
glVertex3dv(G1);
glTexCoord2d(1, 1);
glVertex3dv(H1);
glTexCoord2d(1, 0);
glVertex3dv(H);
glEnd();
glBegin(GL_QUADS);
glColor3f(0.3f, 0.3f, 0.3f);
computeQuadNormal(H, H1, A1, A, normal);
glNormal3dv(normal);
glTexCoord2d(0, 0);
glVertex3dv(H);
glTexCoord2d(0, 1);
glVertex3dv(H1);
glTexCoord2d(1, 1);
glVertex3dv(A1);
glTexCoord2d(1, 0);
glVertex3dv(A);
glEnd();
drawPurpleCylinder();
drawGreenCylinder();
glEnable(GL_BLEND); // (Н) Здесь строится крышка. Чтоб Альфа наложение хорошо работало, то объект, который должен быть прозрачным(для этого альфа и существует)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Должен строится в последнию очередь, иначе он будет просвечиваться "насквозь", если захотите сами поэксперементируйте
// (Н) Аргументы объяснять не буду, сами найдёте инфу
glBegin(GL_TRIANGLES);
computeNormal(B1, H1, C1, normal);
glNormal3d(normal[0], normal[1], 5); // (Н) Это нормаль
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(B1);
glVertex3dv(H1);
glVertex3dv(C1);
glEnd();
glPushMatrix();
glTranslatef(ED[0], ED[1], ED[2]);
glRotatef(18, 0, 0, 1);
double step = 0.1;
double height = 5;
double radius = PI * 2.0 / 2;
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, height);
glNormal3d(0, 0, height);
for (double a = -PI; a <= 0; a += step)
{
glVertex3f(radius * cos(a), radius * sin(a), height);
}
glVertex3f(radius * cos(0), radius * sin(0), height);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(D1, E1, C1, normal);
glNormal3d(normal[0], normal[1], 5);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(D1);
glVertex3dv(E1);
glVertex3dv(C1);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(C1, F1, E1, normal);
glNormal3d(normal[0], normal[1], 5);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(C1);
glVertex3dv(F1);
glVertex3dv(E1);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(G1, H1, C1, normal);
glNormal3d(normal[0], normal[1], 5);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(G1);
glVertex3dv(H1);
glVertex3dv(C1);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(C1, F1, G1, normal);
glNormal3d(normal[0], normal[1], 5);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(C1);
glVertex3dv(F1);
glVertex3dv(G1);
glEnd();
glBegin(GL_TRIANGLES);
computeNormal(A1, B1, H1, normal);
glNormal3d(normal[0], normal[1], 5);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3dv(A1);
glVertex3dv(B1);
glVertex3dv(H1);
glEnd();
glDisable(GL_BLEND);
//Круг с текстурой внизу!
/*glBegin(GL_POLYGON); // (Н) Круг с норм текстурой, хз как работает код взял с Overflow
for (double i = 0; i <= 2; i += 0.01)
{
double x = 9 * cos(i * 3.141593);
double y = 9 * sin(i * 3.141593);
double tx = cos(i * 3.141593) * 0.5 + 0.5; // (Н) Для корректного отображения текстуры нужны эти переменные
double ty = sin(i * 3.141593) * 0.5 + 0.5;
glColor3d(0.5f, 0.5f, 0.5f);
glNormal3d(0, 0, 1);
glTexCoord2d(tx, ty); // (Н) Суюда их засовываем и всё норм
glVertex3d(x, y, 0);
}
glEnd();
*/
/*double A2[] = {4,4,4};
double B2[] = { 4,-4,4 };
double C2[] = { -4,-4,4 };
double D2[] = { -4,4,4 };
double A3[] = { 4,4,0.1 };
double B3[] = { 4,-4,0.1 };
double C3[] = { -4,-4,0.1 };
double D3[] = { -4,4,0.1 };
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS);
glColor4f(0, 1, 0, 0.5);
glTexCoord2d(0, 0);
glVertex3dv(A2);
glTexCoord2d(0, 1);
glVertex3dv(B2);
glTexCoord2d(1, 1);
glVertex3dv(C2);
glTexCoord2d(1, 0);
glVertex3dv(D2);
glEnd();
glDisable(GL_BLEND);
glBegin(GL_QUADS);
glColor3f(1, 0, 0);
glVertex3dv(A3);
glVertex3dv(B3);
glVertex3dv(C3);
glVertex3dv(D3);
glEnd();*/
//Сообщение вверху экрана
glMatrixMode(GL_PROJECTION); //Делаем активной матрицу проекций.
//(всек матричные операции, будут ее видоизменять.)
glPushMatrix(); //сохраняем текущую матрицу проецирования (которая описывает перспективную проекцию) в стек
glLoadIdentity(); //Загружаем единичную матрицу
glOrtho(0, ogl->getWidth(), 0, ogl->getHeight(), 0, 1); //врубаем режим ортогональной проекции
glMatrixMode(GL_MODELVIEW); //переключаемся на модел-вью матрицу
glPushMatrix(); //сохраняем текущую матрицу в стек (положение камеры, фактически)
glLoadIdentity(); //сбрасываем ее в дефолт
glDisable(GL_LIGHTING);
GuiTextRectangle rec; //классик моего авторства для удобной работы с рендером текста.
rec.setSize(300, 200);
rec.setPosition(10, ogl->getHeight() - 200 - 10);
std::stringstream ss;
ss << "T - вкл/выкл текстур" << std::endl;
ss << "E - Переключение текстур" << std::endl;
ss << "L - вкл/выкл освещение" << std::endl;
ss << "F - Свет из камеры" << std::endl;
ss << "G - двигать свет по горизонтали" << std::endl;
ss << "G+ЛКМ двигать свет по вертекали" << std::endl;
ss << "Коорд. света: (" << light.pos.X() << ", " << light.pos.Y() << ", " << light.pos.Z() << ")" << std::endl;
ss << "Коорд. камеры: (" << camera.pos.X() << ", " << camera.pos.Y() << ", " << camera.pos.Z() << ")" << std::endl;
ss << "Параметры камеры: R=" << camera.camDist << ", fi1=" << camera.fi1 << ", fi2=" << camera.fi2 << std::endl;
ss << "UV-развёртка" << std::endl;
rec.setText(ss.str().c_str());
rec.Draw();
glMatrixMode(GL_PROJECTION); //восстанавливаем матрицы проекции и модел-вью обратьно из стека.
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment