トップページ > 記事閲覧
SetCameraNearFarおよび視覚外の描画について
名前:ゆう 日時: 2017/09/27 15:17

現在、3Dゲームを作るうえで勉強しているのですがいくつか質問させてください。 まず、SetCameraNearFarについてなのですが、この関数を使うことで視覚距離より遠いもの(マップモデルの外側など)はレンダリングされてないですか?またクリッピングされていますか? すみません、レンダリングとクリッピングについても浅い知識なので意味合いが違ってたらすみません。 つまり、視覚距離より遠くて、目に見えないのにオブジェクトが生成されているのかどうか知りたいです。 次に、されていなかった場合どういう処理を行えばいいのかアドバイスまたはヒントがほしいです。 また、されていたとしたらどのように行っているのかアドバイスまたはヒントがほしいです。 今考えているのですが全く思いつかない状態です。でも最後まで考えたいので答えではなくヒントがほしいです。不毛かもしれませんがお願いします。
メンテ

Page: 1 |

Re: SetCameraNearFarおよび視覚外の描画について ( No.1 )
名前:管理人 日時:2017/09/28 00:34

> まず、SetCameraNearFarについてなのですが、この関数を使うことで視覚距離より遠いもの(マップモデルの外側など)はレンダリングされてないですか?またクリッピングされていますか? はい、SetCameraNearFar で設定した範囲外のものはレンダリングされません > つまり、視覚距離より遠くて、目に見えないのにオブジェクトが生成されているのかどうか知りたいです。 ゆうさんが考える『オブジェクト』とはどのようなものでしょうか? DXライブラリでは3Dモデルは関数 MV1DrawModel で描画しますが、 これを実行した結果レンダリングが行われても行われなくても、 クリッピングされてもされなくても『オブジェクト』と呼べるものが生成されることはありません 行われるのは『3Dモデルを画面に描画する』処理のみです > 次に、されていなかった場合どういう処理を行えばいいのかアドバイスまたはヒントがほしいです。 >  > また、されていたとしたらどのように行っているのかアドバイスまたはヒントがほしいです。 ゆうさんが考える『オブジェクト』が何なのかが私はまだ理解できていないので、こちらのご質問にはお答えできません (_ _;
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.2 )
名前:ゆう 日時:2017/09/28 09:00

返信ありがとうございます。 オブジェクトと曖昧な表現ですみませんでした。 私が考えてたオブジェクトは視覚距離よりも大きいステージモデルのことを考えてました。 繰り返しになるかもしれませんがもう一つ質問させていただくと、 視覚距離よりも外側にあるステージモデルのその部分はレンダリングされているのかどうかを知りたいです。 つまりステージモデルには、レンダリングされている部分とされてない部分があるのか知りたいです。
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.3 )
名前:管理人 日時:2017/09/30 01:16

> 視覚距離よりも外側にあるステージモデルのその部分はレンダリングされているのかどうかを知りたいです。 > つまりステージモデルには、レンダリングされている部分とされてない部分があるのか知りたいです。 ステージモデルの各部分が視野に入っているかどうか( レンダリングされているかどうか )の判定を行いたいということでしょうか? もしそうだとしますと、すみません、今のところ視野に入っているかどうかを判定するための関数はありません 関数を追加することは可能ですが、よろしければ視野に入っているかどうかを判定する機能を使用して どのようなことをされようとしているのかを教えていただけないでしょうか? m(_ _)m
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.4 )
名前:ゆう 日時:2017/09/30 09:11

今は広大なステージモデルのほうが完成していないので、まだ何かをしようというわけじゃないんですが、 オープンワールドとまではいかないけれどそれなりに広大なマップを導入させようと考えています。 それでステージモデルの中の視野に入っていない部分をレンダリングさせるというのは負荷が大変なことになると思った次第です。 だから判定を行いたいというよりレンダリングされていなければそれで大丈夫です。 最初に用途をはっきりさせていれば良かったです、すみません。 操作しないキャラクターモデルなどは CheckCameraViewClip という関数を使えばなんとかなると思っています。
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.5 )
名前:管理人 日時:2017/09/30 20:36

> だから判定を行いたいというよりレンダリングされていなければそれで大丈夫です。 なるほど 剛体モデル( 主に建物や道などの変形しないモデル )であればフレーム( ノード )単位で視野判定を行い、 視野に入っていない場合はレンダリングされないようになっていますので、 広大なマップが1つのフレーム( ノード )になっていない限りは問題ないと思います ただ、広大なステージモデルの広大さによってはレンダリングのたびに視野判定すること自体が 重い処理となる可能性がありますので、その場合は広大なステージモデル自体をいくつかのモデルに分けて、 プレイヤーの居る周辺のステージモデルのみ MV1DrawModel を行う、という処理を組む必要があるかもしれません > 操作しないキャラクターモデルなどは CheckCameraViewClip という関数を使えばなんとかなると思っています。 はい、その方法で大丈夫です ただ、こちらも広大なステージに数千人居る等になりますと CheckCameraViewClip 自体が重い処理となりますので その場合はもっと単純な計算( プレイヤーとの距離など )での判定との二段構えにする必要があるかもしれません
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.6 )
名前:ゆう 日時:2017/09/30 23:16

