2

我试图找出颜色问题。我创建了一个从高度图加载的景观和一个从 MD2 模型加载的动画。MD2 模型将从位图纹理中获取颜色。景观的颜色必须由 glColor3f 设置。

现在问题出在我的 Draw 方法中:

void drawScene() {
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(cameraPositionX, cameraPositionY, cameraPositionZ, cameraAimX, cameraAimY, cameraAimZ, 0, 1, 0);

GLfloat ambientColor[] = {0.4f, 0.4f, 0.4f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);

GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat lightPos0[] = {-0.5f, 0.8f, 0.1f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);

if (_model != NULL) {
    glPushMatrix();
    glTranslatef(modelPositionX, modelPositionY, modelPositionZ);
    glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
    glRotatef(110.0f, 1.0f, 0.0f, 0.0f);
    glScalef(0.2f, 0.2f, 0.2f);
    _model->draw();
    glPopMatrix();
}

glTranslatef(-(float)(_terrain->width() - 1) / 2,
             0.0f,
             -(float)(_terrain->length() - 1) / 2);

glColor3f(0.0f, 1.0f, 0.0f);
for(int z = 0; z < _terrain->length() - 1; z++) {
    glBegin(GL_TRIANGLE_STRIP);
    for(int x = 0; x < _terrain->width(); x++) {
        Vec3f normal = _terrain->getNormal(x, z);
        glNormal3f(normal[0], normal[1], normal[2]);
        glVertex3f(x, _terrain->getHeight(x, z), z);
        normal = _terrain->getNormal(x, z + 1);
        glNormal3f(normal[0], normal[1], normal[2]);
        glVertex3f(x, _terrain->getHeight(x, z + 1), z + 1);
    }
    glEnd();
}

glutSwapBuffers();

}

当我注释掉 glColor3f(0.0f, 1.0f, 0.0f); 声明,景观将获得与动画从位图纹理获得的颜色相同的颜色。但是当我包含 glColor3f(0.0f, 1.0f, 0.0f); 声明,动画将获得与风景相同的颜色。我想让动画和风景有不同的颜色。

这是完整的 main.cpp 类和 md2model.cpp 类。

主文件

#include <iostream>
#include <stdlib.h>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include "imageloader.h"
#include "imageloader.cpp"
#include "vec3f.h"
#include "vec3f.cpp"
#include "md2model.h"
#include "md2model.cpp"

using namespace std;

class Terrain {
private:
    int w;
    int l;
    float** hs;
    Vec3f** normals;
    bool computedNormals;
public:
    Terrain(int w2, int l2) {
        w = w2;
        l = l2;

        hs = new float*[l];
        for(int i = 0; i < l; i++) {
            hs[i] = new float[w];
        }

        normals = new Vec3f*[l];
        for(int i = 0; i < l; i++) {
            normals[i] = new Vec3f[w];
        }

        computedNormals = false;
    }

    ~Terrain() {
        for(int i = 0; i < l; i++) {
            delete[] hs[i];
        }
        delete[] hs;

        for(int i = 0; i < l; i++) {
            delete[] normals[i];
        }
        delete[] normals;
    }

    int width() {
        return w;
    }

    int length() {
        return l;
    }

    void setHeight(int x, int z, float y) {
        hs[z][x] = y;
        computedNormals = false;
    }

    float getHeight(int x, int z) {
        return hs[z][x];
    }

    void computeNormals() {
        if (computedNormals) {
            return;
        }

        Vec3f** normals2 = new Vec3f*[l];
        for(int i = 0; i < l; i++) {
            normals2[i] = new Vec3f[w];
        }

        for(int z = 0; z < l; z++) {
            for(int x = 0; x < w; x++) {
                Vec3f sum(0.0f, 0.0f, 0.0f);

                Vec3f out;
                if (z > 0) {
                    out = Vec3f(0.0f, hs[z - 1][x] - hs[z][x], -1.0f);
                }
                Vec3f in;
                if (z < l - 1) {
                    in = Vec3f(0.0f, hs[z + 1][x] - hs[z][x], 1.0f);
                }
                Vec3f left;
                if (x > 0) {
                    left = Vec3f(-1.0f, hs[z][x - 1] - hs[z][x], 0.0f);
                }
                Vec3f right;
                if (x < w - 1) {
                    right = Vec3f(1.0f, hs[z][x + 1] - hs[z][x], 0.0f);
                }

                if (x > 0 && z > 0) {
                    sum += out.cross(left).normalize();
                }
                if (x > 0 && z < l - 1) {
                    sum += left.cross(in).normalize();
                }
                if (x < w - 1 && z < l - 1) {
                    sum += in.cross(right).normalize();
                }
                if (x < w - 1 && z > 0) {
                    sum += right.cross(out).normalize();
                }

                normals2[z][x] = sum;
            }
        }

        const float FALLOUT_RATIO = 0.5f;
        for(int z = 0; z < l; z++) {
            for(int x = 0; x < w; x++) {
                Vec3f sum = normals2[z][x];

                if (x > 0) {
                    sum += normals2[z][x - 1] * FALLOUT_RATIO;
                }
                if (x < w - 1) {
                    sum += normals2[z][x + 1] * FALLOUT_RATIO;
                }
                if (z > 0) {
                    sum += normals2[z - 1][x] * FALLOUT_RATIO;
                }
                if (z < l - 1) {
                    sum += normals2[z + 1][x] * FALLOUT_RATIO;
                }

                if (sum.magnitude() == 0) {
                    sum = Vec3f(0.0f, 1.0f, 0.0f);
                }
                normals[z][x] = sum;
            }
        }

        for(int i = 0; i < l; i++) {
            delete[] normals2[i];
        }
        delete[] normals2;

        computedNormals = true;
    }

    Vec3f getNormal(int x, int z) {
        if (!computedNormals) {
            computeNormals();
        }
        return normals[z][x];
    }
};

Terrain* loadTerrain(const char* filename, float height) {
Image* image = loadBMP(filename);
Terrain* t = new Terrain(image->width, image->height);
for(int y = 0; y < image->height; y++) {
    for(int x = 0; x < image->width; x++) {
        unsigned char color =
            (unsigned char)image->pixels[3 * (y * image->width + x)];
        float h = height * ((color / 255.0f) - 0.5f);
        t->setHeight(x, y, h);
    }
}

delete image;
t->computeNormals();
return t;
}

float cameraPositionX = 2;
float cameraPositionY = 2;
float cameraPositionZ = 1;

float cameraAimX = 0;
float cameraAimY = 0;
float cameraAimZ = 0;

float modelPositionX = 0;
float modelPositionY = 1;
float modelPositionZ = 0;

Terrain* _terrain;

MD2Model* _model;

void cleanup() {
delete _terrain;
delete _model;
}

void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
    case 27:
        cleanup();
        exit(0);
}
}

void handleSpecialKeypress(int key, int x, int y) {
switch (key) {
    case GLUT_KEY_UP:
            cameraPositionX -= 0.5;
    cameraAimX -= 0.5;
    modelPositionX -= 0.5;

    if (_model != NULL) {
            _model->advance(0.025f);
        }

    glutPostRedisplay();
            break;
    case GLUT_KEY_DOWN:
            cameraPositionX += 0.5;
    cameraAimX += 0.5;
    modelPositionX += 0.5;

    if (_model != NULL) {
            _model->advance(0.025f);
        }

    glutPostRedisplay();
            break;
case GLUT_KEY_LEFT:
            //Do something
            break;
    case GLUT_KEY_RIGHT:
            //Do something
            break;
  }
}

void initRendering() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glShadeModel(GL_SMOOTH);

_model = MD2Model::load("tallguy.md2");
if (_model != NULL) {
    _model->setAnimation("run");
}
}

void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(105.0, (double)w / (double)h, 1.0, 500.0);
}

