[SOLVEDish] Runtime imported model lighting issues

I am importing .obj files with textures but it seems like the lighting doesn’t update properly on these models. I have imported the same file in the editor and it works fine, so far I have been unable to find any differences between the two components using console.logging them :frowning:
image (left is runtime import)
How can I solve this?

Code:

app.assets.loadFromUrl(url, "model", function (err, asset) {
    entity = new pc.Entity();
    entity.addComponent("model");
    entity.model.model = asset.resource;
    entity.setLocalScale(.2,.2,.2);
    // console.log(entity.model.layers);
    app.root.addChild(entity);

    entity.model.material.diffuseMap = importedTexture;
    entity.model.material.update();
});

Can you check if your obj contains normals? It’s the vn attribute.

The obj parser will find and assign them if available, if not I don’t see it doing any normals calculations. I imagine the editor importer might be doing some additional things on imported models.

If that is the issue, there is a method in the engine to calculate normals on a mesh, if you would like to extend the obj parser to include it. All PRs are welcome:

This is indeed the issue. Ugh :stuck_out_tongue:
I’ll try and get that to work, but I haven’t worked with models this way before… :slight_smile:

1 Like

So we’ve added pc.calculateNormals, but it looks like that function generates flat normals, resulting in this look: TlAAkXNggx

Unfortunately I do not know how to fix this part… any tips? :stuck_out_tongue:

Modified part of the obj-model-parser.js (https://github.com/playcanvas/engine/blob/245afc498fd3e189f6166c6b060a6443e65cf0b9/examples/assets/scripts/loaders/obj-model.js)

var model = new pc.Model();
var groupNames = Object.keys(parsed);
var root = new pc.GraphNode();
// create a new mesh instance for each "group"
for (i = 0; i < groupNames.length; i++) {
    var currentGroup = parsed[groupNames[i]];
    if (!currentGroup.verts.length) continue;
    if (currentGroup.verts.length > 65535) {
        console.warn("Warning: mesh with more than 65535 vertices");
    }
    var indices = currentGroup.verts.map(function (x, i) { return i; }); // (((i/3)|0)*3)+[0,1,2][(i%3)]
    var norms = pc.calculateNormals(currentGroup.verts, indices); // generate normals
    var mesh = pc.createMesh(this._device, currentGroup.verts, {
        normals: norms,
        uvs: currentGroup.uvs
    });
    var mi = new pc.MeshInstance(new pc.GraphNode(), mesh, this._defaultMaterial);
    model.meshInstances.push(mi);
    root.addChild(mi.node);
}
model.graph = root;
model.getGraph().syncHierarchy();
return model;

Not sure why, this method normalizes the normals at the right place, that should be enough.

The terrain tutorial uses the same method to produce smooth normals over the terrain mesh:

https://developer.playcanvas.com/en/tutorials/terrain-generation/

I saw you raised an issue on github about it, that’s great, let’s see if someone can be of help there.