Прочитал книгу по С++, решил попытаться закрепить как нибудь знания, и написать первую какую нибудь интересную программу с использованием новых знаний.
Выбор пал на самый простой 3д рендер. Все казалось довольно простым, кроме одного момента а именно как правильно и быстро рисовать полигоны. Решил что качество меня не особо волнует так как это перваяяя попытка и все такое.
И вот в готовой версии появилась проблема, рисовать то оно все рисует но все очень сильно лагает не знаю дело в кривости кода, или можно как-то решить проблему оптимизации.
Использую WinAPI
Код который отвечает за класс полигона а именно треугольника:
class Triangle{
private:
double lenght = 0; double GlobalLenght = 0;
Point center,new_p1,new_p2,new_p3;
Point step( Point temp1, Point temp2, Point temp3 ){
Point temp = temp1;
lenght = round(sqrt(abs(pow(temp2.x - temp3.x, 2)+pow(temp2.y - temp3.y, 2)+pow(temp2.z - temp3.z, 2))));
lenght *= 2.5;
temp.x = temp.x / lenght; temp.y = temp.y / lenght; temp.z = temp.z / lenght;
return temp;
}
void draw_line( Point temp2 ){
Point temp1,temp3;
temp1 = temp2 - new_p1;
temp1 = step(temp1, temp2,new_p1);
temp3 = new_p1;
for(int i = 0; i < lenght; i++ ){
if ( temp3.z >= 0 ){
if( (int)temp3.y < 480 && (int)temp3.x < 640 ){
if ( buffer_z[(int)temp3.y][(int)temp3.x] > temp3.z ){
SetPixel(mem_dc,(int)temp3.x,(int)temp3.y,RGB(t,0,100));
buffer_z[(int)temp3.y][(int)temp3.x] = temp3.z;
}
}
}
temp3 = temp3 + temp1;
}
}
public:
char t = '#';
Point p1,p2,p3;
Triangle(){ t = '#'; }
Triangle(char ch){
t = ch;
}
// Здесь инициализация полигона
Triangle(Point A, Point B, Point C){
Set(A,B,C);
}
// Здесь инициализация полигона
void Set( Point A, Point B, Point C ){
p1 = A; p2 = B; p3 = C;
double l1,l2;
l1 = ::lenght(A,C);
l2 = ::lenght(B,C);
if ( l1 > l2 ){
p1= B; p2 = A; p3 = C;
}
else if ( ::lenght(A,B) > l2) {
p1 = C; p2 = A; p3 = B;
}
}
// Здесь вход в функцию которая выводит полигон в видео буфер
// Вектор отрезка BC делиться на длину,
// После чего из точки A рисую отрезки к всем точкам что лежать на отрезке BC
// Так заполняется вся площадь треугольника, и я могу сравнить координату Z с той что в буфере.
// ( Придумал сам поэтому более чем уверен что лаги именно из за этого алгоритма )
void draw_to_buffer()
{
Point temp1, temp2;
perspective();
temp1 = new_p3 - new_p2;
temp1 = step(temp1,new_p3,new_p2);
GlobalLenght = lenght;
temp2 = new_p2;
for(int ai = 0; ai <= GlobalLenght; ai++ )
{
draw_line(temp2);
temp2 = temp2 + temp1;
}
}
// Преобразует точки ортогональной проекции в центральную ( если не ошибаюсь вот так называется )
void perspective(){
center.Set(640/2,480/2,0);
new_p1 = p1;
new_p2 = p2;
new_p3 = p3;
new_p3 = new_p3 - center;
new_p3.x = new_p3.x / new_p3.z;
new_p3.y = new_p3.y / new_p3.z;
new_p2 = new_p2 - center;
new_p2.x = new_p2.x / new_p2.z;
new_p2.y = new_p2.y / new_p2.z;
new_p1 = new_p1 - center;
new_p1.x = new_p1.x / new_p1.z;
new_p1.y = new_p1.y / new_p1.z;
new_p1 = new_p1 + center;
new_p2 = new_p2 + center;
new_p3 = new_p3 + center;
}
};
Класс представляет из себя три переменных типа Double где хранятся координаты X,Y,Z
Код всей программки тут:
https://pastebin.com/y2Ns2S1P