Genesis icon indicating copy to clipboard operation
Genesis copied to clipboard

请求在生成地形的时候,取消使用open3d的convert_heightfield_to_watertight_trimesh函数来进行简化。

Open Huisouan opened this issue 1 year ago • 0 comments

在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

`

Huisouan avatar Jan 07 '25 07:01 Huisouan