实用指南:Godot 城市模拟 – 003 根据不规则底面和高度,动态创建节点

news/2025/10/17 22:50:33/文章来源:https://www.cnblogs.com/tlnshuju/p/19148975

实用指南:Godot 城市模拟 – 003 根据不规则底面和高度,动态创建节点

2025-10-17 22:48  tlnshuju  阅读(0)  评论(0)    收藏  举报

下面我将详细分解这段代码的每个步骤,展示如何在 Godot 引擎中从零开始创建一个不规则棱柱体并实现旋转动画:

步骤1:设置场景基础结构

extends Node3D  # 继承自3D场景节点
var prism_mesh_instance: MeshInstance3D  # 声明棱柱体网格实例变量
  • 脚本继承自 Node3D,这是所有3D场景的基类
  • 声明一个 MeshInstance3D 类型的变量,用于存储创建的棱柱体

步骤2:初始化场景 (_ready 函数)

func _ready() -> void:# 定义底面多边形的5个顶点坐标var base_points = [Vector3(-3, 0, -2),  # 点1 (X, Y, Z)Vector3(2, 0, -3),   # 点2Vector3(4, 0, 1),    # 点3Vector3(1, 0, 4),    # 点4Vector3(-2, 0, 3)    # 点5]# 设置棱柱体的高度var height = 2.5# 调用创建棱柱体的核心函数create_prism_from_base_and_height(base_points, height)
  • 在场景加载时自动执行
  • 定义了一个不规则五边形的底面顶点坐标(所有Y值为0,位于XZ平面)
  • 设置棱柱体的高度为2.5个单位
  • 调用核心函数创建棱柱体

步骤3:创建棱柱体核心函数

3.1 验证输入和准备数据

func create_prism_from_base_and_height(base_points: Array, height: float) -> void:# 验证输入是否有效(至少3个点才能构成多边形)if base_points.size() < 3:print("错误:至少需要3个点来构成多边形")returnvar point_count = base_points.size()var prism_points = []  # 存储所有顶点(底面+顶面)
  • 检查底面点数是否足够(至少3个点)
  • 获取底面点数
  • 初始化顶点数组

3.2 计算顶点位置

    # 添加底面顶点for i in range(point_count):prism_points.append(base_points[i])# 添加顶面顶点(底面顶点+Y方向偏移)for i in range(point_count):var top_point = base_points[i] + Vector3(0, height, 0)prism_points.append(top_point)
  • 首先添加所有底面顶点
  • 然后添加顶面顶点(每个底面顶点沿Y轴向上偏移高度值)

3.3 使用 SurfaceTool 创建网格

    # 初始化SurfaceToolvar surface_tool = SurfaceTool.new()surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
  • 创建 SurfaceTool 实例,用于动态生成网格
  • 指定网格使用三角形图元

3.4 创建底面

    # 计算底面中心点(用于三角剖分)var bottom_center = Vector3.ZEROfor point in base_points:bottom_center += pointbottom_center /= point_countbottom_center.y = 0  # 确保在底面平面上# 创建底面三角形(扇形三角剖分)for i in range(point_count):var next_i = (i + 1) % point_countsurface_tool.add_vertex(bottom_center)        # 中心点surface_tool.add_vertex(prism_points[i])      # 当前点surface_tool.add_vertex(prism_points[next_i]) # 下一个点
  • 计算底面多边形的中心点(所有顶点的平均值)
  • 使用扇形三角剖分创建底面:
    • 从中心点出发
    • 连接相邻顶点形成三角形

3.5 创建顶面

    # 计算顶面中心点var top_center = bottom_center + Vector3(0, height, 0)var top_start = point_count  # 顶面顶点起始索引# 创建顶面三角形(类似底面)for i in range(point_count):var next_i = (i + 1) % point_countsurface_tool.add_vertex(top_center)                  # 顶部中心点surface_tool.add_vertex(prism_points[top_start + i]) # 当前顶部点surface_tool.add_vertex(prism_points[top_start + next_i]) # 下一个顶部点
  • 顶面中心点是底面中心点沿Y轴偏移高度值
  • 使用相同的扇形三角剖分方法创建顶面

