04-二维变换和二维观察

nobility 发布于 2020-02-06 1469 次阅读


二维变换和二维观察

齐次坐标

用n+1维向量表示n维向量

规范化齐次坐标:n+1维向量的最后一维是1

变换

平移变换

\begin{matrix}
1 & 0 & 0\\
0 & 1 & 0\\
x变化量 & y变化量 & 1
\end{matrix}
\right]$$

#### 比例变换

- 缩放系数不相等

$$\left[
\begin{matrix}
x缩放系数 & 0 & 0\\
0 & y缩放系数 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

- 等比例缩放

$$\left[
\begin{matrix}
1 & 0 & 0\\
0 & 1 & 0\\
0& 0 & 缩放系数
\end{matrix}
\right]$$

#### 对称变换

- 关于x轴对称

$$\left[
\begin{matrix}
1 & 0 & 0\\
0 & -1 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

- 关于y轴对称

$$\left[
\begin{matrix}
-1 & 0 & 0\\
0 & 1 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

#### 旋转变换

- 绕原点逆时针旋转θ度

$$\left[
\begin{matrix}
cos\theta & sin\theta & 0\\
-sin\theta & cos\theta & 0\\
0& 0 & 1
\end{matrix}
\right]$$

- 绕原点顺时针旋转θ度

$$\left[
\begin{matrix}
cos\theta & -sin\theta & 0\\
sin\theta & cos\theta & 0\\
0& 0 & 1
\end{matrix}
\right]$$

#### 错切变换

- 沿x方向错切

$$\left[
\begin{matrix}
1 & 0 & 0\\
x错切量 & 1 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

- 沿y方向错切

$$\left[
\begin{matrix}
1 & y错切量 & 0\\
0 & 1 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

- 沿xy方向错切

$$\left[
\begin{matrix}
1 & b & 0\\
c & 1 & 0\\
0& 0 & 1
\end{matrix}
\right]$$

#### 复合变换

即变换矩阵相乘(注意顺序,因为矩阵乘法不满足交换律)

#### 多点变换齐次坐标

$$\left[
\begin{matrix}
x_1 & y_1 & 1\\
x_2 & y_2 & 1\\
... & ... & 1
\end{matrix}
\right]$$

#### 相对任意参考点的二维几何变换

1. 将参考点移到原点
2. 对原点进行二维变换
3. 将参考点反平移回原来位置

### 窗口和视区

世界坐标系的窗口与屏幕坐标系中的视区的映射

### 直线裁剪

#### Cohen-Sutherland裁剪算法

![编码裁剪算法](计算机图形学/编码裁剪算法.svg)

#### Liang-Barsky算法

1. 计算p和q值的值

$p_1=x_1-x_2$ $q_1=x_1-x_{left}$

$p_2=x_2-x_1$ $q_2=x_{right}-x_1$

$p_3=y_1-y_2$ $q_3=y_1-y_{bottom}$

$p_4=y_2-y_1$ $q_4=y_{top}-y_1$

2. 计算使用公式$u_k=\frac{q_k}{p_k}$,计算出各个u值

3. 根据$p_k$的符号将$u_k$两两分组

1. $p_k<0$组与0取最大
2. $p_k>0$组与1取最小

4. 得到两个u值分别带入直线参数方程即可得到裁剪后的结果

$$\begin{cases} x=x_1+u(x_2-x_1) \\ y=y_1+u(y_2-y_1) \end{cases}$$

### 多边形裁剪

#### Sutherland-Hodgeman算法

![Sutherland-Hodgeman算法](计算机图形学/Sutherland-Hodgeman算法.svg)

#### Weiler-Atherton算法

![Weiler-Atherton算法](计算机图形学/Weiler-Atherton算法.svg)

### 二维观察流程

1. 用户坐标系生成图形
2. 将用户坐标系下的图形描述变换到观察坐标系
3. 在观察坐标系下对窗口进行裁剪
4. 裁剪后进行窗口到视区的变换
5. 将视区中图形内容变换到设备坐标系中

## 三维变换和三违观察

### 变换

#### 平移变换

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
x变化量 & y变化量 & z变化量 & 0
\end{matrix}
\right]$$

#### 比例变换

- 局部

$$\left[
\begin{matrix}
x缩放系数 & 0 & 0 & 0\\
0 & y缩放系数 & 0 & 0\\
0 & 0 & z缩放系数 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- 整体

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 缩放系数
\end{matrix}
\right]$$

#### 旋转变换

- z轴旋转变换

顺时针

$$\left[
\begin{matrix}
cos\theta & sin\theta & 0 & 0\\
-sin\theta & cos\theta & 0 & 0\\
0& 0 & 1 & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

逆时针

$$\left[
\begin{matrix}
cos\theta & -sin\theta & 0 & 0\\
sin\theta & cos\theta & 0 & 0\\
0& 0 & 1 & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

- x轴旋转变换

顺时针

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & cos\theta & sin\theta & 0\\
0& -sin\theta & cos\theta & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

逆时针

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & cos\theta & -sin\theta & 0\\
0& sin\theta & cos\theta & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

- y轴旋转变换

顺时针

$$\left[
\begin{matrix}
cos\theta & 0 & -sin\theta & 0\\
0 & 1 & 0 & 0\\
sin\theta& 0 & cos\theta & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

逆时针

$$\left[
\begin{matrix}
cos\theta & 0 & sin\theta & 0\\
0 & 1 & 0 & 0\\
-sin\theta& 0 & cos\theta & 0\\
0 & 0 & 0 & 1\end{matrix}
\right]$$

#### 对称变换

- xoy平面

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & -1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- yoz平面

$$\left[
\begin{matrix}
-1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- zox平面

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & -1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- x轴

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & -1 & 0 & 0\\
0 & 0 & -1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- y轴

$$\left[
\begin{matrix}
-1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & -1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- z轴

$$\left[
\begin{matrix}
-1 & 0 & 0 & 0\\
0 & -1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- 原点

$$\left[
\begin{matrix}
-1 & 0 & 0 & 0\\
0 & -1 & 0 & 0\\
0 & 0 & -1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

#### 相对任意参考点的三维变换

1. 将参考点移到原点
2. 针对原点进行变换
3. 参考点反平移到原来位置

#### 参考任意轴的三维旋转变换

1. 将轴线段的一端移动到坐标原点
2. 将轴线段先旋转到坐标系平面上,再旋转到轴上
3. 进行绕轴旋转变换
4. 在将轴线段移动到原来位置

### 投影

#### 三视图

- 主视图(xoz)

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 0 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1
\end{matrix}
\right]$$

- 俯视图(xoy):再绕x轴旋转负九十度,再z轴方向平移$z_0$距离

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & -z_0 & 1
\end{matrix}
\right]$$

- 侧视图(yoz):再绕z轴旋转负九十度,再x轴方向平移$x_0$距离

$$\left[
\begin{matrix}
0 & 0 & 0 & 0\\
-1 & 0 & 0 & 0\\
0 & 0 & 1 & 0\\
-x_0 & 0 & 0 & 1
\end{matrix}
\right]$$

#### 透视投影

- 一点透视:将三维物体平移到适当位置(l,m,n),进行透视变换(d是视距),为了方便绘制,向xoy平面做正投影变换,将结果变换到xoy平面

$$\left[
\begin{matrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 0 & \frac{1}{d}\\
l & m & 0 & 1+\frac{n}{d}
\end{matrix}
\right]$$

- 两点透视

- 三点透视

### 观察变换

#### 观察坐标系

$z_v$:视点(观察坐标系原点)与物体焦点的连线

$y_v$:向上方向

$x_v$:已知y和z轴后,根据右手定则得出

#### 变换

即求世界坐标系中点在观察坐标系中的坐标值

1. 将观察坐标系原点(视点)与世界坐标系移动重合,再经过旋转,使得两坐标系重合
2. 无需逆过程移回去,此变换矩阵就是点在观察坐标系的坐标的变换矩阵

### 三维观察流程

1. 在用户坐标系生成图形
2. 将用户坐标系下的图形描述变换到观察坐标系
3. 根据要求在观察坐标系下进行规范化投影变换
4. 进行三维裁剪
5. 进行正投影,投影到观察平面
6. 将矩形窗口图形依据二维坐标重构二维图形,经过窗口到视区的变换

## 简单光照模型

- 环境光:$I_{环境光}=I_{环境光强度}K_{环境光反射系数}$
- 理想漫反射光:$I_{漫反射光}=I_{点光源强度}K_{漫反射系数}(L_{点光源向量}·N_{物体表面法向量})$
- 镜面反射光:$I_{镜面反射光}=I_{点光源强度}K_{镜面反射系数}(R_{镜面反射方向向量}·V_{视线方向向量})^{n_{镜面反射指数}}$
- 向量点积:$\overrightarrow{a}·\overrightarrow{b}=x_1x_2+y_1y_2+z_1z_2$

四舍五入:+0.5取整

#### DDA(数值微分法)

k[0,1]:x每次加一,增量是k

k[1,+$\infty$]:y每次加一,增量是-1

#### 中点画线法

直线的方程Ax+By+C=0,已知点P(X,Y)

解:将P带入直线方程

k[0,1],第一个中点是x+1,y+0.5,即第一个中点带入直线得到A+0.5B(在直线上的点等于0,由于只需要判断符号,可以用两边同时乘2将小数消去)

- 小于0在直线下方,距上方的点近,取上方点:
- 下一个中点,在原来基础上x+1,y+1,增量是A+B
- 大于0在直线上方,距下方的点近,取下方点
- 下一个中点,在原来基础上x+1,增量是A
- 等于0在直线上,都行

k[1,+$\infty$],第一个中点是x+0.5,y+1,即第一个中点带入直线得到0.5A+B(在直线上的点等于0,由于只需要判断符号,可以用两边同时乘2将小数消去)

- 小于0在直线下方,距左面的点近,取左面点:
- 下一个中点,在原来基础上y+1,增量是B
- 大于0在直线上方,距右面的点近,取右面点
- 下一个中点,在原来基础上x+1,y+1,增量是A+B
- 等于0在直线上,都行

```flow
start=>start: 开始

input=>inputoutput: 输入两点坐标
init=>operation: 得到dx,dy,e=-dx,x=x1,y=y1
draw=>operation: 绘制坐标(x,y)
judge=>condition: 更新e=e+2dy/e+2dx/e-2dy/e-2dx,判断e>0
egt0=>operation: (x,y)更新为(x+1,y+1)/(x+1,y+1)/(x+1,y-1)/(x-1,y+1),e=e-2dx/e=e-2dy/e=e-2dx/e=e-2dy
elte0=>operation: (x,y)更新为(x+1,y)/(x,y+1)/(x+1,y)/(x,y+1)
isdraw=>condition: 是否绘制完毕

end=>end: 结束

start->input->init->draw->isdraw
isdraw(yes)->end
isdraw(no)->judge
judge(yes)->egt0->draw
judge(no)->elte0->draw
```

# 实验1

```c
#include "glut.h"
void init()
{
glClearColor(0.0,0.0,0.0,0.0); //背景清除颜色
}
void display(void)
{
int arr[11] = {GL_POINTS,
GL_LINES,GL_LINE_STRIP,GL_LINE_LOOP,
GL_POLYGON,GL_QUADS,GL_QUAD_STRIP,
GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN
},i=0,j=0,k=0;
float px = -0.9,py=0.9;
int x=0.5,y=0.5;
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(8.0);
glColor3f(1.0, 0.0, 0.0);

for(i=0;i<3;i++){
for(j=0;j<3;j++){
glBegin(arr[k]);
glVertex2f(px, py);
glVertex2f(px+0.2, py);
glVertex2f(px, py-0.2);
glVertex2f(px+0.2, py-0.2);
glEnd();
px+=0.3;
k++;
}
px = -0.9;
py-=0.3;
}
glBegin(arr[k]);
glVertex2f(px, py);
glVertex2f(px+0.2, py);
glVertex2f(px, py-0.2);
glVertex2f(px+0.2, py-0.2);
glEnd();
glFlush();
}
void main()
{
glutInitWindowSize(800,800); //设置窗口大小
glutInitWindowPosition(60,60); //设置窗口显示位置
glutCreateWindow("WireTeapot");//设置窗口标题
glutDisplayFunc(display);
init(); glutMainLoop();
}

```

# 实验2

```c
#include "Line.h"

void drawP(int x,int y){
glColor3f(0.0f,1.0f,0.0f);//设置点的颜色
glPointSize(1.0);
glBegin(GL_POINTS);
glVertex2f(x*1.0, y*1.0);
glEnd();
glFlush();
}

void swap(int &x1,int &x2,int &y1,int &y2) {
int t=0;
t=x1;x1=x2;x2=t;
t=y1;y1=y2;y2=t;
}

void drawLineBresenham(int x1 ,int y1,int x2,int y2)
{
int dx,dy,e,x,y;
dx=x2-x1,dy=y2-y1;

if(dy*dx>0){//k大于0
dx=abs(dx);
dy=abs(dy);
if(dx>dy){//x的变化率大于y的变化率
e=-dx;
if(x1>x2){
swap(x1,x2,y1,y2);
}
}else{//y的变化率大于x的变化率
e=-dy;
if(y1>y2){
swap(x1,x2,y1,y2);
}
}
}else{//k小于0
dx=abs(dx);
dy=abs(dy);
if(dx>dy){//x的变化率大于y的变化率
dy=-1*abs(dy);
e=-dx;
if(x1>x2){ //当最大位移方向的0值比1值大时,要交换点
swap(x1,x2,y1,y2);
}
}else{//y的变化率大于x的变化率
e=-dy;
dx=-1*abs(dx);
if(y1>y2){ //当最大位移方向的0值比1值大时,要交换点
swap(x1,x2,y1,y2);
}
}
}

x=x1,y=y1;//第一个点

if(dy*dx>0){//k大于0
if(dx>dy){//x的变化率大于y的变化率,x自增
while(x<x2){
drawP(x,y);
e+=2*dy;
if(e>0){
x++,y++;
e-=2*dx;
}else{
x++;
}
}
}else{//y的变化率大于x的变化率,y自增
while(y<y2){
drawP(x,y);
e+=2*dx;
if(e>0){
x++,y++;
e-=2*dy;
}else{
y++;
}
}
}
}else{//k小于零
if(dx>dy){//x的变化率大于y的变化率,x自增
while(x<x2){
drawP(x,y);
e-=2*dy;
if(e>0){
x++,y--;
e-=2*dx;
}else{
x++;
}
}
}else{//y的变化率大于x的变化率,y自增
while(y<y2){
drawP(x,y);
e-=2*dx;
if(e>0){
x--,y++;
e-=2*dy;
}else{
y++;
}
}
}
}
}

```

此作者没有提供个人介绍
最后更新于 2020-02-06