OBJ files loaded without normals

Hello,
I am trying to load some obj files:

model = self.loader.loadModel(filepath)
model.reparentTo(self.nodePath_meshes_group)

and then I apply lights to the parent nodepath

self.nodePath_meshes_group.setLight(self.ambient_light_node_path)
self.nodePath_meshes_group.setLight(self.directional_light_node_path

However, the objs appear flat and grey, without any shading, looking like they have no normals.

My obj files look like that , so they are with normals vn (this is a short version, the actual obj’s have around 10.000 - 20.000 vertices each):

v 0.000 0.000 0.000
v 0.000 2.000 0.000
v 1.000 2.000 0.000
v 1.000 0.000 0.000
v 0.000 0.000 3.000
v 1.000 0.000 3.000
v 1.000 2.000 3.000
v 0.000 2.000 3.000
vn 0.8571428571428571 0.42857142857142855 0.2857142857142857
vn 0.8571428571428571 -0.42857142857142855 0.2857142857142857
vn -0.8571428571428571 -0.42857142857142855 0.2857142857142857
vn -0.8571428571428571 0.42857142857142855 0.2857142857142857
vn 0.8571428571428571 0.42857142857142855 -0.2857142857142857
vn -0.8571428571428571 0.42857142857142855 -0.2857142857142857
vn -0.8571428571428571 -0.42857142857142855 -0.2857142857142857
vn 0.8571428571428571 -0.42857142857142855 -0.2857142857142857
f 1 2 3 4
f 1 4 6 5
f 4 3 7 6
f 3 2 8 7
f 2 1 5 8
f 5 6 7 8

I also tried reversing the normals, but I still have the same problem.

When I re-create the geometry procedurally by creating my own GeomVertexFormat.getV3n3() , then they look correct, they have normals and are shaded with the lights. However this takes too long, so I prefer to stick to loading objs.

Any ideas what I might be doing wrong?

Thanks a lot!

This may be related or you may not use Assimp:

If you are not using Assimp, then you can include:

from panda3d.core import loadPrcFileData
loadPrcFileData ("", "load-file-type p3assimp")

Hello,
I added Assimp on the Prc, but unfortunately it doesn’t fix the problem.

Not sure how you generate your .obj files, but it seems that Panda does not load the normals from the example file you posted.
This is the output when printing the vertex data of the loaded model to the console:

defaultobject
  8 rows.
  Array 0 (00000230492AA080, [ vertex(3f) ]):
    row 0:
      vertex 0 0 0
    row 1:
      vertex 0 2 0
    row 2:
      vertex 1 2 0
    row 3:
      vertex 1 0 0
    row 4:
      vertex 1 0 3
    row 5:
      vertex 0 0 3
    row 6:
      vertex 1 2 3
    row 7:
      vertex 0 2 3

As you can see, there is no normal data column, only a vertex data column.
It works when I add texture coordinates and change the definition of the faces as follows:

v 0.000 0.000 0.000
v 0.000 2.000 0.000
v 1.000 2.000 0.000
v 1.000 0.000 0.000
v 0.000 0.000 3.000
v 1.000 0.000 3.000
v 1.000 2.000 3.000
v 0.000 2.000 3.000
vn 0.8571428571428571 0.42857142857142855 0.2857142857142857
vn 0.8571428571428571 -0.42857142857142855 0.2857142857142857
vn -0.8571428571428571 -0.42857142857142855 0.2857142857142857
vn -0.8571428571428571 0.42857142857142855 0.2857142857142857
vn 0.8571428571428571 0.42857142857142855 -0.2857142857142857
vn -0.8571428571428571 0.42857142857142855 -0.2857142857142857
vn -0.8571428571428571 -0.42857142857142855 -0.2857142857142857
vn 0.8571428571428571 -0.42857142857142855 -0.2857142857142857
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000

f 1/1/1 2/2/2 3/3/3 4/4/4
f 1/1/1 4/4/4 6/6/6 5/5/5
f 4/4/4 3/3/3 7/7/7 6/6/6
f 3/3/3 2/2/2 8/8/8 7/7/7
f 2/2/2 1/1/1 5/5/5 8/8/8
f 5/5/5 6/6/6 7/7/7 8/8/8

The output is then as expected:

defaultobject
  8 rows.
  Array 0 (0000028CE0850AB0, [ vertex(3f) normal(3f) ]):
    row 0:
      vertex 0 0 0
      normal 0.857143 0.428571 0.285714
    row 1:
      vertex 0 2 0
      normal 0.857143 -0.428571 0.285714
    row 2:
      vertex 1 2 0
      normal -0.857143 -0.428571 0.285714
    row 3:
      vertex 1 0 0
      normal -0.857143 0.428571 0.285714
    row 4:
      vertex 1 0 3
      normal -0.857143 0.428571 -0.285714
    row 5:
      vertex 0 0 3
      normal 0.857143 0.428571 -0.285714
    row 6:
      vertex 1 2 3
      normal -0.857143 -0.428571 -0.285714
    row 7:
      vertex 0 2 3
      normal 0.857143 -0.428571 -0.285714
  Array 1 (0000028CD6F0C9C0, [ texcoord(3f) ]):
    row 0:
      texcoord 0 0 0
    row 1:
      texcoord 0 0 0
    row 2:
      texcoord 0 0 0
    row 3:
      texcoord 0 0 0
    row 4:
      texcoord 0 0 0
    row 5:
      texcoord 0 0 0
    row 6:
      texcoord 0 0 0
    row 7:
      texcoord 0 0 0

No idea why it has to be like that, but it doesn’t seem to work without the texture coordinates or with a different face format.

Anyway I hope this solves your problem :slight_smile: .

1 Like

Many thanks for your answer. Indeed I wasn’t very careful with the obj format, I changed it as you suggested and it works. Also there’s no need to write texture coordinates, then the faces can be written as:

f 2//2 3//3 1//1

However, in the process of figuring this out, I was really buffled by something.
If the name of my obj starts with a number, for example I used to name them 0.obj, 1.obj and so on, then the normals are not loaded whatever the obj format.
When I changed the name to something like mesh_0.obj, mesh_1.obj then the normals are loaded.

I wonder if there’s a reason for that, or if it is just a bug.

Many thanks for your answers!!

Ah, good point! It’s been a while since I last studied the .obj format, so I forgot that faces could be defined that way.

Hmm, I can’t seem to reproduce this; when I rename my .obj file to 0.obj, the model is loaded correctly with normals. Could it perhaps be that you initially named incorrectly formatted .obj files that way and then loaded them again after correcting them, without clearing the model cache first?
Just to be sure, try loading those files as follows:

model = self.loader.load_model("0.obj", noCache=True)
1 Like

That could be the case. Thanks a lot for pointing that out because I was very baffled by this.