3.6 创建侧面

    # 创建侧面(四边形分解为两个三角形)for i in range(point_count):var next_i = (i + 1) % point_count# 第一个三角形surface_tool.add_vertex(prism_points[i])                   # 底部当前点surface_tool.add_vertex(prism_points[top_start + i])        # 顶部当前点surface_tool.add_vertex(prism_points[next_i])               # 底部下一个点# 第二个三角形surface_tool.add_vertex(prism_points[next_i])               # 底部下一个点surface_tool.add_vertex(prism_points[top_start + i])        # 顶部当前点surface_tool.add_vertex(prism_points[top_start + next_i])   # 顶部下一个点
  • 每个侧面由四边形组成
  • 每个四边形被分解为两个三角形:
    1. 底部点A → 顶部点A → 底部点B
    2. 底部点B → 顶部点A → 顶部点B
  • 确保所有三角形顶点顺序为逆时针(保证法线方向正确)

3.7 生成网格和材质

    # 生成法线(用于光照计算)surface_tool.generate_normals()# 提交网格数据var array_mesh = surface_tool.commit()# 创建网格实例prism_mesh_instance = MeshInstance3D.new()prism_mesh_instance.mesh = array_mesh# 创建材质var material = StandardMaterial3D.new()material.albedo_color = Color(0.2, 0.6, 0.8)  # 蓝色material.cull_mode = BaseMaterial3D.CULL_DISABLED  # 禁用背面剔除prism_mesh_instance.material_override = material# 添加到场景add_child(prism_mesh_instance)
  • 自动生成顶点法线(使光照效果正确)
  • 提交网格数据生成 ArrayMesh
  • 创建 MeshInstance3D 节点并设置网格
  • 创建蓝色材质并禁用背面剔除(保证从内部也能看到)
  • 将棱柱体添加到场景中

3.8 设置摄像机视角

    # 定位摄像机$Camera3D.position = Vector3(0, 10, 10)  # 摄像机位置(斜上方)$Camera3D.look_at(prism_mesh_instance.position)  # 看向棱柱体中心
  • 将摄像机放置在 (0, 10, 10) 位置
  • 让摄像机看向棱柱体中心点 (0, 0, 0)

步骤4:实现旋转动画 (_process 函数)

func _process(delta: float) -> void:if prism_mesh_instance:# 每秒绕Y轴旋转30度prism_mesh_instance.rotate_y(deg_to_rad(30) * delta)
  • 每帧执行一次
  • 检查棱柱体是否已创建
  • 使用 rotate_y() 方法绕Y轴旋转
  • deg_to_rad(30) 将角度转换为弧度
  • 乘以 delta 保证旋转速度与帧率无关

最终效果

当运行此代码时:

  1. 场景初始化时创建一个不规则五边形底面的棱柱体
  2. 棱柱体呈现蓝色,禁用背面剔除
  3. 摄像机从斜上方 (0,10,10) 位置看向棱柱体中心
  4. 棱柱体以每秒30度的速度绕Y轴匀速旋转

完整代码

