当たり判定講座softmedia.sakura.ne.jp/w/images/4/4a/2016年度春季...question !...
TRANSCRIPT
当たり判定講座新製品
オーダー記法計算量
オーダー記法というのは…
とある処理がどれほど時間がかかるのかを表せる方法
書き方は一般的な書き方の例
𝑓1 = 𝑂 𝑛2 𝑓2 = 𝑂 1
他にも意味が違うような書き方がある
𝑓3 = Ω 𝑛2 𝑓4 = θ 𝑛3
どのようにして計算量が決まるか…
それは多回層のループ文の数で考えてしまっていいと思います。
二重ループならば𝑓 = 𝑂 𝑛2
三重ループならば𝑓 = 𝑂 𝑛3
ループ文がなければ𝑓 = 𝑂 1
しかし中には以下のような複数のループが存在する処理がある
int ans = 1; //処理数1
for (unsigned int i = 0; i < n; i++)ans *= i; //ループだから処理数𝑛だね
for (unsigned int i = 0; i < n; i++){
for (unsigned int j = 0; j < n; j++){
std::cout << “特にいみないよ!” << std::endl;//二重ループだから処理数𝑛2だよ
}
}
じゃあこの場合計算量は?????
𝑓 = 𝑂 𝑛2 + 𝑛 + 1
(では)ないです
実はオーダー記法の基本的考えは大雑把でいい!
ここで評価する上での簡単なルール
1. 影響が一番大きい項以外無視
2. 定数倍は無視→係数は書かないよ
という事は!
𝑓 = 𝑂 𝑛2
でいいという事!
Question! 次のプログラムから計算量を求めよう。
int ans = 0;
for (unsigned int i = 0; i < n; i++)ans *= i;
for (unsigned int i = 0; i < n; i++){
for (unsigned int j = 0; j < n; j++){
std::cout << “特にいみないよ!” << std::endl;
}
}
for (unsigned int i = 0; i < n; i++){
for (unsigned int j = 0; j < n; j++){
std::cout << “特に意味のないどうでもいい処理!” << std::endl;
}
}
Answer!プログラムは二重ループが二つと単純なループが一つ加えて代入処理が1つだ。
という事は式にすると
𝑛2 + 𝑛2 + 𝑛 + 1 = 2𝑛2 + 𝑛 + 1
という事はまずルール1より
2𝑛2 + 𝑛 + 1 → 2𝑛2
次にルール2より係数を消す。結果答えは…
𝑓 = 𝑂(𝑛2)
三平方の定理ピタゴラスの定理
基本中の基本ですぞ。
三平方の定理の概要は流石にわかってると思うので割愛する
Question!当たり判定を三平方の定理のみで処理した際に発生する、一番のバグを考えよう。
また説明も考えよう。
Answer!オブジェクトどうしのスピードが速すぎることで起こるバグ。
ゲームはパラパラ漫画のように一枚ずつ描画されて動いている。つまりスピードが速すぎると判定ラインを越えてすれ違いが起こる。
Answer!実際に行いたい処理順
でも早すぎると…
A B AB
次の絵
A B
次の絵
A B AB
次の絵
A B
次の絵
実際の次の絵
ベクトル判定ベクトルって聞くと計算が面倒なイメージ
すり抜けバグをどうしたら回避できるのか…
言葉で表すととんでもなく簡単です!
衝突する二つのオブジェクトが交差する場所を見つける。
Question!
ちょっとした数学の問題!
すり抜けが発生しないように次の指定した変数のみで条件式を組み立てよう。
必要なものは1. 現在のオブジェクトの座標
2. 次のフレームのオブジェクト座標
3. オブジェクトの大きさ
したがって式を立てるために必要な変数は…
1. 現在フレーム𝑡をとする。
2. オブジェクトAの現在座標を 𝑥𝐴𝑡 , 𝑦𝐴𝑡3. オブジェクトBの現在座標を 𝑥𝐵𝑡 , 𝑦𝐵𝑡
4. オブジェクトAの次フレーム座標を 𝑥𝐴(𝑡+1), 𝑦𝐴(𝑡+1)
5. オブジェクトBの次フレーム座標を 𝑥𝐵(𝑡+1), 𝑦𝐵(𝑡+1)
6. オブジェクトAの半径を𝑅𝐴7. オブジェクトBの半径を𝑅𝐵
Hint! オブジェクトAとBのx座標が一致する時間を求める。
次にオブジェクトが重なっているかを調べる。
これだけ!
A
B
A
B
Answer!求める時間を𝑇とした時。
𝑇 = (𝑥𝑡𝐵−𝑥𝑡𝐴)/(∆𝑥𝐴 − ∆𝑥𝐵)0≤ 𝑇 ≤ 1 𝑎𝑛𝑑 𝑅𝐴 + 𝑅𝐵 ≤ 𝑦𝐴𝑡 − 𝑦𝐵𝑡
答えはこれだけじゃないかも?
どうしてこの答えになったかを追って説明していきます。
まずオブジェクトAとBが同じ座標になる時刻を見つける。
オブジェクトが次フレームまでに移動する変位∆𝑥𝐴と∆𝑥𝐵を求める。
∆𝑥𝐴 = 𝑥𝐴𝑡 − 𝑥𝐴 𝑡+1 (1)
∆𝑥𝐵 = 𝑥𝐵𝑡 − 𝑥𝐵 𝑡+1 (2)
次に(1)(2)から変位∆𝑥𝐴と∆𝑥𝐵を次フレームまでの速度として扱う。
この変位∆𝑥𝐴と∆𝑥𝐵の時にオブジェクトAとBが接触する時間𝑡を求める。
𝑥𝐴𝑡 + 𝑡∆𝑥𝐴 = 𝑥𝑡𝐵 + 𝑡∆𝑥𝐵
𝑡∆𝑥𝐴 − 𝑡∆𝑥𝐵 = 𝑥𝑡𝐵 − 𝑥𝑡𝐴
𝑡 ∆𝑥𝐴 − ∆𝑥𝐵 = 𝑥𝑡𝐵 − 𝑥𝑡𝐴
𝑡 = (𝑥𝑡𝐵−𝑥𝑡𝐴)/(∆𝑥𝐴 − ∆𝑥𝐵) (3)
𝑡 = (𝑥𝑡𝐵−𝑥𝑡𝐴)/(∆𝑥𝐴 − ∆𝑥𝐵) (3)
もしも1 < 𝑇の場合、そのオブジェクトは次フレームまでの間に衝突することはない。
また0 ≤ 𝑇 ≤ 1の場合、そのオブジェクトは次フレームまでの間に衝突している可能性がある。
では0 ≤ 𝑇 ≤ 1のときどのような状態になっているか?
答えは二通り!
A
B
A
B
A
B
𝑇 = (𝑥𝑡𝐵−𝑥𝑡𝐴)/(∆𝑥𝐴 − ∆𝑥𝐵) (3)
(3)の式はオブジェクトのx座標を同じ位置にしている。
そのためオブジェクトAとBのy座標から差の絶対値を求め、AとBの半径の合計よりも小さければ衝突していることが分かる。
したがって残りの判定式は次のようになる。
𝑅𝐴 + 𝑅𝐵 ≤ 𝑦𝐴𝑡 − 𝑦𝐵𝑡 (4)
総当たりと四分岐探索サクッと削減!
まず始めにゲームの1フレームに許される処理時間を考えよう。
1秒間に更新されるフレームが60枚のとき、1枚に許される処理時間は何ミリ秒でしょうか?
1秒は1000ミリ秒
したがって
1000/60=16.666666…<ms>
大体17<ms>しか許されない。
ではでは…
Question!画面にあるオブジェクトが500個。
あたり判定1ペアの処理時間が1.5<μs>
総当たりで全てのあたり判定を行った場合、判定を開始してから終了するまでの処理時間はどれほどかかるでしょうか!
Answer! 500𝐶2 × 1.5 × 10−6 = 0.187125<s>
0.187125 × 103 = 187.125<ms>
約187<ms>ということは1フレームの猶予である約17<ms>より170<ms>もオー
バーしてしまっている!!
処理落ち不可避!
そこで!!!
四分岐探索という方法があります!
画面を縦横に分割しましょう。
同じエリアどうしのオブジェクトで判定すればおk!
2 3
0 1
更に分割しましょう!
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
まだまだ分割しましょう!
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
18 19
16 17
22 23
20 21
26 27
24 25
30 31
28 29
34 35
32 33
38 39
36 37
42 43
40 41
46 47
44 45
50 51
48 49
54 55
52 53
58 59
56 57
62 63
60 61
あれあれ?跨いだ時は?
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
18 19
16 17
22 23
20 21
26 27
24 25
30 31
28 29
34 35
32 33
38 39
36 37
42 43
40 41
46 47
44 45
50 51
48 49
54 55
52 53
58 59
56 57
62 63
60 61おぶじぇくと
分割する前に戻そう。あれ?まだ跨いでる…
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13おぶじぇくと
さらに前に戻そう!おk!おさまった!
2 3
0 1
おぶじぇくと
つまりそのオブジェクトがちょうどおさまる分解度を探して記憶しておけばいい!
2 3
0 1
おぶじぇくと
分解度が違う場合は???
18 19
16 17
22 23
20 21
26 27
24 25
30 31
28 29
34 35
32 33
38 39
36 37
42 43
40 41
46 47
44 45
2 3
0 1
おぶじぇくと
3おぶじぇくとおぶじぇくと
分解度が低いものは、分解度の高いものも同じエリアとして判定する。
つまりオブジェクトAは分解度が低いため、オブジェクトBの分解度が高いものも判定を行う。
じゃあオブジェクトCはオブジェクトAとの判定を行うか?
これは行わない。理由はエリアが違うから。 2 3
0 12 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13B
A
C
2 3
0 1
0
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
0
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
18 19
16 17
22 23
20 21
26 27
24 25
30 31
28 29
34 35
32 33
38 39
36 37
42 43
40 41
46 47
44 45
50 51
48 49
54 55
52 53
58 59
56 57
62 63
60 61
0 1 32
2 30 1 6 74 5 10 118 9 14 1512 13
2 30 1 6 74 5 10 118 9 1412 13 ・・・
四分岐画面
Level 0
Level 1
Level 2
Level 3
でもでも…
実はこれ、そのままプログラムを組み立てるとものすごく遅いのです…
どうしてか? 2つ問題点をあげましょう。1. オブジェクトの登録エリア、レベルの検索、そしてその登録。
2. オブジェクトの登録情報を力技検索
解決方法は?
まず一つ目、四分岐探索の木をメモリに作ることです。
これは二次配列を使えば簡単にできます。
じゃあ次は登録エリア、レベルの検索です。
普通に作るとするならif文を用いてオブジェクトがエリアを跨がないようなレベルを探すと思います。
これじゃあダメなんです。
Question! 最大分解度をレベル2とし、これを基準とする。
オブジェクトの始点(2,2)と終点(3,3)としたとき、このオブジェクトが境界を跨がないようにエリアとレベルに高速で登録したい。
またこのオブジェクトはエリア3 レベル1である。
Level 2
2 3
0 1
おぶじぇくと
Level 1
2 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13おぶじぇくと
0 1 2 3
0
1
2
3
y x
Answer! まず最初にエリアの番号がこのような順番になっていたことにお気づきでしょうか?
2 3
0 12 3
0 1
6 7
4 5
10 11
8 9
14 15
12 13
どうしてこのような番号の割り振りかというと…
二進数にすることで理解できると思います。
左右を一桁目、上下を二桁目で表しています。
10 2 11 2
00 2 01 2
では分解度をあげたらどうでしょう?
二桁目までは先ほどと同様です。
三、四桁目は赤線で上下左右を表します。
0000 2 0001 2
0010 2 0011 2
0100 2 0101 2
0110 2 0111 2
1000 2 1001 2
1010 2 1011 2
1100 2 1101 2
1110 2 1111 2
ではさらに分解度をあげたらどうでしょう?
四桁目までは先ほどと同様です。
五、六桁目は赤線で三、四桁目同様上下左右を表します。
000010 2 000011 2
000000 2 000001 2
000110 2 000111 2
000100 2 000101 2
001110 2 001111 2
001100 2 001101 2
001010 2 001011 2
001000 2 001001 2
010010 2 010011 2
010000 2 010001 2
010110 2 010111 2
010100 2 010101 2
011110 2 011111 2
011100 2 011101 2
011010 2 011011 2
011000 2 011001 2
100010 2 100011 2
100000 2 100001 2
100110 2 100111 2
100100 2 100101 2
101110 2 101111 2
101100 2 101101 2
101010 2 101011 2
101000 2 101001 2
110010 2 110011 2
110000 2 110001 2
110110 2 110111 2
110100 2 110101 2
111110 2 111111 2
111100 2 111101 2
111010 2 11011 2
111000 2 111001 2
ここまでくれば以降分解度を上げたときにどうなっていくか予想できるでしょう。
分解度をLとした時必要なビット数Bは次の式で求められます。
𝐵 = 2𝐿
次に二進数の奇数桁はx軸を表し、偶数桁はy軸を表します。
このようなナンバリングを
モートン順序(Morton Order)
と呼びます。
ここで問題文からオブジェクトの始点座標は(2,2)でした。
x軸は2です。二進数に直すと 0010 2
y軸も2です。二進数に直すと 0010 2
モートン順序から奇数桁がx軸、偶数桁はy軸でした。
つまり…
結果モートンナンバーは二進数で 00001100 2となり、
十進数で表すと12となりました。
Level4
y
Level4
x
Level3
y
Level3
x
Level2
y
Level2
x
Level1
y
Level1
x
オブジェクトx軸 0 0 1 0オブジェクトy軸 0 0 1 0
モートンナンバー 0 0 0 0 1 1 0 0
同様に問題文からオブジェクトの終点座標は(3,3)でした。
x軸は2です。二進数に直すと 0011 2
y軸も2です。二進数に直すと 0011 2
結果モートンナンバーは二進数で 00001111 2となり、
十進数で表すと15となりました。
Level4
y
Level4
x
Level3
y
Level3
x
Level2
y
Level2
x
Level1
y
Level1
x
オブジェクトx軸 0 0 1 1オブジェクトy軸 0 0 1 1
モートンナンバー 0 0 0 0 1 1 1 1
これで始点と終点のエリアが分かりました。しかしこれらのナンバーは一致していません。つまりエリアを跨いでいる状態です。
これを解決するためにエリアを跨がないようなレベルを探す方法を解説します。
始点と終点それぞれのモートンナンバーは00001100 2と 00001111 2でした。
この始点と終点のモートンナンバーから排他的論理和をとります。
00001100 2 ⊕ 00001111 2 = 00000011 2
出てきた値を右2ビットシフトします。
この右2ビットシフトを値が0になるまで繰り返し回数nを覚えておきます。
今回は1回だけ行うことで0になります。
最後に始点と終点どちらかのモートンナンバーから先ほどの回数nを右2ビットシフトすることでオブジェクトのモートンナンバーが求まります。
また先ほどの回数nはどのレベルまで引き下げるかを示しており、分解度レベルは次の式で求まります。
最大分解度レベル-n =分解度レベル
0.0000000
0.1000000
0.2000000
0.3000000
0.4000000
0.5000000
0.6000000
0.7000000
200
210
220
230
240
250
260
270
280
290
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
510
520
530
540
550
560
570
580
590
600
610
620
630
640
650
660
670
680
690
700
710
720
730
740
750
760
770
780
790
800
810
820
830
時間
<秒
>
オブジェクト数
総当たりと四分岐探索の比較 モード:debug
四分岐探索
総当たり
0.0000000
0.0002000
0.0004000
0.0006000
0.0008000
0.0010000
0.0012000
0.0014000
0.0016000
0.0018000
0.0020000
200
210
220
230
240
250
260
270
280
290
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
510
520
530
540
550
560
570
580
590
600
610
620
630
640
650
660
670
680
690
700
710
720
730
740
750
760
770
780
790
800
810
820
830
時間
<秒
>
オブジェクト数
総当たりと四分岐探索の比較 モード:release
四分岐探索
総当たり
0.0000000
0.1000000
0.2000000
0.3000000
0.4000000
0.5000000
0.6000000
0.7000000
200
210
220
230
240
250
260
270
280
290
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
510
520
530
540
550
560
570
580
590
600
610
620
630
640
650
660
670
680
690
700
710
720
730
740
750
760
770
780
790
800
810
820
830
時間
<秒
>
オブジェクト数
総当たりと四分岐探索のモード比較
総当たり debug
四分岐探索 debug
総当たり release
四分岐探索 release
TS-590 USBオーディオ機能 設定ガイド - KENWOOD...7 4. 設定方法 4.1 無線機の設定 USB オーディオ機能を使った運用をするために必要な、無線機側(TS-590)の設定を
Cisco APIC Security セキュリティ設定ガイド...NX-OSスタイルCLIを使用した802.1xポート認証の設定 78 NX-OSスタイルCLIを使用した802.1xノード認証の設定
4301 4 +Ã1í7 ê!¸)¡-× è Ú - maff.go.jp...47 2.4 現地確認による検証 (1)現地確認対象地点の選定 2005 年判読で、D 発生地と判読されたもののうち、D