Отображение орфографических видов вращающегося куба в C++

Приведенный ниже код предназначен для отображения ортогональных проекций (вид сбоку, вид спереди и вид сверху) вращающегося куба. Подход, который я выбрал, - это однородные координаты. Я берусь за отображение каждого ребра куба, что касается вида сбоку, я не рассматривал компоненты x вершин куба и рисовал ребра, используя только компоненты y и z. Это показывает и другие боковые грани, как я могу обнаружить только левые боковые грани?

#include<iostream>
#include "graphics.h"
#include<cmath>
using namespace std;

#define PI 22/(float)7

float x =0, y = 0, z= 0;

void matrixmult(int A[4][8], float R[4][4]){
    float res[4][8];
    for(int i = 0; i<4; i++){
        for(int j = 0; j<8; j++){
            res[i][j] = 0;
            for(int k = 0; k<4; k++){
                res[i][j]+=R[i][k]*A[k][j];
            }
        }
    }
    for(int i = 0; i<4; i++){
        for(int j = 0; j<8; j++){
            A[i][j] = res[i][j];
        }
    }
}

void rotMataboutX(float Rx[4][4]){
   float  xrad = PI*x/(float)360;
   float cosx = cos(xrad), sinx = sin(xrad);
    Rx[1][1]=cosx;
    Rx[1][2]=-sinx;
    Rx[2][1]=sinx;
    Rx[2][2]=cosx;
}

void rotMatAboutY(float Ry[4][4]){
    float  yrad = PI*y/(float)360;
    float cosy = cos(yrad), siny = sin(yrad);
    Ry[0][0]=cosy;
    Ry[0][2]=siny;
    Ry[2][0]=-siny;
    Ry[2][2]=cosy;
}

void rotMatAboutZ(float Rz[4][4]){
    float  zrad = PI*z/(float)360;
    float cosz = cos(zrad), sinz = sin(zrad);
    Rz[0][0]=cosz;
    Rz[0][1]=-sinz;
    Rz[1][0]=sinz;
    Rz[1][1]=cosz;
}

void sideView(int A[4][8]){
    int xdisp = 106, ydisp = 120;
    line(xdisp+A[1][0], ydisp+A[2][0], xdisp+A[1][1], ydisp+A[2][1]);
    line(xdisp+A[1][1], ydisp+A[2][1], xdisp+A[1][2], ydisp+A[2][2]);
    line(xdisp+A[1][2], ydisp+A[2][2], xdisp+A[1][3], ydisp+A[2][3]);
    line(xdisp+A[1][3], ydisp+A[2][3], xdisp+A[1][0], ydisp+A[2][0]);
    line(xdisp+A[1][4], ydisp+A[2][4], xdisp+A[1][5], ydisp+A[2][5]);
    line(xdisp+A[1][5], ydisp+A[2][5], xdisp+A[1][6], ydisp+A[2][6]);
    line(xdisp+A[1][6], ydisp+A[2][6], xdisp+A[1][7], ydisp+A[2][7]);
    line(xdisp+A[1][7], ydisp+A[2][7], xdisp+A[1][4], ydisp+A[2][4]);
    line(xdisp+A[1][0], ydisp+A[2][0], xdisp+A[1][4], ydisp+A[2][4]);
    line(xdisp+A[1][1], ydisp+A[2][1], xdisp+A[1][5], ydisp+A[2][5]);
    line(xdisp+A[1][6], ydisp+A[2][6], xdisp+A[1][2], ydisp+A[2][2]);
    line(xdisp+A[1][7], ydisp+A[2][7], xdisp+A[1][3], ydisp+A[2][3]);
    line(xdisp+A[1][7], ydisp+A[2][7], xdisp+A[1][3], ydisp+A[2][3]);
}

