トップページ > 記事閲覧
double型新関数の不具合?
名前:ゆーすけ 日時: 2014/12/17 22:21

管理人様 先日はdouble型サポートの対応どうもありがとうございました。 早速追加された関数を使ってプログラムを書き直したのですが、追加されたConvWorldPosToScreenPosD関数で 以前と同じようなオーバーフローが発生しました。 デバッガで値を確認してみると、今度はQNANではなくINF/INDとなっており、やはりConvWorldPosToScreenPosD関数が 正しい値を返さなかったためエラーが発生したような感じです。 関数の不具合かもしれませんのでよろしければ対応のほどお願いします。 ちなみに問題発生時の設定は以下のようにしています。 なお、カメラの設定時に上方向ベクトルとしてPosGazeを正規化して大きさ1にしたベクトルを与えても同じでした。 DX.SetUseFPUPreserveFlag(DX.TRUE) DX.SetUseLarge3DPositionSupport(DX.TRUE) DX.SetCameraPositionAndTargetAndUpVecD(PosCam, PosGaze, PosGaze) DX.SetupCamera_PerspectiveD(45*π/180) DX.SetCameraNearFarD(10^6, 10^8) Pos1 = DX.ConvWorldPosToScreenPosD(Pnt) Pnt {DxLibDLL.DX.VECTOR_D} DxLibDLL.DX.VECTOR_D x -2895231.2020298475 Double y 4015247.1115206648 Double z 4021729.8417742774 Double Pos1 {DxLibDLL.DX.VECTOR_D} DxLibDLL.DX.VECTOR_D x 1.#INF Double y -1.#IND Double z -1.#INF Double PosCam {DxLibDLL.DX.VECTOR_D} DxLibDLL.DX.VECTOR_D x -2895231.2020298475 Double y 4015247.1115206648 Double z 4021729.8417742774 Double PosGaze {DxLibDLL.DX.VECTOR_D} DxLibDLL.DX.VECTOR_D x -3636440.0439978018 Double y 3882279.6356909312 Double z 5051333.8738953611 Double
メンテ

Page: 1 |

Re: double型新関数の不具合? ( No.1 )
名前:管理人 日時:2014/12/18 01:07

INF/INDとなってしまうのは、Pnt と PosCam の 座標が同じなのが原因です こちらは計算上どうしてもそうなってしまうので、数値の精度は関係ありません Pnt と PosCam の値が同じになってしまわないようにしてください ところで、載せて頂いたプログラムでは SetCameraPositionAndTargetAndUpVecD の直前に SetUseLarge3DPositionSupport を使用していますが、実際には DxLib_Init の前に実行しているんですよね?
メンテ
Re: double型新関数の不具合? ( No.2 )
名前:ゆーすけ 日時:2014/12/18 07:27

