Skip to content

allow saving vertex normal in save_obj #1511

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

Closed
wants to merge 2 commits into from

Conversation

dhbloo
Copy link
Contributor

@dhbloo dhbloo commented Apr 17, 2023

Although we can load per-vertex normals in load_obj, saving per-vertex normals is not supported in save_obj.

This patch fixes this by allowing passing per-vertex normal data in save_obj:

def save_obj(
    f: PathOrStr,
    verts,
    faces,
    decimal_places: Optional[int] = None,
    path_manager: Optional[PathManager] = None,
    *,
    verts_normals: Optional[torch.Tensor] = None,
    faces_normals: Optional[torch.Tensor] = None,
    verts_uvs: Optional[torch.Tensor] = None,
    faces_uvs: Optional[torch.Tensor] = None,
    texture_map: Optional[torch.Tensor] = None,
) -> None:
    """
    Save a mesh to an .obj file.

    Args:
        f: File (str or path) to which the mesh should be written.
        verts: FloatTensor of shape (V, 3) giving vertex coordinates.
        faces: LongTensor of shape (F, 3) giving faces.
        decimal_places: Number of decimal places for saving.
        path_manager: Optional PathManager for interpreting f if
            it is a str.
        verts_normals: FloatTensor of shape (V, 3) giving the normal per vertex.
        faces_normals: LongTensor of shape (F, 3) giving the index into verts_normals
            for each vertex in the face.
        verts_uvs: FloatTensor of shape (V, 2) giving the uv coordinate per vertex.
        faces_uvs: LongTensor of shape (F, 3) giving the index into verts_uvs for
            each vertex in the face.
        texture_map: FloatTensor of shape (H, W, 3) representing the texture map
            for the mesh which will be saved as an image. The values are expected
            to be in the range [0, 1],
    """

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 17, 2023
@@ -728,6 +741,7 @@ def save_obj(
if path_manager is None:
path_manager = PathManager()

save_normals = all([n is not None for n in [verts_normals, faces_normals]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the idea that, if they want, the user can supply verts_normals or faces_normals or both? I think so, and I think the logic for dealing with verts_normals and the logic for dealing with faces_normals should have nothing to do with each other. There's no need for a save_normals flag which makes them interact.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, the logic is that both verts_normal and faces_normal are required to save normals in the OBJ file. faces_normal are used to index the verts_normal, and for the case when each vertex has only one corresponding normal, it should be the same with faces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, I misunderstood completely. Could the inputs be called normals and faces_normals_idx instead of verts_normals and faces_normals? I think it would be clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I've changed it. I took the name similar to verts_uvs and faces_uvs, but it is indeed a bit misleading.

[[0.02, 0.5, 0.73], [0.3, 0.03, 0.361], [0.32, 0.12, 0.47], [0.36, 0.17, 0.9]],
dtype=torch.float32,
)
faces_normals = faces
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps faces_normals = faces * 3 or something to make it more obvious that the format is correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the test with more normals per face

@dhbloo dhbloo force-pushed the save-normal-in-obj branch from fd992b1 to 653e498 Compare April 17, 2023 11:51
@dhbloo dhbloo force-pushed the save-normal-in-obj branch from 26b1e36 to b18836b Compare April 18, 2023 04:36
@facebook-github-bot
Copy link
Contributor

@bottler has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

@bottler merged this pull request in 092400f.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants