【问题标题】:Vector Subscript out of range error - How can i fix this SPECIFIC error?向量下标超出范围错误 - 我该如何解决这个特定错误?
【发布时间】:2015-05-20 16:04:37
【问题描述】:

概述

我一直在研究 OpenGL 3.3 渲染引擎,好消息是,如果我对对象的值进行硬编码,它们将完美渲染。 坏消息是,当尝试加载 .obj 文件时,我遇到了严重的问题。

我使用 GLFW、GLM 和 GLEW,这并不重要,它可能会有所帮助。

注意我的 .obj 加载器基于找到的 here

问题

当我运行我的代码时,我得到了错误:

调试断言失败!
线路:1201
表达式:向量下标超出范围

我该如何解决这个问题?!

我已经调试了代码,我知道是哪些行导致了错误,但在进一步挖掘时,我发现它试图索引下标“0”的向量,所以我尝试为容器初始化一些值,但错误仍然存​​在.

守则

这里是所有代码,请向下滚动查看具体内容。

OBJLoader.cpp

bool OBJLoader::loadGLDataFromOBJ(){

    bool processed = false;
    while (true){

        char currentLine[128];
        int res = fscanf(file, "%s", currentLine);
        if (res == EOF){

            break;
        }

        if (strcmp(currentLine, "v") == 0){
            Vector3f vertex;
            fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
            raw_vPositions.push_back(vertex);
        }
        else if (strcmp(currentLine, "vt") == 0){
            Vector2f uv;
            fscanf(file, "%f %f\n", &uv.x, &uv.y);
            raw_vTextureCoords.push_back(uv);
        }
        else if (strcmp(currentLine, "vn") == 0){
            Vector3f normal;
            fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
            raw_vNormals.push_back(normal);
        }
        else if (strcmp(currentLine, "f") == 0){
            unsigned int vertexData1[3], vertexData2[3], vertexData3[3];
            int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
                &vertexData1[0], &vertexData1[0], &vertexData1[0],
                &vertexData2[1], &vertexData2[1], &vertexData2[1],
                &vertexData3[2], &vertexData3[2], &vertexData3[2]);
            if (matches != 9){
                printf("File can't be read by our simple parser : ( Try exporting with other options\n");
                return false;
            }

            if (!processed){
                gl_vTextureCoords.resize(raw_vPositions.size() * 2);
                gl_vNormals.resize(raw_vPositions.size() * 3);
                processed = true;
            }

            processVertex(vertexData1);
            processVertex(vertexData2);
            processVertex(vertexData3);
        }
    }

    gl_vPositions.resize(raw_vPositions.size() * 3);
    gl_vIndexBuffer.resize(indices.size());

    int vertexPointer = 0;
    for (int i = 0; i < raw_vPositions.size(); i++){
        gl_vPositions[vertexPointer++] = raw_vPositions[i].x;
        gl_vPositions[vertexPointer++] = raw_vPositions[i].y;
    }

    for (int j = 0; j < indices.size(); j++) gl_vIndexBuffer[j] = indices[j];

    return true;
}

void OBJLoader::processVertex(unsigned int vertexData[]){
    int currentVertexPointer = *(vertexData) - 1;
    indices.push_back(currentVertexPointer);

    Vector2f currentTexture = raw_vTextureCoords[*(vertexData+1) - 1];
    gl_vTextureCoords[currentVertexPointer * 2] = currentTexture.x;
    gl_vTextureCoords[currentVertexPointer * 2 + 1] = currentTexture.y;

    Vector3f currentNormal = raw_vNormals[*(vertexData + 2) - 1];
    gl_vNormals[currentVertexPointer * 3] = currentNormal.x;
    gl_vNormals[currentVertexPointer * 3 + 1] = currentNormal.y;
    gl_vNormals[currentVertexPointer * 3 + 2] = currentNormal.z;

}


bool OBJLoader::loadOBJFromFile(const char* filePath){
    file = fopen(filePath, "r");
    if (!file){
        printf("Impossible to open the file !\n");
        return false;
    }
    else{
        printf("File opened: %s", filePath);
    }
    return true;
}



std::vector<float> OBJLoader::getPositions(){
    return this->gl_vPositions;
}
std::vector<float> OBJLoader::getTextureCoords(){
    return this->gl_vTextureCoords;
}
std::vector<float> OBJLoader::getNormals(){
    return this->gl_vNormals;
}
std::vector<unsigned short> OBJLoader::getIndexData(){
    return this->gl_vIndexBuffer;
}

OBJLoader.h

#include "glm/glm.hpp"
#include <vector>

typedef glm::vec3 Vector3f;
typedef glm::vec2 Vector2f;

typedef std::vector<Vector3f> List_Vec3;
typedef std::vector<Vector2f> List_Vec2;
typedef std::vector<unsigned short> List_Int;

class OBJLoader{
private:
    //These will be populated and then outputted to the user.
    std::vector<unsigned short> gl_vIndexBuffer = std::vector<unsigned short>(10);
    std::vector<float> gl_vPositions = std::vector<float>(10);
    std::vector<float> gl_vTextureCoords = std::vector<float>(10);
    std::vector<float> gl_vNormals = std::vector<float>(10);

    //These come from the obj file.
    List_Int indices;
    List_Vec3 raw_vPositions;
    List_Vec2 raw_vTextureCoords;
    List_Vec3 raw_vNormals;

    FILE* file; //The file of the obj.

    //Private functions
    bool loadOBJFromFile(const char* filePath); //Populates the file.
    bool loadGLDataFromOBJ();

    void processVertex(unsigned int[]);

public:
    OBJLoader(){}; //The default constructor.

    bool loadGLDataFromFile(const char* filePath); //Returns true if data loaded.

    std::vector<float> getPositions();
    std::vector<float> getTextureCoords();
    std::vector<float> getNormals();
    std::vector<unsigned short> getIndexData();

};

详情

它的这个功能似乎让我感到悲伤:

void OBJLoader::processVertex(unsigned int vertexData[]){
    int currentVertexPointer = *(vertexData) - 1;
    indices.push_back(currentVertexPointer);

    Vector2f currentTexture = raw_vTextureCoords[*(vertexData+1) - 1];
    gl_vTextureCoords[currentVertexPointer * 2] = currentTexture.x;
    gl_vTextureCoords[currentVertexPointer * 2 + 1] = currentTexture.y;

    Vector3f currentNormal = raw_vNormals[*(vertexData + 2) - 1];
    gl_vNormals[currentVertexPointer * 3] = currentNormal.x;
    gl_vNormals[currentVertexPointer * 3 + 1] = currentNormal.y;
    gl_vNormals[currentVertexPointer * 3 + 2] = currentNormal.z;
}

更具体地说,这些行:

gl_vTextureCoords[currentVertexPointer * 2] = currentTexture.x;
gl_vTextureCoords[currentVertexPointer * 2 + 1] = currentTexture.y;

gl_vNormals[currentVertexPointer * 3] = currentNormal.x;
gl_vNormals[currentVertexPointer * 3 + 1] = currentNormal.y;
gl_vNormals[currentVertexPointer * 3 + 2] = currentNormal.z;

由于某种原因,如果我继续跨过 while 循环,它会在第一次迭代时中断,并且在检查下标的值时,它等于 0,因此它调用类似:

gl_vTextureCoords[0] = currentTexture.x;
gl_vTextureCoords[1] = currentTexture.y;

这在理论和实践中都应该存在。在我的类中定义向量将使用 10 个空值进行初始化,并且在运行时,当循环达到其“f”值时,它无论如何都会调整列表的大小,那么为什么零这样一个硬数字?

【问题讨论】:

  • 你应该在类构造函数中初始化你的类变量

标签: c++ opengl vector range subscript


【解决方案1】:

错误在这里

unsigned int vertexData1[3], vertexData2[3], vertexData3[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
   &vertexData1[0], &vertexData1[0], &vertexData1[0],
   &vertexData2[1], &vertexData2[1], &vertexData2[1],
   &vertexData3[2], &vertexData3[2], &vertexData3[2]);

我很确定你的意思是这样的:

unsigned int vertexData1[3], vertexData2[3], vertexData3[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
   &vertexData1[0], &vertexData1[1], &vertexData1[2],
   &vertexData2[0], &vertexData2[1], &vertexData2[2],
   &vertexData3[0], &vertexData3[1], &vertexData3[2]);

或者也许:

unsigned int vertexData1[3], vertexData2[3], vertexData3[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
   &vertexData1[0], &vertexData2[0], &vertexData3[0],
   &vertexData1[1], &vertexData2[1], &vertexData3[1],
   &vertexData1[2], &vertexData3[2], &vertexData3[2]);

这是一个很好的例子,说明为什么老式的“C”风格编程是一门垂死的艺术——犯简单的错误太容易了,而且后果难以诊断。

【讨论】:

  • 好的,你是对的,谢谢,这已经解决了下标错误,但是我的对象没有正确渲染,我很确定我已经加载了所有的点,我所做的唯一更改我的代码正在用“第一个”示例替换您告诉我的内容。这是我的对象的样子 [link]imgur.com/HGCwTbo 它应该看起来像这样 [link]imgur.com/Gjd75vx
  • 看起来这应该是另一个问题
猜你喜欢
  • 2018-12-13
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多