使用C语言实现二维,三维绘图算法(1)-透视投影

---- 引言----

每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其实想想, Win32中既然存在画线画点函数, 利用计算机图形学的知识, 我们用可以用纯C调用Win32实现三维绘图, 完全不用借助OpenGL和DirectX, 这有重复造轮子的嫌疑, 但是自己动手实现一遍, 毕竟也是有意义的.

[效果演示]

线框效果, 隐藏面采用虚线

颜色填充后效果

[透视投影理论]   

分析:假定投影中心在Z轴上(z=-d处),投影面在xoy面上,与z轴垂直,d为投影面与=投影中心的距离。现求空间一点p(x, y, z)的透视投影p'(x', y', z')点的坐标。

根据相似三角形对应边成比例关系有:

写成矩阵形式如下:

透视缩小效应:物体的透视投影的大小与物体到投影中心的Z方向距离成反比。


    特点:透视投影的深度感更强,更加具有真实感,但透视投影不能够准确反映物体的大小和形状。
    (1)透视投影的大小与物体到投影中心的距离有关。
    (2)一组平行线若平行于投影平面时,它们的透视投影仍然保持平行。
    (3)只有当物体表面平行于投影平面时,该表面上的角度在透视投影中才能被保持。

灭点:透视投影中不平行于投影面的平行线的投影会汇聚到一个点,这个点称为灭点(Vanishing Point)。
    坐标轴方向的平行线在投影面上形成的灭点称作主灭点。 透视投影可以按照主灭点的个数分类:
    (1)一点透视有一个主灭点,即投影面与一个坐标轴正交,与另外两个坐标轴平行。
    (2)二点透视有两个主灭点,即投影面与两个坐标轴相交,与另一个坐标轴平行。
    (2)三点透视有三个主灭点,即投影面与三个坐标轴都相交。

[编程实现要点]

计算三维投影点的函数

void Calc3DPoint(void)
{
x = (-)*x;
xa = cr1*x - sr1*z;
za = sr1*x + cr1*z; x = cr2*xa + sr2*y;
ya = cr2*y - sr2*xa; z = cr3*za - sr3*ya;
y = sr3*za + cr3*ya; x=x+mx; y=y+my; z=z+mz; sx = d*x/z;
sy = d*y/z;
return;
}

逐个画出各个侧面, 并进行消隐形探测

...
surface1:
x1=B1[][]; y01=B1[][]; z1=B1[][];
x2=B1[][]; y2=B1[][]; z2=B1[][];
x3=B1[][]; y3=B1[][]; z3=B1[][];
VisibilityTest(); if(sp>) goto surface2; sx1=B2[][]; sy1=B2[][];
sx2=B2[][]; sy2=B2[][];
sx3=B2[][]; sy3=B2[][];
sx4=B2[][]; sy4=B2[][];
sx5=B3[][]; sy5=B3[][];
DrawPoly(); surface2:
x1=B1[][]; y01=B1[][]; z1=B1[][];
x2=B1[][]; y2=B1[][]; z2=B1[][];
x3=B1[][]; y3=B1[][]; z3=B1[][];
VisibilityTest(); if(sp>) goto surface3; sx1=B2[][]; sy1=B2[][];
sx2=B2[][]; sy2=B2[][];
sx3=B2[][]; sy3=B2[][];
sx4=B2[][]; sy4=B2[][];
sx5=B3[][]; sy5=B3[][];
DrawPoly();
...