extends Node3D
var prism_mesh_instance: MeshInstance3D
func _ready() -> void:
# Called when the node enters the scene tree for the first time.var base_points = [Vector3(-3, 0, -2),  # 点1Vector3(2, 0, -3),   # 点2Vector3(4, 0, 1),    # 点3Vector3(1, 0, 4),    # 点4Vector3(-2, 0, 3)    # 点5]# 棱柱体高度var height = 2.5# 调用函数创建棱柱体create_prism_from_base_and_height(base_points, height)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:if prism_mesh_instance:# 绕y轴旋转,每秒旋转30度prism_mesh_instance.rotate_y(deg_to_rad(30) * delta)
# 根据任意多边形底面和高度创建棱柱体
func create_prism_from_base_and_height(base_points: Array, height: float) -> void:# 验证输入if base_points.size() < 3:print("错误:至少需要3个点来构成多边形")returnvar point_count = base_points.size()# 计算棱柱体的所有顶点var prism_points = []# 底部点(底面多边形)for i in range(point_count):prism_points.append(base_points[i])# 顶部点(底面多边形加上高度)for i in range(point_count):var top_point = base_points[i] + Vector3(0, height, 0)prism_points.append(top_point)# 使用SurfaceTool创建棱柱体var surface_tool = SurfaceTool.new()surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)# 创建底面(多边形三角剖分 - 使用扇形三角剖分)var bottom_center = Vector3.ZEROfor point in base_points:bottom_center += pointbottom_center /= point_countbottom_center.y = 0  # 确保在底面平面上for i in range(point_count):var next_i = (i + 1) % point_countsurface_tool.add_vertex(bottom_center)          # 中心点surface_tool.add_vertex(prism_points[i])        # 当前点surface_tool.add_vertex(prism_points[next_i])   # 下一个点# 创建顶面(多边形三角剖分 - 使用扇形三角剖分)var top_start = point_countvar top_center = bottom_center + Vector3(0, height, 0)for i in range(point_count):var next_i = (i + 1) % point_countsurface_tool.add_vertex(top_center)                         # 顶部中心点surface_tool.add_vertex(prism_points[top_start + i])        # 当前顶部点surface_tool.add_vertex(prism_points[top_start + next_i])   # 下一个顶部点# 创建侧面(连接底部和顶部的四边形面)for i in range(point_count):var next_i = (i + 1) % point_count  # 下一个点的索引(循环)# 侧面四边形分解为两个三角形# 第一个三角形(逆时针顺序)surface_tool.add_vertex(prism_points[i])                    # 底部当前点surface_tool.add_vertex(prism_points[top_start + i])       # 顶部当前点surface_tool.add_vertex(prism_points[next_i])              # 底部下一个点# 第二个三角形(逆时针顺序)surface_tool.add_vertex(prism_points[next_i])              # 底部下一个点surface_tool.add_vertex(prism_points[top_start + i])       # 顶部当前点surface_tool.add_vertex(prism_points[top_start + next_i])  # 顶部下一个点surface_tool.generate_normals()# 生成网格var array_mesh = surface_tool.commit()# 创建节点和材质prism_mesh_instance = MeshInstance3D.new()prism_mesh_instance.mesh = array_meshvar material = StandardMaterial3D.new()material.albedo_color = Color(0.2, 0.6, 0.8)  # 蓝色material.cull_mode = BaseMaterial3D.CULL_DISABLED  # 禁用背面剔除prism_mesh_instance.material_override = materialadd_child(prism_mesh_instance)print("基于不规则多边形底面创建棱柱体完成!点数:", point_count)$Camera3D.position = Vector3(0,10,10)$Camera3D.look_at(prism_mesh_instance.position)

文章来源于:小武的开发空间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/939218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 中断处理

目录背景和价值一、什么时候需要发起中断?1. 用户主动取消操作2. 程序优雅关闭时终止后台线程3. 超时任务处理4. 协作式终止长期运行的任务二、中断异常(InterruptedException)的处理正确的处理方式:1. 如果线程可…

软件工程学习日志2025.10.17

今天深入复习了BP(Backpropagation)神经网络,作为深度学习的基础,其“前馈计算误差,反向传播梯度”的思想贯穿现代许多复杂模型。记录关键点以备回顾:核心思想:双向流动的信息• 前向传播:数据从输入层经隐藏层…

天黑了,睡觉

大家好,晚安啦,拜拜。

升鲜宝生鲜配送供应链管理系统---- 门店收银 POS 离线工作设计文档(支持线上线下一体化)---02

门店收银 POS 离线工作设计文档(支持线上线下一体化)📘 背景与目标 在门店运营中,POS 端(收银机/安卓终端)经常会遇到以下情况: • 网络中断(Wi-Fi、4G、服务器不可达); • 临时维护或总部系统升级; • 云…

2025.10.16NOIP模拟

T1.略 T2.略 T3.思路简单,细节出锅 注意:线段树左右端点有负数时,不要用(l+r)/2,应用(l+r)>>1 T4. n行m列的网格,每个格子有一个权值\(v_{i,j}\)(\(-1e9<=v_{i,j}<=1e9\))和一个指示方向,假设起点为\…

Python 基于Python开发的数据库同步检测工具

程序源码下载地址 https://gitee.com/ishouke/database-checker 数据库同步检测工具 适用环境 win11 Centos7 工具用途 同类型数据库比对,比较库,库表,库模式(针对opengauss)是否一致,比较库表记录数是否一致。 目…

