OpenGL,旋转对象的一块

时间:2014-05-30 03:09:13

标签: opengl glut

我装了直升机.obj文件,它可以用键(wasd)和(o-up)(l-down)移动。现在我想在移动时旋转螺旋桨,但不能这样做。 This is the link to .obj file.

感谢任何回答。

这是我的代码:

#include <stdlib.h>
#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <cmath>
#include <GL/glut.h>
#include <GL/GL.H>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>


using namespace std;
float v[27982][3];
int f[25130][3];
int mX, mY;
int trX, trY, trZ;

GLfloat amblight[] = { 1.0, 0.0, 0.0, 0.0 };
GLfloat diflight[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat speclight[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat position[] = { 1.0, 0.0, 1.0 };
GLfloat difposition[] = { 1.0, 0.0, 1.0, 0.0 };

GLfloat shinines[] = { 120.0 };
GLfloat ambmatherial[] = { 1.0, 0.0, 0.0, 0.0 };
GLfloat difmatherial[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat specmatherial[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat angle = 0.0;

void init() {
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glLightfv(GL_LIGHT0, GL_POSITION, difposition);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diflight);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, difmatherial);

    glLightfv(GL_LIGHT0, GL_SPECULAR, speclight);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specmatherial);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shinines);

}
void idle() {
    glutPostRedisplay();
}
class Coord
{
public:
    float x;
    float y;
    float z;
} a3d, b3d, c3d, original;


Coord norm(Coord a3d, Coord b3d, Coord c3d)
{
    Coord d3D_1, d3D_2, cross;
    d3D_1.x = b3d.x - a3d.x;
    d3D_1.y = b3d.y - a3d.y;
    d3D_1.z = b3d.z - a3d.z;

    d3D_2.x = c3d.x - b3d.x;
    d3D_2.y = c3d.y - b3d.y;
    d3D_2.z = c3d.z - b3d.z;

    cross.x = d3D_1.y * d3D_2.z - d3D_1.z * d3D_2.y;
    cross.y = d3D_1.z * d3D_2.x - d3D_1.x * d3D_2.z;
    cross.z = d3D_1.x * d3D_2.y - d3D_1.y * d3D_2.x;
    double l;

    l = sqrt(cross.x * cross.x + cross.y * cross.y + cross.z * cross.z);
    cross.x /= l;
    cross.y /= l;
    cross.z /= l;
    return cross;
}

void drawHelicopter(){

    glPushMatrix();
    for (int i = 0; i<25130; i++){
        glBegin(GL_TRIANGLES);
        a3d.x = v[f[i][0]][0];
        a3d.y = v[f[i][0]][1];
        a3d.z = v[f[i][0]][2];
        b3d.x = v[f[i][1]][0];
        b3d.y = v[f[i][1]][1];
        b3d.z = v[f[i][1]][2];
        c3d.x = v[f[i][2]][0];
        c3d.y = v[f[i][2]][1];
        c3d.z = v[f[i][2]][2];

        glVertex3f(a3d.x, a3d.y, a3d.z);
        glVertex3f(b3d.x, b3d.y, b3d.z);
        glVertex3f(c3d.x, c3d.y, c3d.z);
        Coord response = norm(a3d, b3d, c3d);
        glNormal3f(response.x, response.y, response.z);
        glEnd();
    }
    glPopMatrix();
}

void display(){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);

    glLoadIdentity();

    glTranslatef(0, 0, -1500); 
    glRotatef(180.0, 0, 1, 0); 

    glTranslatef(trX, trY, trZ);
    glRotatef(mX, 0, 1, 0);
    glRotatef(mY, 1, 0, 0);

    glScalef(1.0f, 1.0f, 1.0f);
    drawHelicopter();


    glutSwapBuffers();
}

void reshape(int w, int h){
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (GLdouble)w / (GLdouble)h, 1.0, 8000.0);
    glMatrixMode(GL_MODELVIEW);
}

void keyPressed(unsigned char key, int x, int y) {
    if (key == 'a'){ trX += 20; }
    else if (key == 'd'){ trX -= 20; }
    else if (key == 'w'){ trZ += 20; }
    else if (key == 's'){ trZ -= 20; }
    else if (key == 'o'){ trY += 20; }
    else if (key == 'l'){ trY -= 20; }
    glutPostRedisplay();
}

void mouse(int x, int y){
    mX = x;
    mY = y;
    glutPostRedisplay();
}

int main(){
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(1200, 640);
    glutCreateWindow("Helicopter");
    glClearColor(0.0, 0.0, 0.0, 0.0);
    int k = 0, m = 0;
    char ch;
    float aa, bb, cc;

    ifstream in("havoc.obj", ios::in);

    string line;
    while (getline(in, line))
    {
        //check v for vertices
        if (line.substr(0, 2) == "v ")
        {
            istringstream vert(line.substr(2));

            vert >> aa;
            vert >> bb;
            vert >> cc;
            v[k][0] = (float)aa;
            v[k][1] = (float)bb;
            v[k][2] = (float)cc;

            k++;
        }

        else if (line.substr(0, 2) == "f ")
        {
            int a, b, c, d; //to store mesh index
            int A, B, C, D; //to store texture index
            int a1, b1, c1;

            const char* chh = line.c_str();
            sscanf(chh, "f %i/%i/%i %i/%i/%i %i/%i/%i", &a, &A, &a1, &b, &B, &b1, &c, &C, &c1); //here it read the line start with f and store the corresponding values in the variables

            f[m][0] = a - 1;
            f[m][1] = b - 1;
            f[m][2] = c - 1;
            m++;
        }
    }
    printf("Use 'w'/'s' keys to move forward/downward\n");
    printf("Use 'a'/'d' keys to move to the left/right\n");
    printf("Use 'o'/'l' keys to move up/down\n");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyPressed);
    glutMotionFunc(mouse);
    glutIdleFunc(idle);
    glutMainLoop();
    return 0;
}

1 个答案:

答案 0 :(得分:2)

所以你遇到的问题是一个常见的问题,我确信许多人在某些时候都会看到3D图形和动画。您有一个模型,您正在使用您的obj文件加载,但您只想旋转直升机的螺旋桨。因此,只要我读到这一点,我就会想到一些东西,分别加载几何体,并将几何体放入树形结构中。

因此,想象一下您的直升机的不同组件作为树的不同节点,例如,我们就说我们有一个人。躯干将是根节点,孩子将是手臂,腿和颈部,并且每个节点儿童将逐渐向下移动直到所有点都被存储。

现在一架直升机要简单得多,因为这时只有一架螺旋桨和直升机的架子。您可以实现这样的树结构,因为如果您想要移动到更复杂的动画和更复杂的对象,它将会很方便。

每个树节点都将包含该节点的当前属性,这也有助于解决其他一些问题,但我们很快就会解决这个问题。因此,对于每个节点,您将在节点模型空间中存储旋转和平移。然后,您将在树中传播这些值。因此,如果您的整个模型旋转,您的根节点将旋转并沿树向下传播其旋转,以便螺旋桨与直升机的主体一起旋转,并且还执行属于其节点的自己的旋转。同样的原则适用于翻译,只记得正确的订购,否则你会发现你的轮换问题不正确。

最后,问题的最终解决方案是将您的实际模型几何体分成3D建模程序中的不同对象,并将它们作为代码中的不同对象加载,它们仍将被编译到同一个obj文件中。然后,您可以使用此信息来构建对象树。

我真的希望这有助于你提供某种方向。 =)