【Godot4.3】用2D网格模拟一点透视

概述

空间的透视是可以在二维平面上参数化计算和模拟的。本篇基于CanvasItem绘制函数draw_colored_polygon()自带的UV坐标和贴图功能,实现基础的平行透视效果。
或者可以叫做一点透视,由一个消失点决定物体的透视效果。

测试代码

extends Node2Dvar rect = Rect2(-50,-50,60,60)  # 透视图形
var dis_p                        # 消失点var thickness:float = 60.0  # 厚度
var scale_rate:float           # 缩放比例
var uvs = Points2D.Vec2Arr("0,0 0,1 1,1 1,0")@export var texture:Texture2D:set(val):texture = valqueue_redraw()func _ready() -> void:dis_p = get_viewport_rect().get_center()  # 消失点func _process(delta: float) -> void:# 矩形跟随鼠标移动rect.position = get_global_mouse_position() - rect.size/2.0queue_redraw()func _draw() -> void:var c = rect.get_center()       # 矩形中心var dir = c.direction_to(dis_p) # 由矩形中心向消失点的方向var dis = c.distance_to(dis_p)  scale_rate = (dis - thickness)/dis# 求偏移矩形var move = Transform2D().translated(-c)var bottom_rect = move * rectbottom_rect = Transform2D().scaled(Vector2.ONE * scale_rate).translated(dir * thickness) * bottom_rectbottom_rect = bottom_rect * move# 求侧边多边形var rect_points = get_rect_points(rect) var bottom_rect_points = get_rect_points(bottom_rect)var side_top = PackedVector2Array([rect_points[0],bottom_rect_points[0],bottom_rect_points[1],rect_points[1]])var side_left = PackedVector2Array([rect_points[0],bottom_rect_points[0],bottom_rect_points[3],rect_points[3]])var side_right = PackedVector2Array([rect_points[1],bottom_rect_points[1],bottom_rect_points[2],rect_points[2]])var side_bottom = PackedVector2Array([rect_points[2],bottom_rect_points[2],bottom_rect_points[3],rect_points[3]])var rect_4:Array[Rect2] = ShapeTests.get_rect_4_parts(get_viewport_rect()) # 四象限划分draw_line(c,dis_p,Color.ORANGE_RED,1)draw_colored_polygon(bottom_rect_points,Color.AQUAMARINE,uvs,texture) # 底面var sides:Array[PackedVector2Array]if rect_4[0].has_point(c):  # 在第一象限sides.append_array([side_top,side_left,side_right,side_bottom])if rect_4[1].has_point(c):  # 在第二象限sides.append_array([side_top,side_right,side_left,side_bottom])if rect_4[2].has_point(c):  # 在第三象限sides.append_array([side_right,side_bottom,side_top,side_left])if rect_4[3].has_point(c):  # 在第四象限sides.append_array([side_left,side_bottom,side_top,side_right])for rec in sides:draw_colored_polygon(rec,Color.CADET_BLUE,uvs,texture)draw_colored_polygon(rect_points,Color.AQUAMARINE,uvs,texture)        # 原始矩形#draw_rect(rect,Color.AQUAMARINE,false,1)#draw_rect(bottom_rect,Color.AQUAMARINE,false,1)# 返回矩形四个角点
func get_rect_points(rect:Rect2) -> PackedVector2Array:var pots:PackedVector2Arrayvar pos = rect.position;	var end = rect.end;	var size = rect.sizepots = [	pos,pos + Vector2(size.x,0),	end,end - Vector2(size.x,0)]return pots

绘制效果:

改进版本

