第一章:从3D到2D

本文是《从0开始图形学》的第一章内容。讲解如何将3D的模型"画"到2D的图形山。

概念解说

图形学渲染,就是将3D的东西"画"到2D的屏幕上,和拍照的效果是一样的,这也是为什么很多3D渲染引擎会有"相机"这个概念,这一节我们来看一下怎么把3D变成2D。

场景定义

首先,我们定义一个渲染场:一个定义好的坐标系中某个3D的箱子,黄色的球体代表相机,如下图所示

我们的渲染结果就应该同相机视角看到的结果一样,如下图所示,透过半透明的"画布",可以看到箱子在"画布"上的样子

问题提出

那么,如何实现上面效果呢?我们先从箱子的整体轮廓入手,很简单,只要将箱子的八个顶点坐标的Z轴分量去掉,找到图片上对应的X,Y就是对应顶点的渲染位置(图中红色的点),再将点和点之间用线连接起来,也就是箱子的8条边(图中黄色的线)

是不是马上就有点立体感了!那代码上要怎么实现呢,很简单!

C核心代码

首先,定义需要渲染的点,以及这些点的关系索引

复制代码
// 定义渲染数据
float _points[8][3] =       // 点的数据
{
    {469.70839522142523, 181.86451044628149, 268.14698315693755}, // x, y, z
    {741.60073227608791, 149.05001503297740, 390.61234945175556},
    {741.60073227608791, 535.42034601093997, 494.13996576730500},
    {469.70839522142523, 568.23484142424411, 371.67459947248699},
    {258.39926772391209, 64.579653989059977, 705.86003423269506},
    {530.29160477857477, 31.765158575755891, 828.32540052751301},
    {530.29160477857477, 418.13548955371851, 931.85301684306251},
    {258.39926772391209, 450.94998496702260, 809.38765054824444},
};

int _planes[6][4] =      // 面的数据
{
    {0, 1, 2, 3},     // 每个面4个角的顶点对应于索引值
    {4, 5, 6, 7},
    {1, 5, 6, 2},
    {3, 2, 6, 7},
    {0, 4, 7, 3},
    {0, 1, 5, 4}
};

第二步,根据上述的实现原理,将其画在结果图上,为方便,我们直接在ShowCGRst函数中对结果图进行修改,这里我们使用了OpenCV的画点函数cv::circle和画线函数cv::line

复制代码
    // 将_points画到结果上
    int x, y, z;

    for (int i = 0; i < 8; ++i)
    {
        x = _points[i][0];
        y = _points[i][1];
        z = _points[i][2];
        cv::circle(cvRst, cv::Point(x, y), 5, cv::Scalar(0, 0, 255), -1);     // 使用OpenCV的画点函数
    }

    // 将点之间的关系(即箱子的边缘线)画出来
    int x1, y1, z1;

    for (int i = 0; i < 6; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            x = _points[_planes[i][j]][0];
            y = _points[_planes[i][j]][1];
            z = _points[_planes[i][j]][2];
            x1 = _points[_planes[i][j + 1]][0];
            y1 = _points[_planes[i][j + 1]][1];
            z1 = _points[_planes[i][j + 1]][2];
            cv::line(cvRst, cv::Point(x, y), cv::Point(x1, y1), cv::Scalar(0, 255, 255), 2);
        }

        x = _points[_planes[i][0]][0];
        y = _points[_planes[i][0]][1];
        z = _points[_planes[i][0]][2];
        cv::line(cvRst, cv::Point(x, y), cv::Point(x1, y1), cv::Scalar(0, 255, 255), 2);
    }

完整代码见开头的下载资源,百度网盘下载处

这里已经画出了箱子的"骨",下一步我们将绘制箱子的"皮"

相关推荐
探物 AI16 天前
【3D·感知】从PointNet到PointPillars:如何让自动驾驶汽车“实时“看见3D世界?
3d·自动驾驶·汽车
苏州邦恩精密16 天前
GOM三维扫描在制造中的真实价值:让“修模”从经验动作变成数据动作
人工智能·科技·机器学习·3d·自动化·制造
YHHLAI16 天前
CSS 3D 硬核解析:四个属性手写旋转立方体
前端·css·3d
云飞云共享云桌面17 天前
传统工作站 vs 云飞云共享云桌面:制造业设计云桌面选型深度对比
运维·服务器·前端·网络·3d·架构·制造
LONGZETECH17 天前
无人机仿真教学软件选型实战:5 个硬核技术维度,避开实训建设踩坑
3d·无人机·交互·cocos2d
装不满的克莱因瓶17 天前
了解3D卷积原理——从空间感知到时空建模的深度学习核心算子
人工智能·pytorch·python·深度学习·机器学习·3d·ai
雪的季节17 天前
Qt Graphs 2D+3D介绍
qt·3d
CG_MAGIC17 天前
3ds Max材质编辑器:精简模式与Slate模式对比
3d·编辑器·材质·贴图·uv·建模教程
装不满的克莱因瓶17 天前
掌握3D CNN模型结构——从时空特征建模到视频理解与医学影像核心架构
人工智能·pytorch·python·深度学习·神经网络·3d·cnn
AniShort17 天前
AniShort携3D世界+3D导演台王炸组合AI短剧协作平台亮相2026横店AI短剧大会 近亿元融资赋能短剧工业化
人工智能·microsoft·3d