Python 基于Python开发的数据库同步检测工具

程序源码下载地址 https://gitee.com/ishouke/database-checker 数据库同步检测工具 适用环境 win11 Centos7 工具用途 同类型数据库比对,比较库,库表,库模式(针对opengauss)是否一致,比较库表记录数是否一致。 目…

当AI学会进化:荣耀与用户的“共生式成长”新范式

「 在科技与人文的交汇处,荣耀始终坚信,真正的创新不应仅是参数的堆叠,更应是一场关于“人”的深刻对话。 」荣耀CEO李健反复提及“灵魂马车”哲学,将对人的关爱、智慧的激发与快乐的传递融为一体,这一理念正悄然…

VSCode的下载安装以及配置

一、下载VSCode 1. 打开VSCode官网 https://code.visualstudio.com2. download下载3.下载特别慢二. 解决VSCode下载速度特别慢 1. 单击右下角全部显示 我是用chrome浏览器,点击右下角的全部显示按钮,可以跳转到下载内…

2025年终极公众号排版神器排行榜 最新案例研究权威测评

2025年终极公众号排版神器排行榜 最新案例研究权威测评谁还在为公众号排版头疼?有一云AI直接让这个问题成为历史。这款被多家白皮书列为行业标杆的工具,正在重新定义内容创作的标准。看看那些头部自媒体账号的排版,…

NAS安装远程协作神器twake

Twake Twake是一款开源可自托管的团队协作平台,把聊天、任务、文档、会议四件套塞进一个工具箱模块 功能点 详细说明🗨️ 实时团队沟通 • 频道 / 私聊 / 群组聊天 • 全局消息搜索 • 文件拖拽上传(文档 / 图片…

把三门问题做成了"游戏"

代码:<html><head><meta charset="UTF-8"> <meta name="screen-orientation" content="landscape"> <meta name="viewport" content="widt…

下一代CPU驱动高性能计算革新

本文探讨了CPU在高性能计算领域的持续主导地位,分析了x86、ARM和RISC-V等架构的竞争格局,并介绍了小芯片设计、封装内存和混合架构等创新技术如何推动CPU性能突破摩尔定律限制。CPU仍是高性能计算的支柱 尽管GPU在当…

[KaibaMath]1010 关于关于收敛数列有界性的证明

[KaibaMath]1010 关于关于收敛数列有界性的证明如果数列收敛,则数列必有界. 反之则不然,例如{(-1)^n}. 下面给出收敛数列有界性的证明.

卫星地图匹配定位 - MKT

卫星地图匹配定位GeoVINS:用于大规模无漂移空中状态估计的地理-视觉-惯性导航系统 https://ieeexplore.ieee.org/abstract/document/11176431

10.17 —— (VP) 2021icpc沈阳

自己 \(vp\) 区域赛以来最好的一把,赛时 \(5\) 题,罚时 \(607\),正式赛大概 \(rk 120\) 左右,属于是蒟蒻的超水平发挥了。尤其是 \(H\) 题最后半小时内想出正解并且 \(1A\),感觉真的特别爽。 \(E, F\) 纯签到。 \…

20251017

今天搞了半天vue的开发环境,我想在edge界面里使用vue2.0,安装vue.js devtools拓展后令人费解的来了,一打开开发者模式后就不能用vue了,不打开开发者模式的情况下还能用,后来尝试了诸多方法,比如edge中使用chrome…

MT签名去除签名校验分析

前言 计划做一个高德车技 8.5.0的逆向,然后重新打包并签名, 结果安装后黑屏或卡在地图界面不动! 一直以为是自己的姿势不对,最后才发现:是此版本的高德做了更严格的签名校验。 我们可以借助于 MT管理器,只需要在…

uml

面向对象

P3643 [APIO2016] 划艇 分析

题目概述 题目链接:https://www.luogu.com.cn/problem/P3643。 给你 \(n\) 个班级,每个班级要么不选数要么选的数在 \([a_i,b_i]\),且选的数比编号比他小的班级选的数都要大,问有多少种方案(对 \((10^9+7)\) 取模…