投影面積

projected-size.png

境界ボリュームの投影面積(あるいはその見積もり)、これをスクリーン空間被覆率(screen space coverage)と呼ぶ。
スクリーンに投影されたボクセルサイズを測る方法。
高速化の余地ありだね。
投影面積には、視野角は関係ない。
あくまで、カメラとオブジェクトと投影面であるニアークリッピング面との距離の関係で決まる。
ただし、同じ投影面のサイズを保ったまま、視野角だけ変えた場合、投影面であるニアークリッピング面とカメラとの距離が変わるので、
結果としてオブジェクトの投影面積が変わることがある。

大体の投影面積を見積もるには

オブジェクトの投影サイズはビュー方向に沿った視点からの距離と共に減少する。
projected-size.png
上の図のように、同じサイズのポリゴンでも、視点からの位置が遠いほど投影された時のサイズは小さくなる。(1)
\begin{align} s=\frac{nr}{distance} \end{align}
  • n…視点とニアークリッピング面間の距離
  • r….ローカル座標でのオブジェクトのサイズ
  • s….投影面でのサイズ見積もり

たとえばpの位置にあってサイズがrの四角形があるとする。
視点とこの四角形の距離は

(2)
\begin{equation} d・(p-v) \end{equation}
  • v….視点の位置
  • d…視点の方向ベクトル

投影面積は ニアークリッピング面⇔カメラの距離、オブジェクト⇔カメラ との距離の比で決まる!!!

視野角は全く関係ない!!

ガチでやるなら、

モデルビュー行列と投影行列をかけざんすればわかるけど、計算コスト高すぎだよね

        vec2<T> projectedsize(const mat4<T>& _modelmatrix,const mat4<T>& _projmatrix,const vec2<int>& _winsize){
                T max_distance = numeric_limits<T>::min();//カメラから頂点への距離の最大値
 
                vec4<T> local_pos;//オブジェクトの中心が原点な座標系
                vec4<T> view_pos;//視点が原点な座標系
                vec4<T> clip_pos;//クリップ座標での位置
                vec2<T> normalized_device_pos;
                //正規化デバイス座標系のキューブの中で投影された中でも一番右上と左下を求めて最大の大きさを知る
                vec2<T> minNrmDvPos(numeric_limits<T>::max(),numeric_limits<T>::max());
                vec2<T>        maxNrmDvPos(-numeric_limits<T>::max(),-numeric_limits<T>::max());
                for(int i = 0;i  < 8;i++)//
                {
                        local_pos.set(corner[i]);
                        //_modelmatrix.print("モデルビュー");
                        view_pos=_modelmatrix*local_pos;
                        // view_pos.print("視点座標");
                        clip_pos=_projmatrix*view_pos;
                        //wで割って正規化デバイス座標になる
                        //正規化デバイス座標はX座標が -1.0f から1.0f,Y座標が-1.0f から 1.0f ,Z軸が0.0f から 1.0f 
                        if( clip_pos.w==0.0){//視界の外にある。本来なら、ビューフラスタムテストで除外されているはず。
                                assert(!"変だ ちゃんとモデルビュー取得した?");//return vec2<T>(0.0,0.0);//見えてないから0
                        }
                        normalized_device_pos.x =clip_pos.x/ clip_pos.w;
                        normalized_device_pos.y =clip_pos.y/ clip_pos.w;
                        if(normalized_device_pos.x<minNrmDvPos.x){
                                minNrmDvPos.x=normalized_device_pos.x;
                        }
                        if(normalized_device_pos.x>maxNrmDvPos.x){
                                maxNrmDvPos.x=normalized_device_pos.x;
                        }
                        //めんどくさいようだけど、xとyは別々にやらなきゃならない。
                        if(normalized_device_pos.y<minNrmDvPos.y){
                                minNrmDvPos.y=normalized_device_pos.y;
                        }
                        if(normalized_device_pos.y>maxNrmDvPos.y){
                                maxNrmDvPos.y=normalized_device_pos.y;
                        }
 
                }
 
                //0.5をかけたのは、正規化デバイス座標の長さが2.0だから。
                vec2<T> winsize((T)_winsize.x*(T)0.5,(T)_winsize.y*(T)0.5);
                return vec2<T>(vec2<T>(maxNrmDvPos-minNrmDvPos)*winsize);//引き算する=距離・サイズ
 
        }

fov physical-size projection unproject

サポートサイト Wikidot.com fovphysical-sizeprojectionunproject