|
|
发表于 2007-3-7 18:43:00
|
显示全部楼层
Re:急!关于camera的小问题
这个问题。。。今天来好好解释一下吧。
(其实用D3DVec3TransformNormal也可以。)
我们先不用D3DX。用数学。
http://bbs.gameres.com/showthread.asp?threadid=73512
预备知识:
点的坐标与几何中的自由向量。
点可以用一组坐标表示(x,y,z)
自由向量,可以平移,他的坐标是终点的坐标减起点的。(看看高中数学书把)
我们说的“向量”,就是指(几何中的)自由向量----表示方向和长度的几何量!。
我们把自由向量的起点平移到原点,则终点坐标就等于向量坐标。
vector3只是一个数据结构而已,他可以表示:
(1)一个点。
(2)一个自由向量。
由于一些原因(我们最后再提,不影响),向量和坐标在d3d中往往不区别。
我们可以用矩阵对3d点作变换:
点的变换可以用点的坐标乘以一个3*3 <3行3列的> 变换矩阵。
我们可以用矩阵对3d向量作变换:
向量的变换可以用点的坐标乘以一个3*3 变换矩阵。
但是,一个vector3乘以一个3*3矩阵不是万能的。比如平移,就不能表示。
齐次坐标:
如果一个点的齐次坐标为:
(x,y,z,w)那么,
他的实际的坐标就是:
(x/w , y/w , z/w)
一个点(x0,y0,z0)的其次坐标可以表示为(x0,y0,z0,1)
一个齐次坐标的变换,需要4*4的矩阵才可以。
这样,我们可以用矩阵表示更多的变换(如平移)。
因为矩阵的内容更加丰富了(从3*3变成了4*4 )
但即使用4*4矩阵和其次坐标,也不是万能的。
比如(x',y',z')=(x^2,y^2,z^2)这个变换,等等,都不行。
不过,在d3d中已经够了。
如果一个点的变换不能用3*3矩阵和普通坐标表示,我们可以用4*4矩阵和齐次坐标.
对于向量,用3*3矩阵可以直接变换,外观上和点的变换没有区别,往往混为一谈!
如果3*3矩阵不行,...那就不像点那么简单了!具体:
如果向量(不是点!)无法直接用其次坐标和4*4矩阵来变换。
那么,怎么办呢?
(1)把向量平移,使得他的的起点在原点O。
(2)设终点为P(x,y,z).
(3)把P用其次坐标表示为(x,y,z,1).
(4)用4*4的矩阵变换P的其次坐标,新的点为P'.
(5)把OP'就是新的变换后的向量。
void Vec3MulMat(D3DXVECTOR3* ret,D3DXVECTOR3* v,D3DXMATRIX* m)
{
ret->x = v->x * m->_11 + v->y * m->_21 + v->z * m->_31;
ret->y = v->x * m->_12 + v->y * m->_22 + v->z * m->_32;
ret->z = v->x * m->_13 + v->y * m->_23 + v->z * m->_33;
}
(***D3DXMATRIX是一个4*4矩阵,我们用它来存储3*3矩阵也可以,多余的内存,就当作是废的!)
这个函数,是3个元素的向量乘以矩阵。D3DVec3TransformNormal和这个相同。
严格的说,D3DVec3TransformCoord是错误的!不符合线性代数。
应当是D3DVec4TransformCoord。
void D3DVec3TransformCoord(D3DXVECTOR3* ret,D3DXVECTOR3* v,D3DXMATRIX* m)
{
ret->x = v->x * m->_11 + v->y * m->_21 + v->z * m->_31 + 1 * m->41;
ret->y = v->x * m->_12 + v->y * m->_22 + v->z * m->_32 + 1 * m->42;
ret->z = v->x * m->_13 + v->y * m->_23 + v->z * m->_33 + 1 * m->43;
}
实际上,一个vector3的 线性 变换矩阵是3*3的。所以,D3DVec3TransformCoord是不符合数学的。
void D3DVec4TransformCoord(D3DXVECTOR4* ret,D3DXVECTOR4* v,D3DXMATRIX* m)
{
ret->x = v->x * m->_11 + v->y * m->_21 + v->z * m->_31 + 1 * m->41;
ret->y = v->x * m->_12 + v->y * m->_22 + v->z * m->_32 + 1 * m->42;
ret->z = v->x * m->_13 + v->y * m->_23 + v->z * m->_33 + 1 * m->43;
ret->w = v->x * m->_14 + v->y * m->_24 + v->z * m->_34 + 1 * m->44;
}
这才是正确的。
那么,D3DVec3TransformCoord是什么意思呢?
可以这么理解:
void D3DVec3TransformCoord(D3DXVECTOR3* ret,D3DXVECTOR3* v,D3DXMATRIX* m)
{
D3DXVECTOR4 ret2,v2;
v2.x=v.x;
v2.y=v.y;
v2.z=v.z;
v2.w=1;
D3DVec4TransformCoord(&ret2,&v2,&m);
ret->x=ret2.x / ret2->w;
ret->y=ret2.y / ret2->w;
ret->z=ret2.z / ret2->w;
}
先把你的普通3维坐标转换为3维齐次坐标,令w=1
然后乘以一个4*4矩阵,
最后在转换结果为普通3维坐标。
有些变换,无法用3*3的矩阵和普通3维坐标来完成,则就要用4*4矩阵和齐次坐标。
D3DVec3TransformCoord和normal只不过起了两个代表性的名字而已拉!
因为一般对坐标的变换,D3DVec3TransformCoord用的多。
对向量而言,D3DVec3TransformNormal用的多。
从数学上讲,vector3(向量/点)的旋转用3*3矩阵就足够表示了。
用D3DVec3TransformNormal也可以。
*******************************************************
广义的向量:
广义的向量,我简单介绍一下,点的坐标,几何中的自由向量,复数,多项式,都是向量。
他们可以用向量的展开式表示为一列数。(按照一定的基集展开)
*“向量”和"vector3"也指向量展开式!
例<1>
在3d空间中
A=(x1,y1,z1) B=(x2,y2,z2)
几何的向量AB的几何中的坐标:AB=(x2-x1,y2-y1,z2-z1)
标准基集:{ 几何的向量(1,0,0) , 几何的向量(0,1,0) , 几何的向量(0,0,1) }
用标准基集展开:向量展开式a=[x2-x1,y2-y1,z2-z1]
如果改变基集,展开式也改变
***************************************************************
我们看到,用标准基集时,几何中向量的展开式在数值上等于他的坐标
因此,在谈论几何中的向量时(比如d3d),往往搞不清楚展开式和坐标
***************************************************************
例<2>
在3d空间中的一个点,从广义上讲,也是一个向量。
在3d空间中
点P=(x,y,z)
标准基集:{ 点(1,0,0) , 点(0,1,0) , 点(0,0,1) }
用标准基集展开:向量展开式a=[x,y,z]
如果改变基集,展开式也改变
***************************************************************
我们看到,用标准基集时,几何中点的展开式在数值上等于他的坐标
因此,在谈论几何中的点时(比如d3d),往往搞不清楚展开式和坐标
***************************************************************
例<3>
多项式5x^2 + 3x + 4
按照基集{x^2, x , 1}展开:
展开式为a=[5,3,4]
按照基集{5x^2,3x,4}展开:
展开式为a'=[1,1,1]
(广义的向量的)线性变换:
一个广义向量的线性变换,在确定了基集的情况下
可以用一个矩阵来表示。
如果向量的展开式有N个元素,则这个向量是N维向量。
他的变换矩阵是N*N的矩阵才可以。
|
|