Foley、van Dam、Feiner、Hughes (第 2 版) による第 6 章 Computer Graphics Principles and Practices (CGP&P) に従って透視投影アルゴリズムを実装しました。私は持っている
N'per = M * Sper * Spar * T (-prp) * R * T (-vrp).
私が理解しているように、最終的な画像は (-1,-1) から (1,1) までの標準的な形式のサイズで、z は (0,-1) である必要があります。ただし、最終的なイメージの XY 寸法 (図 1 を参照) は正しくないようです。私は主に、最終的な画像サイズがどのように決定されるかを理解しようとしています。以下のmatlabコードを含めました。私の視錐台 (f) は、ECEF に変換された特定の緯度/経度でのアイポイント (EP) によって定義されます。距離: 平面に近い (nDist) = 300; ビュー プレーン (vDist) = 900; およびファー プレーン (fDist) = 25000。EP で作成された見通し線 (LOS) ベクトルは、投影の中心です。錐台は、LOS に沿ってその中にある建物を正しく見つけて返します。視野は (10 度 x 10 度) です。現在、これらの建物を定義済みのウィンドウに投影して、「量子化」できるようにしています。(ペイント?) グリッドを表示し、どの建物がビュー プレーンのどの x、y ペアにあるかを示します。残念ながら、ウィンドウが指定されたサイズに戻らないため、ペイントがより困難になります。さらに、正しい寸法にならないために何が間違っているのかを知りたいだけです。
Matlab コード (最適化などの試みはありません。力ずくで実装するだけです!
function iPersProj = getPersProj(bldg, bi, f, plotpersp, fPersPlot)
color = [rand rand rand];
face = eFaces.bottom;
iPersProjBtm = persproj(f, bldg, face);
face = eFaces.top;
iPersProjTop = persproj(f, bldg, face);
iPersProj = [iPersProjTop;iPersProjBtm];
hold on;
scatter3(iPersProjTop(:,1), ...
iPersProjTop(:,2), ...
iPersProjTop(:,3),'+','CData',color);
scatter3(iPersProjBtm(:,1), ...
iPersProjBtm(:,2), ...
iPersProjBtm(:,3),'o','CData',color);
pPersProj=[iPersProjTop;
iPersProjTop(1,:); ...
iPersProjBtm; ...
iPersProjBtm(1,:); ...
iPersProjBtm(2,:); ...
iPersProjTop(4,:); ...
iPersProjTop(3,:); ...
iPersProjBtm(3,:); ...
iPersProjBtm(4,:); ...
iPersProjTop(2,:); ...
iPersProjTop(1,:)];
line (pPersProj(:,1), pPersProj(:,2),'Color',color);
text (pPersProj(1,1), pPersProj(1,2), int2str(bi));
end
function proj = persproj(f, bldg, face)
vrp = f.vC; %center view plane
vpn = f.Z; % LOS for frustum
cop = -f.EP;
F = f.vDist - f.nDist;
B = f.vDist - f.fDist;
umin = -5;
vmin = -5;
umax = 5;
vmax = 5;
R = getrotation (f);
Tvrp = gettranslation(-vrp);
ed = R * Tvrp * [f.EP 1]'; %translate eyepoint to camera?
prp = [0 0 ed(3)];
sh = getsh(prp, umax, umin, vmax, vmin);
Tprp = gettranslation(-prp);
vrpp = -prp(3); %(sh * Tprp * [0;0;0;1]); %vrp-prime per CGP&P
zmin = -(vrpp + F)/(vrpp+B);
zmax = -(vrpp + B)/(vrpp+B);
zprj = -vrpp/(vrpp+B);
sper = getsper(vrpp, B, umax, umin, vmax, vmin);
M=[ 1 0 0 0; ...
0 1 0 0; ...
0 0 1/(1+zmin) -zmin/(1+zmin); ...
0 0 -1 0];
proj = zeros(4,4);
for i=1:4
Q=bldg.coords(i,:,face);
uvdw = M * sper * sh * Tprp * R * Tvrp * [Q';1];
proj (i,1) = uvdw(1);
proj (i,2) = uvdw(2);
proj (i,3) = uvdw(3);
end
end
function sper = getsper (vrpz, B, umax, umin, vmax, vmin)
dx=umax-umin;
dy=vmax-vmin;
sper=zeros(4,4);
sper(1,1) = 2*vrpz/(dx*(vrpz+B));
sper(2,2) = 2*vrpz/(dy*(vrpz+B));
sper(3,3) = -1/(vrpz+B);
sper(4,4) = 1;
end
function sh = getsh (prp, umax, umin, vmax, vmin)
sx=umax+umin;
sy=vmax+vmin;
cw = [sx/2 sy/2 0 1]';
dop = cw - [prp 1]';
shx = - dop(1)/dop(3);
shy = - dop(2)/dop(3);
sh=zeros(4,4);
sh(1,1) = 1;
sh(2,2) = 1;
sh(3,3) = 1;
sh(4,4) = 1;
sh(1,3) = shx;
sh(2,3) = shy;
end
function R = getrotation (f)
rz = f.Z;
rx=cross(f.Y, rz);
rx=rx/norm(rx);
ry=cross(rz,rx);
R=zeros(4,4);
R(1,1:3) = rx;
R(2,1:3) = ry;
R(3,1:3) = rz;
R(4,4) = 1;
end
function T = gettranslation(p)
T = zeros(4,4);
T(1:3,4) = p';
T(1,1) = 1;
T(2,2) = 1;
T(3,3) = 1;
T(4,4) = 1;
end
図 1: 予測投影ですが、次元は (-1,-1) から (1,1) ではありません1