I got a problem when I want to import a simple model using assimp, whenever I compile the code it throws:
0xC0000005: Access violation reading location 0x00000000.
I know this is something about a null pointer but I just can't find it, the code goes as follows:
Model::Model(GLchar* path)
{
loadModel(path);
}
void Model::loadModel(std::string path)
{
Assimp::Importer import;
const aiScene* scene = import.ReadFile(
path,
aiProcess_Triangulate |
aiProcess_FlipUVs);
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){
std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
return;
}
directory = path.substr(0, path.find_last_of('/'));
aiNode* node = scene->mRootNode;
for (GLuint i = 0; i < node->mNumChildren; i++){
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (GLuint i = 0; i < node->mNumChildren; i++){
processNode(node->mChildren[i], scene);
}
}
I use this Model class as a global variable:
//include stuff
//other global variable
Model mymodel("D:/Project/xxx/xxx.obj");
int main(){
//...
return 0;
}
The thing is that the error happens just between the line directory = path.substr(0, path.find_last_of('/')); and the line aiNode* node = scene->mRootNode; so I don't know how to debug it, could anyone tell me how to fix this? I use Visual Studio 2013-64 and assimp-3.1.1.
Thank you very much.
I think the problem could be in this part of the code:
Model::Model(GLchar* path)
{
loadModel(path); // path is declared a string in loadModel function - type conversion might not be happening as expected.
}
Check, if you are getting a correct/valid value in the path variable on the line:
directory = path.substr(0, path.find_last_of('/'));
This link might be helpful:
GLchar could not be resolved
Note: I am not familiar with OpenGL, but looking at the error you are getting this is the first place I would check.
Related
I've constructed a quick python script that reads a wavefront .obj file and outputs the verticies and faces to files. I have another C++ function that reads these files and creates a mesh based of-of those.
The issue that I'm experiencing is that this works perfectly sometimes, and other time not so much - with the same mesh. E.g. I start my PhysX program, and create 10 of the same objects of the same mesh and some of them look like this:
and others look like this:
The following C++ is the code that loads the verticies and triangles:
bool ModelLoader::LoadVertexFile(const std::string& fileLocation)
{
std::ifstream file(fileLocation);
if (!file) {
std::cerr << "Failed to load vertex data\n";
return false;
}
float x, y, z;
vertexArray.clear();
while (file >> x >> y >> z)
{
vertexArray.push_back(PhysicsEngine::PxVec3(x, y, z));
}
return true;
}
bool ModelLoader::LoadTrianglesFile(const std::string& fileLocation)
{
std::ifstream file(fileLocation);
if (!file) {
std::cerr << "Failed to load vertex data\n";
return false;
}
int x;
triangleArray.clear();
while (file >> x)
{
triangleArray.push_back(x);
}
return true;
}
This is the code for creating constructing the mesh
CustomObject(const PxTransform& pose = PxTransform(PxIdentity), string vertfile = "", string trigfile = "") :
StaticActor(pose)
{
modelLoader = new ModelLoader();
if(!modelLoader->LoadVertexFile(vertfile))
throw new Exception("Failed to load VertexFile.");
if(!modelLoader->LoadTrianglesFile(trigfile))
throw new Exception("Failed to load TrianglesFile.");
PxTriangleMeshDesc mesh_desc;
mesh_desc.points.count = (PxU32)modelLoader->vertexArray.size();
mesh_desc.points.stride = sizeof(PxVec3);
mesh_desc.points.data = &modelLoader->vertexArray.front();
mesh_desc.triangles.count = (PxU32)modelLoader->triangleArray.size();
mesh_desc.triangles.stride = 3 * sizeof(PxU32);
mesh_desc.triangles.data = &modelLoader->triangleArray.front();
CreateShape(PxTriangleMeshGeometry(CookMesh(mesh_desc)));
}
So if anyone can help me figure out whats going wrong it would be really appreciated
My OpenGL ES application isn't working. I'm using SDL for windowing management, and it holds the context. After looking around, I noticed that the vertex shader and the fragment shader showed up as 0 on the debugger. Even the program was 0. Could this be a reason? I followed my shader compiling and linking code to a template that was previously made.
If it is, what is wrong? Here is the code:
GLuint ShaderHelper::compileShader(GLenum type, std::string fileName) {
std::string fileContents;
std::ifstream fin;
std::string path;
// Getting the necessary path...
// These are abstractions for getting file contents
// from the main bundle.
if (type == GL_VERTEX_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "vsh");
} else if (type == GL_FRAGMENT_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "fsh");
} else {
std::cout << "ERROR: Invalid shader type at filename " << fileName << std::endl;
exit(1);
}
fin.open(path);
if (!fin.is_open()) {
std::cout << "ERROR: Failed to open file " << fileName << std::endl;
exit(1);
}
// Retrieving the string from the file...
while (!fin.eof()) {
char CLine[255];
fin.getline(CLine, 255);
std::string line = CLine;
fileContents = fileContents + line;
fileContents = fileContents + " \n";
}
fin.close();
// I'm creating these variables because a pointer is needed for
// glShaderSource
GLuint shaderHandle = glCreateShader(type);
const GLint shaderStringLength = (GLint)fileContents.size();
const GLchar *shaderCString = fileContents.c_str();
glShaderSource(shaderHandle, 1, &shaderCString, &shaderStringLength);
glCompileShader(shaderHandle);
return shaderHandle;
}
void ShaderHelper::linkProgram(std::vector<GLuint *> shaderArray) {
program = glCreateProgram();
for (int i = 0; i < shaderArray.size(); i++) {
glAttachShader(program, *shaderArray[i]);
}
glLinkProgram(program);
}
void ShaderHelper::addUniform(uniform_t uniform) {
std::string name = uniform.name;
uniforms[name] = uniform;
// With that step done, we need to assign the location...
uniforms[name].location = glGetUniformLocation(program, uniforms[name].name.c_str());
}
EDIT: After suggestions, I ran my code through glError(). I fixed an error, but I still got a blank screen. I'm no longer getting 0 as my shader values. I set glClearColor to a white image, and it's just appearing pure white. I adjusted numbers in the MV matrix and projection matrix, but there's still nothing at all. I disabled face culling, but still nothing. Also, shaders are compiling and linking fine. So now what?
The dreaded blank screen can be caused by a variety of problems:
Your context is not created correctly or you're not presenting your scene properly. Does changing your clear color to something else than black show anything?
Your transformation matrix is wrong. How are you setting up the position of the "camera"? Are you using something like GLM to set up a matrix? If so, have a look at glm::perspective() and glm:::lookAt(). Make sure you're passing the matrix to the shader and that you're using it to set gl_Position in your vertex shader.
The geometry you're trying to display is facing away from the viewer. Try glDisable(GL_CULL_FACE). If it works, reverse the order of your vertices.
An OpenGL call is failing somewhere. Make sure you check glGetError() after every call. I usually have something like the following:
struct gl_checker
{
~gl_checker()
{
const auto e = glGetError();
assert(e == GL_NO_ERROR);
}
};
template <class F>
inline auto gl_call(F f) -> decltype(f())
{
gl_checker gc;
return f();
}
which can be used like this:
gl_call([]{ glDisable(GL_CULL_FACE); });
Your shaders fail to compile or link. Have a look at glGetShaderiv() with GL_COMPILE_STATUS and glGetProgramiv() with GL_LINK_STATUS. If they report an error, have a look at glGetShaderInfoLog() and glGetProgramInfoLog().
As for the partial code you provided, I see nothing strictly wrong with it. Providing the shaders and a smaller, complete program might help with finding the problem.
I'm trying to write some code to read a list of file names from a config file named "TextureList.txt" and then use those files to create a shader resource view for each texture. The listing below shows what I currently have:
LPCSTR textures[MAX_TEXTURES];
std::ifstream texturesToLoad;
texturesToLoad.open("TextureList.txt");
int numberOfTextures = 0;
while(!texturesToLoad.eof())
{
std::string textureName;
std::getline(texturesToLoad, textureName);
textures[numberOfTextures] = textureName.c_str();
numberOfTextures++;
char debugMsg[100];
sprintf(debugMsg, "numberOfTextures = %d\n", numberOfTextures);
OutputDebugString(debugMsg);
OutputDebugString(textureName.c_str());
OutputDebugString("\n");
}
for(int i = 0; i < numberOfTextures; i++)
{
d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
textures[i], 0, 0, &colorMap_[i], 0 );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to load the texture image!" );
return false;
}
}
The debugs at the bottom of the while loop show that the file is being read correctly, it obtains all of the file names and calculates the correct number of textures; however it fails when it tries to create the first resource view.
Can anyone tell me where I'm going wrong?
I don't know if it helps but it works if I replace everything above the for loop with hard coded file names using the following line:
const LPCSTR textures[3] = {"tex1.dds", "tex2.dds", "tex3.dds"};
I've been trying to get Assimp to work correctly for the past two weeks, to no avail, so I decided asking here was the best thing to do. I followed thecplusplusguy's tutorial on importing static meshes, and I've copied it word for word in an effort to get it to work.
When I try to import an .obj (a cube, if that matters) it says I have an "Unhandled exception at 0x00EF061B in OpenGL.exe: 0xC0000005: Access violation reading location 0xABABAFFB", it stops the program and tells me it's on line 30 of my code ( "for(int i=0; imNumMeshes; i++)" ).
#include "sceneloader.h"
sceneLoader::sceneLoader(){
std::cout<<"New scene created."<<std::endl;
}
sceneLoader::sceneLoader(const char* filename){
std::cout<<"Scene loading hath begun."<<std::endl;
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(filename,aiProcess_GenSmoothNormals | aiProcess_Triangulate |
aiProcess_CalcTangentSpace | aiProcess_FlipUVs |
aiProcess_JoinIdenticalVertices);
if(scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE){
std::cout<<"MFLAGS - Scene '"<<filename<<"' could not be loaded."<<std::endl;
return;
}
if(!scene->mRootNode){
std::cout<<"MROOTNODE - Scene '"<<filename<<"' could not be loaded."<<std::endl;
return;
}
std::cout<<"Recursive processing about to begin."<<std::endl;
recursiveProcess(scene->mRootNode,scene);
std::cout<<"Recursive processing finished."<<std::endl;
}
void sceneLoader::recursiveProcess(aiNode* node, const aiScene* scene){
//process
for(int i = 0; i<node->mNumMeshes;i++){ //HERE IS THE PROBLEM
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
processMesh(mesh,scene);
}
//recursion
for(int i = 0; 0<node->mNumChildren;i++){
recursiveProcess(node->mChildren[i],scene);
}
}
When I've added couts to debug it, the "scene->mNumMeshes" returns 1 (which it should, since it's one cube), but "node->mNumMeshes" returns 0.
I understand that an unhandled exception occurs when there's a null pointer, and that the null pointer here is the "node->mNumMeshes", but why is it null? And how would I fix this?
My bad.
There was a typo:
void sceneLoader::recursiveProcess(aiNode* node, const aiScene* scene){
//process
for(int i = 0; i<node->mNumMeshes;i++){
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
processMesh(mesh,scene);
}
//recursion
for(int i = 0; 0<node->mNumChildren;i++){ //IT SHOULD BE AN i INSTEAD OF A ZERO
recursiveProcess(node->mChildren[i],scene);
}
}
Finished code looks like this:
void sceneLoader::recursiveProcess(aiNode* node, const aiScene* scene){
//process
for(unsigned int i = 0; i<node->mNumMeshes;i++){
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
processMesh(mesh,scene);
}
//recursion
if(node->mNumChildren > 0){
for(unsigned int i = 0; i<node->mNumChildren;i++){
recursiveProcess(node->mChildren[i],scene);
}
}
}
Sorry.
Won't happen again.
For some odd reason, my application likes to break on me when I switch to release and run it outside of my debugger. Here's what works for me, and here's what doesn't
(Qt Creator is the IDE)
Debugging with debug configuration - ok
Running with debug configuration - ok
Debugging with release configuration - ok
Running with release configuration - application crash
My UI is one project, and the core for some stuff as a separate dependency. On Windows (compiling with MSVCC), I hit a menu button, which eventually calls down to a function. In that function, the app breaks on adding a new element to a vector. e.g:
str *x = new str();
str *y = new str();
/* ...set some of x & y's members... */
vector.push_back(x); // works fine
vector.push_back(y); // causes crash
If I comment out the line vector.push_back(y);, the app continues no problem until the app leaves the event scope (i.e. the end of OnMenuButtonClick). On OS X, it's similar to the issue of adding an element to a vector, except I have:
std::vector<foo *> SomeFunction()
{
std::vector<foo *> returningVector;
/* do stuff */
std::vector<foo *> goo = GetFooObjects();
for (int i = 0; i < goo.size(); i++)
{
returningVector.push_back(goo[i]); // breaks here
}
}
So what are some causes of this strange behavior without a debugger attached and not under debug configuration? I've checked to make sure all of my variables are initialized, so I'm stumped. If you want to view the code above, the first part can be located here, and the second part here. Please forgive anything you see as "bad", and if you have suggestions that you just can't contain, then please do message me on GitHub.
Edit:
I looked more into it, and found out exactly what's causing the problem, but don't know how to fix it. This is the function where my app crashes (on OS X):
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
vector<Drive *> Return;
if (HardDisks)
{
vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();
for (int i = 0; i < (int)Disks.size(); i++)
{
DISK_DRIVE_INFORMATION ddi = Disks.at(i);
// First, try reading the disk way
Streams::xDeviceStream* DS = NULL;
try
{
char path[0x200] = {0};
wcstombs(path, ddi.Path, wcslen(ddi.Path));
DS = new Streams::xDeviceStream(ddi.Path);
}
catch (xException& e)
{
continue;
}
if (DS == NULL || DS->Length() == 0 || DS->Length() < HddOffsets::Data)
{
// Disk is not of valid length
continue;
}
DS->SetPosition(HddOffsets::Data);
// Read the FATX partition magic
int Magic = DS->ReadInt32();
// Close the stream
DS->Close();
// Compare the magic we read to the *actual* FATX magic
if (Magic == FatxMagic)
{
Drive *d = new Drive(Disks.at(i).Path, Disks.at(i).FriendlyName, false);
Return.push_back(d);
}
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < (int)LogicalDisks.size(); i++)
{
Return.push_back(LogicalDisks.at(i));
}
return Return;
}
If I change if (HardDisks) to if (HardDisks = false), the app works just fine. So, I looked into that scope and discovered that after vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();, the heap gets corrupt or something like that. I noticed this because in the debugger, after that function is called, my HardDisks bool changes to "false", which wasn't what it was before.
Here is GetPhysicalDisks:
vector<Drive::DISK_DRIVE_INFORMATION> Drive::GetPhysicalDisks( void )
{
// RIGHT AFTER this vector is initialized, everything goes to hell
vector<Drive::DISK_DRIVE_INFORMATION> ReturnVector;
DIR *dir;
dirent *ent;
dir = opendir("/dev/");
if (dir != NULL)
{
// Read the shit
while ((ent = readdir(dir)) != NULL)
{
// Check the directory name, and if it starts with "disk" then keep it!
QRegExp exp("disk*");
exp.setPatternSyntax(QRegExp::Wildcard);
exp.setCaseSensitivity(Qt::CaseInsensitive);
if (exp.exactMatch(ent->d_name))
{
DISK_DRIVE_INFORMATION curdir;
memset(curdir.FriendlyName, 0, sizeof(curdir.FriendlyName));
memset(curdir.Path, 0, sizeof(curdir.Path));
char diskPath[0x50] = {0};
sprintf(diskPath, "/dev/r%s", ent->d_name);
mbstowcs(curdir.Path, diskPath, strlen(diskPath));
int device;
if ((device = open(diskPath, O_RDONLY)) > 0)
{
#ifdef __linux
hd_driveid hd;
if (!ioctl(device, HDIO_GET_IDENTITY, &hd))
{
swprintf(curdir.FriendlyName, strlen(hd) * 2, L"%hs", hd.model);
}
#elif defined __APPLE__
mbstowcs(curdir.FriendlyName, ent->d_name, strlen(ent->d_name));
#endif
ReturnVector.push_back(curdir);
}
}
}
}
return ReturnVector;
}
While this isn't a real answer as to what happened, I did find a way to fix the problem. Looking at my edit above, I edited my Drive::GetFATXDrives function like so:
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
// Initialize Disks vector up here
vector<DISK_DRIVE_INFORMATION> Disks;
// Call the function to get the hard disks
if (HardDisks)
Drive::GetPhysicalDisks(Disks);
vector<Drive *> ReturnVector;
if (HardDisks)
{
Streams::xDeviceStream* DS = NULL;
for (int i = 0; i < (int)Disks.size(); i++)
{
/* ... */
}
if (DS)
{
DS->Close();
delete DS;
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < LogicalDisks.size(); i++)
{
ReturnVector.push_back(LogicalDisks[i]);
}
return ReturnVector;
}
And my Drive::GetPhysicalDisks function now takes a vector<DISK_DRIVE_INFORMATION> reference instead of returning one. Seemed to make my program work just fine after that.