あ・・・よくよく見ると同じになってますね(汗 試していてPntとPosCamが同じでない条件で発生したこともあったのですがなぜか再現しないようなので、 再現性についてもうちょっとよく調べてみます。 SetUseLarge3DPositionSupportはInit前に実行していました。 ついでと言ってはなんですがもう一点質問させていただきます。 DrawCone3DやDrawLine3Dでワールド空間に描画しようとすると、配置場所のワールド座標が大きな値になった時に 本来の配置場所から少しずれて描画されるような現象が起こっています。 Pnt1,Pnt2,Pnt3の3点についてPnt1とPnt2、Pnt2とPnt3を結ぶ線分をそれぞれDrawLine3Dで描画し、 Pnt2にDrawCone3Dで円錐を置いたところ、本来ならPntが円錐内部に配置されて折れた点が見えなくなるはずのところ、 円錐の位置がPnt2からずれたためにPnt2の点が丸見えになります。 テスト条件は下記のようになります。 Pnt1.x=5000000 Pnt1.y=0 Pnt1.z=4000000 Pnt2.x=5000000 Pnt2.y=7000000 Pnt2.z=4000000 Pnt3.x=4999990 Pnt3.y=6999990 Pnt3.z=3999990 Top=DX.VAddD(Pnt2,DX.VGetD(1,0,1)) Bottom=DX.VAddD(Pnt2,DX.VGetD(-1,0,-1)) DX.DrawLine3D(Pnt1,Pnt2,DX.GetColor(255,255,0)) DX.DrawLine3D(Pnt2,Pnt3,DX.GetColor(255,255,0)) DX.DrawCone3D(Top,Bottom,0.4,20,DX.GetColor(255,255,0),DX.GetColor(255,255,255),DX.TRUE) ※実際にはDrawLine3DとDrawCone3Dの座標はVECTOR_D型からVECTOR型にキャストしています この条件で注視点をPnt2(こちらはVECTOR_Dのまま)に固定し、カメラを適当に動かしてみると ずれているのがはっきりわかります。 Pnt1,2,3やTop,Bottom等の座標の絶対値を小さく(数百程度)してみるとこの現象は収まるようなので、 配置位置の座標が大きくなると不具合が出るのかなと思っています。 当初はVECTOR_D型をVECTOR型にキャストしたことにより生じた誤差の影響かとも思いましたが、 DrawCone3DもDrawLine3Dも同じようにVECTOR型にキャストしているのでおそらく関係ないのではと考えています。 毎度脱線が多くて申し訳ありませんが、よろしければ対応のほどお願いします。
メンテ
Re: double型新関数の不具合? ( No.3 )
名前:管理人 日時:2014/12/20 03:14

> DrawCone3DやDrawLine3Dでワールド空間に描画しようとすると、配置場所のワールド座標が大きな値になった時に > 本来の配置場所から少しずれて描画されるような現象が起こっています。 すみません、DrawCone3D などで対応した精度向上の処理を DrawPixel3D, DrawLine3D, DrawTriangle3D ではしていなかったのが原因です DrawPixel3D, DrawLine3D, DrawTriangle3D も精度向上処理を行うようにして、且つ VECTOR_D や double を使用する 関数名の末尾に D が付いた DrawCube3DD、DrawCone3DD などの関数も追加してみましたので、よろしければお試しになってみてください m(_ _;m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
メンテ
Re: double型新関数の不具合? ( No.4 )
名前:ゆーすけ 日時:2014/12/20 06:58

対応ありがとうございます。 おかげでオブジェクトを描画する際に座標をVECTOR型にキャストする必要がなくなりました。 ですがDrawLine3DDとDrawCone3DDを使ってもやはり少しずれているようです。 作っているプログラム中では人工衛星などのようにある程度の速度で物体を中心の地球に対して移動させ、 最新の物体の座標と過去の物体の座標をDrawLine3DDで結んで物体の航跡を描き、最新の物体の座標に DrawCone3DDで円錐を置いています。 この状態で注視点を物体の現在の座標に固定して至近距離から眺めると、前述の現象が発生して円錐が指定の座標から ずれるため、カメラから見ると円錐が激しく上下左右に跳ね回っているかのように見え、また物体の航跡が 物体から切り離されてしまっている状態で、実用上は問題ないとはいえやはり気にかかるところです。 円錐は長さ2、半径0.4ほどで、ずれの大きさは画面内での跳ね回り方から見てせいぜい1以下だと思うのですが、 既に高精度化を施しているということはこの辺が精度の限界ということになるでしょうか??
メンテ
Re: double型新関数の不具合? ( No.5 )
名前:管理人 日時:2014/12/20 11:05

SetUseLarge3DPositionSupport( TRUE ) ; を実行した際の処理負荷が更に上がる代わりに DrawLine3D, DrawCone3D などの3D図形描画関数での計算精度が悪くなる原因を 一つ減らす対処をしてみましたので、よろしければお試しください m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) ( 前回までのものでもモデル描画の方には今回の変更と同じ精度向上処理を行っていました  本件の対応は3D図形描画→モデル描画の順番で行っていて、モデル描画の際に更に精度を  高くする方法を思いついて実装したのですが、それを3D図形描画にも既に施していると  思い込んでしまっていました・・・ ) ただ、今回の変更によって向上した計算精度でも、DrawLine3DD の Pos1 と Pos2 の 距離が float 型では精度が足りないほどの大きな値になる場合はズレが発生してしまうので、 もしそのような現象が発生してしまった場合は Pos1 と Pos2 を結ぶ直線を何回かの DrawLine3DD に分割して描画するようにしてください
メンテ
Re: double型新関数の不具合? ( No.6 )
名前:ゆーすけ 日時:2014/12/20 12:41

早速の対応ありがとうございます。 描画時の負荷はかなり上がりましたがDrawLine3DDのズレについては解消され 期待通りの描画結果になったのが確認できました。 ちなみに.NET版で描画処理の部分だけをBackGroundWorkerで別スレッドに追い出すことは さすがにできませんよね・・・?
メンテ
Re: double型新関数の不具合? ( No.7 )
名前:管理人 日時:2014/12/21 15:13

> ちなみに.NET版で描画処理の部分だけをBackGroundWorkerで別スレッドに追い出すことは > さすがにできませんよね・・・? 正常に動作するかはわかりませんが、DXライブラリの描画関係の関数を呼ぶスレッドを 一つに限定すれば大丈夫かもしれません ( 少なくとも複数のスレッドから描画関係の関数を呼んだら間違いなく正常に動作しないと思います ) あと、このタイミングで申し上げるのもあれですが、やはり処理負荷の問題が大きくなってしまいますので float 型でも1000分の1スケールにすれば精度の問題がなくなるとのことでしたら そちらの方法を選択されたほうが良いかもしれません・・・ (・・;;
メンテ
Re: double型新関数の不具合? ( No.8 )
名前:ゆーすけ 日時:2014/12/21 17:18

ありがとうございます。 仰るように描画系の関数のみ描画専用の別スレッドに追い出して、必要なパラメータについては構造体変数で一まとめにして BackGroundWorkerの引数として描画スレッドに渡してやったところ動きました。 描画が重いこと自体は変わりませんが、描画スレッドと別に走っている物理計算スレッドが描画処理でパワーを食われて 実時間シミュレーションができなくなるのは避けられました。 3930K+GTX570の自作機では別スレッドにしなくてもゴリ押しで何とかなってたのですが、一昔前のノートPCのCPU内蔵iGPでも ある程度動くようにしようとすると描画の別スレッド化なしはかなり厳しい感じです・・・ 1000分の1スケール化は私も考えたのですが、そうするとZバッファの精度の問題なのか(NearFarを0.001にしなければならない) 地面の内部に潜り込んだ線が見えてしまう等表示が正常に行われなくなる箇所が出てきてしまいます。 作ろうとしているのはゲームではなくシミュレータなので、フレームレートが多少犠牲になるのは割り切って 物理計算のパフォーマンスとある程度の表示の正確さ重視で行きたいと思います。 毎度低レベルな質問に対して懇切丁寧な対応ありがとうございます。 また疑問点、トラブル等が出てきましたらよろしくお願いします。
メンテ

Page: 1 |

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

   クッキー保存