2

I need to import a 3D object mesh into my OpenGL code on Visual Studio 2010. I'm relateively new to OpenGL so I've been learning from the following tutorial (Number 7):

http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/

Now, the tutorial uses a simple code rather than a library to import ".obj" files Those who've used the tutorial will know that the "cube.obj" that has been provided by the creator of the tutorial works just fine. However, the moment I try loading my own simple cube mesh, the program notifies me that "Our simple parser cannot handle the .obj file. Please try exporting with other options".

I figured this to be a problem with the code and moved on to his Assimp tutorial: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/

This time around, "Suzanne.obj" has been provided as a sample. Yet again, whenever I try exporting my own object into the code, the program now crashes saying "Visual Studio has stopped working". This only occurs with the objects I export. In an attempt to narrow down the cause of the problem, I used the "cube.obj" provided in Tutorial 7 with Tutorial 9, and it worked just fine. So it seems for now as though the issue lies in the export of the object from Blender.

I've followed all the instructions in Tutorial 7 regarding to what options need be checked while exporting objects. It is worth noting however, the ".obj" code of the objects I export appear in a single line without any line breaks. This is the obj code of a simple cube mesh I exported:

# Blender v2.73 (sub 0) OBJ File: 'ROOM.blend'
# www.blender.org
mtllib room.mtl
o Cube_Cube.004
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 6//1 2//1 1//1
f 7//2 3//2 2//2
f 8//3 4//3 3//3
f 5//4 1//4 4//4
f 2//5 3//5 4//5
f 7//6 6//6 5//6
f 5//1 6//1 1//1
f 6//2 7//2 2//2
f 7//3 8//3 3//3
f 8//4 5//4 4//4
f 1//5 2//5 4//5
f 8//6 7//6 5//6

The .obj code of the cube provided in the tutorial in comparison is as follows:

# Blender3D v249 OBJ File: untitled.blend
# www.blender3d.org
mtllib cube.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.748573 0.750412
vt 0.749279 0.501284
vt 0.999110 0.501077
vt 0.999455 0.750380
vt 0.250471 0.500702
vt 0.249682 0.749677
vt 0.001085 0.750380
vt 0.001517 0.499994
vt 0.499422 0.500239
vt 0.500149 0.750166
vt 0.748355 0.998230
vt 0.500193 0.998728
vt 0.498993 0.250415
vt 0.748953 0.250920
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.000001 0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn 0.000000 1.000000 -0.000000
vn -0.000000 -1.000000 0.000000
usemtl Material_ray.png
s off
f 5/1/1 1/2/1 4/3/1
f 5/1/1 4/3/1 8/4/1
f 3/5/2 7/6/2 8/7/2
f 3/5/2 8/7/2 4/8/2
f 2/9/3 6/10/3 3/5/3
f 6/10/4 7/6/4 3/5/4
f 1/2/5 5/1/5 2/9/5
f 5/1/6 6/10/6 2/9/6
f 5/1/7 8/11/7 6/10/7
f 8/11/7 7/12/7 6/10/7
f 1/2/8 2/9/8 3/13/8
f 1/2/8 3/13/8 4/14/8

On debugging the crashed program, the following exception occurs:

Unhandled exception at 0x00007FF76255E2D5 in tutorial09_AssImp.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

The call stack is as follows:

tutorial09_AssImp.exe!aiVector3t::aiVector3t(const aiVector3t & o) Line 67 C++ tutorial09_AssImp.exe!loadAssImp(const char * path, std::vector > & indices, std::vector,std::allocator

& vertices, std::vector,std::allocator & uvs, std::vector,std::allocator & normals) Line 149 C++ tutorial09_AssImp.exe!main() Line 92 C++

Moreover, the exception occurs in vector3.h which looks as so:

/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------

Copyright (c) 2006-2012, assimp team

All rights reserved.

Redistribution and use of this software in source and binary forms, 
with or without modification, are permitted provided that the following 
conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of the assimp team, nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of the assimp team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file aiVector3D.h
 *  @brief 3D vector structure, including operators when compiling in C++
 */
