三维几何图形创作方法(Geometry3D)之二

           本文所讲的内容已经开源,你可以在 这里 找到源代码。 


        前面我们介绍了三维图形的轴测投影画法,这里介绍一组三维图形,创作这些图形主页使用“斜二测”画法。

多面体

        先看一类比较简单的三维图形,这类图形,完全由顶点、棱、面组成,称为多面体。他很像二维图形中的多边形。

        长方体、棱台都是多面体。

        在多面体作图中,顶点、棱是比较关键的元素,具体哪些顶点之间有棱连接,是由具体的图形决定的。多面体有一些共性,需要首先处理这些共性。

  • 共性1:包围多边形

        当给定了一组顶点,一个基础的问题是,这些顶点在二维平面映射后的点集的包围多边形是怎样的。包围多边形一般用于确定图形的可点击范围,在接下来的另一个问题中,也会用到包围多边形的算法。

        计算最小包围多边形的算法,网上有很多文章,这里介绍一下简单步骤:

  1. 寻找最下面、最右边的点
  2. 以该点作为原点,调整点的坐标
  3. 将所有点按其极坐标角度排序
  4. 初始化一个栈,元素是点,将(0,0)点入栈
  5. 遍历所有排序后的点,做如下处理
    1. 循环从栈中拿出顶部两个点
      1. 与当前点组成一个有向角,计算夹脚变化方向
      2. 如果方向大于 0,则用当前点替换栈顶,退出循环
      3. 弹出这两个点,继续循环,直到栈中少于两个元素
    2. 当栈中只有一个元素时,直接入栈
  6. 将栈中所有点调整偏移量,回到原来的位置
  7. 最后,栈中所有点按顺序形成包围多边形

共性2:棱的可见性

        我们知道,这些棱中有些是被其他部分遮挡,看不见的,看不见的棱需要用虚线表示。但是怎么确定一条棱的可见性呢?我们也大致说下思路:

  1. 将所有棱的中点补充到顶点集合中
  2. 将所有三维点,按 y 坐标排序,y 越大,越在屏幕后面,同时计算其二维映射坐标
  3. 遍历排序后的点
    1. 用一个多边形记录已经遍历过的点,在二维平面的包围多边形
    2. 判断当前正在遍历的点相对于包围多边形的位置
    3. 如果中包围多边形里面,则该点是不可见的(因为被前面的点组成的面挡住了)
  4. 如果一个棱的两个顶点、一个中点,有任何一个不可见,则该棱不可见。

        有可能一个棱的两个顶点是可见的,但是棱不可见,通过加入中点可以基本覆盖这种场景的正确性。

        有了上面的基础,接下来我们就来看看如何计算每种特殊的多面体的顶点。

长方体

        相对来说,长方体的快速绘制要比正方体简单,正方体是作为长方体的特例来处理的。

         输入的两点 A、B 中,都是长方体的一个顶点。根据矢量 AB 的方向所在的象限,可以分为四种情况,这四种情况,A 点分别对应长方体的 “左后上”、“右后上”、“右前下”、“左前下”顶点,B 点对应另一个相对的顶点。

        快速绘制长方体(斜二测图),我们假定在三维 X 轴方向的长度为 w,在 Y、Z 轴方向的长度相等,都是 h。

         为方便计算,我们还假定 A 点所在点长方体的前面或者后面(垂直于 Y 轴)与 X、Z 轴组成的平面重合,也就是起点 A 对应的 Y 轴坐标永远为 0,这并不影响后续计算以及图形绘制。

        所以我们就有了下面的这个方程:

\begin{bmatrix} 1 & \sqrt{2}/4 & 0 \\ 0 & -\sqrt{2}/4 & -1 \end{bmatrix} * \begin{bmatrix} x_{0} \\ 0 \\ z_{0} \end{bmatrix} = \begin{bmatrix} x_{A} \\ y_{A} \end{bmatrix}

\begin{bmatrix} 1 & \sqrt{2}/4 & 0 \\ 0 & -\sqrt{2}/4 & -1 \end{bmatrix} * \begin{bmatrix} x_{0} + w\\ h \\ z_{0} + h \end{bmatrix} = \begin{bmatrix} x_{B} \\ y_{B} \end{bmatrix}

        这里不考虑 A、B 的相对方向性, 所以 w、h 可能为负值。

        求解方程可以等到:

\\ z_{0} = -y_{B} \\ h = (y_{B} - y_{A}) / (1 + C) \\ x_{0} = x_{A} - C * h \\ w = x_{B} - x_{0}

        其中:C = \sqrt{2} / 4

        有了上面的基础,我们可以列出长方体 8 个顶点的三维坐标了。

