Как я могу нарисовать простую форму космического корабля в 3d? - PullRequest
0 голосов
/ 06 января 2012

У меня есть программа, которая рисует простую форму, похожую на пирамиду, которую я могу вращать с помощью клавиш со стрелками, но я хочу превратить эту фигуру в простой самолет, и вместо вращения я хочу, чтобы она все еще двигалась (летала) с помощью клавиш со стрелками , как мне этого добиться?

Вот что у меня есть:

#include "shared/gltools.h"   // GLTools

#include "shared/math3d.h"    // 3D Math Library

// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;


// Change viewing volume and viewport.  Called when window is resized
void ChangeSize(int w, int h)
    {
    GLfloat fAspect;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    fAspect = (GLfloat)w/(GLfloat)h;

    // Reset coordinate system
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Produce the perspective projection
    gluPerspective(35.0f, fAspect, 1.0, 40.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }




// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
    {
    GLbyte *pBytes;
    GLint iWidth, iHeight, iComponents;
    GLenum eFormat;

    // Light values and coordinates
    GLfloat  whiteLight[] = { 0.05f, 0.05f, 0.05f, 1.0f };
    GLfloat  sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
    GLfloat  lightPos[] = { -10.f, 5.0f, 5.0f, 1.0f };

    glEnable(GL_DEPTH_TEST);    // Hidden surface removal
    glFrontFace(GL_CCW);        // Counter clock-wise polygons face out
    glEnable(GL_CULL_FACE);     // Do not calculate inside

    // Enable lighting
    glEnable(GL_LIGHTING);

    // Setup and enable light 0
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
    glLightfv(GL_LIGHT0,GL_AMBIENT,sourceLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
    glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
    glEnable(GL_LIGHT0);

    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);

    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Load texture
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);



    pBytes = gltLoadTGA("stone.tga", &iWidth, &iHeight, &iComponents, &eFormat);        
    glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
    free(pBytes);

    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_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
//try these too
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);   

    glEnable(GL_TEXTURE_2D);
    }

// Respond to arrow keys
void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        xRot-= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

        xRot = (GLfloat)((const int)xRot % 360);
        yRot = (GLfloat)((const int)yRot % 360);

    // Refresh the Window
    glutPostRedisplay();
    }


// Called to draw scene
void RenderScene(void)
    {
    M3DVector3f vNormal;
        //defines the corner vertices of the pyramid
    M3DVector3f vCorners[5] = {
                            { 0.0f, 0.3f, 0.0f },     // Top          0

                              { -0.25f, 0.0f, -.25f },    // Back left     1

                              { 0.5f, 0.0f, -0.50f },    // Back right    2

                              { 0.25f, 0.0f, 0.25f },           // Front right   3


                              { -0.99f, 0.0f, 0.99f }};    // Front left    4

    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Save the matrix state and do the rotations
    glPushMatrix();
        // Move object back and do in place rotation
        glTranslatef(0.0f, -0.25f, -4.0f);
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);

        // Draw the Pyramid
        //try different colours
        glColor3f(1.0f, 1.0f, 1.0f);//a white pyramid
       // glColor3f(1.0f, 0.0f, 0.0f); // a red pyramid 
        //glColor3f(1.0,0.7,0.7);//reddish
        glBegin(GL_TRIANGLES);

            // Bottom section - two triangles

            glNormal3f(0.0f, -1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);

            glTexCoord2f(0.0f, 1.0f);
            glVertex3fv(vCorners[1]);


            glTexCoord2f(1.0f, 1.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[3]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);

        //Faces

            // Front Face
            m3dFindNormal(vNormal, vCorners[0], vCorners[4], vCorners[3]);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);//notice the 0.5 here
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[4]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[3]);

            // Left Face
            m3dFindNormal(vNormal, vCorners[0], vCorners[1], vCorners[4]);
            glNormal3fv(vNormal);
             glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[1]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[4]);

            // Back Face
            m3dFindNormal(vNormal, vCorners[0], vCorners[2], vCorners[1]);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);

            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[2]);

            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[1]);

            // Right Face
            m3dFindNormal(vNormal, vCorners[0], vCorners[3], vCorners[2]);
            glNormal3fv(vNormal);
            glTexCoord2f(0.5f, 1.0f);
            glVertex3fv(vCorners[0]);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3fv(vCorners[3]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3fv(vCorners[2]);
        glEnd();


    // Restore the matrix state
    glPopMatrix();

    // Buffer swap
    glutSwapBuffers();
    }



int main(int argc, char *argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Textured Pyramid");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    SetupRC();
    glutMainLoop();

    return 0;
    }

Ответы [ 3 ]

1 голос
/ 06 января 2012

Ну, вам придется смоделировать ваш "самолет" или что-то еще с точки зрения вершин и их связей (то есть треугольников). Боюсь, если ваш мозг не способен представить все координаты, вам придется использовать какое-то программное обеспечение, чтобы сделать это для вас (и я полагаю, что вы тоже некий художник).

Тогда все, что вам нужно сделать, это написать загрузчик для формата файла, который использовало ваше программное обеспечение для моделирования, чтобы сохранить ваш «самолет», преобразовать его в вашу систему координат, поместить полученные вершины в ваш рендерер, и все будет в порядке. Легко, не правда ли?

0 голосов
/ 06 января 2012

Это довольно большой вопрос ... и невероятно ленивый.

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

Теперь, чтобы заставить вещь двигаться, вам нужно либо динамически обновить вершины вашей модели, либо узнать о преобразованиях и конвейере вершин. Вы можете перемещать камеру или перемещать мир вокруг камеры - любой способ эквивалентен. Могут помочь glRotate, glTranslate или glTransform, а также передача матриц в шейдеры.

Надеюсь, этого достаточно, чтобы с некоторой мыслью или поиском в Google вы могли заполнить довольно большие пробелы. Вам вряд ли удастся справиться с этим вручную до конца ... если у вас есть элементарное понимание геометрии (декартовы координаты) и немного знаний API (glTranslate), это не так уж сложно.

0 голосов
/ 06 января 2012

{0,0,0}, {3,3,0}, {- 3,3,0}

Существует список вершин для очень простого трехмерного пространства - треугольника. Вы можете использовать это для создания VBO, или просто подключить его вручную и glDrawArray (). :)

...