EGE专栏:EGE专栏

上一篇:EGE基础入门篇(六):基本图形

下一篇:EGE基础入门篇(八):清屏与重绘

一、 组合图形

1. 复杂图形由基本图形组合而成

  复杂的图形可以由基本图形组合而成,如多边形可以由多个三角形组合而成。
  同一个图形也可由基本图形以不同的方式进行组合。并且可以利用后绘制的图形会将先绘制图形覆盖的原理。

2. 绘制的顺序性

  图形的绘制是有先后顺序的,并不能随意地按任意顺序进行绘制。
  当后绘制的图形和先绘制的图形重叠时,如果图形不透明,那么先绘制的图形会被后绘制的图形所覆盖。即使图形是透明的,也会造成混合后的颜色不相同。

  如下图所示,当物体存在一定的遮挡关系时,需要按由远到近的顺序,先画远处的物体,再画近处的物体,这样绘制出的图形才会符合实际。否则,图中的树木会被草地和高山所覆盖。

  在三维物体渲染中,深度排序算法也叫画家算法,通过先对物体按照离视点远近的顺序进行排序,再将物体按顺序进行绘制的方法来得到正确的渲染结果。

  如下图所示,图中为通过调整结点和边的绘制顺序,得到了两种不同的绘制结果,而右边按先边后结点顺序绘制出的二叉树图形才是我们想要的。

二、组合图形的绘制

  

1. 彭罗斯三角形

  彭罗斯三角形是利用视觉错觉构造的一种不可能图形,在三维空间中并不真实客观存在。在二维空间中,可以在某个特定角度观察到这种"不可能图形",所以彭罗斯三角形是二维图形的三维投射形成的光学错觉。彭罗斯三角形在《纪念碑谷》中有着大量的运用。



  在二维绘图中,有多种绘图方式,既可以将彭罗斯三角形看作是三个互不重叠的多边形组合而成,也可以是特殊构造的三维图形的投影(纪念碑谷中的做法,适合三维模型),还可以改变三维物体表面投影的遮挡关系来形成。
  这里我们通过构造三维模型,利用其投影来绘制彭罗斯三角形。
  我们先根据物体在三维坐标系中的位置得到其顶点的三维坐标,然后将其投影到平面上,得到在平面上的二维坐标,然后在变换到窗口坐标系上,即可得到多边形每个顶点的坐标,调用ege_fillpoly() 绘图即可。

  我们对一个单位立方体进行分析,可以发现立方体被投影成了正六边形。由于投影面垂直于向量vvv,与vvv垂直的线段投影后长度不变。从图中可以看出平面ABC垂直于向量vvv,所以投影后AB、AC和BCAB、AC和BCAB、AC和BC长度均不变,长度为2\sqrt{2}2​。通过对在坐标轴上的三个点A、B、D映射关系分析,我们就能得到相应的变换关系。
  三维空间上的顶变换后到xOyxOyxOy平面后,再通过视口变换转换成窗口坐标系上的坐标,就可以利用EGE中的绘图函数进行绘图了。

完整代码如下:

#include <graphics.h>
#include <cmath>typedef struct Rect
{float x, y;float width, height;
} Rect;typedef struct Vertex
{float x, y, z;
} Vertex;//投影到xOy平面上
ege_point vertexPrejection(Vertex vertex)
{static const double sqrtOf2 = sqrt(2.0);static const double sqrtOf3 = sqrt(3.0);static const double sqrtOf6 = sqrt(6.0);// 根据点的投影:// (1, 0, 0)映射到(√2/2,  √6/6, 0)// (0, 1, 0)映射到(0,     √6/3, 0)// (0, 0, 1)映射到(√2/2, -√6/6, 0)// 得到:变换矩阵(坐标为列向量)// |x| = |√2/2,    0,  √2/2| |x|// |y| = |√6/6, √6/3, -√6/6| |y|// |z| = |   0,    0,     0| |z|ege_point point;point.x = vertex.x * (sqrtOf2 / 2.0) + vertex.z * (sqrtOf2 / 2.0);point.y = vertex.x * (sqrtOf6 / 6.0) + vertex.y * (sqrtOf6 / 3.0) + vertex.z * (-sqrtOf6 / 6.0);return point;
}int main() {//定义窗口大小,以及窗口中心int winWidth = 640, winHeight = 640;Rect viewRect = { -2.0f, -2.0f, 8.0f, 8.0f };     //投影截取范围:左下角(-2, -2),宽高为8x8的矩形区域int xCenter = winWidth / 2, yCenter = winHeight / 2;initgraph(winWidth, winHeight, INIT_RENDERMANUAL);ege_enable_aa(true);setbkcolor(EGERGB(0xFF, 0xFF, 0xFF));//三个多边形的顶点坐标(凹六边形)Vertex vertices[3][6] = {{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 5.0f, 1.0f}, {0.0f, 5.0f, 4.0f}, {0.0f, 6.0f, 5.0f}, {0.0f, 6.0f, 0.0f},},{{0.0, 0.0f, 1.0f}, {6.0f, 0.0f, 1.0f}, {6.0f, 1.0f, 1.0f},{1.0, 1.0f, 1.0f}, {1.0f, 4.0f, 1.0f}, {0.0f, 5.0f, 1.0f},},{{0.0f, 6.0f, 0.0f}, {0.0f, 6.0f, 5.0f}, {2.0f, 1.0f, 0.0f},{1.0f, 1.0f, 1.0f}, {6.0f, 1.0f, 1.0f}, {1.0f, 6.0f, 0.0f},},};//多边形的颜色color_t colors[3] = { EGEARGB(255, 2, 118, 191), EGEARGB(255, 94, 175, 228),EGEARGB(255, 146, 202, 239) };const int numPolys = 3;const int numPoints = 6;//计算缩放比例int xratio = (float)winWidth / viewRect.width;int yratio = (float)winHeight / viewRect.height;ege_point points[6];//将三维空间中的多边形顶点先投影到二维平面上,再转到窗口坐标系中,然后将多边形绘制出来for (int i = 0; i < numPolys; i++) {for (int j = 0; j < numPoints; j++) {//三维空间中的坐标投影到xOy平面上points[j]   = vertexPrejection(vertices[i][j]);//视口变换:ViewRect 变换到窗口[(0, 0), winWidth, winHeight]points[j].x = (points[j].x - viewRect.x) * xratio;points[j].y = winHeight - (points[j].y - viewRect.y) * yratio;}//设置颜色,绘制多边形setfillcolor(colors[i]);ege_fillpoly(numPoints, points);}getch();closegraph();return 0;
}

运行结果如图:

2. 国际象棋棋盘


  国际象棋棋盘为正方形,由64个黑白(深色与浅色)相间的格子组成;棋子分黑白(深色与浅色)两方共32枚,每方各16枚。棋盘格子颜色分深色浅色两种,颜色并不固定。每个格子的绘制只需要计算出左上角坐标格子宽高即可,然后使用填充矩形来绘制。

  先对每个格子进行坐标定义,用 (列号colcolcol, 行号rowrowrow) 来表示每个格子 (行号row :0 ~ 7,列号col:0 ~ 7),可以得到格子左上角在窗口上的坐标(left,top)(left, top)(left,top)为
窗口坐标(left,top)=(列号col⋅列宽width,行号row⋅行高height)窗口坐标(left,top) = (列号col \cdot 列宽width, 行号row \cdot 行高height) 窗口坐标(left,top)=(列号col⋅列宽width,行号row⋅行高height)  调用ege_fillrect(left, top, width, height) 即可进行绘制。

完整代码如下

#include <graphics.h>
#include <cmath>int main() {//定义格子宽高及格子行列数int gridWidth = 80, gridHeight = 80;int numCol = 8, numRow = 8;//计算窗口宽高及中心位置int winWidth = numCol * gridWidth, winHeight = numRow * gridHeight;int xCenter = winWidth / 2, yCenter = winHeight / 2;//创建窗口initgraph(winWidth, winHeight, INIT_RENDERMANUAL);ege_enable_aa(true);setbkcolor_f(EGERGB(0xFF, 0xFF, 0xFF));//定义深色和浅色color_t darkColor  = EGEARGB(255, 34, 34, 34);color_t lightColor = EGEARGB(255, 216, 216, 216);//绘制格子for (int row = 0; row < numRow; row++) {for (int col = 0; col < numCol; col++) {int x = col * gridWidth, y = row * gridHeight;color_t gridColor = darkColor;//根据格子位置确定颜色()if ((row + col) % 2 == 0) {gridColor = lightColor;}//绘制格子setfillcolor(gridColor);ege_fillrect(x, y, gridWidth, gridHeight);}}getch();closegraph();return 0;
}

运行结果如图


EGE专栏:EGE专栏

上一篇:EGE基础入门篇(六):基本图形

下一篇:EGE基础入门篇(八):清屏与重绘