\begin{bmatrix} x_{0} & x_{0} + w & x_{0} + w & x_{0} & x_{0} + w & x_{0} + w & x_{0} & x_{0} \\ y_{0} & y_{0} & y_{0} & y_{0} & y_{0} +h & y_{0} +h & y_{0} +h & y_{0} +h \\ z_{0} & z_{0} & z_{0} + h & z_{0} + h & z_{0} + h & z_{0} & z_{0} & z_{0} + h \end{bmatrix}

        这里,前 4 个顶点同在长方体的前面或者后面(包含 A 点),所以 y 坐标都是 y0 = 0,后面 4 个顶点在对面,y 坐标都是 y0  + h = h 。

        在实际绘图时,需要通过三维坐标到二维坐标的变换矩阵 A,将上面的坐标转化为屏幕坐标。

        最后 12 个边(棱)分别为:

    makeLine(0, 1);
    makeLine(1, 2);
    makeLine(2, 3);
    makeLine(3, 0);
    makeLine(0, 6);
    makeLine(6, 5);
    makeLine(5, 4);
    makeLine(4, 7);
    makeLine(7, 6);
    makeLine(7, 3);
    makeLine(4, 2);
    makeLine(5, 1);

正方体

        在输入的两点 A、B 中,我们以 A 点作为正方体的一个顶点,规定 B 点可以位于正方体前面(或者后面)的底边上,也可以位于不包含 A 的侧面上。

                           

           有了前面针对长方体的计算基础,要满足上面的规定,只需同样算出两个边长 w、h,然后取他们长度最大的一个,作为正方体的边长,后面的计算就是一模一样的了。

正棱台

        在棱柱、棱锥、棱台中,我们从棱台开始,因为棱柱、棱锥其实是棱台的一种特例。

        正棱台的上下两个面都是正多边形,可以沿用前面正多边形的算法来计算各个顶点的坐标。

        这里,我们规定棱台上下两个面的半径(r,R)存在固定的比例,比如(r = R * 0.5),还规定多边形的最外侧棱平行于 x 轴,正多边形中心点的 y 坐标为 0。

        在输入的两点 A、B 中,我们以 A 点作为小正多边形的中心,B 点作为大正多边形的最外侧棱上点一个顶点,假设棱台高 h,大正多边形中点对应的三维点坐标为 (x0, 0, z0),顶点 B 相对中心的方向角为 t,那么就有了下面的方程:

\begin{bmatrix} 1 & \sqrt{2}/4 & 0 \\ 0 & -\sqrt{2}/4 & -1 \end{bmatrix} * \begin{bmatrix} x_{0} \\ 0 \\ z_{0} + h\end{bmatrix} = \begin{bmatrix} x_{A} \\ y_{A} \end{bmatrix}

\begin{bmatrix} 1 & \sqrt{2}/4 & 0 \\ 0 & -\sqrt{2}/4 & -1 \end{bmatrix} * \begin{bmatrix} x_{0} + R * cos(t) \\ - R * sin(t) \\ z_{0} \end{bmatrix} = \begin{bmatrix} x_{B} \\ y_{B} \end{bmatrix}

        求解方程得到:

\begin{bmatrix} x_{0} \\ y_{0} \\ z_{0}\end{bmatrix} = \begin{bmatrix} x_{A} \\ 0 \\ C*R*sin(t) - y_{B} \end{bmatrix}

\begin{bmatrix} h \\ R\\ r \end{bmatrix} = \begin{bmatrix} -y_{A} - z_{0}\\ (x_{B} - x_{A}) / (cos(t) - C*sin(t))\\ R * 0.5 \end{bmatrix}

        其中:C = \sqrt{2} / 4

        结合之前二维正多边形顶点的计算方法,可以确定各顶点的 x、y 坐标,另外 z 坐标就是 z0 和 z0 + h。对于正 n 棱台,总共有 2n 个顶点。

        最后,正 n 棱台,有 3n 个棱,这是不难给出的。

正棱锥

        当正棱台上下两个面的半径(r,R)的比例为 0 时,即 r = 0 时,就变成正棱锥。此时,小多边形退化为一个顶点,总顶点数变为 n + 1,棱数变为 2n。其他计算完成沿用正棱台的过程就行了。

正棱柱

        正棱柱则更简单,将正棱台上下两个面的半径(r,R)的比例设置为 1 即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting Horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值