void drawScene() {
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(cameraPositionX, cameraPositionY, cameraPositionZ, cameraAimX, cameraAimY, cameraAimZ, 0, 1, 0);

GLfloat ambientColor[] = {0.4f, 0.4f, 0.4f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);

GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat lightPos0[] = {-0.5f, 0.8f, 0.1f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);

if (_model != NULL) {
    glPushMatrix();
    glTranslatef(modelPositionX, modelPositionY, modelPositionZ);
    glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
    glRotatef(110.0f, 1.0f, 0.0f, 0.0f);
    glScalef(0.2f, 0.2f, 0.2f);
    _model->draw();
    glPopMatrix();
}

glTranslatef(-(float)(_terrain->width() - 1) / 2,
             0.0f,
             -(float)(_terrain->length() - 1) / 2);

//glColor3f(0.0f, 1.0f, 0.0f);
for(int z = 0; z < _terrain->length() - 1; z++) {
    glBegin(GL_TRIANGLE_STRIP);
    for(int x = 0; x < _terrain->width(); x++) {
        Vec3f normal = _terrain->getNormal(x, z);
        glNormal3f(normal[0], normal[1], normal[2]);
        glVertex3f(x, _terrain->getHeight(x, z), z);
        normal = _terrain->getNormal(x, z + 1);
        glNormal3f(normal[0], normal[1], normal[2]);
        glVertex3f(x, _terrain->getHeight(x, z + 1), z + 1);
    }
    glEnd();
}

glutSwapBuffers();
}

int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);

glutCreateWindow("Terrain");
initRendering();

_terrain = loadTerrain("heightmap.bmp", 50);

glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutSpecialFunc(handleSpecialKeypress);
glutReshapeFunc(handleResize);

glutMainLoop();
return 0;
}

M2DModel.cpp

#include <fstream>
#include "imageloader.h"
#include "md2model.h"
#include "string.h"

using namespace std;