使用C语言实现二维,三维绘图算法(1)-透视投影的更多相关文章

  1. 使用C语言实现二维,三维绘图算法(3)-简单的二维分形

    使用C语言实现二维,三维绘图算法(3)-简单的二维分形 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  2. 使用C语言实现二维,三维绘图算法(2)-解析曲面的显示

    使用C语言实现二维,三维绘图算法(2)-解析曲面的显示 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  3. ARCGIS二维三维导航

    在使用代码前需要先安装arcgis10.0    或者10.1都可以    不过本人建议初学者安装10.0比较容易安装.. 安装方式和二维三维地图的加载网上都有,就不在此一一赘述了. 先从基本的功能开 ...

  4. [图形学] 习题8.12 NLN二维线段裁剪算法实现

    Nicholl-Lee-Nicholl二维线段裁剪算法相对于Cohen-Sutherland和Liang-Barsky算法来说,在求交点之前进行了线段端点相对于几个区域的判断,可以确切的知道要求交点的 ...

  5. C语言之二维数组

    二维数组 还是一个数组,只不过数组中得每一个元素又是一个数组 1). 声明语法 类型 数组名[行][列]; 例:  int nums[2][3];//2行3列的二维数组,保存的数据类型是int类型 c ...

  6. VC、OpenGL、ArcGIS Engine开发的二维三维结合的GIS系统

    一.前言 众所周知,二维GIS技术发展了近四十年,伴随着计算机软硬件以及关系型数据库的飞速发展,二维GIS技术已日臻完善.在对地理信息的分析功能上有着无可比拟的优势.一些宏观的地理信息,一维的地理信息 ...

  7. ARCGIS二维三维互动

    当对三维模型进行操作时(如导航.平移)二维地图自动跟进. private void Synckron() { m_pGlobe = this._GlobeControl.Globe; m_pMap = ...

  8. ARCGIS二维三维放大缩小

    private void ULZoomPan() { ESRI.ArcGIS.SystemUI.ICommand com = new ControlsGlobeFixedZoomOutCommand( ...

  9. ARCGIS二维三维平移

    private void glZoomPan() { ESRI.ArcGIS.SystemUI.ICommand com = new ControlsGlobePanTool(); com.OnCre ...

随机推荐

  1. 51Nod 算法马拉松12 Rikka with sequences

    当时做比赛的时候听说过这类用KD_Tree维护的数据结构题 然后知道是KD_Tree,然而并不知道怎么写QAQ 比赛完了之后%了一发代码 其基本思路是这样的: 1.首先我们把询问[L,R]看成二维平面 ...

  2. Project Euler 78:Coin partitions

    Coin partitions Let p(n) represent the number of different ways in which n coins can be separated in ...

  3. hdu 3863 No Gambling

    #include<stdio.h> int main() { int n; ) { printf("I bet on Oregon Maple~\n"); } ; } ...

  4. MyBatis Mapper 文件例子

    转载:http://blog.csdn.net/ppby2002/article/details/20611737 <?xml version="1.0" encoding= ...

  5. 张小龙谈如何写E-mail软件

    编者语:鼎鼎大名的Foxmail软件制作者,你一定不会陌生吧!本刊第三期特刊还刊登过此君的生活照一张,可谓威风八面.小编此次突发奇想,“死缠烂打”,费了九牛二虎之力,终于约他写了一篇有关写E-mail ...

  6. Linux和Linux之间共享目录

    1.Linux 服务器端NFS服务器的配置 以root身份登陆Linux服务器,编辑/etc目录下的共享目录配置文件exports,指定共享目录及权限等. 执行如下命令编辑文件/etc/exports ...

  7. 利用PhantomJS搭建Highcharts export服务

    利用PhantomJS搭建Highcharts export服务 一直在使用Highcharts做web图表的展示, 但是当发送定时的报表邮件的遇到了这个问题. 为了保证邮件图表和web页图表样式一致 ...

  8. Android Dialogs(6)Dialog类使用示例:用系统theme和用自定义的theme

    使用dialog时有很多 方法,其中一个就是直接 使用基类Dialog,可用来作一个没有按钮的非模态提示框,它可以直接从系统的主题构造也可从自定义的主题构造. 基本步骤: a,构造 b,调用dialo ...

  9. hdu 4952 Number Transformation (找规律)

    题目链接 题意:给你个x,k次操作,对于第i次操作是:要找个nx,使得nx是>=x的最小值,且能整除i,求k次操作后的数 分析: 经过打表找规律,会发现最后的x/i,这个倍数会趋于一个固定的值, ...

  10. hdu 1885 Key Task (三维bfs)

    题目 之前比赛的一个题, 当时是崔老师做的,今天我自己做了一下.... 还要注意用bfs的时候  有时候并不是最先到达的就是答案,比如HDU 3442 这道题是要求最小的消耗血量伤害,但是并不是最先到 ...