extends Node2Dvar rect = Rect2(-50,-50,60,60)  # 透视图形
var dis_p                        # 消失点var thickness_rate:float = 0.2  # 厚度比例
var scale_rate:float = 0.8       # 缩放比例
var uvs = Points2D.Vec2Arr("0,0 0,1 1,1 1,0")   # 顶点UV坐标## 纹理
@export var texture:Texture2D:set(val):texture = valqueue_redraw()func _ready() -> void:dis_p = get_viewport_rect().get_center()  # 消失点func _process(delta: float) -> void:# 矩形跟随鼠标移动rect.position = get_global_mouse_position() - rect.size/2.0queue_redraw()func _draw() -> void:var c = rect.get_center()       # 矩形中心var dir = c.direction_to(dis_p) # 由矩形中心向消失点的方向var dis = c.distance_to(dis_p)# 求偏移矩形var move = Transform2D().translated(-c)var bottom_rect = move * rectbottom_rect = Transform2D().scaled(Vector2.ONE * scale_rate) * bottom_rectbottom_rect = bottom_rect * movebottom_rect.position = c.lerp(dis_p,thickness_rate) - bottom_rect.size/2.0# 求矩形的点集var r1_pots = ShapeTests.get_rect_points(rect) var r2_pots = ShapeTests.get_rect_points(bottom_rect)# 绘制底面draw_colored_polygon(r2_pots,Color.AQUAMARINE,uvs,texture)var sides = ShapeTests.get_rect_rect_sides(rect,bottom_rect)  # 获取测边多边形var order = ShapeTests.get_sides_order(c,dis_p)               # 获取绘制顺序# 按顺序绘制侧边面for i in order:draw_colored_polygon(sides[i],Color.CADET_BLUE,uvs,texture)# 绘制原始矩形draw_colored_polygon(r1_pots,Color.AQUAMARINE,uvs,texture)

部分代码已经总结为函数,放入ShapeTests函数库,总结的函数如下:

# 求两个矩形相连的侧边多边形
func get_rect_rect_sides(rect1:Rect2,rect2:Rect2) -> Array[PackedVector2Array]:var sides:Array[PackedVector2Array]var r1_pots = get_rect_points(rect1) var r2_pots = get_rect_points(rect2)var side_top = PackedVector2Array([r1_pots[0],r2_pots[0],r2_pots[1],r1_pots[1]])var side_left = PackedVector2Array([r1_pots[0],r2_pots[0],r2_pots[3],r1_pots[3]])var side_right = PackedVector2Array([r1_pots[1],r2_pots[1],r2_pots[2],r1_pots[2]])var side_bottom = PackedVector2Array([r1_pots[2],r2_pots[2],r2_pots[3],r1_pots[3]])sides.append_array([side_top,side_right,side_bottom,side_left])return sides# 返回一个点p在另一个点c所划分的四象限的哪个象限
func get_pos_quadrant(p:Vector2,c:Vector2) -> int:var quadrant:intvar ang = c.direction_to(p).angle()if ang> -PI and ang <= - PI * 0.5:  # 在第一象限quadrant = 0if ang> - PI * 0.5 and ang<= 0:    # 在第二象限quadrant = 1if ang> 0 and ang<= PI * 0.5:      # 在第三象限quadrant = 2if ang> PI * 0.5 and ang<= PI:   # 在第四象限quadrant = 3return quadrant# 返回各个象限绘制的顺序
func get_sides_order(c:Vector2,dis_p:Vector2) -> Array[int]:var sides_order:Array[int]match get_pos_quadrant(c,dis_p):0:sides_order.append_array([0,3,1,2])1:sides_order.append_array([0,1,2,3])2:sides_order.append_array([1,2,3,0])3:sides_order.append_array([2,3,0,1])return sides_order

以下是改进版本的测试效果:
请添加图片描述
改进版本更符合我最初的设想。

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

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

相关文章

【课程学习】Wireless Communications

Goldsmith A. Wireless communications[M]. Cambridge university press, 2005. Wireless Communications 无线通信课程 文章目录 2-Path Loss, Shadowing, and Multipath2.4-Two-Ray Multipath Model时延扩展 delay spread P33 3-Statistical Multipath Channel Models3.3-Wid…

