Genesis
Genesis copied to clipboard
请求在生成地形的时候,取消使用open3d的convert_heightfield_to_watertight_trimesh函数来进行简化。
在genesis生成复杂地形的时候,convert_heightfield_to_watertight_trimesh函数里面使用了open3d的simplify_quadric_decimation对mesh进行简化。然而这个函数在计算上可能有一定的问题,请看如下链接:simplify_quadric_decimation works horrible #2581
是否可以先暂时不要使用这个简化,直接使用sdf_mesh。
def convert_heightfield_to_watertight_trimesh(height_field_raw, horizontal_scale, vertical_scale, slope_threshold=None): """ Adapted from Issac Gym'sconvert_heightfield_to_trimesh` function.
Convert a heightfield array to a triangle mesh represented by vertices and triangles.
Optionally, corrects vertical surfaces above the provide slope threshold:
If (y2-y1)/(x2-x1) > slope_threshold -> Move A to A' (set x1 = x2). Do this for all directions.
B(x2,y2)
/|
/ |
/ |
(x1,y1)A---A'(x2',y1)
Parameters:
height_field_raw (np.array): input heightfield
horizontal_scale (float): horizontal scale of the heightfield [meters]
vertical_scale (float): vertical scale of the heightfield [meters]
slope_threshold (float): the slope threshold above which surfaces are made vertical. If None no correction is applied (default: None)
Returns:
vertices (np.array(float)): array of shape (num_vertices, 3). Each row represents the location of each vertex [meters]
triangles (np.array(int)): array of shape (num_triangles, 3). Each row represents the indices of the 3 vertices connected by this triangle.
"""
hf = height_field_raw
num_rows = hf.shape[0]
num_cols = hf.shape[1]
y = np.linspace(0, (num_cols - 1) * horizontal_scale, num_cols)
x = np.linspace(0, (num_rows - 1) * horizontal_scale, num_rows)
yy, xx = np.meshgrid(y, x)
if slope_threshold is not None:
assert False # our sdf representation doesn't support steep slopes well
slope_threshold *= horizontal_scale / vertical_scale
move_x = np.zeros((num_rows, num_cols))
move_y = np.zeros((num_rows, num_cols))
move_corners = np.zeros((num_rows, num_cols))
move_x[: num_rows - 1, :] += hf[1:num_rows, :] - hf[: num_rows - 1, :] > slope_threshold
move_x[1:num_rows, :] -= hf[: num_rows - 1, :] - hf[1:num_rows, :] > slope_threshold
move_y[:, : num_cols - 1] += hf[:, 1:num_cols] - hf[:, : num_cols - 1] > slope_threshold
move_y[:, 1:num_cols] -= hf[:, : num_cols - 1] - hf[:, 1:num_cols] > slope_threshold
move_corners[: num_rows - 1, : num_cols - 1] += (
hf[1:num_rows, 1:num_cols] - hf[: num_rows - 1, : num_cols - 1] > slope_threshold
)
move_corners[1:num_rows, 1:num_cols] -= (
hf[: num_rows - 1, : num_cols - 1] - hf[1:num_rows, 1:num_cols] > slope_threshold
)
xx += (move_x + move_corners * (move_x == 0)) * horizontal_scale
yy += (move_y + move_corners * (move_y == 0)) * horizontal_scale
# create triangle mesh vertices and triangles from the heightfield grid
vertices_top = np.zeros((num_rows * num_cols, 3), dtype=np.float32)
vertices_top[:, 0] = xx.flatten()
vertices_top[:, 1] = yy.flatten()
vertices_top[:, 2] = hf.flatten() * vertical_scale
triangles_top = -np.ones((2 * (num_rows - 1) * (num_cols - 1), 3), dtype=np.uint32)
for i in range(num_rows - 1):
ind0 = np.arange(0, num_cols - 1) + i * num_cols
ind1 = ind0 + 1
ind2 = ind0 + num_cols
ind3 = ind2 + 1
start = 2 * i * (num_cols - 1)
stop = start + 2 * (num_cols - 1)
triangles_top[start:stop:2, 0] = ind0
triangles_top[start:stop:2, 1] = ind3
triangles_top[start:stop:2, 2] = ind1
triangles_top[start + 1 : stop : 2, 0] = ind0
triangles_top[start + 1 : stop : 2, 1] = ind2
triangles_top[start + 1 : stop : 2, 2] = ind3
# bottom plane
z_min = np.min(vertices_top[:, 2]) - 1.0
vertices_bottom = np.zeros((num_rows * num_cols, 3), dtype=np.float32)
vertices_bottom[:, 0] = xx.flatten()
vertices_bottom[:, 1] = yy.flatten()
vertices_bottom[:, 2] = z_min
triangles_bottom = -np.ones((2 * (num_rows - 1) * (num_cols - 1), 3), dtype=np.uint32)
for i in range(num_rows - 1):
ind0 = np.arange(0, num_cols - 1) + i * num_cols
ind1 = ind0 + 1
ind2 = ind0 + num_cols
ind3 = ind2 + 1
start = 2 * i * (num_cols - 1)
stop = start + 2 * (num_cols - 1)
triangles_bottom[start:stop:2, 0] = ind0
triangles_bottom[start:stop:2, 2] = ind3
triangles_bottom[start:stop:2, 1] = ind1
triangles_bottom[start + 1 : stop : 2, 0] = ind0
triangles_bottom[start + 1 : stop : 2, 2] = ind2
triangles_bottom[start + 1 : stop : 2, 1] = ind3
triangles_bottom += num_rows * num_cols
# side face
triangles_side_0 = np.zeros([2 * (num_rows - 1), 3], dtype=np.uint32)
for i in range(num_rows - 1):
ind0 = i * num_cols
ind1 = (i + 1) * num_cols
ind2 = ind0 + num_rows * num_cols
ind3 = ind1 + num_rows * num_cols
triangles_side_0[2 * i] = [ind0, ind2, ind1]
triangles_side_0[2 * i + 1] = [ind1, ind2, ind3]
triangles_side_1 = np.zeros([2 * (num_cols - 1), 3], dtype=np.uint32)
for i in range(num_cols - 1):
ind0 = i
ind1 = i + 1
ind2 = ind0 + num_rows * num_cols
ind3 = ind1 + num_rows * num_cols
triangles_side_1[2 * i] = [ind0, ind1, ind2]
triangles_side_1[2 * i + 1] = [ind1, ind3, ind2]
triangles_side_2 = np.zeros([2 * (num_rows - 1), 3], dtype=np.uint32)
for i in range(num_rows - 1):
ind0 = i * num_cols + num_cols - 1
ind1 = (i + 1) * num_cols + num_cols - 1
ind2 = ind0 + num_rows * num_cols
ind3 = ind1 + num_rows * num_cols
triangles_side_2[2 * i] = [ind0, ind1, ind2]
triangles_side_2[2 * i + 1] = [ind1, ind3, ind2]
triangles_side_3 = np.zeros([2 * (num_cols - 1), 3], dtype=np.uint32)
for i in range(num_cols - 1):
ind0 = i + (num_rows - 1) * num_cols
ind1 = i + 1 + (num_rows - 1) * num_cols
ind2 = ind0 + num_rows * num_cols
ind3 = ind1 + num_rows * num_cols
triangles_side_3[2 * i] = [ind0, ind2, ind1]
triangles_side_3[2 * i + 1] = [ind1, ind2, ind3]
vertices = np.concatenate([vertices_top, vertices_bottom], axis=0)
triangles = np.concatenate(
[triangles_top, triangles_bottom, triangles_side_0, triangles_side_1, triangles_side_2, triangles_side_3],
axis=0,
)
# This a uniformly-distributed full mesh, which gives faster sdf generation
sdf_mesh = trimesh.Trimesh(vertices, triangles, process=False)
# This is the mesh used for non-sdf purposes. It's losslessly simplified from the full mesh, to save memory cost for storing verts and faces
#mesh = sdf_mesh.simplify_quadric_decimation(face_count=0, maximum_error=0.0)
return sdf_mesh, sdf_mesh
`