【图形学】投影和消隐简介

2024-02-08 04:20
文章标签 简介 图形学 投影 消隐

本文主要是介绍【图形学】投影和消隐简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

投影

正交投影

对于物体上任意一点的三维坐标P(x,y,z),投影后的三维坐标为 P ′ ( x ′ , y ′ , z ′ ) P^\prime(x^\prime,y^\prime,z^\prime) P(x,y,z),那么正交投影的方程为 { x ′ = x y ′ = y z ′ = 0 \begin{cases} x^\prime=x\\y^\prime=y\\z^\prime=0 \end{cases} x=xy=yz=0

斜投影

在这里插入图片描述

如图所示,空间中一点 P 1 ( x , y , z ) P_1(x,y,z) P1(x,y,z)在xOy面上的斜投影坐标 P 2 ( x ′ , y ′ , 0 ) P_2(x^\prime,y^\prime,0) P2(x,y,0)正交投影点 P 3 ( x , y , 0 ) P_3(x,y,0) P3(x,y,0),那么有 { x ′ = x − L cos ⁡ β = x − z cot ⁡ α cos ⁡ β y ′ = y − L sin ⁡ β = y − z cot ⁡ α sin ⁡ β \begin{cases} x^\prime=x-L\cos\beta=x-z\cot\alpha\cos\beta\\ y^\prime=y-L\sin\beta=y-z\cot\alpha\sin\beta \end{cases} {x=xLcosβ=xzcotαcosβy=yLsinβ=yzcotαsinβ

透视投影

透视投影有三个坐标系,世界坐标系,观察坐标系,屏幕坐标系
在这里插入图片描述

在这里插入图片描述

观察坐标系到投影坐标系的转换可以用相似求出
在这里插入图片描述

{ x ′ = n ⋅ x z y ′ = n ⋅ y z \begin{cases} x^\prime=n\cdot \frac{x}{z}\\ y^\prime=n\cdot \frac{y}{z} \end{cases} {x=nzxy=nzy

建立投影类

class CProjection
{
public:CProjection();~CProjection();void SetViewPoint(double R);CPoint3 GetViewPoint();CPoint2 ObliqueProjection(CPoint3 WorldPoint);//正交投影CPoint2 OrthogonalProjection(CPoint3 WorldPoint);//斜二测投影CPoint2 PerspectiveProjection(CPoint3 WorldPoint);//透视投影
private:CPoint3 m_viewPoint;double R, d;
};CProjection::CProjection()
{R = 1200; d = 800;m_viewPoint.m_x = 0;m_viewPoint.m_y = 0;m_viewPoint.m_z = R;
}CProjection::~CProjection()
{
}void CProjection::SetViewPoint(double R)
{this->R = R;
}CPoint3 CProjection::GetViewPoint()
{return m_viewPoint;
}CPoint2 CProjection::ObliqueProjection(CPoint3 WorldPoint)//斜二测投影
{CPoint2 ScreenPoint;ScreenPoint.m_x = WorldPoint.m_x - 0.3536 * WorldPoint.m_z;ScreenPoint.m_y = WorldPoint.m_y - 0.3536 * WorldPoint.m_z;return ScreenPoint;
}CPoint2 CProjection::OrthogonalProjection(CPoint3 WorldPoint)//正交投影
{CPoint2 ScreenPoint;ScreenPoint.m_x = WorldPoint.m_x ;ScreenPoint.m_y = WorldPoint.m_y ;return ScreenPoint;
}CPoint2 CProjection::PerspectiveProjection(CPoint3 WorldPoint)
{CPoint2 ScreenPoint;CPoint3 ViewPoint;ViewPoint.m_x = WorldPoint.m_x;ViewPoint.m_y = WorldPoint.m_y;ViewPoint.m_z = m_viewPoint.m_z - WorldPoint.m_z;ScreenPoint.m_x = d * ViewPoint.m_x / ViewPoint.m_z;ScreenPoint.m_y = d * ViewPoint.m_y / ViewPoint.m_z;return ScreenPoint;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

消隐,背面剔除算法

给定视点位置或视线方向后,确定场景中哪些物体表面是可见的、哪些物体表面是不可见的,即是消隐。
背面剔除算法主要是针对凸多面体,其表面要么可见,要么不可见。算法要给出测试每个表面是否可见的表达式。
在这里插入图片描述
如图所示,根据表面的外法向量 N ⃗ \vec N N 和式向量 V ⃗ \vec V V 的夹角 θ \theta θ来进行可见性判定。
N ⃗ = P 2 P 4 ⃗ × P 3 P 4 ⃗ \vec N=\vec {P_2P_4} \times \vec {P_3P_4} N =P2P4 ×P3P4
给定视点坐标 O ( x v , y v , z v ) O(x_v,y_v,z_v) O(xv,yv,zv)后,视向量表示为 V ⃗ = ( x v − x 4 , y v − y 4 , z v − z 4 ) \vec V=(x_v-x_4,y_v-y_4,z_v-z_4) V =(xvx4,yvy4,zvz4)
将法向量 N ⃗ \vec N N 归一化为单位向量 n ⃗ \vec n n ,将视向量归一化为单位向量 v ⃗ \vec v v ,则有
n ⃗ ⋅ v ⃗ = cos ⁡ θ \vec n \cdot \vec v=\cos\theta n v =cosθ
可见性的判定如下:

  • cos ⁡ θ > 0 \cos\theta>0 cosθ>0时,表面可见,绘制多边形的边界线
  • cos ⁡ θ = 0 \cos\theta=0 cosθ=0时,表面多边形退化为一条直线
  • cos ⁡ θ < 0 \cos\theta<0 cosθ<0时,表面多边形不可见
    为了实现背面剔除算法,这里设计一个三维向量类CVector3

这里给的例子是一个立方体,那如果是一个贝塞尔曲面拟合的物体(比如球),那么用递归曲面片的方式绘制曲面,对于每一个细分曲面片又可以看成一个平面四边形,求出法向量即可。
在这里插入图片描述

三维向量类CVector3

class CVector3
{
public:CVector3();virtual ~CVector3();CVector3(double x, double y, double z);//绝对向量CVector3(const CPoint3& p);CVector3(const CPoint3& p0, const CPoint3& p1);//相对向量double Magnitude();//计算向量的模CVector3 Normalize();//归一化向量friend CVector3 operator + (const CVector3& v0, const CVector3& v1);//运算符重载friend CVector3 operator - (const CVector3& v0, const CVector3& v1);friend CVector3 operator * (const CVector3& v, double t);friend CVector3 operator * (double t, const CVector3& v);friend CVector3 operator / (const CVector3& v, double t);friend double DotProduct(const CVector3& v0, const CVector3& v1);//计算向量的点积friend CVector3 CrossProduct(const CVector3& v0, const CVector3& v1);//计算向量的叉积
private:double m_x, m_y, m_z;
};
CVector3::CVector3(void)
{m_x = 0.0, m_y = 0.0, m_z = 1.0;//指向z轴正向
}CVector3::~CVector3(void)
{
}CVector3::CVector3(double x, double y, double z)//绝对向量
{m_x = x;m_y = y;m_z = z;
}
CVector3::CVector3(const CPoint3& p)
{m_x = p.m_x;m_y = p.m_y;m_z = p.m_z;
}
CVector3::CVector3(const CPoint3& p0, const CPoint3& p1)//相对向量
{m_x = p1.m_x - p0.m_x;m_y = p1.m_y - p0.m_y;m_z = p1.m_z - p0.m_z;
}
double CVector3::Magnitude(void)//向量的模
{return sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
}
CVector3 CVector3::Normalize(void)//归一化为单位向量
{CVector3 vector;double magnitude = sqrt(m_x * m_x + m_y * m_y + m_z * m_z);if (fabs(magnitude) < 1e-6)magnitude = 1.0;vector.m_x = m_x / magnitude;vector.m_y = m_y / magnitude;vector.m_z = m_z / magnitude;return vector;
}
void CVector3::IntoOut()
{if (m_x * m_y < 0&&m_x*m_z>0) {m_x = -m_x, m_z = -m_z;}else if (m_x * m_z < 0 && m_x * m_y>0) {m_x = -m_x, m_y = -m_y;}else if (m_y * m_z < 0 && m_y * m_z>0) {m_y = -m_y, m_z = -m_z;}
}
CVector3 operator + (const CVector3& v0, const CVector3& v1)//向量的和
{CVector3 vector;vector.m_x = v0.m_x + v1.m_x;vector.m_y = v0.m_y + v1.m_y;vector.m_z = v0.m_z + v1.m_z;return vector;
}CVector3 operator - (const CVector3& v0, const CVector3& v1)//向量的差
{CVector3 vector;vector.m_x = v0.m_x - v1.m_x;vector.m_y = v0.m_y - v1.m_y;vector.m_z = v0.m_z - v1.m_z;return vector;
}CVector3 operator * (const CVector3& v, double t)//向量与常量的积
{CVector3 vector;vector.m_x = v.m_x * t;vector.m_y = v.m_y * t;vector.m_z = v.m_z * t;return vector;
}CVector3 operator * (double t, const CVector3& v)//常量与向量的积
{CVector3 vector;vector.m_x = v.m_x * t;vector.m_y = v.m_y * t;vector.m_z = v.m_z * t;return vector;
}CVector3 operator / (const CVector3& v, double scalar)//向量数除
{if (fabs(scalar) < 1e-6)scalar = 1.0;CVector3 vector;vector.m_x = v.m_x / scalar;vector.m_y = v.m_y / scalar;vector.m_z = v.m_z / scalar;return vector;
}double DotProduct(const CVector3& v0, const CVector3& v1)//向量的点积
{return(v0.m_x * v1.m_x + v0.m_y * v1.m_y + v0.m_z * v1.m_z);
}CVector3 CrossProduct(const CVector3& v0, const CVector3& v1)//向量的叉积
{CVector3 vector;vector.m_x = v0.m_y * v1.m_z - v0.m_z * v1.m_y;vector.m_y = v0.m_z * v1.m_x - v0.m_x * v1.m_z;vector.m_z = v0.m_x * v1.m_y - v0.m_y * v1.m_x;return vector;
}

示例,球的消隐

在这里插入图片描述

需要项目代码请评论区留言或私信

这篇关于【图形学】投影和消隐简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/689886

相关文章

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

业务协同平台--简介

一、使用场景         1.多个系统统一在业务协同平台定义协同策略,由业务协同平台代替人工完成一系列的单据录入         2.同时业务协同平台将执行任务推送给pda、pad等执行终端,通知各人员、设备进行作业执行         3.作业过程中,可设置完成时间预警、作业节点通知,时刻了解作业进程         4.做完再给你做过程分析,给出优化建议         就问你这一套下

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

【Tools】AutoML简介

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 AutoML(自动机器学习)是一种使用机器学习技术来自动化机器学习任务的方法。在大模型中的AutoML是指在大型数据集上使用自动化机器学习技术进行模型训练和优化。

SaaS、PaaS、IaaS简介

云计算、云服务、云平台……现在“云”已成了一个家喻户晓的概念,但PaaS, IaaS 和SaaS的区别估计还没有那么多的人分得清,下面就分别向大家普及一下它们的基本概念: SaaS 软件即服务 SaaS是Software-as-a-Service的简称,意思是软件即服务。随着互联网技术的发展和应用软件的成熟, 在21世纪开始兴起的一种完全创新的软件应用模式。 它是一种通过Internet提供

LIBSVM简介

LIBSVM简介 支持向量机所涉及到的数学知识对一般的化学研究者来说是比较难的,自己编程实现该算法难度就更大了。但是现在的网络资源非常发达,而且国际上的科学研究者把他们的研究成果已经放在网络上,免费提供给用于研究目的,这样方便大多数的研究者,不必要花费大量的时间理解SVM算法的深奥数学原理和计算机程序设计。目前有关SVM计算的相关软件有很多,如LIBSVM、mySVM、SVMLight等,这些

urllib与requests爬虫简介

urllib与requests爬虫简介 – 潘登同学的爬虫笔记 文章目录 urllib与requests爬虫简介 -- 潘登同学的爬虫笔记第一个爬虫程序 urllib的基本使用Request对象的使用urllib发送get请求实战-喜马拉雅网站 urllib发送post请求 动态页面获取数据请求 SSL证书验证伪装自己的爬虫-请求头 urllib的底层原理伪装自己的爬虫-设置代理爬虫coo

新一代车载(E/E)架构下的中央计算载体---HPC软件架构简介

老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。 无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、焦虑、毁掉你本就不多的热情和定力。 时间不知不觉中,快要来到夏末秋初。一年又过去了一大半,成

AI学习指南深度学习篇-带动量的随机梯度下降法简介

AI学习指南深度学习篇 - 带动量的随机梯度下降法简介 引言 在深度学习的广阔领域中,优化算法扮演着至关重要的角色。它们不仅决定了模型训练的效率,还直接影响到模型的最终表现之一。随着神经网络模型的不断深化和复杂化,传统的优化算法在许多领域逐渐暴露出其不足之处。带动量的随机梯度下降法(Momentum SGD)应运而生,并被广泛应用于各类深度学习模型中。 在本篇文章中,我们将深入探讨带动量的随

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工