ありがとうございます。 レンダリングされないような処理をされているのですね、わかりました。 広大すぎるのも処理に関わるということなので一応分割も視野に入れて作ろうと思います。 また、出来るだけ扱いやすい位置にものは関数だけに頼らないでベクトル計算のほうが処理的には軽くなりそうなのでその方で行おうと思います。 あと一つ、出来たら教え頂きたいことがありまして、そのレンダリングされないような処理を、 フレーム単位で視野判定を行ってしているとおっしゃていますがどういったやり方というかアルゴリズムなのか少し教えていただけると助かります。
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.7 )
名前:管理人 日時:2017/10/01 02:06

> あと一つ、出来たら教え頂きたいことがありまして、そのレンダリングされないような処理を、 > フレーム単位で視野判定を行ってしているとおっしゃていますがどういったやり方というかアルゴリズムなのか少し教えていただけると助かります。 SetDrawArea や SetCameraNearFar が実行されたタイミングで事前に『任意の座標』が 視錐台の上下左右奥手前の6面のそれぞれ視錐台に対して内側にあるか外側にあるかを判定するために 必要な情報を計算しておきます 実際のソース( DxGraphics.cpp の Graphics_DrawSetting_RefreshBlend3DTransformMatrix 関数内 )は以下のようになっています GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.top, 0.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.top, 0.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.bottom, 0.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.bottom, 0.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.top, 1.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.top, 1.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.left, GSYS.DrawSetting.DrawAreaF.bottom, 1.0 ) ) ; GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 1 ] = NS_ConvScreenPosToWorldPosD( VGetD( GSYS.DrawSetting.DrawAreaF.right, GSYS.DrawSetting.DrawAreaF.bottom, 1.0 ) ) ; VECTOR_D Normal ; // XZ平面 Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 0 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ; Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 1 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], &Normal ) ; // YZ平面 Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 2 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], &Normal ) ; Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 3 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ; // XY平面 Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 4 ], &GSYS.DrawSetting.ViewClipPos[ 0 ][ 0 ][ 0 ], &Normal ) ; Normal = VCrossD( VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 1 ], GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] ), VSubD( GSYS.DrawSetting.ViewClipPos[ 1 ][ 1 ][ 0 ], GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ] ) ) ; CreateNormalizePlaneD( &GSYS.DrawSetting.ClippingPlane[ 5 ], &GSYS.DrawSetting.ViewClipPos[ 1 ][ 0 ][ 0 ], &Normal ) ; フレームが視野に入っているかの判定では、フレームに含まれるメッシュの全頂点座標から 最小のX,Y,Z座標・最大のX,Y,Z座標で形成されるキューブの8頂点と、事前に計算しておいた視錐台判定用の情報を使って キューブが視錐台の中に入っているかどうかを調べます 実際のソースは以下のようになっています DxModel.cpp の MV1DrawModelBase 関数内 // 可視チェック用頂点座標を算出する Tmp = Frame->BaseData->MaxPosition ; VectorTransform4X4CT( &CheckPos[ 0 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.x = Frame->BaseData->MinPosition.x ; VectorTransform4X4CT( &CheckPos[ 1 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.y = Frame->BaseData->MinPosition.y ; VectorTransform4X4CT( &CheckPos[ 2 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.x = Frame->BaseData->MaxPosition.x ; VectorTransform4X4CT( &CheckPos[ 3 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.z = Frame->BaseData->MinPosition.z ; VectorTransform4X4CT( &CheckPos[ 4 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.y = Frame->BaseData->MaxPosition.y ; VectorTransform4X4CT( &CheckPos[ 5 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.x = Frame->BaseData->MinPosition.x ; VectorTransform4X4CT( &CheckPos[ 6 ], &Tmp, &Frame->LocalWorldMatrix ) ; Tmp.y = Frame->BaseData->MinPosition.y ; VectorTransform4X4CT( &CheckPos[ 7 ], &Tmp, &Frame->LocalWorldMatrix ) ; // 可視チェック if( Graphics_Camera_CheckCameraViewClip_Box_PosDim( CheckPos ) == TRUE ) continue ; DxGraphics.cpp の Graphics_Camera_CheckCameraViewClip_Box_PosDim 関数 // 8座標で形作るボックスがカメラの視界に入っているかどうかを判定する( 戻り値 TRUE:視界に入っていない FALSE:視界に入っている )( CheckPosは VECTOR 8個分の配列の先頭アドレス、配列の各要素番号の内容 0:+x +y +z 1:-x +y +z 2:-x -y +z 3:+x -y +z 4:+x -y -z 5:+x +y -z 6:-x +y -z 7:-x -y -z ) extern int Graphics_Camera_CheckCameraViewClip_Box_PosDim( VECTOR *CheckBoxPos ) { BYTE clip[ 8 ] ; VECTOR *pos ; int i ; // 各頂点が可視領域に入っているかどうかを調べる pos = CheckBoxPos ; for( i = 0 ; i < 8 ; i ++, pos ++ ) { clip[ i ] = 0 ; if( GSYS.DrawSetting.ClippingPlane[ 0 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 0 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 0 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 0 ].w < 0.0f ) clip[ i ] |= CLIP_XM ; if( GSYS.DrawSetting.ClippingPlane[ 1 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 1 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 1 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 1 ].w < 0.0f ) clip[ i ] |= CLIP_XP ; if( GSYS.DrawSetting.ClippingPlane[ 2 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 2 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 2 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 2 ].w < 0.0f ) clip[ i ] |= CLIP_YM ; if( GSYS.DrawSetting.ClippingPlane[ 3 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 3 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 3 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 3 ].w < 0.0f ) clip[ i ] |= CLIP_YP ; if( GSYS.DrawSetting.ClippingPlane[ 4 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 4 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 4 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 4 ].w < 0.0f ) clip[ i ] |= CLIP_ZM ; if( GSYS.DrawSetting.ClippingPlane[ 5 ].x * pos->x + GSYS.DrawSetting.ClippingPlane[ 5 ].y * pos->y + GSYS.DrawSetting.ClippingPlane[ 5 ].z * pos->z + GSYS.DrawSetting.ClippingPlane[ 5 ].w < 0.0f ) clip[ i ] |= CLIP_ZP ; if( clip[ i ] == 0 ) return FALSE ; } // どれかの側に全ての頂点が寄っている場合は100%可視領域に入っていない if( ( ( clip[0] & CLIP_XP ) && ( clip[1] & CLIP_XP ) && ( clip[2] & CLIP_XP ) && ( clip[3] & CLIP_XP ) && ( clip[4] & CLIP_XP ) && ( clip[5] & CLIP_XP ) && ( clip[6] & CLIP_XP ) && ( clip[7] & CLIP_XP ) ) || ( ( clip[0] & CLIP_XM ) && ( clip[1] & CLIP_XM ) && ( clip[2] & CLIP_XM ) && ( clip[3] & CLIP_XM ) && ( clip[4] & CLIP_XM ) && ( clip[5] & CLIP_XM ) && ( clip[6] & CLIP_XM ) && ( clip[7] & CLIP_XM ) ) || ( ( clip[0] & CLIP_YP ) && ( clip[1] & CLIP_YP ) && ( clip[2] & CLIP_YP ) && ( clip[3] & CLIP_YP ) && ( clip[4] & CLIP_YP ) && ( clip[5] & CLIP_YP ) && ( clip[6] & CLIP_YP ) && ( clip[7] & CLIP_YP ) ) || ( ( clip[0] & CLIP_YM ) && ( clip[1] & CLIP_YM ) && ( clip[2] & CLIP_YM ) && ( clip[3] & CLIP_YM ) && ( clip[4] & CLIP_YM ) && ( clip[5] & CLIP_YM ) && ( clip[6] & CLIP_YM ) && ( clip[7] & CLIP_YM ) ) || ( ( clip[0] & CLIP_ZP ) && ( clip[1] & CLIP_ZP ) && ( clip[2] & CLIP_ZP ) && ( clip[3] & CLIP_ZP ) && ( clip[4] & CLIP_ZP ) && ( clip[5] & CLIP_ZP ) && ( clip[6] & CLIP_ZP ) && ( clip[7] & CLIP_ZP ) ) || ( ( clip[0] & CLIP_ZM ) && ( clip[1] & CLIP_ZM ) && ( clip[2] & CLIP_ZM ) && ( clip[3] & CLIP_ZM ) && ( clip[4] & CLIP_ZM ) && ( clip[5] & CLIP_ZM ) && ( clip[6] & CLIP_ZM ) && ( clip[7] & CLIP_ZM ) ) ) return TRUE ; // ここにきたら見えているということ return FALSE ; } DXライブラリのソースはダウンロードページからダウンロードすることができますので、 よろしければ直にご覧になってみてください
メンテ
Re: SetCameraNearFarおよび視覚外の描画について ( No.8 )
名前:ゆう 日時:2017/10/01 16:58

ご親切に本当にありがとうございます。 うまい言葉が見つからなかったのですが、 どういったやり方なのか少しわかり、自分の詰まりの改善と少しのやる気が沸いてきました。自分は少し回りくどく考えていたみたいでした。 それで、この機会に初めてソースコードを覗いてみましたがすごい量で驚きました。 教えていただいた DxGraphics.cpp と DxModel.cpp を重点的に参考として見て見ようと思います。 また時間の限りほかの部分も面白そうなので見て見たいと思います。 本当にありがとうございます。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存