HarmonyOS应用六之应用程序进阶一

目录&#xff1a; 1、UIAbility的冷启动和UIAbility热启动2、静态资源和动态资源的访问3、页面跳转3.1、页面返回跳转 4、HAR的ArkUI组件、接口、资源&#xff0c;供其他应用或当前应用的其他模块引用4.1、导出HAR的ArkUI组件4.2、引用HAR的ArkUI组件 5、循环渲染6、状态管理最…

【MySQL】多表联合查询常见练习题

数据库表如下&#xff1a; teacher&#xff1a;老师表 course&#xff1a;课程表 student&#xff1a;学生表 class&#xff1a;班级表 sc&#xff1a;成绩表 一、根据上面5张表写sql语句 1. 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数 select student.…

在Ubuntu 20.04中安装CARLA

0. 引言 CARLA (Car Learning to Act) 是一款开源自动驾驶模拟器&#xff0c;其支持自动驾驶系统全管线的开发、训练和验证&#xff08;Development, Training, and Validation of autonomous driving systems&#xff09;。Carla提供了丰富的数字资产&#xff0c;例如城市布局…

国外电商系统开发-运维系统功能清单开发

一、最终效果图 二、功能清单 功能 描述 自定义日志绘图 根据Nginx、Apache登录日志文件绘图&#xff0c;绘图数据包括&#xff1a;访问量走势&#xff0c;500错误&#xff0c;200正确百分比等 创建服务器 加入服务器 主机状态自动检查 加入主机到系统后&#xff0c;系统…

MyBatis——ORM

MyBatis——ORM 验证映射配置ResultType本质是ResultMap具体的转换逻辑 概括的说&#xff0c;MyBatis中&#xff0c;对于映射关系的声明是由开发者在xml文件手动完成的。比如对查询方法而言&#xff0c;你需要显式声明ResultType或ResultMap&#xff0c;这里其实就是在定义数据…

(16)MATLAB仿真Nakagami-m分布1

文章目录 前言一、Nakagami分布二、MATLAB建模代码三、仿真结果画图四、总结 前言 Nakagami衰落模型最初是由于该模型与短波电离层传播的经验结果相匹配而提出的。它还用于仿真来自多个干扰源的情况&#xff0c;因为多个独立且同分布&#xff08;i.i.d&#xff09;的瑞利分布随…

基于四种网络结构的WISDM数据集仿真及对比:Resnet、LSTM、Shufflenet及CNN

在上节中&#xff0c;我们已经详细介绍了WISDM数据集及如何使用CNN网络训练&#xff0c;得到了六个维度的模型仿真指标及五个维度的可视化分析&#xff0c;那么现在我们将训练模型推广到其他网路结构中去&#xff0c;通过仿真实验来对比一下不同网络之间对于WISDM数据集的训练效…

大语言模型入门(三)——提示词编写注意事项

一、提示词编写原则 提示词的编写应当遵循两个原则&#xff0c; 一个是指令必须清晰且具体&#xff0c;另一个是应当给模型充足的时间去思考。首先&#xff0c;你的指令足够清晰和具体&#xff0c;才能让大模型明确你需要它执行的任务&#xff0c;从而降低我们得到无关或者不正…

kubernetes-强制删除命名空间

一、故障现象 1、删除命名空间卡住、强制删除也卡住 2、其他终端显示命名空间下无资源 二、处理步骤 1、kubectl get namespace cilium-test -o json > temp.json 获取你需要删除的命名空间json描述文件。 2、修改finalize字段 3、替换 kubectl replace --raw "/api/v1…

Pikachu-xss防范措施 - href输出 js输出

总体原则&#xff1a; 输入做过滤&#xff0c;输出做转义 过滤&#xff1a;根据业务需要进行过滤&#xff0c;如&#xff1a;输入点要求输入手机号&#xff0c;则只允许输入手机号格式的数字&#xff1b; 转义&#xff1a;所有输出到前端的数据&#xff0c;都根据输出点进行转…

