Ursina开发Minecraft删除Mesh顶点调用Mesh.generate()报错求助
问题
用Ursina开发Minecraft,手动通过添加顶点构建Chunk的Mesh,但删除顶点后调用Mesh.generate()触发错误。以下是测试代码及报错信息:
测试代码
from ursina import * from ursina.shaders import basic_lighting_shader, lit_with_shadows_shader from ursina.prefabs.first_person_controller import FirstPersonController app = Ursina() bte = Entity(model='block.obj',color=color.rgba(1,1,0,0.4),visible=False) bte.scale=1.1 bte.origin_y+=0.05 sun = DirectionalLight(rotation=Vec3(45, 45, 45)) vertices = [# 底面 [0, 0, 0], #0 [0, 0, 1], #1 [1, 0, 1], #2 [1, 0, 1], #3 [1, 0, 0], #4 [0, 0, 0], #5 # 顶面 [0, 1, 0], #0 [1, 1, 0], #1 [1, 1, 1], #2 [1, 1, 1], #3 [0, 1, 1], #4 [0, 1, 0], #5 # 左面 [0, 0, 0], #0 [0, 1, 0], #1 [0, 1, 1], #2 [0, 1, 1], #3 [0, 0, 1], #4 [0, 0, 0], #5 # 右面 [1, 0, 0], #0 [1, 0, 1], #1 [1, 1, 1], #2 [1, 1, 1], #3 [1, 1, 0], #4 [1, 0, 0], #5 # 前面 [0, 0, 0], #0 [1, 0, 0], #1 [1, 1, 0], #2 [1, 1, 0], #3 [0, 1, 0], #4 [0, 0, 0], #5 # 后面 [0, 0, 1], #0 [0, 1, 1], #1 [1, 1, 1], #2 [1, 1, 1], #3 [1, 0, 1], #4 [0, 0, 1], #5 ] normals = [[-1 if number == 0 else number for number in sublist] for sublist in vertices] amesh = Mesh() amesh.normals.extend(normals) amesh.uvs.extend([[0,0], [0,1], [1,1], [1,1], [1,0], [0,0], # 底面 [0,0], [1,0], [1,1], [1,1], [0,1], [0,0], # 顶面 [0,0], [0,1], [1,1], [1,1], [1,0], [0,0], # 左面 [0,0], [1,0], [1,1], [1,1], [0,1], [0,0], # 右面 [0,0], [1,0], [1,1], [1,1], [0,1], [0,0], # 前面 [0,0], [0,1], [1,1], [1,1], [1,0], [0,0], # 后面 ]) amesh.vertices.extend(vertices) amesh.vertices.remove([0, 0, 0]) amesh.generate()
报错信息(翻译后)
:prc(警告): 配置变量win-size的整数值无效: 864.0 :prc(警告): 配置变量win-size的整数值无效: 1536.0 已知管道类型: wglGraphicsPipe (3个辅助显示模块尚未加载。) 设置窗口位置: Vec2(192, 108) :prc(警告): 将配置变量paste-emit-keystrokes的默认值从'1'改为'0'。 :pnmimage:png(警告): iCCP: 已知不正确的sRGB配置文件 package_folder: D:\MiniConda\Lib\site-packages\ursina asset_folder: d:\Downloads\myCode\Python\小游戏\Minecraft-Ursina-2.0 读取obj文件路径: d:\Downloads\myCode\Python\小游戏\Minecraft-Ursina-2.0\assets\block.obj 保存.bam文件到: d:\Downloads\myCode\Python\小游戏\Minecraft-Ursina-2.0\models_compressed\block.bam 断言失败: (num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0 位于c:\buildslave\sdk-windows-amd64\build\panda\src\gobj\geomPrimitive.cxx第388行 回溯(最近的调用最后): 文件 "d:\Downloads\myCode\Python\小游戏\Minecraft-Ursina-2.0\test.py", 第75行, in <module> amesh.generate() 文件 "D:\MiniConda\Lib\site-packages\ursina\mesh.py", 第139行, in generate prim.close_primitive() AssertionError: (num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0 位于c:\buildslave\sdk-windows-amd64\build\panda\src\gobj\geomPrimitive.cxx第388行
解决方案
错误原因
- 数据不匹配:Mesh的
vertices、normals、uvs三个列表是严格一一对应的,每个顶点必须对应一个法线和UV坐标。你只删除了vertices中的一个元素,却没有同步删除normals和uvs中对应的元素,导致三者长度不一致。 - 顶点数不符合要求:Ursina默认用三角形绘制Mesh,顶点总数必须是3的倍数(每个三角形3个顶点)。你删除1个顶点后,总数不再是3的倍数,触发了底层Panda3D的断言检查。
- 删除操作不彻底:
list.remove([0,0,0])只会删除列表中第一个匹配的元素,而你的原始顶点列表中有多个[0,0,0],这种删除方式逻辑混乱,无法精准控制要移除的面或顶点。
修复步骤
- 同步修改所有关联数据:如果要删除顶点,必须同时从
vertices、normals、uvs中删除对应位置的元素,保证三者长度一致。 - 保证顶点数为3的倍数:每次修改后检查顶点总数,确保能被3整除(因为每个三角形需要3个顶点)。
- 提前构建正确的顶点列表:更高效的方式是在构建原始
vertices、normals、uvs时,就只保留需要的面/顶点,而不是先添加全部再删除。
示例修改
比如要移除底面的所有顶点,直接在原始列表中删除底面对应的6个顶点,同时同步删除法线和UV的对应部分:
# 移除底面的顶点、法线、UV del vertices[:6] del normals[:6] del amesh.uvs[:6] # 再将处理后的列表添加到Mesh amesh.vertices.extend(vertices) amesh.normals.extend(normals) amesh.uvs.extend(uvs) amesh.generate()
内容的提问来源于stack exchange,提问作者麦格麦格
相关产品推荐
相关产品推荐

