如何在Python的Panda3D引擎中创建三维几何形状及建筑基元?
在Panda3D中创建几何形状方案
一、内置简单几何形状
Panda3D自带基础几何体的预制模型,直接通过loader.loadModel()加载即可,无需手动构建顶点:
from direct.showbase.ShowBase import ShowBase class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # 加载立方体 cube = self.loader.loadModel("models/primitives/box") cube.reparentTo(self.render) cube.setPos(0, 5, 0) # 加载金字塔 pyramid = self.loader.loadModel("models/primitives/pyramid") pyramid.reparentTo(self.render) pyramid.setPos(-2, 5, 0) # 平行六面体:通过非均匀缩放立方体实现 parallelepiped = self.loader.loadModel("models/primitives/box") parallelepiped.reparentTo(self.render) parallelepiped.setPos(2, 5, 0) parallelepiped.setScale(1.5, 0.8, 1) app = MyApp() app.run()
二、自定义多边形基底的建筑基元
对于基底为任意多边形、墙体垂直于基底平面的结构,需要手动构建顶点和面:
核心步骤
- 定义基底顶点(按顺时针/逆时针顺序排列,示例用XY平面)
- 生成顶面顶点(将基底顶点沿Z轴拉伸指定高度)
- 三角化基底和顶面(Panda3D的Geom优先支持三角形面)
- 生成墙体:将相邻基底顶点与对应顶面顶点组成四边形,再拆分为两个三角形
- 将所有面组合为Geom,通过GeomNode生成NodePath加入场景
代码示例(五边形基底建筑)
from direct.showbase.ShowBase import ShowBase from panda3d.core import ( GeomVertexArrayFormat, GeomVertexFormat, GeomVertexData, Geom, GeomTriangles, GeomNode, Vec3, DirectionalLight, LVector3 ) class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # 1. 定义基底顶点(XY平面,顺时针顺序) base_verts = [ Vec3(0, 0, 0), Vec3(1, 0, 0), Vec3(1.5, 1, 0), Vec3(0.5, 2, 0), Vec3(-0.5, 1, 0) ] building_height = 2.0 # 2. 创建顶点格式(包含位置和法线,用于光照计算) array_format = GeomVertexArrayFormat() array_format.add_column("vertex", 3, Geom.NT_float32, Geom.C_point) array_format.add_column("normal", 3, Geom.NT_float32, Geom.C_normal) vert_format = GeomVertexFormat.register_format(GeomVertexFormat().add_array(array_format)) # 3. 填充顶点数据 vdata = GeomVertexData("building_data", vert_format, Geom.UH_static) v_writer = GeomVertexWriter(vdata, "vertex") n_writer = GeomVertexWriter(vdata, "normal") # 添加底面顶点和法线 for v in base_verts: v_writer.add_data3(v) n_writer.add_data3(0, 0, -1) # 底面法线向下 # 添加顶面顶点和法线 top_verts = [v + Vec3(0, 0, building_height) for v in base_verts] for v in top_verts: v_writer.add_data3(v) n_writer.add_data3(0, 0, 1) # 顶面法线向上 # 4. 构建几何体的面 geom = Geom(vdata) num_base_verts = len(base_verts) top_offset = num_base_verts # 三角化底面 base_tris = GeomTriangles(Geom.UH_static) for i in range(1, num_base_verts - 1): base_tris.add_vertices(0, i, i + 1) geom.add_primitive(base_tris) # 三角化顶面 top_tris = GeomTriangles(Geom.UH_static) for i in range(1, num_base_verts - 1): top_tris.add_vertices(top_offset, top_offset + i, top_offset + i + 1) geom.add_primitive(top_tris) # 生成墙体(每个相邻顶点对拆成两个三角形) wall_tris = GeomTriangles(Geom.UH_static) for i in range(num_base_verts): curr_base = i next_base = (i + 1) % num_base_verts curr_top = curr_base + top_offset next_top = next_base + top_offset # 第一个三角形 wall_tris.add_vertices(curr_base, next_base, curr_top) # 第二个三角形 wall_tris.add_vertices(next_base, next_top, curr_top) # 计算墙面法线(可选,提升光照效果) edge = base_verts[next_base] - base_verts[curr_base] normal = edge.cross(Vec3(0,0,1)).normalized() # 注:若要精细化法线,需给墙体每个顶点单独设置,此处简化处理 geom.add_primitive(wall_tris) # 5. 添加到场景 geom_node = GeomNode("building_node") geom_node.add_geom(geom) building_np = self.render.attach_new_node(geom_node) building_np.setPos(-1, 5, 0) # 添加方向光,让几何体可见 light_node = self.render.attach_new_node(DirectionalLight("sun")) light_node.node().set_direction(LVector3(-5, 5, -7)) self.render.set_light(light_node) app = MyApp() app.run()
三、NodePath快速理解
NodePath是操作场景对象的核心工具,可视为场景节点的操作句柄:
- 所有可见对象必须挂载到
render根节点下,用reparentTo(self.render)或attach_new_node()实现 - 常用操作:
setPos(x, y, z):设置对象位置setHpr(h, p, r):设置旋转(航向、俯仰、滚转)setScale(sx, sy, sz):缩放对象attach_new_node(node):创建并挂载新节点到当前NodePath下
内容的提问来源于stack exchange,提问作者ЧАС
相关产品推荐
相关产品推荐

