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

Black output when rendering top down image #845

Open
Kurokabe opened this issue Nov 20, 2024 · 2 comments
Open

Black output when rendering top down image #845

Kurokabe opened this issue Nov 20, 2024 · 2 comments

Comments

@Kurokabe
Copy link

With kaolin==0.16.0, when I use easy_render with the camera above the center of my mesh, and the camera looking straight down, I get a black image.

from kaolin.render.easy_render import render_mesh, default_lighting
from kaolin.io.usd import import_mesh
from kaolin.render.camera import Camera
import torch
from torchvision.transforms import ToPILImage

mesh = import_mesh("my_mesh.usd", triangulate=True, with_materials=True).to("cuda")

mesh.vertices.min(axis=0), mesh.vertices.max(axis=0)
center = (mesh.vertices.min(axis=0)[0] + mesh.vertices.max(axis=0)[0]) / 2

offset = 0.0

camera_y_position = 3.0

eye = torch.tensor([center[0], camera_y_position , center[2]], dtype=torch.float32)
at = torch.tensor([center[0] + offset, 0, center[2]], dtype=torch.float32)

lighting = default_lighting().to("cuda")
camera = Camera.from_args(
                eye=eye,
                at=at,
                up=torch.tensor([0.0, 1.0, 0.0]),
                fov=45,  
                width=512, height=512,
                device='cuda'
            )

with torch.jit.optimized_execution(False):
    with torch.no_grad():
        render = render_mesh(
                camera,
                mesh,
                lighting,
            )
        

ToPILImage()(render["render"][0].transpose(0, 2))

But if I add a slight offset, e.g. offset = 0.01 to either the X or Z coordinate, then I get a proper rendering.

@Kurokabe Kurokabe changed the title Black image when rendering top down image Black output when rendering top down image Nov 20, 2024
@Caenorst
Copy link
Collaborator

Caenorst commented Nov 25, 2024

Hi @Kurokabe , Looking into it

EDIT: actually if you look at your code the up axis is aligned with forward, so the camera is basically undefined, if camera is looking perfectly down I suggest setting a different up axis.

@Kurokabe
Copy link
Author

Thank you @Caenorst for your answer, I was able to fix it by setting a different up axis.

I have been experimenting with camera rotations with azimuth and elevation angles, but I am faced with weird results, if you can have a look:

Here is an example mesh:
chair.zip

And below the code to generate an animation:

from kaolin.render.easy_render import render_mesh, default_lighting
from kaolin.io.usd.mesh import import_mesh, SurfaceMesh
from kaolin.render.camera import Camera
import torch
from copy import deepcopy
from kaolin.ops.pointcloud import center_points
from torchvision.transforms import ToPILImage
from kaolin.ops.coords import spherical2cartesian
from kaolin.render.camera import blender_coords
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
import numpy as np

mesh = import_mesh("./chair.usd", triangulate=True, with_normals=True).to("cuda")

def center_mesh(mesh: SurfaceMesh, normalize: bool):
    mesh = deepcopy(mesh)
    mesh = mesh.to_batched()
    mesh.vertices = center_points(mesh.vertices, normalize=normalize)
    mesh = mesh.set_batching(SurfaceMesh.Batching.NONE)
    return mesh

def render(mesh, azimuth, elevation):
    mesh = center_mesh(mesh, normalize=True).to("cuda")

    # Convert azimuth and elevation to radians
    azimuth_tensor = torch.deg2rad(torch.tensor(azimuth, dtype=torch.float32))
    elevation_tensor = torch.deg2rad(torch.tensor(elevation, dtype=torch.float32))

    # Compute eye position
    x, y, z = spherical2cartesian(azimuth=azimuth_tensor, elevation=elevation_tensor, distance=2.0)
    eye = torch.tensor([x, y, z], dtype=torch.float32)

    # Camera target (always at origin)
    at = torch.tensor([0.0, 0.0, 0.0], dtype=torch.float32)

    # Forward vector (from eye to target)
    forward = -eye / torch.linalg.norm(eye)

    # Fixed world up vector
    world_up = torch.tensor([0.0, 0.0, 1.0], dtype=torch.float32)

    # Right and up vectors
    right = torch.cross(world_up, forward)
    right = right / torch.linalg.norm(right)  # Normalize right vector
    up = torch.cross(forward, right)  # Up vector from forward and right

    print(f"Eye: {eye}, Up: {up}")

    # Lighting and camera setup
    lighting = default_lighting().to("cuda")
    camera = Camera.from_args(eye=eye, at=at, up=up, fov=45, width=512, height=512, device="cuda")
    camera.extrinsics.change_coordinate_system(blender_coords())
    
    with torch.jit.optimized_execution(False):
        with torch.no_grad():
            render = render_mesh(camera, mesh, lighting)

    return ToPILImage()(render["render"][0].transpose(0, 2))

When I run the following to animate the azimuth between 0° and 360° :

frames = []
for angle in range(0, 360, 10): 
    frame = render(mesh, azimuth=angle, elevation=0)
    frames.append(frame)

fig, ax = plt.subplots()

def update(frame):
    ax.clear()
    ax.imshow(np.asarray(frames[frame]))
    ax.axis('off')  # Hide axes

ani = FuncAnimation(fig, update, frames=len(frames), interval=100)  # Interval in ms
HTML(ani.to_jshtml())

I get this result where as if the elevation was impacted:
rotation_azimuth

And when I animate the elevation between 0° and 360° with the following:

frames = []
for angle in range(0, 360, 10): 
    frame = render(mesh, azimuth=0, elevation=angle)
    frames.append(frame)

fig, ax = plt.subplots()

def update(frame):
    ax.clear()
    ax.imshow(np.asarray(frames[frame]))
    ax.axis('off')  # Hide axes

ani = FuncAnimation(fig, update, frames=len(frames), interval=100)  # Interval in ms
HTML(ani.to_jshtml())

I get this result as if the azimuth is impacted
rotation_elevation

Furthermore, at 180°, there is a 'flip' that occurs as well.

The mesh is oriented with Z up and I've changed the camera coordinate system to also be with Z up, as in Blender
image
When looking at the eye and up vectors, they seem correct, but I don't understand the following (potential issue with the Camera?):

  1. Why when moving the azimuth, the elevation is impacted and vice versa
  2. Why does the flip occurs at 180°?

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

No branches or pull requests

2 participants