def parse_shape(node, material_dict, shape_id, device, shape_group_dict=None): if node.attrib['type'] == 'obj' or node.attrib['type'] == 'serialized': to_world = torch.eye(4) serialized_shape_id = 0 mat_id = -1 light_intensity = None filename = '' max_smooth_angle = -1 for child in node: if 'name' in child.attrib: if child.attrib['name'] == 'filename': filename = child.attrib['value'] elif child.attrib['name'] == 'toWorld': to_world = parse_transform(child) elif child.attrib['name'] == 'shapeIndex': serialized_shape_id = int(child.attrib['value']) elif child.attrib['name'] == 'maxSmoothAngle': max_smooth_angle = float(child.attrib['value']) if child.tag == 'ref': mat_id = material_dict[child.attrib['id']] elif child.tag == 'emitter': for grandchild in child: if grandchild.attrib['name'] == 'radiance': light_intensity = parse_vector( grandchild.attrib['value']) if light_intensity.shape[0] == 1: light_intensity = torch.tensor(\ [light_intensity[0], light_intensity[0], light_intensity[0]]) if node.attrib['type'] == 'obj': # Load in CPU for rebuild_topology _, mesh_list, _ = pyredner.load_obj(filename, obj_group=False, device=torch.device('cpu')) vertices = mesh_list[0][1].vertices indices = mesh_list[0][1].indices uvs = mesh_list[0][1].uvs normals = mesh_list[0][1].normals uv_indices = mesh_list[0][1].uv_indices normal_indices = mesh_list[0][1].normal_indices else: assert (node.attrib['type'] == 'serialized') mitsuba_tri_mesh = redner.load_serialized(filename, serialized_shape_id) vertices = torch.from_numpy(mitsuba_tri_mesh.vertices) indices = torch.from_numpy(mitsuba_tri_mesh.indices) uvs = torch.from_numpy(mitsuba_tri_mesh.uvs) normals = torch.from_numpy(mitsuba_tri_mesh.normals) if uvs.shape[0] == 0: uvs = None if normals.shape[0] == 0: normals = None uv_indices = None # Serialized doesn't use different indices for UV & normal normal_indices = None # Transform the vertices and normals vertices = torch.cat((vertices, torch.ones(vertices.shape[0], 1)), dim=1) vertices = vertices @ torch.transpose(to_world, 0, 1) vertices = vertices / vertices[:, 3:4] vertices = vertices[:, 0:3].contiguous() if normals is not None: normals = normals @ (torch.inverse(torch.transpose(to_world, 0, 1))[:3, :3]) normals = normals.contiguous() assert (vertices is not None) assert (indices is not None) if max_smooth_angle >= 0: if normals is None: normals = torch.zeros_like(vertices) new_num_vertices = redner.rebuild_topology(\ redner.float_ptr(vertices.data_ptr()), redner.int_ptr(indices.data_ptr()), redner.float_ptr(uvs.data_ptr() if uvs is not None else 0), redner.float_ptr(normals.data_ptr() if normals is not None else 0), redner.int_ptr(uv_indices.data_ptr() if uv_indices is not None else 0), int(vertices.shape[0]), int(indices.shape[0]), max_smooth_angle) print('Rebuilt topology, original vertices size: {}, new vertices size: {}'.format(\ int(vertices.shape[0]), new_num_vertices)) vertices.resize_(new_num_vertices, 3) if uvs is not None: uvs.resize_(new_num_vertices, 2) if normals is not None: normals.resize_(new_num_vertices, 3) lgt = None if light_intensity is not None: lgt = pyredner.AreaLight(shape_id, light_intensity) vertices = vertices.to(device) indices = indices.to(device) if uvs is not None: uvs = uvs.to(device) if normals is not None: normals = normals.to(device) if uv_indices is not None: uv_indices = uv_indices.to(device) if normal_indices is not None: normal_indices = normal_indices.to(device) return pyredner.Shape(vertices, indices, uvs=uvs, normals=normals, uv_indices=uv_indices, normal_indices=normal_indices, material_id=mat_id), lgt elif node.attrib['type'] == 'rectangle': indices = torch.tensor([[0, 2, 1], [1, 2, 3]], dtype=torch.int32) vertices = torch.tensor([[-1.0, -1.0, 0.0], [-1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0, 1.0, 0.0]]) uvs = None normals = None to_world = torch.eye(4) mat_id = -1 light_intensity = None for child in node: if 'name' in child.attrib: if child.attrib['name'] == 'toWorld': to_world = parse_transform(child) if child.tag == 'ref': mat_id = material_dict[child.attrib['id']] elif child.tag == 'emitter': for grandchild in child: if grandchild.attrib['name'] == 'radiance': light_intensity = parse_vector( grandchild.attrib['value']) if light_intensity.shape[0] == 1: light_intensity = torch.tensor(\ [light_intensity[0], light_intensity[0], light_intensity[0]]) # Transform the vertices # Transform the vertices and normals vertices = torch.cat((vertices, torch.ones(vertices.shape[0], 1)), dim=1) vertices = vertices @ torch.transpose(to_world, 0, 1) vertices = vertices / vertices[:, 3:4] vertices = vertices[:, 0:3].contiguous() if normals is not None: normals = normals @ (torch.inverse(torch.transpose(to_world, 0, 1))[:3, :3]) normals = normals.contiguous() assert (vertices is not None) assert (indices is not None) lgt = None if light_intensity is not None: lgt = pyredner.AreaLight(shape_id, light_intensity) vertices = vertices.to(device) indices = indices.to(device) if uvs is not None: uvs = uvs.to(device) if normals is not None: normals = normals.to(device) return pyredner.Shape(vertices, indices, uvs=uvs, normals=normals, material_id=mat_id), lgt # Add instance support # TODO (simply transform & create a new shape now) elif node.attrib['type'] == 'instance': shape = None for child in node: if 'name' in child.attrib: if child.attrib['name'] == 'toWorld': to_world = parse_transform(child) if child.tag == 'ref': shape = shape_group_dict[child.attrib['id']] # transform instance vertices = shape.vertices normals = shape.normals vector1 = torch.ones(vertices.shape[0], 1, device=vertices.device) to_world = to_world.to(vertices.device) vertices = torch.cat((vertices, vector1), dim=1) vertices = vertices @ torch.transpose(to_world, 0, 1) vertices = vertices / vertices[:, 3:4] vertices = vertices[:, 0:3].contiguous() if normals is not None: normals = normals @ (torch.inverse(torch.transpose(to_world, 0, 1))[:3, :3]) normals = normals.contiguous() # assert(vertices is not None) # assert(indices is not None) # lgt = None # if light_intensity is not None: # lgt = pyredner.AreaLight(shape_id, light_intensity) return pyredner.Shape(vertices, shape.indices, uvs=shape.uvs, normals=normals, material_ids=shape.material_id), None else: print('Shape type {} is not supported!'.format(node.attrib['type'])) assert (False)
def parse_shape(node, material_dict, shape_id): if node.attrib['type'] == 'obj' or node.attrib['type'] == 'serialized': to_world = tf.eye(4) serialized_shape_id = 0 mat_id = -1 light_intensity = None filename = '' max_smooth_angle = -1 for child in node: if 'name' in child.attrib: if child.attrib['name'] == 'filename': filename = child.attrib['value'] elif child.attrib['name'] == 'toWorld': to_world = parse_transform(child) elif child.attrib['name'] == 'shapeIndex': serialized_shape_id = int(child.attrib['value']) elif child.attrib['name'] == 'maxSmoothAngle': max_smooth_angle = float(child.attrib['value']) if child.tag == 'ref': mat_id = material_dict[child.attrib['id']] elif child.tag == 'emitter': for grandchild in child: if grandchild.attrib['name'] == 'radiance': light_intensity = parse_vector( grandchild.attrib['value']) if light_intensity.shape[0] == 1: light_intensity = tf.constant([ light_intensity[0], light_intensity[0], light_intensity[0] ]) if node.attrib['type'] == 'obj': _, mesh_list, _ = pyredner.load_obj(filename) # Convert to CPU for rebuild_topology vertices = mesh_list[0][1].vertices.cpu() indices = mesh_list[0][1].indices.cpu() uvs = mesh_list[0][1].uvs normals = mesh_list[0][1].normals uv_indices = mesh_list[0][1].uv_indices normal_indices = mesh_list[0][1].normal_indices if uvs is not None: uvs = uvs.cpu() if normals is not None: normals = normals.cpu() if uv_indices is not None: uv_indices = uv_indices.cpu() else: assert (node.attrib['type'] == 'serialized') mitsuba_tri_mesh = redner.load_serialized(filename, serialized_shape_id) vertices = tf.convert_to_tensor(mitsuba_tri_mesh.vertices) indices = tf.convert_to_tensor(mitsuba_tri_mesh.indices) uvs = tf.convert_to_tensor(mitsuba_tri_mesh.uvs) normals = tf.convert_to_tensor(mitsuba_tri_mesh.normals) if uvs.shape[0] == 0: uvs = None if normals.shape[0] == 0: normals = None # Transform the vertices and normals vertices = tf.concat( (vertices, tf.ones([vertices.shape[0], 1], dtype=tf.float32)), axis=1) vertices = vertices @ tf.transpose(to_world, [0, 1]) vertices = vertices / vertices[:, 3:4] vertices = vertices[:, 0:3] if normals is not None: normals = normals @ (tf.linalg.inv(tf.transpose(to_world, [0, 1]))[:3, :3]) assert (vertices is not None) assert (indices is not None) if max_smooth_angle >= 0: if normals is None: normals = tf.zeros_like(vertices) new_num_vertices = redner.rebuild_topology(\ redner.float_ptr(pyredner.data_ptr(vertices)), redner.int_ptr(pyredner.data_ptr(indices)), redner.float_ptr(pyredner.data_ptr(uvs) if uvs is not None else 0), redner.float_ptr(pyredner.data_ptr(normals) if normals is not None else 0), redner.int_ptr(pyredner.data_ptr(uv_indices) if uv_indices is not None else 0), int(vertices.shape[0]), int(indices.shape[0]), max_smooth_angle) print('Rebuilt topology, original vertices size: {}, new vertices size: {}'.format(\ int(vertices.shape[0]), new_num_vertices)) vertices.resize_(new_num_vertices, 3) if uvs is not None: uvs.resize_(new_num_vertices, 2) if normals is not None: normals.resize_(new_num_vertices, 3) lgt = None if light_intensity is not None: lgt = pyredner.AreaLight(shape_id, light_intensity) return pyredner.Shape(vertices=vertices, indices=indices, uvs=uvs, normals=normals, material_id=mat_id), lgt elif node.attrib['type'] == 'rectangle': indices = tf.constant([[0, 2, 1], [1, 2, 3]], dtype=tf.int32) vertices = tf.constant([[-1.0, -1.0, 0.0], [-1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0, 1.0, 0.0]]) uvs = None normals = None to_world = tf.eye(4) mat_id = -1 light_intensity = None for child in node: if 'name' in child.attrib: if child.attrib['name'] == 'toWorld': to_world = parse_transform(child) if child.tag == 'ref': mat_id = material_dict[child.attrib['id']] elif child.tag == 'emitter': for grandchild in child: if grandchild.attrib['name'] == 'radiance': light_intensity = parse_vector( grandchild.attrib['value']) if light_intensity.shape[0] == 1: light_intensity = tf.constant([ light_intensity[0], light_intensity[0], light_intensity[0] ]) # Transform the vertices and normals vertices = tf.concat( (vertices, tf.convert_to_tensor(np.ones(vertices.shape[0], 1), dtype=tf.float32)), axis=1) vertices = vertices @ tf.transpose(to_world, [0, 1]) vertices = vertices / vertices[:, 3:4] vertices = vertices[:, 0:3] if normals is not None: normals = normals @ (tf.linalg.inv(tf.transpose(to_world, [0, 1]))[:3, :3]) assert (vertices is not None) assert (indices is not None) lgt = None if light_intensity is not None: lgt = pyrender.Light(shape_id, light_intensity) return pyredner.Shape(vertices=vertices, indices=indices, uvs=uvs, normals=normals, material_id=mat_id), lgt else: assert (False)