def get_light_buffer(obj): light = obj.data light_type_name = light.type light_type = common.LightType.SUN if light_type_name == "POINT": light_type = common.LightType.POINT elif light_type_name == "SPOT": light_type = common.LightType.SPOT elif light_type_name == "SUN": light_type = common.LightType.SUN elif light_type_name == "AREA": light_type = common.LightType.AREA else: return None color = light.color power = light.energy if bpy.context.scene.render.engine == "CYCLES": shadow = light.cycles.cast_shadow else: shadow = light.use_shadow spot_blend = 10.0 spot_size = 0.0 if light_type == common.LightType.SPOT: spot_size = light.spot_size spot_blend = light.spot_blend return (common.encode_string(get_object_path(obj)) + common.encode_string(light.name_full) + common.encode_int(light_type.value) + common.encode_int(shadow) + common.encode_color(color) + common.encode_float(power) + common.encode_float(spot_size) + common.encode_float(spot_blend))
def send_camera_attributes(self, obj): buffer = (common.encode_string(obj.name_full) + common.encode_float(obj.data.lens) + common.encode_float(obj.data.dof.aperture_fstop) + common.encode_float(obj.data.dof.focus_distance)) self.add_command( common.Command(MessageType.CAMERA_ATTRIBUTES, buffer, 0))
def send_light_attributes(self, obj): buffer = ( common.encode_string(obj.name_full) + common.encode_float(obj.data.energy) + common.encode_color(obj.data.color) ) self.add_command(common.Command(MessageType.LIGHT_ATTRIBUTES, buffer, 0))
def get_camera_buffer(obj): cam = obj.data focal = cam.lens front_clip_plane = cam.clip_start far_clip_plane = cam.clip_end aperture = cam.dof.aperture_fstop sensor_fit_name = cam.sensor_fit sensor_fit = common.SensorFitMode.AUTO if sensor_fit_name == "AUTO": sensor_fit = common.SensorFitMode.AUTO elif sensor_fit_name == "HORIZONTAL": sensor_fit = common.SensorFitMode.HORIZONTAL elif sensor_fit_name == "VERTICAL": sensor_fit = common.SensorFitMode.VERTICAL sensor_width = cam.sensor_width sensor_height = cam.sensor_height path = get_object_path(obj) return ( common.encode_string(path) + common.encode_string(obj.name_full) + common.encode_float(focal) + common.encode_float(front_clip_plane) + common.encode_float(far_clip_plane) + common.encode_float(aperture) + common.encode_int(sensor_fit.value) + common.encode_float(sensor_width) + common.encode_float(sensor_height) )
def get_camera_buffer(obj): cam = obj.data focal = cam.lens front_clip_plane = cam.clip_start far_clip_plane = cam.clip_end dof_enabled = cam.dof.use_dof aperture = cam.dof.aperture_fstop colimator_name = cam.dof.focus_object.name_full if cam.dof.focus_object is not None else "" sensor_fit_name = cam.sensor_fit sensor_fit = common.SensorFitMode.AUTO if sensor_fit_name == "AUTO": sensor_fit = common.SensorFitMode.AUTO elif sensor_fit_name == "HORIZONTAL": sensor_fit = common.SensorFitMode.HORIZONTAL elif sensor_fit_name == "VERTICAL": sensor_fit = common.SensorFitMode.VERTICAL sensor_width = cam.sensor_width sensor_height = cam.sensor_height path = get_object_path(obj) return (common.encode_string(path) + common.encode_string(obj.name_full) + common.encode_float(focal) + common.encode_float(front_clip_plane) + common.encode_float(far_clip_plane) + common.encode_bool(dof_enabled) + common.encode_float(aperture) + common.encode_string(colimator_name) + common.encode_int(sensor_fit.value) + common.encode_float(sensor_width) + common.encode_float(sensor_height))
def send_grease_pencil_time_offset(client: Client, obj): grease_pencil = obj.data buffer = common.encode_string(grease_pencil.name_full) for modifier in obj.grease_pencil_modifiers: if modifier.type != "GP_TIME": continue offset = modifier.offset scale = modifier.frame_scale custom_range = modifier.use_custom_frame_range frame_start = modifier.frame_start frame_end = modifier.frame_end buffer += (common.encode_int(offset) + common.encode_float(scale) + common.encode_bool(custom_range) + common.encode_int(frame_start) + common.encode_int(frame_end)) client.add_command( common.Command(common.MessageType.GREASE_PENCIL_TIME_OFFSET, buffer, 0)) break
def encode_base_mesh(obj): # Temporary for curves and other objects that support to_mesh() # #todo Implement correct base encoding for these objects mesh_data = obj.data if obj.type == "MESH" else obj.to_mesh() if mesh_data is None: # This happens for empty curves # This is temporary, when curves will be fully implemented we will encode something return bytes() binary_buffer = encode_base_mesh_geometry(mesh_data) # Shape keys # source https://blender.stackexchange.com/questions/111661/creating-shape-keys-using-python if mesh_data.shape_keys is None: binary_buffer += common.encode_int(0) # Indicate 0 key blocks else: logger.debug("Writing %d shape keys", len(mesh_data.shape_keys.key_blocks)) binary_buffer += common.encode_int(len( mesh_data.shape_keys.key_blocks)) # Encode names for key_block in mesh_data.shape_keys.key_blocks: binary_buffer += common.encode_string(key_block.name) # Encode vertex group names for key_block in mesh_data.shape_keys.key_blocks: binary_buffer += common.encode_string(key_block.vertex_group) # Encode relative key names for key_block in mesh_data.shape_keys.key_blocks: binary_buffer += common.encode_string(key_block.relative_key.name) # Encode data shape_keys_buffer = [] fmt_str = "" for key_block in mesh_data.shape_keys.key_blocks: shape_keys_buffer.extend( (key_block.mute, key_block.value, key_block.slider_min, key_block.slider_max, len(key_block.data))) fmt_str += f"1I1f1f1f1I{(3 * len(key_block.data))}f" for i in range(len(key_block.data)): shape_keys_buffer.extend(key_block.data[i].co) binary_buffer += struct.pack(f"{fmt_str}", *shape_keys_buffer) binary_buffer += common.encode_bool(mesh_data.shape_keys.use_relative) # Vertex Groups verts_per_group = {} for vertex_group in obj.vertex_groups: verts_per_group[vertex_group.index] = [] for vert in mesh_data.vertices: for vg in vert.groups: verts_per_group[vg.group].append((vert.index, vg.weight)) binary_buffer += common.encode_int(len(obj.vertex_groups)) for vertex_group in obj.vertex_groups: binary_buffer += common.encode_string(vertex_group.name) binary_buffer += common.encode_bool(vertex_group.lock_weight) binary_buffer += common.encode_int( len(verts_per_group[vertex_group.index])) for vg_elmt in verts_per_group[vertex_group.index]: binary_buffer += common.encode_int(vg_elmt[0]) binary_buffer += common.encode_float(vg_elmt[1]) # Normals binary_buffer += common.encode_bool(mesh_data.use_auto_smooth) binary_buffer += common.encode_float(mesh_data.auto_smooth_angle) binary_buffer += common.encode_bool(mesh_data.has_custom_normals) if mesh_data.has_custom_normals: mesh_data.calc_normals_split( ) # Required otherwise all normals are (0, 0, 0) normals = [] for loop in mesh_data.loops: normals.extend((*loop.normal, )) binary_buffer += struct.pack(f"{len(normals)}f", *normals) # UV Maps for uv_layer in mesh_data.uv_layers: binary_buffer += common.encode_string(uv_layer.name) binary_buffer += common.encode_bool(uv_layer.active_render) # Vertex Colors for vertex_colors in mesh_data.vertex_colors: binary_buffer += common.encode_string(vertex_colors.name) binary_buffer += common.encode_bool(vertex_colors.active_render) if obj.type != "MESH": obj.to_mesh_clear() return binary_buffer
def get_material_buffer(client: Client, material): name = material.name_full buffer = common.encode_string(name) principled = None diffuse = None # Get the nodes in the node tree if material.node_tree: nodes = material.node_tree.nodes # Get a principled node if nodes: for n in nodes: if n.type == "BSDF_PRINCIPLED": principled = n break if n.type == "BSDF_DIFFUSE": diffuse = n # principled = next(n for n in nodes if n.type == 'BSDF_PRINCIPLED') if principled is None and diffuse is None: base_color = (0.8, 0.8, 0.8) metallic = 0.0 roughness = 0.5 opacity = 1.0 emission_color = (0.0, 0.0, 0.0) buffer += common.encode_float(opacity) + common.encode_string("") buffer += common.encode_color(base_color) + common.encode_string("") buffer += common.encode_float(metallic) + common.encode_string("") buffer += common.encode_float(roughness) + common.encode_string("") buffer += common.encode_string("") buffer += common.encode_color(emission_color) + common.encode_string("") return buffer elif diffuse: opacity = 1.0 opacity_texture = None metallic = 0.0 metallic_texture = None emission = (0.0, 0.0, 0.0) emission_texture = None # Get the slot for 'base color' # Or principled.inputs[0] base_color = (1.0, 1.0, 1.0) base_color_texture = None base_color_input = diffuse.inputs.get("Color") # Get its default value (not the value from a possible link) if base_color_input: base_color = base_color_input.default_value base_color_texture = client.get_texture(base_color_input) roughness = 1.0 roughness_texture = None roughness_input = diffuse.inputs.get("Roughness") if roughness_input: roughness_texture = client.get_texture(roughness_input) if len(roughness_input.links) == 0: roughness = roughness_input.default_value normal_texture = None norma_input = diffuse.inputs.get("Normal") if norma_input: if len(norma_input.links) == 1: normal_map = norma_input.links[0].from_node if "Color" in normal_map.inputs: color_input = normal_map.inputs["Color"] normal_texture = client.get_texture(color_input) else: opacity = 1.0 opacity_texture = None opacity_input = principled.inputs.get("Transmission") if opacity_input: if len(opacity_input.links) == 1: invert = opacity_input.links[0].from_node if "Color" in invert.inputs: color_input = invert.inputs["Color"] opacity_texture = client.get_texture(color_input) else: opacity = 1.0 - opacity_input.default_value # Get the slot for 'base color' # Or principled.inputs[0] base_color = (1.0, 1.0, 1.0) base_color_texture = None base_color_input = principled.inputs.get("Base Color") # Get its default value (not the value from a possible link) if base_color_input: base_color = base_color_input.default_value base_color_texture = client.get_texture(base_color_input) metallic = 0.0 metallic_texture = None metallic_input = principled.inputs.get("Metallic") if metallic_input: metallic_texture = client.get_texture(metallic_input) if len(metallic_input.links) == 0: metallic = metallic_input.default_value roughness = 1.0 roughness_texture = None roughness_input = principled.inputs.get("Roughness") if roughness_input: roughness_texture = client.get_texture(roughness_input) if len(roughness_input.links) == 0: roughness = roughness_input.default_value normal_texture = None norma_input = principled.inputs.get("Normal") if norma_input: if len(norma_input.links) == 1: normal_map = norma_input.links[0].from_node if "Color" in normal_map.inputs: color_input = normal_map.inputs["Color"] normal_texture = client.get_texture(color_input) emission = (0.0, 0.0, 0.0) emission_texture = None emission_input = principled.inputs.get("Emission") if emission_input: # Get its default value (not the value from a possible link) emission = emission_input.default_value emission_texture = client.get_texture(emission_input) buffer += common.encode_float(opacity) if opacity_texture: buffer += common.encode_string(opacity_texture) else: buffer += common.encode_string("") buffer += common.encode_color(base_color) if base_color_texture: buffer += common.encode_string(base_color_texture) else: buffer += common.encode_string("") buffer += common.encode_float(metallic) if metallic_texture: buffer += common.encode_string(metallic_texture) else: buffer += common.encode_string("") buffer += common.encode_float(roughness) if roughness_texture: buffer += common.encode_string(roughness_texture) else: buffer += common.encode_string("") if normal_texture: buffer += common.encode_string(normal_texture) else: buffer += common.encode_string("") buffer += common.encode_color(emission) if emission_texture: buffer += common.encode_string(emission_texture) else: buffer += common.encode_string("") return buffer