资讯详情

EGE基础入门篇(七):组合图形

EGE专栏:EGE专栏

上一篇:EGE基本介绍(6):基本图形

下一篇:EGE基本介绍(8):清屏和重绘

一、 组合图形

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

??可以使用复杂的图形多边形可由多个三角形组成。 ??同一图形也可以以不同的方式由基本图形组合。并且可以使用后绘制的图形将首先绘制图形覆盖的原理。 在这里插入图片描述

2. 绘制的顺序性

??图形的绘制有序,不能随意按任何顺序绘制。 ??

??如下图所示,当物体存在一定的遮挡关系时,需要按由远到近的顺序,先画远处的物体,再画近处的物体,这样绘制出的图形才会符合实际。否则,图中的树木会被草地和高山所覆盖。 ??在三维物体渲染中,也叫,通过按照远离视点的顺序对物体进行排序,然后按顺序绘制物体,以获得正确的渲染结果。 ??如下图所示,图为通过,得到两种不同的绘制结果,右侧按压二叉树图形是我们想要的。

二、组合图形的绘制

??

1. 彭罗斯三角形

??它是一种利用视觉错觉构造的不可能图形,在三维空间中并不真实和客观。这种图形可以从特定的角度观察到二维空间"不可能图形",因此,彭罗斯三角形是二维图形三维投影形成的光学错觉。彭罗斯三角形广泛应用于纪念碑谷。

??在二维绘图中,绘图方法有很多种,可以看作是三个不重叠的多边形组合,也可以看作是的投影(纪念碑谷的做法适合三维模型),也可以改变三维物体表面投影的屏蔽关系。 ??在这里,我们通过构建三维模型来绘制彭罗斯三角形。 ??我们首先根据物体在三维坐标系中的位置得到顶点的三维坐标,然后投影到平面上,得到平面上的二维坐标,然后转换到窗口坐标系,得到每个顶点的多边形坐标 绘图即可。

??通过对单位立方体的分析,可以发现立方体被投影成正六角形。因为投影面垂直于向量 v v v,与 v v v垂直线段投影后长度不变。从图中可以看出平面ABC垂直于向量 v v v,所以投影后 A B 、 A C 和 B C AB、AC和BC AB、AC和BC长度不变,长度为 2 \sqrt{2} 2 。通过对在坐标轴上的三个点A、B、D映射关系分析,我们就能得到相应的变换关系。   三维空间上的顶变换后到 x O y xOy xOy平面后,再通过视口变换转换成窗口坐标系上的坐标,就可以利用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枚。棋盘格子颜色分两种,颜色并不固定。每个格子的绘制只需要计算出即可,然后使用来绘制。

  先对每个格子进行坐标定义,用 (列号 c o l col col, 行号 r o w row row) 来表示每个格子 (行号row :0 ~ 7,列号col:0 ~ 7),可以得到格子左上角在窗口上的坐标 ( l e f t , t o p ) (left, top) (left,top)为 窗 口 坐 标 ( l e f t , t o p ) = ( 列 号 c o l ⋅ 列 宽 w i d t h , 行 号 r o w ⋅ 行 高 h e i g h t ) 窗口坐标(left,top) = (列号col \cdot 列宽width, 行号row \cdot 行高height) 窗口坐标(left,top)=(列号col⋅列宽width,行号row⋅行高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红外传感器p60074

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司