class_docstr: An implementation of a rendering backend in Blender/Cycles.
class_docstr_tok: ["An","implementation","of","a","rendering","backend","in","Blender\/Cycles","."]
code: def _add_asset(self, obj: core.FileBasedObject):
      if obj.render_filename is None:
          return None  # if there is no render file, then ignore this object
      _, _, extension = obj.render_filename.rpartition(".")
      with RedirectStream(
          stream=sys.stdout, disabled=self.verbose
      ):  # reduce the logging noise
          with io.StringIO() as fstdout:  # < scratch stdout buffer
              with redirect_stdout(
                  fstdout
              ):  # < also suppresses python stdout
                  if extension == "obj":
                      bpy.ops.import_scene.obj(
                          filepath=obj.render_filename,
                          use_split_objects=False,
                          **obj.render_import_kwargs,
                      )
                  elif extension in ["glb", "gltf"]:
                      bpy.ops.import_scene.gltf(
                          filepath=obj.render_filename,
                          **obj.render_import_kwargs,
                      )
                      # gltf files often contain "Empty" objects as placeholders for camera / lights etc.
                      # here we are interested only in the meshes, so delete everything else
                      non_mesh_objects = [
                          obj
                          for obj in bpy.context.selected_objects
                          if obj.type != "MESH"
                      ]
                      bpy.ops.object.delete(
                          {"selected_objects": non_mesh_objects}
                      )
                      # make sure one of the objects is active, otherwise join() fails.
                      # see https://blender.stackexchange.com/questions/132266/joining-all-meshes-in-any-context-gets-error
                      bpy.context.view_layer.objects.active = (
                          bpy.context.selected_objects[0]
                      )
                      bpy.ops.object.join()
                      # By default gltf objects are loaded with a different rotation than obj files
                      # here we compensate for that to ensure alignment between pybullet and blender
                      assert len(bpy.context.selected_objects) == 1
                      blender_obj = bpy.context.selected_objects[0]
                      blender_obj.rotation_quaternion = (
                          0.707107,
                          -0.707107,
                          0,
                          0,
                      )
                      bpy.ops.object.transform_apply(
                          location=False, rotation=True, scale=False
                      )
  
                  elif extension == "fbx":
                      bpy.ops.import_scene.fbx(
                          filepath=obj.render_filename,
                          **obj.render_import_kwargs,
                      )
                  elif extension in ["x3d", "wrl"]:
                      bpy.ops.import_scene.x3d(
                          filepath=obj.render_filename,
                          **obj.render_import_kwargs,
                      )
  
                  elif extension == "blend":
                      # for now we require the paths to be encoded in the render_import_kwargs. That is:
                      # - filepath = dir / "Object" / object_name
                      # - directory = dir / "Object"
                      # - filename = object_name
  
                      bpy.ops.wm.append(**obj.render_import_kwargs)
                  else:
                      raise ValueError(
                          f"Unknown file-type: '{extension}' for {obj}"
                      )
  
      assert len(bpy.context.selected_objects) == 1
      blender_obj = bpy.context.selected_objects[0]
  
      # deactivate auto_smooth because for some reason it lead to no smoothing at all
      # TODO: make smoothing configurable
      blender_obj.data.use_auto_smooth = False
  
      register_object3d_setters(obj, blender_obj)
      obj.observe(
          AttributeSetter(
              blender_obj,
              "active_material",
              converter=self._convert_to_blender_object,
          ),
          "material",
      )
      obj.observe(AttributeSetter(blender_obj, "scale"), "scale")
      obj.observe(
          KeyframeSetter(blender_obj, "scale"), "scale", type="keyframe"
      )
      return blender_obj
  
imports: import collections
  import io
  import logging
  import os
  import sys
  from contextlib import redirect_stdout
  from typing import Any, Dict, Optional, Sequence, Union
  import tempfile
  from kubric.safeimport.bpy import bpy
  import numpy
  import tensorflow
  from singledispatchmethod import singledispatchmethod
  import kubric
  from kubric import core
  from kubric.core.assets import UndefinedAsset
  from kubric.redirect_io import RedirectStream
  from kubric.renderer import blender_utils
  from kubric import file_io
  from kubric.file_io import PathLike
label_desc: Use image node_id 25 for calling the Blender obj's underlying member method code with example usage: obj._add_asset(obj) and returns: blender_obj, None