向量下标超出范围错误 - 如何修复此特定错误?
Vector Subscript out of range error - How can i fix this SPECIFIC error?
概览
我一直在研究 OpenGL 3.3 渲染引擎,好消息是,如果我对对象的值进行硬编码,它们将完美呈现。
坏消息是,在尝试 加载 .obj 文件时,我 运行 遇到了严重的问题。
我使用 GLFW、GLM 和 GLEW 这并不重要,它可能会有所帮助。
N.B。我的 .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;
这在理论上和实践中都应该存在。在 class 中,我定义向量将用 10 个空值初始化,而在 运行 中,当循环达到其 'f' 值时,它无论如何都会调整列表的大小,所以为什么为零这样一个硬数字?
错误在这里
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" 风格的编程是一门垂死的艺术——犯下难以诊断的后果的简单错误太容易了。
概览
我一直在研究 OpenGL 3.3 渲染引擎,好消息是,如果我对对象的值进行硬编码,它们将完美呈现。 坏消息是,在尝试 加载 .obj 文件时,我 运行 遇到了严重的问题。
我使用 GLFW、GLM 和 GLEW 这并不重要,它可能会有所帮助。
N.B。我的 .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;
这在理论上和实践中都应该存在。在 class 中,我定义向量将用 10 个空值初始化,而在 运行 中,当循环达到其 'f' 值时,它无论如何都会调整列表的大小,所以为什么为零这样一个硬数字?
错误在这里
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" 风格的编程是一门垂死的艺术——犯下难以诊断的后果的简单错误太容易了。