【MySQL】DML数据操作语句和基本的DQL语句

目录 一、Mysql对数据的增删改 1. 增加数据 2. 修改数据&#xff08;UPDATE语句&#xff09; 3. 删除 3.1 delete、truncate、drop区别 二、DQL语言&#xff08;重点&#xff09; 1. 单表查询 1.1 最简单的查询 1.2 从表中获取数据 1.3 字段名起别名 1.4 添加字段 1…

深度学习——线性神经网络(一、线性回归)

目录 一、线性回归1.1 线性回归的基本元素1.1.1 术语介绍1.1.2 线性模型1.1.3 损失函数1.1.4 解析解1.1.5 随机梯度下降1.1.6 模型预测 1.2 正态分布与平方损失 因为线性神经网络篇幅比较长&#xff0c;就拆成几篇博客分开发布。目录序号保持连贯性。 一、线性回归 回归&#x…

Linux:深入理解冯诺依曼结构与操作系统

目录 1. 冯诺依曼体系结构 1.1 结构分析 1.2 存储结构分布图 2. 操作系统 2.1 概念 2.2 如何管理 2.3 什么是系统调用和库函数 1. 冯诺依曼体系结构 1.1 结构分析 不管是何种计算机&#xff0c;如个人笔记本电脑&#xff0c;服务器&#xff0c;都是遵循冯诺依曼结构。…

基于Springboot的在线订餐系统设计与实现(论文+源码)_kaic

摘 要 当今世界&#xff0c;互联网以及和互联网有关的行业都在不断的发展&#xff0c;也在持续走进人们的生活&#xff0c;在此趋势下人们对于通过互联网解决生活问题的需求愈来愈多&#xff0c;本文考虑到了这些情况后做出了该订餐系统。 本系统选择了MySQL作为主要存储单元…

深入探讨Windows 11专业版与Windows 11专业工作站版的差异

前言 深入探讨Windows 11专业版与Windows 11专业工作站版的差异&#xff0c;可以更全面地理解这两款操作系统版本面向的不同用户群体、硬件支持、性能特点以及应用场景&#xff0c;从而为专业用户和企业选择最合适的平台提供依据。 硬件支持与扩展能力 Windows 11专业版&…

Apache OFBiz SSRF漏洞CVE-2024-45507分析

Apache OFBiz介绍 Apache OFBiz 是一个功能丰富的开源电子商务平台&#xff0c;包含完整的商业解决方案&#xff0c;适用于多种行业。它提供了一套全面的服务&#xff0c;包括客户关系管理&#xff08;CRM&#xff09;、企业资源规划&#xff08;ERP&#xff09;、订单管理、产…

记录一次学习--委派攻击学习

目录 为什么要使用委派 什么账号可以使用委派 非约束性委派 这里有一张图 利用 流程 约束性委派 这里有一张图 如何利用 条件 具体流程 为什么要使用委派 这个是因为可能A服务需要B服务的支持&#xff0c;但是A服务的权限不可以使用B服务。然后这时就可以让域用户将…

OpenStack Yoga版安装笔记(十四)启动一个实例

1、官方文档 OpenStack Installation Guidehttps://docs.openstack.org/install-guide/ 本次安装是在Ubuntu 22.04上进行&#xff0c;基本按照OpenStack Installation Guide顺序执行&#xff0c;主要内容包括&#xff1a; 环境安装 &#xff08;已完成&#xff09;OpenStack…

OpenCV计算机视觉库

计算机视觉和图像处理 Tensorflow入门深度神经网络图像分类目标检测图像分割OpenCVPytorchNLP自然语言处理 OpenCV 一、OpenCV简介1.1 简介1.2 OpenCV部署1.3 OpenCV模块 二、OpenCV基本操作2.1 图像的基本操作2.1.1 图像的IO操作2.1.2 绘制几何图像2.1.3 获取并修改图像的像素…