Search code examples
c++openglglslassimpwavefront

Understanding OBJ loading via ASSIMP


I am using ASSIMP 4.0.1 by compiling my own binaries. I keep getting the normals loaded incorrectly. I have reduced my cube.obj down to just a single triangle ... and I would like to confirm that it is doing it wrong and that I'm not insane. Finally how can I fix it would also be a question. Here's what the OBJ file looks like:

mtllib cube.mtl
g cube Mesh
usemtl cube Mesh_cube

v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
f 1/1/1 2/2/1 3/3/1

now given the last line, I'm loading a single triangle with the attributes:

Loaded Sample

What I'm drawing is the normal of the triangle and this clearly says it's (0.0, 1.0, 0.0) since it's RGB with green being the color. The triangle is created with an offset (translation) that's -30.0f away from origin in the x-axis and shaded directly with normal passed into fragment shader from vertex shader. At this point, I'm suspecting that this obj file is incorrect? Notice the last normal, (number 3 that is), why is it (0.0, 0.0, -1.0) ? Shouldn't this be (0.0, 0.0, 1.0) (pointing outwards from screen)? Finally why is this green instead of red from vertex 1 and green to vertex 2 and black at vertex 3? I am using the following vertex and fragment shaders:

#version 430
in vec3 POSITION;
in vec4 NORMAL;
in vec2 TEXCOORD0;

out vec4 normal;
out vec2 uv0;

uniform mat4 ModelMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 NormalMatrix;
uniform vec3 CameraPosition;

void main()
{
    //normal = normalize(ModelMatrix * NORMAL);
    normal = normalize(NORMAL);
    uv0 = TEXCOORD0;

    vec4 worldPosition = ModelMatrix * vec4(POSITION, 1.0);
    //toCamera = normalize(CameraPosition - worldPosition.xyz);

    gl_Position = ViewProjectionMatrix * worldPosition;
}

--

#version 430
in vec4 normal;
in vec2 uv0;

out vec4 outFragColor;

uniform sampler2D TEXTURE_0;

uniform vec3 DirectionalLightDirection;
uniform vec4 DiffuseReflectance;
uniform float Shininess;

//Blinn-Phong lighting ... TODO make this a macro

float calculateDiffuseTerm(vec3 N, vec3 L)
{
    return clamp(dot(N, L), 0.0, 1.0);
}

float calculateSpecularTermWithHalfVector(vec3 N, vec3 L, vec3 V)
{
    float term = 0.0;
    if(dot(N, L) > 0.0)
    {
        vec3 H = normalize(L+V);
        term = pow(dot(N, H), Shininess);
    }
    return term;
}

void main()
{
    //Calculate diffuse
    vec4 textureColor = texture(TEXTURE_0, uv0);

    vec3 directionalLight = -1.0 * DirectionalLightDirection;
    float diffuseTerm = calculateDiffuseTerm(normalize(normal.xyz), directionalLight);

    outFragColor = normalize(normal);// diffuseTerm * DiffuseReflectance;
}

Solution

  • At this point, I'm suspecting that this obj file is incorrect? Notice the last normal, (number 3 that is), why is it (0.0, 0.0, -1.0) ?

    Why do you say that? Your OBJ file defines a triangle with all 3 vertices sharing the normal 1 (in OBJs one-based indexing), which is clearly (0,0,1), and is also what assimp did load.

    Wavefront OBJ uses the convention

    vertex/texcoord/normal 
    

    and not vertex/normal/texcoord as you seem to expect.