#ifndef AI_VECTOR3D_H_INC
#define AI_VECTOR3D_H_INC

#include <math.h>


#include "./Compiler/pushpack1.h"

#ifdef __cplusplus

template<typename TReal> class aiMatrix3x3t;
template<typename TReal> class aiMatrix4x4t;

// ---------------------------------------------------------------------------
/** Represents a three-dimensional vector. */
template <typename TReal>
class aiVector3t 
{
public:

    aiVector3t () : x(), y(), z() {}
    aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
    explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
    aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {} //exception generated here

public:

    // combined operators
    const aiVector3t& operator += (const aiVector3t& o);
    const aiVector3t& operator -= (const aiVector3t& o);
    const aiVector3t& operator *= (TReal f);
    const aiVector3t& operator /= (TReal f);

    // transform vector by matrix
    aiVector3t& operator *= (const aiMatrix3x3t<TReal>& mat);
    aiVector3t& operator *= (const aiMatrix4x4t<TReal>& mat);

    // access a single element
    TReal operator[](unsigned int i) const;
    TReal& operator[](unsigned int i);

    // comparison
    bool operator== (const aiVector3t& other) const;
    bool operator!= (const aiVector3t& other) const;

    template <typename TOther>
    operator aiVector3t<TOther> () const;

public:

    /** @brief Set the components of a vector
     *  @param pX X component
     *  @param pY Y component
     *  @param pZ Z component  */
    void Set( TReal pX, TReal pY, TReal pZ);

    /** @brief Get the squared length of the vector
     *  @return Square length */
    TReal SquareLength() const;


    /** @brief Get the length of the vector
     *  @return length */
    TReal Length() const;


    /** @brief Normalize the vector */
    aiVector3t& Normalize();


    /** @brief Componentwise multiplication of two vectors
     *  
     *  Note that vec*vec yields the dot product.
     *  @param o Second factor */
    const aiVector3t SymMul(const aiVector3t& o);

    TReal x, y, z;  
} PACK_STRUCT;


typedef aiVector3t<float> aiVector3D;

#else

struct aiVector3D {

    float x,y,z;
} PACK_STRUCT;

#endif // __cplusplus

#include "./Compiler/poppack1.h"

#ifdef __cplusplus



#endif // __cplusplus

#endif // AI_VECTOR3D_H_INC

Apparently I'm not doing something right while exporting my models. What could I possible be doing wrong? Is there a step I'm missing?

  • I've been following the same tutorial and find the author's explanations to be too brief as to be confusing at times. I eventually used another library to parse the .obj files. – yuqli Jul 21 '20 at 20:36

1 Answers1

2

The program crashes at line 149 of objloader.cpp (says the callstack) This line is about UV coordinates. You model doesn't have any, which should ring a bell =)

You will have the same problem with normals, btw.

So, you have 2 options :

  • Make the object have UVs and normals
  • Make the loader support meshes without UVs or normals.

Since you'll need them anyway, I'd recommend the first one.

In Blender :

  • For the UVs, go to edit mode, select all vertices ('A' key), mesh->UVs->automatic unwrap ; If you struggle, Tutorial 15 contains a video which shows everything you need.
  • For normals, just tick the "export normals" option when exporting to OBJ.

In any case, the output OBJ must have v (position), vn (normals), vt (UVs) and f (connectivity between the 'v's )

EDIT : Explanation on why the top of the callstack talks about aiVector3Dt : line 148 is

aiVector3D UVW = mesh->mTextureCoords[0][i];

UVW is a copy of mesh->mTextureCoords[0][i], which doesn't point to a valid place in memory, because the buffer wasn't allocated, because your OBJ doesn't have any. So the constructor (in the callstack : aiVector3Dt::aiVector3Dt() ) crashes when trying to copy this memory block to UVW. There's a small difference here, because the crash happens one line later, but it's just a compiler optimization. So, the code of aiVector3D is perfectly correct, but you're giving him a bad adress. You can see this in the debugger by setting the current frame to loadAssImp(), and spy on mesh->mTextureCoords[0].

Calvin1602
  • 9,413
  • 2
  • 44
  • 55