docstr: Meshes with TexturesAtlas joined into a scene
docstr_tok: ["Meshes","with","TexturesAtlas","joined","into","a","scene"]
code: def _join_atlas(self, rasterizer_type):
      """Meshes with TexturesAtlas joined into a scene"""
      # Test the result of rendering two tori with separate textures.
      # The expected result is consistent with rendering them each alone.
      torch.manual_seed(1)
      device = torch.device("cuda:0")
  
      plain_torus = torus(r=1, R=4, sides=5, rings=6, device=device)
      [verts] = plain_torus.verts_list()
      verts_shifted1 = verts.clone()
      verts_shifted1 *= 1.2
      verts_shifted1[:, 0] += 4
      verts_shifted1[:, 1] += 5
      verts[:, 0] -= 4
      verts[:, 1] -= 4
  
      [faces] = plain_torus.faces_list()
      map_size = 3
      # Two random atlases.
      # The averaging of the random numbers here is not consistent with the
      # meaning of the atlases, but makes each face a bit smoother than
      # if everything had a random color.
      atlas1 = torch.rand(
          size=(faces.shape[0], map_size, map_size, 3), device=device
      )
      atlas1[:, 1] = 0.5 * atlas1[:, 0] + 0.5 * atlas1[:, 2]
      atlas1[:, :, 1] = 0.5 * atlas1[:, :, 0] + 0.5 * atlas1[:, :, 2]
      atlas2 = torch.rand(
          size=(faces.shape[0], map_size, map_size, 3), device=device
      )
      atlas2[:, 1] = 0.5 * atlas2[:, 0] + 0.5 * atlas2[:, 2]
      atlas2[:, :, 1] = 0.5 * atlas2[:, :, 0] + 0.5 * atlas2[:, :, 2]
  
      textures1 = TexturesAtlas(atlas=[atlas1])
      textures2 = TexturesAtlas(atlas=[atlas2])
      mesh1 = Meshes(verts=[verts], faces=[faces], textures=textures1)
      mesh2 = Meshes(
          verts=[verts_shifted1], faces=[faces], textures=textures2
      )
      self.assertEqual(textures1._num_faces_per_mesh, [len(faces)])
      self.assertEqual(textures2._num_faces_per_mesh, [len(faces)])
      mesh_joined = join_meshes_as_scene([mesh1, mesh2])
      self.assertEqual(textures1._num_faces_per_mesh, [len(faces)])
      self.assertEqual(textures2._num_faces_per_mesh, [len(faces)])
      self.assertEqual(
          mesh_joined.textures._num_faces_per_mesh, [len(faces) * 2]
      )
  
      R, T = look_at_view_transform(18, 0, 0)
      cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
  
      raster_settings = RasterizationSettings(
          image_size=512,
          blur_radius=0.0,
          faces_per_pixel=1,
          perspective_correct=rasterizer_type.__name__
          == "MeshRasterizerOpenGL",
      )
  
      lights = AmbientLights(device=device)
      blend_params = BlendParams(
          sigma=0.5,
          gamma=1e-4,
          background_color=torch.tensor([1.0, 1.0, 1.0], device=device),
      )
  
      rasterizer = rasterizer_type(
          cameras=cameras, raster_settings=raster_settings
      )
      if rasterizer_type == MeshRasterizer:
          shader = HardPhongShader(
              device=device,
              blend_params=blend_params,
              cameras=cameras,
              lights=lights,
          )
      else:
          shader = SplatterPhongShader(
              device=device,
              blend_params=blend_params,
              cameras=cameras,
              lights=lights,
          )
  
      renderer = MeshRenderer(rasterizer, shader)
  
      output = renderer(mesh_joined)
  
      image_ref = load_rgb_image(
          f"test_joinatlas_final_{rasterizer_type.__name__}.png",
          DATA_DIR,
      )
  
      if DEBUG:
          debugging_outputs = []
          for mesh_ in [mesh1, mesh2]:
              debugging_outputs.append(renderer(mesh_))
          Image.fromarray(
              (output[0, ..., :3].cpu().numpy() * 255).astype(np.uint8)
          ).save(
              DATA_DIR
              / f"DEBUG_test_joinatlas_final_{rasterizer_type.__name__}.png"
          )
          Image.fromarray(
              (
                  debugging_outputs[0][0, ..., :3].cpu().numpy() * 255
              ).astype(np.uint8)
          ).save(
              DATA_DIR
              / f"test_joinatlas_1_{rasterizer_type.__name__}.png"
          )
          Image.fromarray(
              (
                  debugging_outputs[1][0, ..., :3].cpu().numpy() * 255
              ).astype(np.uint8)
          ).save(
              DATA_DIR
              / f"test_joinatlas_2_{rasterizer_type.__name__}.png"
          )
  
      result = output[0, ..., :3].cpu()
      self.assertClose(result, image_ref, atol=0.05)
  
imports: import os
  import unittest
  from collections import namedtuple
  from itertools import product
  import numpy
  import torch
  from PIL import Image
  from pytorch3d.io import load_obj, load_objs_as_meshes
  from pytorch3d.renderer import AmbientLights, FoVOrthographicCameras, FoVPerspectiveCameras, look_at_view_transform, Materials, MeshRasterizer, MeshRenderer, MeshRendererWithFragments, OrthographicCameras, PerspectiveCameras, PointLights, RasterizationSettings, TexturesAtlas, TexturesUV, TexturesVertex
  from pytorch3d.renderer.fisheyecameras import FishEyeCameras
  from pytorch3d.renderer.mesh.shader import BlendParams, HardFlatShader, HardGouraudShader, HardPhongShader, SoftPhongShader, SoftSilhouetteShader, SplatterPhongShader, TexturedSoftPhongShader
  from pytorch3d.renderer.opengl import MeshRasterizerOpenGL
  from pytorch3d.structures.meshes import join_meshes_as_batch, join_meshes_as_scene, Meshes
  from pytorch3d.utils.ico_sphere import ico_sphere
  from pytorch3d.utils.torus import torus
  from .common_testing import get_pytorch3d_dir, get_tests_dir, load_rgb_image, TestCaseMixin
label_desc: Use image node_id 22 for calling the TestRenderMeshes obj's underlying member method code with example usage: obj._join_atlas(rasterizer_type) without return types