void frontView(int A[4][8]){
    int xdisp = 319, ydisp = 120;
    line(xdisp+A[0][0], ydisp+A[1][0], xdisp+A[0][1], ydisp+A[1][1]);
    line(xdisp+A[0][1], ydisp+A[1][1], xdisp+A[0][2], ydisp+A[1][2]);
    line(xdisp+A[0][2], ydisp+A[1][2], xdisp+A[0][3], ydisp+A[1][3]);
    line(xdisp+A[0][3], ydisp+A[1][3], xdisp+A[0][0], ydisp+A[1][0]);
    line(xdisp+A[0][4], ydisp+A[1][4], xdisp+A[0][5], ydisp+A[1][5]);
    line(xdisp+A[0][5], ydisp+A[1][5], xdisp+A[0][6], ydisp+A[1][6]);
    line(xdisp+A[0][6], ydisp+A[1][6], xdisp+A[0][7], ydisp+A[1][7]);
    line(xdisp+A[0][7], ydisp+A[1][7], xdisp+A[0][4], ydisp+A[1][4]);
    line(xdisp+A[0][0], ydisp+A[1][0], xdisp+A[0][4], ydisp+A[1][4]);
    line(xdisp+A[0][1], ydisp+A[1][1], xdisp+A[0][5], ydisp+A[1][5]);
    line(xdisp+A[0][6], ydisp+A[1][6], xdisp+A[0][2], ydisp+A[1][2]);
    line(xdisp+A[0][7], ydisp+A[1][7], xdisp+A[0][3], ydisp+A[1][3]);
    line(xdisp+A[0][7], ydisp+A[1][7], xdisp+A[0][3], ydisp+A[1][3]);
}

void topView(int A[4][8]){
    int xdisp = 534, ydisp = 120;
    line(xdisp+A[0][0], ydisp+A[2][0], xdisp+A[0][1], ydisp+A[2][1]);
    line(xdisp+A[0][1], ydisp+A[2][1], xdisp+A[0][2], ydisp+A[2][2]);
    line(xdisp+A[0][2], ydisp+A[2][2], xdisp+A[0][3], ydisp+A[2][3]);
    line(xdisp+A[0][3], ydisp+A[2][3], xdisp+A[0][0], ydisp+A[2][0]);
    line(xdisp+A[0][4], ydisp+A[2][4], xdisp+A[0][5], ydisp+A[2][5]);
    line(xdisp+A[0][5], ydisp+A[2][5], xdisp+A[0][6], ydisp+A[2][6]);
    line(xdisp+A[0][6], ydisp+A[2][6], xdisp+A[0][7], ydisp+A[2][7]);
    line(xdisp+A[0][7], ydisp+A[2][7], xdisp+A[0][4], ydisp+A[2][4]);
    line(xdisp+A[0][0], ydisp+A[2][0], xdisp+A[0][4], ydisp+A[2][4]);
    line(xdisp+A[0][1], ydisp+A[2][1], xdisp+A[0][5], ydisp+A[2][5]);
    line(xdisp+A[0][6], ydisp+A[2][6], xdisp+A[0][2], ydisp+A[2][2]);
    line(xdisp+A[0][7], ydisp+A[2][7], xdisp+A[0][3], ydisp+A[2][3]);
    line(xdisp+A[0][7], ydisp+A[2][7], xdisp+A[0][3], ydisp+A[2][3]);
}

int main(){
    int gd = DETECT, gm;
    initgraph(&gd, &gm, "C:\\TC\\BGI");
    int A[4][8]={{0, 50, 50, 0, 0, 50, 50, 0},
                {0, 0, 50, 50, 0, 0, 50, 50},
                {0, 0, 0, 0, 50, 50, 50, 50},
                {1, 1, 1 ,1 ,1 ,1, 1, 1}};


    float cosx = cos(x), sinx = sin(x);
    float Rx[4][4]={{1, 0, 0, 0},
            {0, cosx, -sinx, 0},
            {0, sinx, cosx, 0},
            {0, 0, 0, 1}};

    float cosy = cos(y), siny = sin(y);
    float Ry[4][4]={{cosy, 0, siny, 0},
            {0, 1, 0, 0},
            {-siny, 0, cosy, 0},
            {0, 0, 0, 1}};

    float cosz = cos(z), sinz = sin(z);
    float Rz[4][4]={{cosz, -sinz, 0, 0},
            {sinz, cosz, 0, 0},
            {0, 0, 1, 0},
            {0, 0, 0, 1}};

    cout<<"Matrix A:\n";
     for(int i = 0; i<4; i++){
        for(int j = 0; j<8; j++){
            cout<<A[i][j]<<" ";
        }
        cout<<endl;
    }
    sideView(A);
    topView(A);
    frontView(A);

    while(1){
        char axisofrot;
        cin>>axisofrot;
        switch(axisofrot){
        case 'X':
        case 'x':
            cout<<"ROTATING ABOUT X:\n";
            x+=5;
            cout<<"X:\t"<<x<<"\n";
            cout<<"Y:\t"<<y<<"\n";
            cout<<"Z:\t"<<z<<"\n";
            rotMataboutX(Rx);
            cout<<"Matrix Rx:\n";
            for(int i = 0; i<4; i++){
                for(int j = 0; j<4; j++){
                    cout<<Rx[i][j]<<" ";
                }
                cout<<endl;
            }
            matrixmult(A, Rx);
            break;
        case 'Y':
        case 'y':
            cout<<"ROTATING ABOUT Y:\n";
            y+=5;
            cout<<"X:\t"<<x<<"\n";
            cout<<"Y:\t"<<y<<"\n";
            cout<<"Z:\t"<<z<<"\n";
            rotMatAboutY(Ry);
            cout<<"Matrix Ry:\n";
            for(int i = 0; i<4; i++){
                for(int j = 0; j<4; j++){
                    cout<<Ry[i][j]<<" ";
                }
                cout<<endl;
            }
            matrixmult(A, Ry);
            break;
        case 'Z':
        case 'z':
            cout<<"ROTATING ABOUT Z:\n";
            z+=5;
            cout<<"X:\t"<<x<<"\n";
            cout<<"Y:\t"<<y<<"\n";
            cout<<"Z:\t"<<z<<"\n";
            rotMatAboutY(Rz);
            cout<<"Matrix Rz:\n";
            for(int i = 0; i<4; i++){
                for(int j = 0; j<4; j++){
                    cout<<Rz[i][j]<<" ";
                }
                cout<<endl;
            }
            matrixmult(A, Rz);
            break;
        }
        cout<<"Matrix A:\n";
        for(int i = 0; i<4; i++){
            for(int j = 0; j<8; j++){
                cout<<A[i][j]<<" ";
            }
            cout<<endl;
        }
        cleardevice();
        delay(100);
        sideView(A);
        topView(A);
        frontView(A);
    }
    getch();
    closegraph();
    return 0;
}

Изначально без ротацииИзначально без поворота

После поворота на 20 градусов по осям x, y и z После поворота


person Nisha    schedule 15.04.2018    source источник
comment
Ваши орфографические взгляды выглядят неправильно. Почитайте о проекционных матрицах и отсечении обратной стороны.   -  person meowgoesthedog    schedule 15.04.2018


Ответы (1)


Что вам нужно, так это использовать нормали и отсечение задней грани. Итак, если вы определяете вектор нормали n, указывающий на ваш куб для каждой грани, чем:

if (dot ( n , camera_view_direction) < 0) render_face;

решит, рендерите ли вы лицевую или изнаночную сторону. Оба вектора должны быть в одной системе координат, так что либо трансформируйте n, либо вид камеры, либо и то, и другое... Не забывайте, что трансформация векторов выполняется без смещения!!!

Если у вас нет нормалей n, вы можете вычислить их на ходу для каждой грани, определяемой точками p0,p1,p2,..., следующим образом:

n = cross (p1-p0,p2-p1)

но ориентация, если она указывает внутрь или наружу, будет зависеть от правила намотки вашего лица, порядка перекрестных операндов и соглашений вашей системы координат. Так что настройте в соответствии с вашими потребностями (хорошей идеей будет визуализировать нормали, чтобы визуально увидеть, верны ли они)

также взгляните на это:

Для дополнительных идей и математики. Все представления и преобразования могут быть представлены матрицей 4x4, и вы можете избавиться от своих проекционных функций и вместо этого использовать только матрицы.

person Spektre    schedule 15.04.2018