def import_surface(asset_directory, target_ctx=None, ior=DEFAULT_IOR, metallic_ior=DEFAULT_METALLIC_IOR, projection_type="triplanar", object_space=0, clip_opacity=True, color_spaces=(), triplanar_blend=0.5, **kwargs): # Initial data ix = get_ix(kwargs.get("ix")) if not target_ctx: target_ctx = ix.application.get_working_context() if not check_context(target_ctx, ix=ix): return None asset_directory = os.path.normpath(asset_directory) if not os.path.isdir(asset_directory): ix.log_warning("Invalid directory specified: " + asset_directory) return None logging.debug("Asset directory: " + asset_directory) logging.debug("Importing generic surface:") surface_height = DEFAULT_DISPLACEMENT_HEIGHT scan_area = DEFAULT_UV_SCALE tileable = True asset_name = os.path.basename(os.path.normpath(asset_directory)) textures = get_textures_from_directory(asset_directory) if not textures: ix.log_warning("No textures found in directory.") return None logging.debug("Found textures: ") logging.debug(str(textures)) streamed_maps = get_stream_map_files(textures) if streamed_maps: logging.debug("Streamed maps: ") logging.debug(str(streamed_maps)) surface = Surface(ix, projection=projection_type, uv_scale=scan_area, height=surface_height, tile=tileable, object_space=object_space, triplanar_blend=triplanar_blend, ior=ior, metallic_ior=metallic_ior) mtl = surface.create_mtl(asset_name, target_ctx) surface.create_textures(textures, color_spaces, streamed_maps, clip_opacity=clip_opacity) logging.debug("Finished importing surface.") logging.debug("+++++++++++++++++++++++++++++++") return surface
def import_surface(asset_directory, target_ctx=None, ior=DEFAULT_IOR, projection_type='triplanar', object_space=0, clip_opacity=True, color_spaces=None, triplanar_blend=0.5, resolution=None, lod=None, **kwargs): """Imports a Megascans surface.""" logging.debug("++++++++++++++++++++++.") logging.debug("Import Megascans surface called.") ix = get_ix(kwargs.get('ix')) if not target_ctx: target_ctx = ix.application.get_working_context() if not check_context(target_ctx, ix=ix): return None if not os.path.isdir(asset_directory): return ix.log_warning('Invalid directory specified: ' + asset_directory) if not color_spaces: color_spaces = get_color_spaces(MEGASCANS_COLOR_SPACES, ix=ix) logging.debug('Asset directory: ' + asset_directory) # Initial data json_data = get_json_data_from_directory(asset_directory) logging.debug('JSON data:') logging.debug(str(json_data)) if not json_data: ix.log_warning( 'Could not find a Megascans JSON file. Defaulting to standard settings.' ) surface_height = json_data.get('surface_height', DEFAULT_DISPLACEMENT_HEIGHT) displacement_offset = DEFAULT_DISPLACEMENT_OFFSET logging.debug('Surface height JSON test: ' + str(surface_height)) scan_area = json_data.get('scan_area', DEFAULT_UV_SCALE) logging.debug('Scan area JSON test: ' + str(scan_area)) tileable = json_data.get('tileable', True) asset_name = os.path.basename(os.path.normpath(asset_directory)) logging.debug('Asset name: ' + asset_name) if scan_area[0] >= 2 and scan_area[1] >= 2: height = 0.2 else: height = 0.02 # All assets except 3dplant have the material in the root directory of the asset. logging.debug('Searching for textures: ') lod_match_template = r'(?:_LOD(?P<lod>[0-9]*)|_NormalBump$)' textures = get_textures_from_directory( asset_directory, resolution=resolution, lod=lod, lod_match_template=lod_match_template) if not textures: ix.log_warning( 'No textures found in directory. Directory is empty or resolution is invalid.' ) return None logging.debug('Found textures: ') logging.debug(str(textures)) streamed_maps = get_stream_map_files(textures) if streamed_maps: logging.debug('Streamed maps: ') logging.debug(str(streamed_maps)) surface = Surface(ix, projection=projection_type, uv_scale=scan_area, height=height, tile=tileable, object_space=object_space, triplanar_blend=triplanar_blend, ior=ior, specular_strength=1, displacement_offset=displacement_offset) mtl = surface.create_mtl(asset_name, target_ctx) surface.create_textures(textures, color_spaces=color_spaces, streamed_maps=streamed_maps, clip_opacity=clip_opacity) logging.debug("Import Megascans surface done.") logging.debug("++++++++++++++++++++++.") return surface
def import_3dplant(asset_directory, target_ctx=None, ior=DEFAULT_IOR, object_space=0, clip_opacity=True, use_displacement=True, color_spaces=MEGASCANS_COLOR_SPACES, triplanar_blend=0.5, resolution=None, lod=None, **kwargs): """Imports a Megascans 3D object.""" ix = get_ix(kwargs.get('ix')) logging.debug("*******************") logging.debug("Setting up 3d plant...") # Megascans 3dplant importer. The 3dplant importer requires 2 materials to be created. # Let's first find the textures of the Atlas and create the material. if not target_ctx: target_ctx = ix.application.get_working_context() if not check_context(target_ctx, ix=ix): return None asset_directory = os.path.normpath(asset_directory) if not os.path.isdir(asset_directory): return ix.log_warning("Invalid directory specified: " + asset_directory) logging.debug("Asset directory: " + asset_directory) # Initial data json_data = get_json_data_from_directory(asset_directory) logging.debug("JSON data:") logging.debug(str(json_data)) if not json_data: ix.log_warning( "Could not find a Megascans JSON file. Defaulting to standard settings." ) asset_type = json_data.get('type', 'surface') logging.debug("Asset type from JSON test: " + asset_type) surface_height = json_data.get('surface_height', DEFAULT_DISPLACEMENT_HEIGHT) logging.debug("Surface height JSON test: " + str(surface_height)) scan_area = json_data.get('scan_area', DEFAULT_UV_SCALE) logging.debug("Scan area JSON test: " + str(scan_area)) tileable = json_data.get('tileable', True) asset_name = os.path.basename(os.path.normpath(asset_directory)) logging.debug("Asset name: " + asset_name) logging.debug(os.path.join(asset_directory, 'Textures/Atlas/')) atlas_textures = get_textures_from_directory(os.path.join( asset_directory, 'Textures/Atlas/'), resolution=resolution) if not atlas_textures: ix.log_warning( "No atlas textures found in directory. Files might have been exported flattened from Bridge.\n" "Testing import as Atlas.") import_atlas(asset_directory, target_ctx=target_ctx, use_displacement=use_displacement, clip_opacity=clip_opacity, resolution=resolution, **kwargs) return None logging.debug("Atlas textures: ") logging.debug(str(atlas_textures)) streamed_maps = get_stream_map_files(atlas_textures) logging.debug("Atlas streamed maps: ") logging.debug(str(streamed_maps)) atlas_surface = Surface(ix, projection='uv', uv_scale=scan_area, height=scan_area[0], tile=tileable, object_space=object_space, triplanar_blend=triplanar_blend, ior=ior, double_sided=True, specular_strength=1, displacement_multiplier=0.1) plant_root_ctx = ix.cmds.CreateContext(asset_name, "Global", str(target_ctx)) atlas_mtl = atlas_surface.create_mtl(ATLAS_CTX, plant_root_ctx) atlas_surface.create_textures(atlas_textures, color_spaces=color_spaces, streamed_maps=streamed_maps, clip_opacity=clip_opacity) atlas_ctx = atlas_surface.ctx # Find the textures of the Billboard and create the material. billboard_textures = get_textures_from_directory(os.path.join( asset_directory, 'Textures/Billboard/'), resolution=resolution) if not billboard_textures: ix.log_warning("No Billboard textures found in directory.") else: logging.debug("Billboard textures: ") logging.debug(str(billboard_textures)) streamed_maps = get_stream_map_files(billboard_textures) logging.debug("Billboard streamed maps: ") logging.debug(str(streamed_maps)) billboard_surface = Surface(ix, projection='uv', uv_scale=scan_area, height=scan_area[0], tile=tileable, object_space=object_space, triplanar_blend=triplanar_blend, ior=ior, double_sided=True, specular_strength=1, displacement_multiplier=0.1) billboard_mtl = billboard_surface.create_mtl(BILLBOARD_CTX, plant_root_ctx) billboard_surface.create_textures(billboard_textures, color_spaces=color_spaces, streamed_maps=streamed_maps, clip_opacity=clip_opacity) billboard_ctx = billboard_surface.ctx for dir_name in os.listdir(asset_directory): variation_dir = os.path.join(asset_directory, dir_name) if os.path.isdir(variation_dir) and dir_name.startswith('Var'): logging.debug("Variation dir found: " + variation_dir) files = [ f for f in os.listdir(variation_dir) if os.path.isfile(os.path.join(variation_dir, f)) ] # Search for models files and apply material for f in files: filename, extension = os.path.splitext(f) if extension.lower() == ".obj": logging.debug("Found obj: " + f) filename, extension = os.path.splitext(f) polyfile = ix.cmds.CreateObject(filename, "GeometryPolyfile", "Global", str(plant_root_ctx)) ix.cmds.SetValue( str(polyfile) + ".filename", [os.path.normpath(os.path.join(variation_dir, f))]) # Megascans .obj files are saved in cm, Clarisse imports them as meters. polyfile.attrs.scale_offset[0] = .01 polyfile.attrs.scale_offset[1] = .01 polyfile.attrs.scale_offset[2] = .01 geo = polyfile.get_module() for i in range(geo.get_shading_group_count()): if filename.endswith('3'): geo.assign_material(billboard_mtl.get_module(), i) if clip_opacity and billboard_surface.get( 'opacity'): geo.assign_clip_map( (billboard_surface.get('opacity') ).get_module(), i) else: geo.assign_material(atlas_mtl.get_module(), i) if clip_opacity and atlas_surface.get('opacity'): geo.assign_clip_map( atlas_surface.get('opacity').get_module(), i) lod_level_match = re.sub('.*?([0-9]*)$', r'\1', filename) if int( lod_level_match ) in ATLAS_LOD_DISPLACEMENT_LEVELS and use_displacement: geo.assign_displacement( atlas_surface.get( 'displacement_map').get_module(), i) elif extension.lower() == ".abc": logging.debug("Found abc: " + f) abc_reference = ix.cmds.CreateFileReference( str(plant_root_ctx), [os.path.normpath(os.path.join(variation_dir, f))]) for item in get_items(abc_reference, kind=('GeometryAbcMesh', 'AbcXform'), ix=ix): if not item.attrs.parent[0]: item.attrs.scale_offset[0] = .01 item.attrs.scale_offset[1] = .01 item.attrs.scale_offset[2] = .01 shading_layer = ix.cmds.CreateObject(asset_name + SHADING_LAYER_SUFFIX, "ShadingLayer", "Global", str(plant_root_ctx)) logging.debug("Creating shading layers and groups...") for i in range(0, 4): ix.cmds.AddShadingLayerRule(str(shading_layer), i, ["filter", "", "is_visible", "1"]) ix.cmds.SetShadingLayerRulesProperty(str(shading_layer), [i], "filter", ["./*LOD" + str(i) + "*"]) ix.cmds.SetShadingLayerRulesProperty(str(shading_layer), [i], "material", [str(atlas_mtl)]) if atlas_surface.get('opacity') and clip_opacity: ix.cmds.SetShadingLayerRulesProperty( str(shading_layer), [i], "clip_map", [str(atlas_surface.get('opacity'))]) if atlas_surface.get( 'displacement' ) and i in ATLAS_LOD_DISPLACEMENT_LEVELS and use_displacement: ix.cmds.SetShadingLayerRulesProperty( str(shading_layer), [i], "displacement", [str(atlas_surface.get('displacement_map'))]) group = ix.cmds.CreateObject( asset_name + "_LOD" + str(i) + GROUP_SUFFIX, "Group", "Global", str(plant_root_ctx)) group.attrs.inclusion_rule = "./*LOD" + str(i) + "*" ix.cmds.AddValues([group.get_full_name() + ".filter"], ["GeometryAbcMesh"]) ix.cmds.AddValues([group.get_full_name() + ".filter"], ["GeometryPolyfile"]) ix.cmds.RemoveValue([group.get_full_name() + ".filter"], [2, 0, 1]) logging.debug("...done setting up shading rules, groups and 3d plant") logging.debug("*****************************************************")