namespace {
//Normals used in the MD2 file format
float NORMALS[486] =
    {-0.525731f,  0.000000f,  0.850651f,
     -0.442863f,  0.238856f,  0.864188f,
     -0.295242f,  0.000000f,  0.955423f,
     -0.309017f,  0.500000f,  0.809017f,
     -0.162460f,  0.262866f,  0.951056f,
      0.000000f,  0.000000f,  1.000000f,
      0.000000f,  0.850651f,  0.525731f,
     -0.147621f,  0.716567f,  0.681718f,
      0.147621f,  0.716567f,  0.681718f,
      0.000000f,  0.525731f,  0.850651f,
      0.309017f,  0.500000f,  0.809017f,
      0.525731f,  0.000000f,  0.850651f,
      0.295242f,  0.000000f,  0.955423f,
      0.442863f,  0.238856f,  0.864188f,
      0.162460f,  0.262866f,  0.951056f,
     -0.681718f,  0.147621f,  0.716567f,
     -0.809017f,  0.309017f,  0.500000f,
     -0.587785f,  0.425325f,  0.688191f,
     -0.850651f,  0.525731f,  0.000000f,
     -0.864188f,  0.442863f,  0.238856f,
     -0.716567f,  0.681718f,  0.147621f,
     -0.688191f,  0.587785f,  0.425325f,
     -0.500000f,  0.809017f,  0.309017f,
     -0.238856f,  0.864188f,  0.442863f,
     -0.425325f,  0.688191f,  0.587785f,
     -0.716567f,  0.681718f, -0.147621f,
     -0.500000f,  0.809017f, -0.309017f,
     -0.525731f,  0.850651f,  0.000000f,
      0.000000f,  0.850651f, -0.525731f,
     -0.238856f,  0.864188f, -0.442863f,
      0.000000f,  0.955423f, -0.295242f,
     -0.262866f,  0.951056f, -0.162460f,
      0.000000f,  1.000000f,  0.000000f,
      0.000000f,  0.955423f,  0.295242f,
     -0.262866f,  0.951056f,  0.162460f,
      0.238856f,  0.864188f,  0.442863f,
      0.262866f,  0.951056f,  0.162460f,
      0.500000f,  0.809017f,  0.309017f,
      0.238856f,  0.864188f, -0.442863f,
      0.262866f,  0.951056f, -0.162460f,
      0.500000f,  0.809017f, -0.309017f,
      0.850651f,  0.525731f,  0.000000f,
      0.716567f,  0.681718f,  0.147621f,
      0.716567f,  0.681718f, -0.147621f,
      0.525731f,  0.850651f,  0.000000f,
      0.425325f,  0.688191f,  0.587785f,
      0.864188f,  0.442863f,  0.238856f,
      0.688191f,  0.587785f,  0.425325f,
      0.809017f,  0.309017f,  0.500000f,
      0.681718f,  0.147621f,  0.716567f,
      0.587785f,  0.425325f,  0.688191f,
      0.955423f,  0.295242f,  0.000000f,
      1.000000f,  0.000000f,  0.000000f,
      0.951056f,  0.162460f,  0.262866f,
      0.850651f, -0.525731f,  0.000000f,
      0.955423f, -0.295242f,  0.000000f,
      0.864188f, -0.442863f,  0.238856f,
      0.951056f, -0.162460f,  0.262866f,
      0.809017f, -0.309017f,  0.500000f,
      0.681718f, -0.147621f,  0.716567f,
      0.850651f,  0.000000f,  0.525731f,
      0.864188f,  0.442863f, -0.238856f,
      0.809017f,  0.309017f, -0.500000f,
      0.951056f,  0.162460f, -0.262866f,
      0.525731f,  0.000000f, -0.850651f,
      0.681718f,  0.147621f, -0.716567f,
      0.681718f, -0.147621f, -0.716567f,
      0.850651f,  0.000000f, -0.525731f,
      0.809017f, -0.309017f, -0.500000f,
      0.864188f, -0.442863f, -0.238856f,
      0.951056f, -0.162460f, -0.262866f,
      0.147621f,  0.716567f, -0.681718f,
      0.309017f,  0.500000f, -0.809017f,
      0.425325f,  0.688191f, -0.587785f,
      0.442863f,  0.238856f, -0.864188f,
      0.587785f,  0.425325f, -0.688191f,
      0.688191f,  0.587785f, -0.425325f,
     -0.147621f,  0.716567f, -0.681718f,
     -0.309017f,  0.500000f, -0.809017f,
      0.000000f,  0.525731f, -0.850651f,
     -0.525731f,  0.000000f, -0.850651f,
     -0.442863f,  0.238856f, -0.864188f,
     -0.295242f,  0.000000f, -0.955423f,
     -0.162460f,  0.262866f, -0.951056f,
      0.000000f,  0.000000f, -1.000000f,
      0.295242f,  0.000000f, -0.955423f,
      0.162460f,  0.262866f, -0.951056f,
     -0.442863f, -0.238856f, -0.864188f,
     -0.309017f, -0.500000f, -0.809017f,
     -0.162460f, -0.262866f, -0.951056f,
      0.000000f, -0.850651f, -0.525731f,
     -0.147621f, -0.716567f, -0.681718f,
      0.147621f, -0.716567f, -0.681718f,
      0.000000f, -0.525731f, -0.850651f,
      0.309017f, -0.500000f, -0.809017f,
      0.442863f, -0.238856f, -0.864188f,
      0.162460f, -0.262866f, -0.951056f,
      0.238856f, -0.864188f, -0.442863f,
      0.500000f, -0.809017f, -0.309017f,
      0.425325f, -0.688191f, -0.587785f,
      0.716567f, -0.681718f, -0.147621f,
      0.688191f, -0.587785f, -0.425325f,
      0.587785f, -0.425325f, -0.688191f,
      0.000000f, -0.955423f, -0.295242f,
      0.000000f, -1.000000f,  0.000000f,
      0.262866f, -0.951056f, -0.162460f,
      0.000000f, -0.850651f,  0.525731f,
      0.000000f, -0.955423f,  0.295242f,
      0.238856f, -0.864188f,  0.442863f,
      0.262866f, -0.951056f,  0.162460f,
      0.500000f, -0.809017f,  0.309017f,
      0.716567f, -0.681718f,  0.147621f,
      0.525731f, -0.850651f,  0.000000f,
     -0.238856f, -0.864188f, -0.442863f,
     -0.500000f, -0.809017f, -0.309017f,
     -0.262866f, -0.951056f, -0.162460f,
     -0.850651f, -0.525731f,  0.000000f,
     -0.716567f, -0.681718f, -0.147621f,
     -0.716567f, -0.681718f,  0.147621f,
     -0.525731f, -0.850651f,  0.000000f,
     -0.500000f, -0.809017f,  0.309017f,
     -0.238856f, -0.864188f,  0.442863f,
     -0.262866f, -0.951056f,  0.162460f,
     -0.864188f, -0.442863f,  0.238856f,
     -0.809017f, -0.309017f,  0.500000f,
     -0.688191f, -0.587785f,  0.425325f,
     -0.681718f, -0.147621f,  0.716567f,
     -0.442863f, -0.238856f,  0.864188f,
     -0.587785f, -0.425325f,  0.688191f,
     -0.309017f, -0.500000f,  0.809017f,
     -0.147621f, -0.716567f,  0.681718f,
     -0.425325f, -0.688191f,  0.587785f,
     -0.162460f, -0.262866f,  0.951056f,
      0.442863f, -0.238856f,  0.864188f,
      0.162460f, -0.262866f,  0.951056f,
      0.309017f, -0.500000f,  0.809017f,
      0.147621f, -0.716567f,  0.681718f,
      0.000000f, -0.525731f,  0.850651f,
      0.425325f, -0.688191f,  0.587785f,
      0.587785f, -0.425325f,  0.688191f,
      0.688191f, -0.587785f,  0.425325f,
     -0.955423f,  0.295242f,  0.000000f,
     -0.951056f,  0.162460f,  0.262866f,
     -1.000000f,  0.000000f,  0.000000f,
     -0.850651f,  0.000000f,  0.525731f,
     -0.955423f, -0.295242f,  0.000000f,
     -0.951056f, -0.162460f,  0.262866f,
     -0.864188f,  0.442863f, -0.238856f,
     -0.951056f,  0.162460f, -0.262866f,
     -0.809017f,  0.309017f, -0.500000f,
     -0.864188f, -0.442863f, -0.238856f,
     -0.951056f, -0.162460f, -0.262866f,
     -0.809017f, -0.309017f, -0.500000f,
     -0.681718f,  0.147621f, -0.716567f,
     -0.681718f, -0.147621f, -0.716567f,
     -0.850651f,  0.000000f, -0.525731f,
     -0.688191f,  0.587785f, -0.425325f,
     -0.587785f,  0.425325f, -0.688191f,
     -0.425325f,  0.688191f, -0.587785f,
     -0.425325f, -0.688191f, -0.587785f,
     -0.587785f, -0.425325f, -0.688191f,
     -0.688191f, -0.587785f, -0.425325f};

//Returns whether the system is little-endian
bool littleEndian() {
    //The short value 1 has bytes (1, 0) in little-endian and (0, 1) in
    //big-endian
    short s = 1;
    return (((char*)&s)[0]) == 1;
}

//Converts a two-character array to an unsigned short, using little-endian
//form
unsigned short toUShort(const char* bytes) {
    return (unsigned short)(((unsigned char)bytes[1] << 8) |
                            (unsigned char)bytes[0]);
}

//Converts a four-character array to a float, using little-endian form
float toFloat(const char* bytes) {
    float f;
    if (littleEndian()) {
        ((char*)&f)[0] = bytes[0];
        ((char*)&f)[1] = bytes[1];
        ((char*)&f)[2] = bytes[2];
        ((char*)&f)[3] = bytes[3];
    }
    else {
        ((char*)&f)[0] = bytes[3];
        ((char*)&f)[1] = bytes[2];
        ((char*)&f)[2] = bytes[1];
        ((char*)&f)[3] = bytes[0];
    }
    return f;
}

//Reads the next two bytes as an unsigned short, using little-endian form
unsigned short readUShort(ifstream &input) {
    char buffer[2];
    input.read(buffer, 2);
    return toUShort(buffer);
}

//Reads the next four bytes as a float, using little-endian form
float readFloat(ifstream &input) {
    char buffer[4];
    input.read(buffer, 4);
    return toFloat(buffer);
}

//Calls readFloat three times and returns the results as a Vec3f object
Vec3f readVec3f(ifstream &input) {
    float x = readFloat(input);
    float y = readFloat(input);
    float z = readFloat(input);
    return Vec3f(x, y, z);
}

//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image *image) {
    GLuint textureId;
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGB,
                 image->width, image->height,
                 0,
                 GL_RGB,
                 GL_UNSIGNED_BYTE,
                 image->pixels);
    return textureId;
}
}

MD2Model::~MD2Model() {
if (frames != NULL) {
    for(int i = 0; i < numFrames; i++) {
        delete[] frames[i].vertices;
    }
    delete[] frames;
}

if (texCoords != NULL) {
    delete[] texCoords;
}
if (triangles != NULL) {
    delete[] triangles;
}
}

MD2Model::MD2Model() {
frames = NULL;
texCoords = NULL;
triangles = NULL;
time = 0;
}


//Loads the MD2 model

MD2Model* MD2Model::load(const char* filename) {
ifstream input;
input.open(filename, istream::binary);

char buffer[64];
input.read(buffer, 4); //Should be "IPD2", if this is an MD2 file
if (buffer[0] != 'I' || buffer[1] != 'D' ||
    buffer[2] != 'P' || buffer[3] != '2') {
    return NULL;
}
if (readInt(input) != 8) { //The version number
    return NULL;
}

int textureWidth = readInt(input);   //The width of the textures
int textureHeight = readInt(input);  //The height of the textures
readInt(input);                      //The number of bytes per frame
int numTextures = readInt(input);    //The number of textures
if (numTextures != 1) {
    return NULL;
}
int numVertices = readInt(input);    //The number of vertices
int numTexCoords = readInt(input);   //The number of texture coordinates
int numTriangles = readInt(input);   //The number of triangles
readInt(input);                      //The number of OpenGL commands
int numFrames = readInt(input);      //The number of frames

//Offsets (number of bytes after the beginning of the file to the beginning
//of where certain data appear)
int textureOffset = readInt(input);  //The offset to the textures
int texCoordOffset = readInt(input); //The offset to the texture coordinates
int triangleOffset = readInt(input); //The offset to the triangles
int frameOffset = readInt(input);    //The offset to the frames
readInt(input);                      //The offset to the OpenGL commands
readInt(input);                      //The offset to the end of the file

//Load the texture
input.seekg(textureOffset, ios_base::beg);
input.read(buffer, 64);
if (strlen(buffer) < 5 ||
    strcmp(buffer + strlen(buffer) - 4, ".bmp") != 0) {
    return NULL;
}
Image* image = loadBMP(buffer);
GLuint textureId = loadTexture(image);
delete image;
MD2Model* model = new MD2Model();
model->textureId = textureId;

//Load the texture coordinates
input.seekg(texCoordOffset, ios_base::beg);
model->texCoords = new MD2TexCoord[numTexCoords];
for(int i = 0; i < numTexCoords; i++) {
    MD2TexCoord* texCoord = model->texCoords + i;
    texCoord->texCoordX = (float)readShort(input) / textureWidth;
    texCoord->texCoordY = 1 - (float)readShort(input) / textureHeight;
}

//Load the triangles
input.seekg(triangleOffset, ios_base::beg);
model->triangles = new MD2Triangle[numTriangles];
model->numTriangles = numTriangles;
for(int i = 0; i < numTriangles; i++) {
    MD2Triangle* triangle = model->triangles + i;
    for(int j = 0; j < 3; j++) {
        triangle->vertices[j] = readUShort(input);
    }
    for(int j = 0; j < 3; j++) {
        triangle->texCoords[j] = readUShort(input);
    }
}

//Load the frames
input.seekg(frameOffset, ios_base::beg);
model->frames = new MD2Frame[numFrames];
model->numFrames = numFrames;
for(int i = 0; i < numFrames; i++) {
    MD2Frame* frame = model->frames + i;
    frame->vertices = new MD2Vertex[numVertices];
    Vec3f scale = readVec3f(input);
    Vec3f translation = readVec3f(input);
    input.read(frame->name, 16);

    for(int j = 0; j < numVertices; j++) {
        MD2Vertex* vertex = frame->vertices + j;
        input.read(buffer, 3);
        Vec3f v((unsigned char)buffer[0],
                (unsigned char)buffer[1],
                (unsigned char)buffer[2]);
        vertex->pos = translation + Vec3f(scale[0] * v[0],
                                          scale[1] * v[1],
                                          scale[2] * v[2]);
        input.read(buffer, 1);
        int normalIndex = (int)((unsigned char)buffer[0]);
        vertex->normal = Vec3f(NORMALS[3 * normalIndex],
                               NORMALS[3 * normalIndex + 1],
                               NORMALS[3 * normalIndex + 2]);
    }
}

model->startFrame = 0;
model->endFrame = numFrames - 1;
return model;

}


void MD2Model::setAnimation(const char* name) {
/* The names of frames normally begin with the name of the animation in
 * which they are, e.g. "run", and are followed by a non-alphabetical
 * character.  Normally, they indicate their frame number in the animation,
 * e.g. "run_1", "run_2", etc.
 */
bool found = false;
for(int i = 0; i < numFrames; i++) {
    MD2Frame* frame = frames + i;
    if (strlen(frame->name) > strlen(name) &&
        strncmp(frame->name, name, strlen(name)) == 0 &&
        !isalpha(frame->name[strlen(name)])) {
        if (!found) {
            found = true;
            startFrame = i;
        }
        else {
            endFrame = i;
        }
    }
    else if (found) {
        break;
    }
}

}


void MD2Model::advance(float dt) {
if (dt < 0) {
    return;
}

time += dt;
if (time < 1000000000) {
    time -= (int)time;
}
else {
    time = 0;
}
}

void MD2Model::draw() {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//Figure out the two frames between which we are interpolating
int frameIndex1 = (int)(time * (endFrame - startFrame + 1)) + startFrame;
if (frameIndex1 > endFrame) {
    frameIndex1 = startFrame;
}

int frameIndex2;
if (frameIndex1 < endFrame) {
    frameIndex2 = frameIndex1 + 1;
}
else {
    frameIndex2 = startFrame;
}

MD2Frame* frame1 = frames + frameIndex1;
MD2Frame* frame2 = frames + frameIndex2;

//Figure out the fraction that we are between the two frames
float frac =
    (time - (float)(frameIndex1 - startFrame) /
     (float)(endFrame - startFrame + 1)) * (endFrame - startFrame + 1);

//Draw the model as an interpolation between the two frames
glBegin(GL_TRIANGLES);
for(int i = 0; i < numTriangles; i++) {
    MD2Triangle* triangle = triangles + i;
    for(int j = 0; j < 3; j++) {
        MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
        MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
        Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
        Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
        if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
            normal = Vec3f(0, 0, 1);
        }
        glNormal3f(normal[0], normal[1], normal[2]);

        MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
        glTexCoord2f(texCoord->texCoordX, texCoord->texCoordY);
        glVertex3f(pos[0], pos[1], pos[2]);
    }
}
glEnd();
}
4

2 回答 2

1

当我注释掉 glColor3f(0.0f, 1.0f, 0.0f); 声明,景观将获得与动画从位图纹理获得的颜色相同的颜色。但是当我包含 glColor3f(0.0f, 1.0f, 0.0f); 声明,动画将获得与风景相同的颜色。我想让动画和风景有不同的颜色。

glColor3f(0.0f, 1.0f, 0.0f);在景观之前和模型之前调用glColor3f(1.0f, 1.0f, 1.0f);staet 是从上一次调用中保存的,导致输出错误。

另请注意,glColor*函数已被弃用。

于 2013-01-22T10:47:55.763 回答
0

我不知道这是否可行,但尝试glColor3f(1.0f, 1.0f, 1.0f);在你的 for 循环之后调用,就在你的glutSwapBuffers();. 它应该消除您之前调用glColor3f(0.0f, 1.0f, 0.0f);.

于 2013-01-22T10:47:20.797 回答