Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering an Obj file with implicit face normals #1837

Open
itanbp opened this issue Apr 18, 2018 · 12 comments
Open

Rendering an Obj file with implicit face normals #1837

itanbp opened this issue Apr 18, 2018 · 12 comments
Labels

Comments

@itanbp
Copy link

itanbp commented Apr 18, 2018

Hi,
I'm trying to render a submarine object from poly.
In this specific submarine object the vertex normal indices are implicit.
You can see it when looking at the "faces" lines, for example f 40/91 41/90 37/89 36/88

I previously tried to use rajawali to render the object, but I got a runtime exception there are no normals specified for this model.

It looks like rajawali expect for explicit declaration of face normals, although:

Vertices are stored in a counter-clockwise order by default, making explicit declaration of face normals unnecessary.
from .obj wiki

In the documentation stated that

Construct a mesh with default vertex layout float3 a_position float2 a_texcoord float3 a_normal

and also:

Usually each mesh vertex may have a position, normal and texture coordinate.

My question is, does GVRMesh intended to parse and render an Obj file with implicit face normals?

Thanks!

@bohuang3d
Copy link

There are many special cases as you observe if it's currently unsupported. And we may choose to utilize time to support more modern file formats with the resources we have.

I'd say the fastest way to resolve this is to convert the models so there are no implicit normals via Blender for example

@thomasflynn
Copy link

@itanbp we use assimp (assimp.org) for loading in many file formats, including obj. @NolaDonato will assimp support what he is looking for?

and fwiw, we have our own parser for x3d that will generate normals if they are not provided in the file. if it would be possible to export to x3d (read the file in blender, export to x3d), that may do what you need.

@liaxim
Copy link
Contributor

liaxim commented Apr 18, 2018

@itanbp Assimp doesn't generate the normals for us when using the model you referenced (tells us there are no normals). You can still load the model and view it but there will be no lighting effects.

@itanbp
Copy link
Author

itanbp commented Apr 18, 2018

@bohuang3d @thomasflynn @liaxim thank you all for your quick answers!

I'm intending to work with Poly project, which is a large, free to use, 3D virtual objects library. Poly is also accessible via an API.

Using Blender (as a solution for the implicit normals) isn't relevant as I'm building an Android app that fetches 3D models, and displays them to the user.

What do you suggest? What is the effort of calculating the normals and changing this files to explicitly declare the face normals?

@thomasflynn
Copy link

there appears to be a 'GenNormals' post process flag for assimp (http://assimp.sourceforge.net/lib_html/postprocess_8h.html). let us investigate that and see if we can enable it.

@NolaDonato
Copy link
Contributor

Our vertex format requires there be a normal for each position. The best we can do is to generate the same normal for each position. This means that many vertices will have more than one normal and will have to be duplicated. Your mesh will get bigger. If you render it with one of our shaders, it will have a faceted look. Is this what you want?

Or do you just want us to generate vertex normals if you don't have them?

@itanbp
Copy link
Author

itanbp commented Apr 19, 2018

@thomasflynn the GenNormals flag looks like the right solution -

This is ignored if normals are already there at the time this flag
is evaluated.

@NolaDonato I'm not sure I fully understand the difference between the two options you mentioned, but this 3D model and many similar ones with the same issue are exported without normal vectors at all.
For instance, you can notice that in the submarine model it doesn't have vn lines at all.

If it helps, my goal is to render the model the same way they are in Poly, see how the object renderer here

@thomasflynn
Copy link

@itanbp take a look at GVRImportSettings and then try using the variation of loadModel() (in GVRAssetImporter) that takes the import settings. It looks like you should be able to set that flag in the import settings and it'll get passed to assimp.

@liaxim
Copy link
Contributor

liaxim commented Apr 19, 2018

EnumSet<GVRImportSettings> importSettings = EnumSet.of(CALCULATE_NORMALS, TRIANGULATE) works. TRIANGULATE required to avoid exception in AiMesh. Doesn't look much like the referenced example though. Added a light but didn't help much.

@NolaDonato
Copy link
Contributor

Try this. It looks lit and faceted for me:

public class SampleActivity extends GVRActivity {

@Override
protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setMain(new SampleMain());
}
private static void centerModel(GVRSceneObject model, GVRTransform camTrans)
{
    GVRSceneObject.BoundingVolume bv = model.getBoundingVolume();
    float x = camTrans.getPositionX();
    float y = camTrans.getPositionY();
    float z = camTrans.getPositionZ();
    float sf = 1 / bv.radius;
    model.getTransform().setScale(sf, sf, sf);
    bv = model.getBoundingVolume();
    model.getTransform().setPosition(x - bv.center.x, y - bv.center.y, z - bv.center.z - 1.5f);
}

private static class SampleMain extends GVRMain {
    @Override
    public void onInit(GVRContext gvrContext) {
        GVRScene scene = gvrContext.getMainScene();
        GVRSceneObject model;
        GVRDirectLight headLight = new GVRDirectLight(gvrContext);
        GVRSceneObject lightObj = new GVRSceneObject(gvrContext);
        GVRPointLight toplight = new GVRPointLight(gvrContext);
        EnumSet<GVRImportSettings> settings = GVRImportSettings.getRecommendedSettingsWith(EnumSet.of(GVRImportSettings.TRIANGULATE, GVRImportSettings.CALCULATE_NORMALS));

        scene.getMainCameraRig().getHeadTransformObject().attachComponent(headLight);
        scene.getRoot().attachComponent(toplight);
        scene.setBackgroundColor(1, 1, 0.2f, 1);
        headLight.setAmbientIntensity(0.3f, 0.3f, 0.3f, 1.0f);
        headLight.setDiffuseIntensity(0.7f, 0.7f, 0.7f, 1.0f);
        toplight.setAmbientIntensity(0.3f, 0.3f, 0.3f, 1.0f);
        toplight.setDiffuseIntensity(0.7f, 0.7f, 0.7f, 1.0f);
        lightObj.attachComponent(toplight);
        lightObj.getTransform().setPosition(0, 2, 0);
        scene.addSceneObject(lightObj);
        try
        {
            model = gvrContext.getAssetLoader().loadModel("submarine/CUPIC_SUBMARINE.obj",settings, true, scene);
            centerModel(model, scene.getMainCameraRig().getTransform());
            model.getTransform().rotateByAxis(45.0f, 0, 1, 0);
        }
        catch (IOException e)
        {
            Log.e("ASSET", e.getMessage());
        }
    }
}

}

@liaxim
Copy link
Contributor

liaxim commented Apr 20, 2018

Works for me too. The mistake I made was not to use GVRImportSettings.getRecommendedSettingsWith so I was missing required import flags. GVRImportSettings.getRecommendedSettingsWith should be at least mentioned in the javadoc if not automatically used.

TRIANGULATE is already in the recommended settings.

@itanbp
Copy link
Author

itanbp commented Apr 20, 2018

thank you all for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants