LookAt矩阵(归一化平行投影)

问题描述 投票:0回答:1

我目前正在学习3D计算机图形学,并将平行投影规范化为Canocial视图体积(LookAt Matrix为熟悉的名称)。我尝试使用下面的纯JavaScript作为参数将其实现为代码。

var VRP = new Vertex(0,0,0);
var VPN = new Vertex(0,0,1);
var VUP = new Vertex(0,1,0);
var PRP = new Vertex(8,8,100);
var Window = [-1,17,-1,17];
var F = 1, B = -1;

现在,这是我的尝试。我首先将其转换为Canocial View体积。[注意:您可以直接将这些步骤跳过至代码here,并帮助我修复代码以将多维数据集向前移动到摄像机(屏幕)而不是移开

1。将VRP转换为来源

var TVRP = [];
TVRP[0] = [1, 0, 0, -VRP.x];
TVRP[1] = [0, 1, 0, -VRP.y];
TVRP[2] = [0, 0, 1, -VRP.z];
TVRP[3] = [0, 0, 0, 1];

2。旋转VRC,以使n轴,u轴和v轴与z轴,x轴和y轴依次对齐

function normalizeViewPlane(VPN) {
    var unitVector = calculateUnitVector(VPN); //VPN/|VPN|
    return normalizeVector(VPN,unitVector);
}

function normalizeViewUp(VUP, n) {
    var dtProd = dotProduct(n,VUP);
    var nVUP = new Vertex(n.x*dtProd, n.y*dtProd, n.z*dtProd);
    VUP = new Vertex(VUP.x-nVUP.x, VUP.y-nVUP.y, VUP.z-nVUP.z);
    var unitVector = calculateUnitVector(VUP); //VUP/|VUP|
    return normalizeVector(VUP,unitVector);
}

function normalizeUVN(n,u) {
    var V = crossProduct(n,u);
    var unitVector = calculateUnitVector(V); //V/|V|
    return normalizeVector(V,unitVector);
}

var n = normalizeViewPlane(VPN);
var v = normalizeViewUp(VUP, n);
var u = normalizeUVN(v, n);

var RVRC = [];
RVRC[0] = [u.x, u.y, u.z, 0];
RVRC[1] = [v.x, v.y, v.z, 0];
RVRC[2] = [n.x, n.y, n.z, 0];
RVRC[3] = [0, 0, 0, 1];
//Perform matrix multiplication 4x4 R.T(-VRP)
var res = multiplyMatrix4x4(RVRC, TVRP);

3。剪切DOP变得平行于z轴

function shearDOP(PRP, uMaxMin, vMaxMin) {
    var CW = new Vertex(uMaxMin,vMaxMin,0);
    var mPRP = new Vertex(PRP.x,PRP.y,PRP.z);
    return new Vertex(CW.x - mPRP.x, CW.y - mPRP.y, CW.z - mPRP.z);
}

var uMaxMin = (Window[1]+Window[0])/2;
var vMaxMin = (Window[3]+Window[2])/2;
var DOP = shearDOP(PRP,uMaxMin,vMaxMin);       
var HX = (DOP.x/DOP.z)*-1;
var HY = (DOP.y/DOP.z)*-1;

 var Hpar = [];
 Hpar[0] = [1,0,HX,0];
 Hpar[1] = [0,1,HY,0];
 Hpar[2] = [0,0,1,0];
 Hpar[3] = [0,0,0,1];
 //res = R.T(-VRP)
 res = multiplyMatrix4x4(Hpar,res);

4。转换到视图体积原点的前面中心

var Tpar = [];
Tpar[0] = [1,0,0,-uMaxMin];
Tpar[1] = [0,1,0,-vMaxMin];
Tpar[2] = [0,0,1,-F];
Tpar[3] = [0,0,0,1];
//res=Hpar.R.T(-VRP)
res = multiplyMatrix4x4(Tpar,res);  

5。缩放以使视图体积受到平面的限制

var uMaxMin2 = 2/(Window[1]-Window[0]);
var vMaxMin2 = 2/(Window[3]-Window[2]);
var Spar = [];
Spar[0] = [uMaxMin2, 0, 0, 0];
Spar[1] = [0, vMaxMin2, 0, 0];
Spar[2] = [0, 0, 1 / (F - B), 0];
Spar[3] = [0, 0, 0, 1];
 //res=Tpar.Hpar.R.T(-VRP)
res = multiplyMatrix4x4(Spar, res);

在将其转换为Canocial视图体积之后,我决定将多维数据集顶点乘以该最终结果转换矩阵。

//res=Spar.Tpar.Hpar.R.T(-VRP)
p = multiplyMatrix1x4(res,p);
//M is the parameter of cube vertice
M.x = p[0];
M.y = p[1];
M.z = p[2];

因此,我的立方体正从摄像机移开,如下图所示。

the cube moving away

但是,我希望立方体移动到离摄像机最近的位置,而不是移开,如下图所示(对象是房子)

The house move closest to the camera

我是否错过了步骤或误解了转换为Canocial View的算法?我将修改哪个函数或变量以使立方体像上面的房子一样?JSFiddle:https://jsfiddle.net/Marfin/hL2bmvz5/20/参考:https://telin.ugent.be/~sanja/ComputerGraphics/L06_Viewing_Part2_6pp.pdf

我目前正在学习3D计算机图形学,并将平行投影规范化为Canocial视图体积(LookAt Matrix为熟悉的名称)。我尝试使用纯JavaScript将其实现为代码...

javascript matrix graphics 3d
1个回答
0
投票

[通常,如果您的凸轮正看着盒子,并且您希望凸轮朝盒子移动,请在凸轮和盒子之间获取矢量,然后将凸轮朝这个方向移动:

cam += (box-cam)

© www.soinside.com 2019 - 2024. All rights reserved.