# 图形学矩阵变换。

2 篇文章 0 订阅

static void makeTranslateMatrix(float x, float y, float z, float m[16])
{
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = x;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = y;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = z;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
}

static void makeScaleMatrix(float ax, float ay, float az, float m[16])
{
m[0] = ax; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = ay; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = az; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
}

1. 绕x轴将向量V旋转a角度到xoz平面，记为Tx(a)；
2. 绕y轴将向量V旋转b角度到与x轴重合，记为Ty(b);
3. 将物体绕x轴（向量V）旋转θ角度，记为Tx(θ);
4. 2的逆过程，记为Ty(-b);
5. 1的逆过程，记为Tx(-a)；

cosa = v2/sqrt(v1^2+v2^2);
cosb = v0;

x′＝x
y′＝ycosθ－zsinθ
z′＝ysinθ＋zcosθ

static void makeRotateMatrix(float angle, float ax, float ay, float az,float m[16])
{
float radians, sine, cosine, ab, bc, ca, tx, ty, tz;
float axis[3];
float mag;

axis[0] = ax;
axis[1] = ay;
axis[2] = az;
mag = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
if (mag)
{
axis[0] /= mag;
axis[1] /= mag;
axis[2] /= mag;
}
//normalizing above

radians = angle * myPi / 180.0;
ab = axis[0] * axis[1] * (1 - cosine);
bc = axis[1] * axis[2] * (1 - cosine);
ca = axis[2] * axis[0] * (1 - cosine);
tx = axis[0] * axis[0];
ty = axis[1] * axis[1];
tz = axis[2] * axis[2];

m[0] = tx + cosine * (1 - tx);
m[1] = ab + axis[2] * sine;
m[2] = ca - axis[1] * sine;
m[3] = 0.0f;

m[4] = ab - axis[2] * sine;
m[5] = ty + cosine * (1 - ty);
m[6] = bc + axis[0] * sine;
m[7] = 0.0f;

m[8] = ca + axis[1] * sine;
m[9] = bc - axis[0] * sine;
m[10] = tz + cosine * (1 - tz);
m[11] = 0;

m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1;
}

gluLookAt(double eyex, double eyey, double eyez, double centerx, double centery, double centerz, double upx, double upy, double upz）

1. 将眼坐标系变换到同世界坐标系重合。
2.代数的方法。

1. 代数上已经证明的公式：先移动eye的位置到世界坐标系的原点，再进行正交变换；
2. 由基本的变换合成，如下：
1）移动眼睛的位置到世界坐标系原点；
2）将眼坐标系绕世界坐标系x轴旋转，使得眼坐标系的z轴位于世界坐标系xoz平面；
3）将眼坐标系绕世界坐标系y轴旋转，使得眼坐标系的z轴和世界坐标系z轴重合；
4）将眼坐标系绕世界坐标系z轴旋转，使得眼坐标系的x、y轴和世界坐标系x、y轴重合；

x' =(OP-Oeye).u = OP.u - Oeye.u =(x,y,z).(u[0],u[1],u[2]) -Oeye.(u[0],u[1],u[2]);

y、z类似，我想你应该能写出矩阵来了吧，此处矩阵略过，直接看代码吧。

/* Build a row-major (C-style) 4x4 matrix transform based on the parameters for gluLookAt. */
static void buildLookAtMatrix(double eyex, double eyey, double eyez,
double centerx, double centery, double centerz,
double upx, double upy, double upz,float m[16])
{
double x[3], y[3], z[3], mag;

/* Difference eye and center vectors to make Z vector. */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
/* Normalize Z. */
mag = sqrt(z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
if (mag) {
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}

/* Up vector makes Y vector. */
y[0] = upx;
y[1] = upy;
y[2] = upz;

/* X vector = Y cross Z. */
x[0] = y[1]*z[2] - y[2]*z[1];
x[1] = -y[0]*z[2] + y[2]*z[0];
x[2] = y[0]*z[1] - y[1]*z[0];

/* Recompute Y = Z cross X. */
y[0] = z[1]*x[2] - z[2]*x[1];
y[1] = -z[0]*x[2] + z[2]*x[0];
y[2] = z[0]*x[1] - z[1]*x[0];

/* Normalize X. */
mag = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}

/* Normalize Y. */
mag = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}

/* Build resulting view matrix. */
m[0*4+0] = x[0]; m[0*4+1] = x[1];
m[0*4+2] = x[2]; m[0*4+3] = -x[0]*eyex + -x[1]*eyey + -x[2]*eyez;

m[1*4+0] = y[0]; m[1*4+1] = y[1];
m[1*4+2] = y[2]; m[1*4+3] = -y[0]*eyex + -y[1]*eyey + -y[2]*eyez;

m[2*4+0] = z[0]; m[2*4+1] = z[1];
m[2*4+2] = z[2]; m[2*4+3] = -z[0]*eyex + -z[1]*eyey + -z[2]*eyez;

m[3*4+0] = 0.0; m[3*4+1] = 0.0; m[3*4+2] = 0.0; m[3*4+3] = 1.0;
}

z'= f(z)/w' = （Zfar+Znear） / ( Zfar – Znear ) + [2* Zfar*Znear / ( Zfar – Znear )]/z

1. 在透视投影中这种关系是非线性的，而且非线性的程度与Frustum函数中的far/near（或gluPerspective函数中的zFar/zNear）成比例—— 也不是严格成比例，因为有一个Zfar*Znear 在。
2. 这种非线性在靠近近截面时增加了Z值的精度，而且增加了深度缓存的效率；但是在视见体的其它部分则降低了精度，也就减少了深度缓存的精确性—— 在上图，将[-Zfar,-Znear]之间等分，呵呵，靠近-Znear得到的Z’的范围显然大得多。
3. 根据经验，far/near比值大于1000会有这种不好的效果。所以一般far/near比值应小于1000。要想解决这个问题，最简单的方法是通过将近截面远离眼睛来降低far/near比值，其唯一的副作用是离眼睛很近的物体可能会被裁减掉，但在特定的应用程序中这很少是个问题，近截面的位置对X、Y坐标的投影没有影响，因此这对图像的影响很小——这个要牢记，呵呵。

• 0
点赞
• 5
收藏
觉得还不错? 一键收藏
• 1
评论
12-22 844
12-21 4万+
06-07
01-06 2911
04-12 12万+
07-27 2万+
03-11 2214
05-27 2万+

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。