EGE基础入门篇(七):组合图形相关推荐

  1. EGE基础入门篇(六):基本图形

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(五):窗口简单操作 下一篇:EGE基础入门篇(七):组合图形 一.EGE提供的基本图形 EGE绘制图形相关库函数文档 https://xege.org ...

  2. EGE基础入门篇(八):清屏与重绘

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(七):组合图形 下一篇:EGE基础入门篇(九):双缓冲与手动渲染 一.清屏   清屏即 清除屏幕(clear screen) ,可以将窗口上的输出内容 ...

  3. EGE基础入门篇(三):开场动画

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(二):开始使用EGE 下一篇:EGE基础入门篇(四):窗口简单操作 文章目录 开场动画 1. EGE开场动画的默认方式 2. 开场动画的开启 3. 开 ...

  4. EGE基础入门篇(九):双缓冲与手动渲染

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(八):清屏与重绘 下一篇: 文章目录 一.双缓冲机制 1. 单缓冲绘图 1.1 单缓冲绘图的缺点 1.2 系统读取帧缓冲 2. 双缓冲绘图 2.1 双 ...

  5. EGE基础入门篇(二):开始使用EGE

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(一):绘图基础知识 下一篇:EGE基础入门篇(三):开场动画 EGE基础入门篇(二) 文章最后修改时间:2021年6月23日19:30:47 文章目录 ...

  6. linux入门_Linux超详细0基础入门篇(一)

    首先要感谢大康老师对我在Linux操作系统上的教导. 今天来讲一下用途广泛的Linux的基础入门教程 仅仅是做入门使用,如果想更加深入的学习那就需要自己做探索了. 本次例子使用的是kali linux ...

  7. Linux基础入门篇知识回顾

    Linux基础入门篇知识回顾 一.回顾书籍 二.基础知识 1.计算机基础知识 1.1计算机的特点及发展趋势 ①特点 ②发展趋势 1.2计算机系统组成 ①计算机硬件概念 ②计算机硬件各部分功能 ![在这 ...

  8. 《Ansible权威指南 》一 第一篇 Part 1 基础入门篇

    本节书摘来自华章出版社<Ansible权威指南 >一书中的第1章,第1.1节,李松涛 魏 巍 甘 捷 著更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 ...

  9. matlab画图入门篇--各种基本图形绘制的函数与实例【转载】

    MATLAB画图入门篇--各种基本图形绘制的函数与实例 一. 二维图形(Two dimensional plotting) 1. 基本绘图函数(Basic plotting function):Plo ...

最新文章

  1. 有一种尴尬,叫大厂中层
  2. java serialization/deserialization (序列化对象自描述)
  3. ElastciSearch简单总结(笔记)
  4. 悦虎144固件,华强北二代悦虎144固件,1562M芯片144固件
  5. Golang切片的三种简单使用方式及区别
  6. OS操作系统概念简介
  7. Java多线程编程总结 链接
  8. 显卡刷bios改型号_怎么刷显卡bios(显卡刷BIOS可以提高性能)
  9. Karen与测试 奇迹淫巧+快速幂
  10. phpmyadmin scriptssetup.php 反序列化漏洞(WooYun-2016-199433)
  11. QQ游戏当前在线总人数查看
  12. angularJs - 弹窗
  13. win easypanel安装php,windows下kangle虚拟主机-kangleeasypanel安装图文教程以及心得
  14. SQP21-19-10-1CC-18高压定量叶片泵
  15. weui UI库适用范围
  16. mysql dlz驱动,安装wddns3 /dlz_mysql_driver.c:76:19: 错误:mysql.h:没有那个文件或目录...
  17. 登录江苏人社网办大厅
  18. 一文读懂iOS如何使用TestFlight进行测试
  19. 使用Python操控手机微信app(最新教程)
  20. 关于sap的Logon的几个参数

热门文章

  1. java圆和椭圆的关系_圆与椭圆 - brifuture - 博客园
  2. Python编程笔记6字典
  3. Web前端开发之浏览器兼容问题
  4. java面向对象的小项目_java第二季面向对象结课小项目之答答租车系统
  5. 蓝桥杯 ADV-154 质数的后代
  6. 等保三级合规要求:HTTPS安全加密将势在必行
  7. 机器人编程基础-ETH ROS 2022-Programming for Robotics
  8. freemarker导出excel,office打不开的问题
  9. Linux下使用ClamAV病毒查杀
  10. 10 nginx 中的 slab