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


    目录

    画线操作

    画三角形操作

    按区间取点来进行绘制

    加入纹理


    画线操作

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

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

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

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

    1. class Point {
    2. public:
    3. float m_x;
    4. float m_y;
    5. RGBA m_color;
    6. floatV2 m_uv;
    7. Point(float _x = 0, float _y = 0, RGBA _color = RGBA(0, 0, 0, 0), floatV2 _uv = floatV2(0.0, 0.0)) {
    8. m_x = _x, m_y = _y, m_color = _color, m_uv = _uv;
    9. }
    1. //===========================Render==================================================
    2. void Render() {
    3. _canvas->clear();
    4. GT::Point ptArray[] = {
    5. {0.0,200.0, GT::RGBA(255,0,0),GT::floatV2(0,0)},
    6. {800.0,200.0, GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
    7. {100.0,600.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    8. {800.0,300.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    9. {200.0,150.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    10. };
    11. _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    12. _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    13. _canvas->gtDrawArray(GT::GT_LINE, 0, 5);
    14. //在这里画到设备上,hMem相当于缓冲区
    15. BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
    16. }
    1. void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
    2. {
    3. GT::Point pt0, pt1;
    4. byte* _vertexData = m_state.m_vertexData.m_data;
    5. byte* _colorData = m_state.m_colorData.m_data;
    6. switch (_mode) {
    7. case GT_LINE:
    8. _count /= 2;
    9. for (int i = 0; i < _count; i ++) {
    10. //取坐标,按步长
    11. float* _vertexDataFloat = (float*)_vertexData;
    12. pt0.m_x = _vertexDataFloat[0];
    13. pt0.m_y = _vertexDataFloat[1];
    14. _vertexData += m_state.m_vertexData.m_stride;
    15. _vertexDataFloat = (float*)_vertexData;
    16. pt1.m_x = _vertexDataFloat[0];
    17. pt1.m_y = _vertexDataFloat[1];
    18. _vertexData += m_state.m_vertexData.m_stride;
    19. //取颜色坐标
    20. RGBA* _colorDataRGBA = (RGBA*)_colorData;
    21. pt0.m_color = _colorDataRGBA[0];
    22. _colorData += m_state.m_colorData.m_stride;
    23. _colorDataRGBA = (RGBA*)_colorData;
    24. pt1.m_color = _colorDataRGBA[0];
    25. _colorData += m_state.m_colorData.m_stride;
    26. //画线
    27. drawLine(pt0, pt1);
    28. }
    29. break;
    30. case GL_TRIANGLE:
    31. break;
    32. default:
    33. break;
    34. }
    35. }

    简单解析一下:

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

    1. GT::Point ptArray[] = {
    2. {0.0,200.0, GT::RGBA(255,0,0),GT::floatV2(0,0)},
    3. {800.0,200.0, GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
    4. {100.0,600.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    5. {800.0,300.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    6. {200.0,150.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    7. };

    那么接下来的事就是如何利用这些信息来描绘这些点,并且调用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的坐标信息以及颜色信息,然后进行画线的过程。

    1. void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
    2. {
    3. GT::Point pt0, pt1;
    4. byte* _vertexData = m_state.m_vertexData.m_data;
    5. byte* _colorData = m_state.m_colorData.m_data;
    6. switch (_mode) {
    7. case GT_LINE:
    8. _count /= 2;
    9. for (int i = 0; i < _count; i ++) {
    10. //取坐标,按步长
    11. float* _vertexDataFloat = (float*)_vertexData;
    12. pt0.m_x = _vertexDataFloat[0];
    13. pt0.m_y = _vertexDataFloat[1];
    14. _vertexData += m_state.m_vertexData.m_stride;
    15. _vertexDataFloat = (float*)_vertexData;
    16. pt1.m_x = _vertexDataFloat[0];
    17. pt1.m_y = _vertexDataFloat[1];
    18. _vertexData += m_state.m_vertexData.m_stride;
    19. //取颜色坐标
    20. RGBA* _colorDataRGBA = (RGBA*)_colorData;
    21. pt0.m_color = _colorDataRGBA[0];
    22. _colorData += m_state.m_colorData.m_stride;
    23. _colorDataRGBA = (RGBA*)_colorData;
    24. pt1.m_color = _colorDataRGBA[0];
    25. _colorData += m_state.m_colorData.m_stride;
    26. //画线
    27. drawLine(pt0, pt1);
    28. }
    29. break;
    30. case GL_TRIANGLE:
    31. break;
    32. default:
    33. break;
    34. }
    35. }

    测试一下:

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

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

    画三角形操作

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

    1. //===========================Render==================================================
    2. void Render() {
    3. _canvas->clear();
    4. GT::Point ptArray[] = {
    5. {0.0,200.0, GT::RGBA(255,0,0),GT::floatV2(0,0)},
    6. {400.0,200.0, GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
    7. {500.0,400.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    8. {600.0,300.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    9. {200.0,150.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    10. {150.0,150.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    11. {220.0,100.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    12. };
    13. _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    14. _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    15. _canvas->gtDrawArray(GT::GL_TRIANGLE, 0, 7);
    16. //在这里画到设备上,hMem相当于缓冲区
    17. BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
    18. }
    1. void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
    2. {
    3. //三个点
    4. GT::Point pt0, pt1, pt2;
    5. byte* _vertexData = m_state.m_vertexData.m_data;
    6. byte* _colorData = m_state.m_colorData.m_data;
    7. byte* _texCoordData = m_state.m_texCoordData.m_data;
    8. switch (_mode) {
    9. case GT_LINE:
    10. ......
    11. break;
    12. case GL_TRIANGLE:
    13. _count /= 3;
    14. for (int i = 0; i < _count; i++) {
    15. //取坐标,按步长
    16. //pt0
    17. float* _vertexDataFloat = (float*)_vertexData;
    18. pt0.m_x = _vertexDataFloat[0];
    19. pt0.m_y = _vertexDataFloat[1];
    20. _vertexData += m_state.m_vertexData.m_stride;
    21. //pt1
    22. _vertexDataFloat = (float*)_vertexData;
    23. pt1.m_x = _vertexDataFloat[0];
    24. pt1.m_y = _vertexDataFloat[1];
    25. _vertexData += m_state.m_vertexData.m_stride;
    26. //pt2
    27. _vertexDataFloat = (float*)_vertexData;
    28. pt2.m_x = _vertexDataFloat[0];
    29. pt2.m_y = _vertexDataFloat[1];
    30. _vertexData += m_state.m_vertexData.m_stride;
    31. //取颜色坐标
    32. //pt1
    33. RGBA* _colorDataRGBA = (RGBA*)_colorData;
    34. pt0.m_color = _colorDataRGBA[0];
    35. _colorData += m_state.m_colorData.m_stride;
    36. //pt2
    37. _colorDataRGBA = (RGBA*)_colorData;
    38. pt1.m_color = _colorDataRGBA[0];
    39. _colorData += m_state.m_colorData.m_stride;
    40. //pt3
    41. _colorDataRGBA = (RGBA*)_colorData;
    42. pt2.m_color = _colorDataRGBA[0];
    43. _colorData += m_state.m_colorData.m_stride;
    44. //画三角形
    45. drawTriange(pt0, pt1, pt2);
    46. }
    47. break;
    48. default:
    49. break;
    50. }
    51. }

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

    按区间取点来进行绘制

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

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

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

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

    只需修改一下即可:

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

    测试:

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

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

    .

    加入纹理

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

    1. case GL_TRIANGLE:
    2. _count /= 3;
    3. for (int i = 0; i < _count; i++) {
    4. ......
    5. //取uv坐标
    6. floatV2* _uvData = (floatV2*)_texCoordData;
    7. pt0.m_uv = _uvData[0];
    8. _texCoordData += m_state.m_texCoordData.m_stride;
    9. _uvData = (floatV2*)_texCoordData;
    10. pt1.m_uv = _uvData[0];
    11. _texCoordData += m_state.m_texCoordData.m_stride;
    12. _uvData = (floatV2*)_texCoordData;
    13. pt2.m_uv = _uvData[0];
    14. _texCoordData += m_state.m_texCoordData.m_stride;

    测试:

    1. //===========================Render==================================================
    2. void Render() {
    3. _canvas->clear();
    4. GT::Point ptArray[] = {
    5. {0.0,0.0, GT::RGBA(255,0,0),GT::floatV2(0,0)},
    6. {500.0,0.0, GT::RGBA(0,255,0),GT::floatV2(1.0,0)},
    7. {500.0,300.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)},
    8. {0.0,300.0, GT::RGBA(0,0,255),GT::floatV2(0.0,1.0)},
    9. {0.0,0.0, GT::RGBA(0,0,255),GT::floatV2(0,0)},
    10. {500.0,300.0, GT::RGBA(0,0,255),GT::floatV2(1.0,1.0)}
    11. };
    12. _canvas->gtVertexPointer(2, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)ptArray);
    13. _canvas->gtColorPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_color);
    14. _canvas->gtTexCoordPointer(1, GT::GT_FLOAT, sizeof(GT::Point), (GT::byte*)&ptArray[0].m_uv);
    15. _canvas->gtDrawArray(GT::GL_TRIANGLE, 0, 6);
    16. _canvas->enableTexture(true);
    17. _canvas->bindTexture(_bkImage);
    18. //在这里画到设备上,hMem相当于缓冲区
    19. BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
    20. }

     

  • 相关阅读:
    mysql存储过程
    java的泛型机制详解篇一(基础知识点)
    【nacos】5.3 nacos 更新mqtt配置,自动加载连接EMQX
    oracle数据库禁用触发器
    Net 编译器平台--- Roslyn Scripting APIs
    【FPGA教程案例72】基础操作2——Xilinx原语学习及应用2
    Python中list列表的常见操作
    Vue3-watch监听ref和reactive数据的五种情况及watchEffect
    2007-2019年36家上市银行绿色信贷余额、绿色信贷占比、资产收益率、不良贷款率等数据
    Mapbox 与 Babylon.js 可视化 添加地形
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/127962806