- ベストアンサー
表面の導出
今下のような配列に立方体のデータが入っているとすると a(n,8):立方体を構成する頂点の番号[nは立方体の数] x(m),y(m),z(m):頂点の座標[mは頂点の数] 表面を構成する頂点の番号を検索するにはどのようにしたらよいでしょうか? b(r,4):表面を構成する頂点の番号[rは面の数]
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
ANo.#5で説明したのはANo.#4と同じく、見える面を抽出する方法です。6面体のこちらから見える面を画面にどのように描画するかについては、ANo.#4で「立方体同士の干渉による見え隠れについては別途考慮されているものとします」としている通り、考慮していません。ANo.#4、ANo.#5の方法を利用して画面に描画するとしたら、一般に行われている方法だと思いますが1つ1つの立方体を視点から遠い順に描くことになると思います。従って各々の6面体の6面の内こちらを向いていないいくつかの面について描画処理を省略できるというもので、手前にある6面体によって隠される部分を考慮して新たに画面上に描かれる面を生成する(或いは完全に隠された部分は削除してしまう)と言う処理は考えていません。 ANo.#5の補足にあるように、「画面上に見える部分のみを取り出す」と言うことになると、直方体や6面体の面と言うよりはそれらの干渉によってできる(上の「生成」)画面上の面になるので、これまでとは別の処理が必要になります。ANo.#5の補足からijiriさんの取り出したいと望んでいたのはこの面のことだったことが分かりましたが、立方体の表面と言う言葉からはこのことには全く思い至りませんでした。 ・「立方体のデータaが集まってさらに大きい立方体を作っています.」 ・「aの中の頂点の番号が共有しているものがある」 と言うのはこの辺のことと関係あるのでしょうか? そこで画面上に描く面のみを取り出す方法ですが、だいぶ難しくなりそうです。うまく説明しているサイトがあるようなので、隠線処理・隠面処理、zバッファ法、スキャンライン法などをキーワードにして探して見られたらいかがでしょうか。 http://nis-lab.is.s.u-tokyo.ac.jp/~nis/CG/cgtxt/rindex.htm (上のような処理を考えておられるなら関係ないかも知れませんが) ANo.#4、#5の方法で、描画するたびに処理を行うのかと言うことで計算量を心配されているようですが、6面体の方向・配置が変わって描画し直すときは当然必要となり、避けることはできないと思います。(全体の処理内容を理解した上で何らかの工夫により処理を軽減することの可能性はあり得るでしょうが)
その他の回答 (5)
- tgb
- ベストアンサー率78% (32/41)
「回転を何度も行う場合でもこの方法で描画するのが良いのでしょうか.」と言う質問ですが、 直方体が時間的に動いている場合、指定した時間によって直方体の方向が変わりますが、時々刻々変わる方向に対して表(おもて)の面を求めるのにANo.#4の方法が使えるかという意味と考えます。 ・先ず、#4の方法は取りあえずは描画には関係なく見える面を抽出する方法です。 ・直方体の位置・方向が時々刻々変わる場合はその時点で求まる直方体の新しい頂点座標から#4の方法を使って見える面を抽出し直し、この面を再描画することになると思います。 ・良いかどうかと言うのがどういう観点で質問されているのかよく分かりませんが、心配されている点がある場合はもっと具体的に説明していただけたら、お役に立てるかも知れません。 一般の6面体(平行6面体もこれに含める)の場合の方法ですが、そのまえに訂正させていただきたいと思います。ANo.#4で立方体の頂点番号の付番が一定の規則になっているかどうか聞いたのですが、面データがありますので直接そちらの方を使用することにしたいと思います。その面データでの頂点番号の付番順ですが、1234と振っていくときの方向について、右手で親指を伸ばして他の4本指を軽く握り、4本指の付け根から指先に向かって1234としたとき、この方向を6面体の1つの面の1234に合わせた場合に親指が常に外側(或いは常に内側)を向くようになっているか確認してください。そうなっていれば既存の面データがそのまま使えます。そうでない場合はコメントください(最後の方の#2の部分参照)。以下では外側を向くようになっているものとして話を進めます。 1)1つの6面体について視点を向いた面を抽出することを考えます。複数の6面体の場合は以下の処理を繰り返します。 2)6面体の各面をi=1,6とします。各面の頂点をpj(j=1,4)とします。視点をvとします。 3)i=1~6まで各面iについて処理4)5)を繰り返し、6面体の各面の表・裏を決めます。 4)p1からp2へ向かうベクトルをa、p1からp4へ向かうベクトルをbとし、c=a×b(外積・ベクトル積)とします。p1からvへ向かうベクトルをdとします。r=c・d(内積)とします。 視点が無限遠にある場合はp1の位置に拘わらずdは視点の方向ベクトル(固定の値)を視点に向かうように取ってください。大きさは任意ですが、計算の精度の観点からは平均的なcの大きさ即ち6面体の平均的な寸法のオーダーがよいと思います。 5)rが+ならその面は表を向いています(こちらから見えます)。-なら裏を向いています。r=0ならちょうど面が1つの線に見えるような位置になっています。 #1 この方法は立方体・直方体の場合にも適用可能ですが、計算量はANo.#4の方法より多くなるかも知れません。 #2 上に述べたチェックで親指が ・内側を向いていた場合: 処理4)でp2とp4を入れ替えて計算します。 ・バラバラの場合: 面倒ですが新たに面データをつくることになります。applicationとして作成中でデータはこれから作成するという場合は一定の規則にして面データb(r,4)を作成すべきだと思います。システムの他の部分との関係でb(r,4)のデータはそのままにして処理したい場合はコメントしてください。
- tgb
- ベストアンサー率78% (32/41)
何をしようとしているかについての具体的な話をお伺いしたのでだいぶ分かってきたようです。ANo.#3に対する補足から私が理解したことを確認したいと思います。 「表面」と言うのは小立方体(または直方体)を囲む大立方体の6つの表面と言うことではなく、1つの立方体がある角度で置かれている場合に画面を通してこちら側から見える面ということになると理解しました。従って、大立方体、小立方体と言う考えは不要で、1つ1つの立方体に対して6つの面の中からこちら側から見える3面(角度によっては2面、或いは1面)を選び出すと言うことになります。(この場合、立方体同士の干渉にによる見え隠れについては別途考慮されているものとします。) 以上のような前提で以下のように考えることができると思います。方法の適用の条件ですが、視点は無限遠、形状は直方体としています。平行6面体や一般の6面体についても考えたい場合、或いは有限位置での視点で表示する場合について必要なら、コメントしてください。計算量が多くなるかも知れませんが、別の方法を考えます。その際、頂点の番号を振る順が全ての6面体で一定していないと困りますので確認をお願いします。(例えば6面体の下側の4角形に対し、辺の周りに1、2、3、4と振ったあと1の点に戻り、そこから上側に移って下の場合と同じ方向に5、6、7、8と振っていて、ねじに見立てて1234の方向に回すとねじが1から5の方向に進むようになっていると言ったような関係です。全ての6面体について順序が一定していれば、読み替えが可能ですのでこの通りでなくとも構いません。) 3面の選び出しですが、このためには視点の方向が分かっている必要があります。(3次元データを画面に表示しているので当然そのデータは既知だと思います) これを使って以下のようにします。 1)適当に1点P(例えば原点)を選びます。 2)点Pから視点に向かうベクトルをVとします。ベクトルVの大きさ(絶対値)は任意です。平均的な直方体の寸法と同じオーダーにしておけばよいと思います。ベクトルは必ず視点へ向かう方向にとってください。 3)直方体の8つの点について順に(i=1~8)点Pを通るV方向ベクトルへの正射影(j=1~8)をつくります。即ち、点Pを通り、ベクトルVの方向を持つ直線(m)と点iから直線mへ垂線を引いてできる交点j(=点iのmへの正射影)を求めます。点Pからこの点jまでの距離sjを求めます(ベクトルVの向きに正として)。sjは視線上で測った各頂点の位置(大きい方が手前、即ち視点に近い)を示しています。 4)j=1~8でsjが最大となる点(視点に近い点)を選びます。 ・4つの点についてsjが等しくなり、これが最大になる場合 これはその4点からなる面が視線・ベクトルVに直交(或いは画面に平行)の場合です。 ・2つの点についてsjが等しくなり、これが最大になる場合 これは2点を結ぶ辺が画面に平行の場合です。 ・1つの点で最大になる場合 直方体が完全に斜めになっている場合です。 以上の3通りのいずれかになる筈です。 5)処理4)のsj最大点の数に応じて、着目した立方体の頂点・面に対して以下のようにします。 ・4つの場合 その4点を頂点とする面が表の面(こちら側を向いた面)として1つ選び出せます。 ・2つの場合 その2点を頂点とする面が2つ選び出せます。 ・1つの場合 その1点を頂点とする面が3つ選び出せます。 以上のように面の選び出しができると思います。 1つだけ気になる点があります。ANo.#1で「立方体のデータaが集まってさらに大きい立方体を作っています.」と言われていますが、この「大きな立方体」はANo.#3の補足説明からは理解しがたいのですがもしこの点に関して問題があれば補足していただけないでしょうか。(今回の説明ではこの点は無視しています。)
補足
ありがとうございます. 質問の内容はこれで合っています. もしよろしければ一般の六面体についてもご教授いただけないでしょうか? (番号を振る順は全ての6面体で一定になっています) さらに質問なのですが,回転を何度も行う場合でもこの方法で描画するのが良いのでしょうか. 「立方体のデータaが集まってさらに大きい立方体を作っています.」というのは,aの中の頂点の番号が共有しているものがあるという意味で書きました.
- tgb
- ベストアンサー率78% (32/41)
申し訳ないのですが、まだ問題の輪郭が掴めないようです。 私の理解する範囲で、ANo.#2の補足に基づいて、本問題の簡単な実例: 方向、大きさの異なる小立方体がお互いに離れた位置に 3個あるとするとして、これから、本問題で要求する 大立方体を求める を考えてみます。この例からすぐに分かるように、 ・大立方体をいくつにしたらよいか決まらない ・そのサイズをいくらにしたらよいか決まらない と言うことになります。 このような問題を考えているとは思えないので、更に補足が必要なように思います。
補足
説明が下手なために何度も申し訳ありません. 現在上記に示すような配列を使って画面上に形状を書くという作業を行っています. 六面体の各頂点には値が与えられておりそれを元に色を塗る作業を行おうとしています. しかしながら,すべての面(n×6)について描画を行うと処理に時間がかかってしまいます. そこで,表面を選び出して描画の処理を少なくしようと思っています. また,現在の描画方法は配列aからrを取り出して,rに入っている頂点の座標番号からX,Y,Zそれぞれの座標を取り出しているといった単純なものです.
- tgb
- ベストアンサー率78% (32/41)
補足説明を考慮して処理方法を考えようとするとだいぶ煩雑になると思います。また、無駄な処理をすることのないよう、もう少し補足をしていただく必要があると思います。 ・最終的に大きな立方体は1つなのか? それともいくつかのグループがあるのか?(当然こちらの方がより煩雑になります) ・大きな立方体の表面は必ず小さな立方体で構成されているのか? それとも表面が間欠的になっていて不完全な立方体なのか? ・上と関連して、大きな立方体の内部の間欠性はどうなのか? ・全ての立方体は同一の方向を向いているのか?(大立方体が1つなら一致しているものと考えますが) また、1つの頂点に集まる3つの辺は座標軸の方向に一致しているのかいないのか? 更に、小立方体の大きさは一定しているのかバラバラなのか? 一定している場合、位置は格子状(格子間隔が小立方体のサイズ?)なのか任意の位置か? ・r=6*nとしていますが、2つの小さな立方体が1つの面を共有して接しているとき、b(r,4)のデータとしてはこのような同一の面に対して立方体毎に別の番号が割り当てられているということなのか?それとも他に意味があるのか? ・最終的に欲しいデータの形はどのようなものなのか配列などで具体的に示せないでしょうか?
補足
ありがとうございます. ・最終的に大きな立方体は1つなのか? それともいくつかのグループがあるのか?(当然こちらの方がより煩雑になります) >1つの場合といくつかのグループで構成されている場合があります. ・大きな立方体の表面は必ず小さな立方体で構成されているのか? それとも表面が間欠的になっていて不完全な立方体なのか? >これも間欠的になっている場合もあります. ・上と関連して、大きな立方体の内部の間欠性はどうなのか? >内部に間欠性はあります. ・全ての立方体は同一の方向を向いているのか?(大立方体が1つなら一致していないものと考えますが) >同一方向を向いていません. また、1つの頂点に集まる3つの辺は座標軸の方向に一致しているのかいないのか? >一致していません. 更に、小立方体の大きさは一定しているのかバラバラなのか? 一定している場合、位置は格子状(格子間隔が小立方体のサイズ?)なのか任意の位置か? >立方体の大きさは一定ではありません. ・r=6*nとしていますが、2つの小さな立方体が1つの面を共有して接しているとき、b(r,4)のデータとしてはこのような同一の面に対して立方体毎に別の番号が割り当てられているということなのか?それとも他に意味があるのか? >b(r,4)はa(n,8)から取り出したものでありますので,同一の面に対して立方体毎に別の番号がふられています. ・最終的に欲しいデータの形はどのようなものなのか配列などで具体的に示せないでしょうか? >最終的には表面となる面の数mと表面を構成する頂点の番号s(m,4)を取り出したいと考えています.
- tgb
- ベストアンサー率78% (32/41)
立方体のデータa(n,8)と面のデータb(r,4)が与えられていて、立方体の番号i(=1~n)が与えられたとき、立方体の面として全体の面データからどの面番号j(=1~r)を6個取り出すかと言う問題と解釈します。 もっと効率的な方法があるかも知れませんが、虱潰しに指定の立方体の点番号と合致するような面をbの中から探していけばよいと思います。この場合、x、y、z座標は不要です。 以下のようになります。 1.立方体番号iと面番号jとを与えて、与えられた面番号についてこの面の4つの点の点番号全てが、与えられた立方体の8つの点の点番号いずれかと一致するかどうかチェックできるようにします。...f1(i,j) 2.立方体iが与えられたとき、f2を使って面1から順にrまでチェックを繰り返します。面が見つかる度にデータc(n,6)に格納します。一致する点が全て見つかるような面の数が6になったら途中で終了します...f2(i) 3.立方体i=1~nについて、f2を使った処理を繰り返します。 以上でc(n,6)が出来上がります。c(n,6)をつくらずに必要な度に処理2を行って6つの面を取り出すと言うことも可能です。
補足
ご回答ありがとうございます. すいません.説明不足でした. 立方体のデータaが集まってさらに大きい立方体を作っています. このような場合立方体の表面を取り出す方法を知りたいです. ちなみにr=n*6となっています.
補足
#5の方法は視点から遠い面の順に描画していくということで良いのでしょうか. できれば,値を用いて色を塗る際の計算量を減らすため,画面上に見える部分のみを取り出したいと考えています. 立方体数(30000個以上の場合もある)×6の処理を描画するたびに行うと計算量が多くなるのではないかということを心配しています.