C++模拟OpenGL库——图形学状态机接口封装(二):基于状态机接口的画线&画三角形

目录

画线操作

画三角形操作

按区间取点来进行绘制

加入纹理


画线操作

上次我们定义了一系列状态机接口,并遗留了:

void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)

没有去实现,这次对他进行一个实现,一个利用状态机接口画线的功能。

这里直接上代码,并且连带着之前的关键类,方便理解:

	class Point {
	public:
		float m_x;
		float m_y;
		RGBA m_color;
		floatV2 m_uv;

		Point(float _x = 0, float _y = 0, RGBA _color = RGBA(0, 0, 0, 0), floatV2 _uv = floatV2(0.0, 0.0)) {
			m_x = _x, m_y = _y, m_color = _color, m_uv = _uv;
		}

		
//===========================Render==================================================
void Render() {
    _canvas->clear();

    GT::Point ptArray[] = {
        {0.0,200.0,       GT::RGBA(255,0,0),GT::floatV2(0,0)},
        {800.0,200.0,     GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
        {100.0,600.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {800.0,300.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {200.0,150.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    };

    _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    _canvas->gtDrawArray(GT::GT_LINE, 0, 5);

    //在这里画到设备上,hMem相当于缓冲区
    BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
}
	void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
	{
		GT::Point pt0, pt1;
		byte* _vertexData = m_state.m_vertexData.m_data;
		byte* _colorData = m_state.m_colorData.m_data;
		switch (_mode) {
		case GT_LINE:
			_count /= 2;
			for (int i = 0; i < _count; i ++) {
				//取坐标,按步长
				float* _vertexDataFloat = (float*)_vertexData;
				pt0.m_x = _vertexDataFloat[0];
				pt0.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;

				_vertexDataFloat = (float*)_vertexData;
				pt1.m_x = _vertexDataFloat[0];
				pt1.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;

				//取颜色坐标
				RGBA* _colorDataRGBA = (RGBA*)_colorData;
				pt0.m_color = _colorDataRGBA[0];

				_colorData += m_state.m_colorData.m_stride;

				_colorDataRGBA = (RGBA*)_colorData;
				pt1.m_color = _colorDataRGBA[0];
				_colorData += m_state.m_colorData.m_stride;

				//画线
				drawLine(pt0, pt1);
			}
			break;
		case GL_TRIANGLE:
			break;
		default:
			break;
		}
	}

简单解析一下:

首先我们从上往下看,我们有了一个Point类,里面包含了坐标xy,颜色RGBA信息m_color,以及uv坐标。
我们在Render函数里设定里五个点,分别是:

    GT::Point ptArray[] = {
        {0.0,200.0,       GT::RGBA(255,0,0),GT::floatV2(0,0)},
        {800.0,200.0,     GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
        {100.0,600.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {800.0,300.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {200.0,150.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    };

那么接下来的事就是如何利用这些信息来描绘这些点,并且调用drawLine来绘制直线了。
首先用gtVertexPointer获得点的信息:

_canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);

参数分别意味着:

  • 2:平面上的点,有两个元素
  • GT::GT_FLOAT:值类型是float类型
  • sizeof(GT::Point):每次步长是一个Point类的大小,这一点很重要
  • GT::byte*)ptArray:从这部分数据中的哪个位置开始取数据

对于

 _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);

也是同理,不多赘述。值得注意的是我们要从Point中的m_color部分开始取颜色的数据

接下来就是如何遍历这个Point数组,来取数据,并且把取来的数据进行一个装配,配置好点pt1和pt2的坐标信息以及颜色信息,然后进行画线的过程。

	void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
	{
		GT::Point pt0, pt1;
		byte* _vertexData = m_state.m_vertexData.m_data;
		byte* _colorData = m_state.m_colorData.m_data;
		switch (_mode) {
		case GT_LINE:
			_count /= 2;
			for (int i = 0; i < _count; i ++) {
				//取坐标,按步长
				float* _vertexDataFloat = (float*)_vertexData;
				pt0.m_x = _vertexDataFloat[0];
				pt0.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;

				_vertexDataFloat = (float*)_vertexData;
				pt1.m_x = _vertexDataFloat[0];
				pt1.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;

				//取颜色坐标
				RGBA* _colorDataRGBA = (RGBA*)_colorData;
				pt0.m_color = _colorDataRGBA[0];

				_colorData += m_state.m_colorData.m_stride;

				_colorDataRGBA = (RGBA*)_colorData;
				pt1.m_color = _colorDataRGBA[0];
				_colorData += m_state.m_colorData.m_stride;

				//画线
				drawLine(pt0, pt1);
			}
			break;
		case GL_TRIANGLE:
			break;
		default:
			break;
		}
	}

测试一下:

五个点,只能画出两条线。在Canvas::gtDrawArray有一个_count /= 2;,作用就是这个。

(其实颜色不对,估计是和windows下的RGBA 值没有对应上,,有时间再看看改改吧。原理上是对的,暂时就可以了)

画三角形操作

原理和画线是一样的,只不过每次绘制需要多加一个点,并且可以加入纹理的信息:

//===========================Render==================================================
void Render() {
    _canvas->clear();

    GT::Point ptArray[] = {
        {0.0,200.0,       GT::RGBA(255,0,0),GT::floatV2(0,0)},
        {400.0,200.0,     GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
        {500.0,400.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {600.0,300.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {200.0,150.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {150.0,150.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {220.0,100.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    };

    _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    _canvas->gtDrawArray(GT::GL_TRIANGLE, 0, 7);

    //在这里画到设备上,hMem相当于缓冲区
    BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
}
	void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
	{
		//三个点
		GT::Point pt0, pt1, pt2;
		byte* _vertexData = m_state.m_vertexData.m_data;
		byte* _colorData = m_state.m_colorData.m_data;
		byte* _texCoordData = m_state.m_texCoordData.m_data;

		switch (_mode) {
		case GT_LINE:
			......
			break;
		case GL_TRIANGLE:
			_count /= 3;
			for (int i = 0; i < _count; i++) {
				//取坐标,按步长
				//pt0
				float* _vertexDataFloat = (float*)_vertexData;
				pt0.m_x = _vertexDataFloat[0];
				pt0.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;
				//pt1
				_vertexDataFloat = (float*)_vertexData;
				pt1.m_x = _vertexDataFloat[0];
				pt1.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;
				//pt2
				_vertexDataFloat = (float*)_vertexData;
				pt2.m_x = _vertexDataFloat[0];
				pt2.m_y = _vertexDataFloat[1];
				_vertexData += m_state.m_vertexData.m_stride;

				//取颜色坐标
				//pt1
				RGBA* _colorDataRGBA = (RGBA*)_colorData;
				pt0.m_color = _colorDataRGBA[0];
				_colorData += m_state.m_colorData.m_stride;
				//pt2
				_colorDataRGBA = (RGBA*)_colorData;
				pt1.m_color = _colorDataRGBA[0];
				_colorData += m_state.m_colorData.m_stride;
				//pt3
				_colorDataRGBA = (RGBA*)_colorData;
				pt2.m_color = _colorDataRGBA[0];
				_colorData += m_state.m_colorData.m_stride;

				//画三角形
				drawTriange(pt0, pt1, pt2);
			}
			break;
		default:
			break;
		}
	}

结果如下,(颜色不对,先忽略下。。):

按区间取点来进行绘制

我们之前绘制的点,都是默认从头到尾的,比如:

_canvas->gtDrawArray(GT::GL_TRIANGLE, 0, 7);

有7个点,从0到7这样取。那如果要是想从2到5这样取呢?回到函数定义上:

void gtDrawArray(DRAW_MODE _mode,int _first,int _count);//从first的点,画count个点

只需修改一下即可:

void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
	{
		//三个点
		GT::Point pt0, pt1, pt2;
		byte* _vertexData = m_state.m_vertexData.m_data + _first * m_state.m_vertexData.m_stride;
		byte* _colorData = m_state.m_colorData.m_data + _first * m_state.m_colorData.m_stride;
		byte* _texCoordData = m_state.m_texCoordData.m_data + _first * m_state.m_texCoordData.m_stride;
		_count -= _first;
        .....................

测试:

_canvas->gtDrawArray(GT::GL_TRIANGLE, 2, 7);

取了5个点,只能画一个三角形。

.

加入纹理

void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count) 中:

case GL_TRIANGLE:
			_count /= 3;
			for (int i = 0; i < _count; i++) {
				......

				//取uv坐标
				floatV2* _uvData = (floatV2*)_texCoordData;
				pt0.m_uv = _uvData[0];
				_texCoordData += m_state.m_texCoordData.m_stride;

				_uvData = (floatV2*)_texCoordData;
				pt1.m_uv = _uvData[0];
				_texCoordData += m_state.m_texCoordData.m_stride;

				_uvData = (floatV2*)_texCoordData;
				pt2.m_uv = _uvData[0];
				_texCoordData += m_state.m_texCoordData.m_stride;

测试:

//===========================Render==================================================
void Render() {
    _canvas->clear();

    GT::Point ptArray[] = {
        {0.0,0.0,        GT::RGBA(255,0,0),GT::floatV2(0,0)},
        {500.0,0.0,      GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
        {500.0,300.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
        {0.0,300.0,      GT::RGBA(0,0,255),GT::floatV2(0.0,1.0)},
        {0.0,0.0,        GT::RGBA(0,0,255),GT::floatV2(0,0)},
        {500.0,300.0,    GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}        
    };

    _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    _canvas->gtTexCoordPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_uv);
    _canvas->gtDrawArray(GT::GL_TRIANGLE, 0, 6);

    _canvas->enableTexture(true);
    _canvas->bindTexture(_bkImage);

    //在这里画到设备上,hMem相当于缓冲区
    BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值