zoukankan      html  css  js  c++  java
  • 三维变换之斜投影、透视投影

    编译器:VS2013

    原理:依旧是矩阵相乘,只要求得矩阵就可以很方便的求出结果

    注意!注意!注意!

    楼主数学学得不好,齐次坐标这里没好好听,齐次坐标的第四个坐标值一直为1,楼主懵逼的也按物体坐标等比例放大导致错误调了两天

    错误:

    1 int a[8][4] = { 0, 0, 0, 200, 200, 0, 0,200, 200, 200, 0,200, 0, 200, 0,200, 0, 0, 200,200, 200, 0, 200,200, 200, 200, 200,200, 0, 200, 200,200};

    正确:

    1 int a[8][4] = { 0, 0, 0, 1, 200, 0, 0, 1, 200, 200, 0, 1, 0, 200, 0, 1, 0, 0, 200, 1, 200, 0, 200, 1, 200, 200, 200, 1, 0, 200, 200, 1 };

    主函数块

     1 #include "stdafx.h"
     2 #include<stdio.h>
     3 #include"graphics.h"
     4 #include<stdlib.h>
     5 #include<math.h>
     6 
     7 #define PI 3.14159
     8 
     9 //函数声明
    10 void apoint(int a[][4]);//一点透视
    11 void oblique2_30(int a[][4]);//斜二测45°
    12 void oblique2_45(int a[][4]);//斜二测30°
    13 void twopoint(int a[][4]);//两点透视
    14 void threepoint(int a[][4]);//三点透视
    15 void putline(double b[][4]);//画线函数
    16 
    17 int main()
    18 {
    19     int gdriver = DETECT, gmove;
    20     int a[8][4] = { 0, 0, 0, 1, 200, 0, 0, 1, 200, 200, 0, 1, 0, 200, 0, 1, 0, 0, 200, 1, 200, 0, 200, 1, 200, 200, 200, 1, 0, 200, 200, 1 };
    21     
    22     initgraph(&gdriver, &gmove, "");
    23     setcolor(YELLOW);
    24 
    25     apoint(a);//一点透视
    26     //oblique2_30(a);//斜二测30°
    27     //oblique2_45(a);//斜二测45°
    28     //twopoint(a);//两点透视
    29     //threepoint(a);//三点透视
    30 
    31     system("pause");
    32 
    33     closegraph();
    34 
    35     return 0;
    36 }

    一点透视:

     1 //一点透视
     2 void apoint(int a[][4])
     3 {
     4     double k = 160, m = 220, n = 400, d = 500,b[8][4];
     5     int i;
     6 
     7     for (i = 0; i < 8; i++)
     8     {
     9         b[i][3] = (d + n + a[i][2]) / d*1.0;//其次变换
    10         b[i][0] = (a[i][0] + k) / b[i][3]*1.0;//x变换
    11         b[i][1] = (a[i][1] + m) / b[i][3]*1.0;//y变换
    12         b[i][2] = 0;//z变换
    13         b[i][3] = 1;//齐次坐标赋1
    14     }
    15 
    16     putline(b);//画线函数

    画线函数

     1 void putline(double b[][4])
     2 {
     3     int i;
     4 
     5     //小图层
     6     for (i = 0; i < 3; i++)
     7         line(b[i][0], b[i][1], b[i + 1][0], b[i + 1][1]);
     8 
     9     //小图层尾连接
    10     line(b[3][0], b[3][1], b[0][0], b[0][1]);
    11 
    12     //大图层
    13     for (i = 4; i < 7; i++)
    14         line(b[i][0], b[i][1], b[i + 1][0], b[i + 1][1]);
    15 
    16     //大图层首尾连接
    17     line(b[4][0], b[4][1], b[7][0], b[7][1]);
    18 
    19     //大小图层连接
    20     for (i = 0; i < 4; i++)
    21         line(b[i][0], b[i][1], b[i + 4][0], b[i + 4][1]);
    22 }

    二点透视

     1 //两点透视
     2 void twopoint(int a[][4])
     3 {
     4     double p = 0.002, r = 0.002, A = PI / 6.0, k = 150, n = 30, m = 50;
     5     //二维数组c为转换矩阵
     6     double b[8][4] = { 0 };
     7     //转换矩阵
     8     double c[4][4] = { { cos(A), 0, 0, p*cos(A) - r*sin(A) }, { 0, 1, 0, 0 }, { sin(A), 0, 0, p*sin(A) + r*cos(A) }, { k*cos(A) + n*sin(A), m, 0, p*(k*cos(A) + n*sin(A)) + r*(n*cos(A) - k*sin(A)) + 1 } };
     9     int i, j, x;
    10 
    11     //矩阵相乘
    12     for (i = 0; i < 8; i++)
    13         for (j = 0; j < 4; j++)
    14             for (x = 0; x < 4; x++)
    15                 b[i][j] += a[i][x] * c[x][j];
    16             
    17     for (i = 0; i < 8; i++)
    18         for (j = 0; j < 4; j++)
    19         {
    20             b[i][j] /= b[i][3];//使齐次坐标变为1
    21             b[i][j] = (int)b[i][j];//取整
    22         }
    23 
    24     putline(b);//画线函数
    25 }

    三点透视

     1 //三点透视
     2 void threepoint(int a[][4])
     3 {
     4     double p = 0.0015,q=0.0015, r = 0.0015, A = PI / 6.0,B=PI/45, k = 150, n = 30, m = 30;
     5     //二维数组c为转换矩阵
     6     double b[8][4] = { 0 };
     7     //转换矩阵
     8     double c[4][4] = { { cos(A),sin(A)*sin(B),0,p }, { 0,cos(B),0,q }, { sin(A),-cos(A)*sin(B),0,r }, { k*cos(A)+n*sin(A), m*cos(B)+sin(B)*(k*sin(B)-n*cos(A)),0,k*p+m*q+n*r} };
     9     int i, j, x;
    10 
    11     //矩阵相乘
    12     for (i = 0; i < 8; i++)
    13         for (j = 0; j < 4; j++)
    14             for (x = 0; x < 4; x++)
    15                 b[i][j] += a[i][x] * c[x][j];
    16 
    17     for (i = 0; i < 8; i++)
    18         for (j = 0; j < 4; j++)
    19         {
    20             b[i][j] /= b[i][3];//使齐次坐标变为1
    21             b[i][j] = (int)b[i][j];//取整
    22         }
    23 
    24     putline(b);//画线函数,括号内强制转换成int
    25 }

    斜二测30°

     1 //斜二测30°
     2 void oblique2_45(int a[][4])
     3 {
     4     double b[8][4];
     5     int i;
     6 
     7     for (i = 0; i < 8; i++)
     8     {
     9         b[i][0] = a[i][0] + a[i][2] * cos(PI / 4)*sqrt(5.0) / 5 * 1.0;//x变换
    10         b[i][1] = a[i][1] + a[i][2] * sin(PI / 4)*sqrt(5.0) / 5 * 2.0;//y变换
    11         b[i][2] = 0;//z变换
    12         b[i][3] = 1;//齐次坐标变换
    13     }
    14 
    15     putline(b);//画线函数
    16 }

    斜二测45°

     1 //斜二测45°
     2 void oblique2_30(int a[][4])
     3 {
     4     double b[8][4];
     5     int i;
     6 
     7     for (i = 0; i < 8; i++)
     8     {
     9         b[i][0] = a[i][0] + a[i][2] * cos(PI / 6)*sqrt(5.0) / 5 * 1.0;//x变换
    10         b[i][1] = a[i][1] + a[i][2] * sin(PI / 6)*sqrt(5.0) / 5 * 2.0;//y变换
    11         b[i][2] = 0;//z变换
    12         b[i][3] = 1;//齐次坐标变换
    13     }
    14 
    15     putline(b);//画线函数
    16 }

  • 相关阅读:
    移动支付
    PowerBI
    PowerBI
    Fiddler 页面字段(图标)含义详解
    Fiddler 抓包淘宝小程序(Android)
    【练习读写excel文件】读取sheet1里面a列的值,逐行粘贴到sheet2,3,4,5,6,7里面的指定字段
    【练习读写excel文件】根据某一字段将相同的类拆分
    【练习读写excel文件】创建workbook和批量创建Sheet
    require.js的使用的坑!
    js的异步的问题的再次理解
  • 原文地址:https://www.cnblogs.com/cdp1591652208/p/6919092.html
Copyright © 2011-2022 走看看