1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: math_Geometry.h
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 24054 $
14 *---------------------------------------------------------------------------*/
15
16 #ifndef NN_MATH_GEOMETRY_H_
17 #define NN_MATH_GEOMETRY_H_
18
19 #include <nn/math/math_Config.h>
20 #include <nn/math/math_Types.h>
21 #include <nn/math/math_Triangular.h>
22
23 namespace nn { namespace math {
24
25 // 線や面等のジオメトリオブジェクトを定義しておく
26
27 // 名前予約
28 struct LINE2;
29 struct RAY2;
30 struct SEGMENT2;
31 struct CIRCLE2;
32 struct TRIANGLE2;
33
34 struct LINE3;
35 struct RAY3;
36 struct SEGMENT3;
37 struct SPHERE;
38 struct TRIANGLE3;
39 struct PLANE;
40 struct CYLINDER;
41 struct CONE;
42 struct AABB;
43 struct CAPSULE;
44
45 enum IntersectionResult
46 {
47 INTERSECTION_NONE = 0,
48 INTERSECTION_1 = 1,
49 INTERSECTION_2 = 2,
50
51 INTERSECTION_LINE3_ON_PLANE = 2,
52 INTERSECTION_RAY3_ON_PLANE = INTERSECTION_LINE3_ON_PLANE,
53 INTERSECTION_SEGMENT3_ON_PLANE = INTERSECTION_LINE3_ON_PLANE,
54
55 INTERSECTION_OUTSIDE = 0,
56 INTERSECTION_INSIDE = 1,
57 INTERSECTION_INTERSECT = 2
58 };
59
60 /* =======================================================================
61 クラス定義
62 ======================================================================== */
63
64
65 /* ------------------------------------------------------------------------
66 LINE3:
67
68 L: P + td
69 パラメトリック形式の線(3D)である。Pが起点でdが線の方向である。
70 使用時にdは正規化されていることが前提となっている。
71 ------------------------------------------------------------------------ */
72 struct LINE3
73 {
74 public:
75 typedef LINE3 self_type;
76 public:
LINE3LINE377 LINE3() {}
78 LINE3(const f32* p, bool isNormalized = false)
PLINE379 : P(p), d(p + 3)
80 { if (!isNormalized) Normalize(); }
81 LINE3(const VEC3& Pt, const VEC3& dir, bool isNormalized = false)
PLINE382 : P(Pt), d(dir)
83 { if (!isNormalized) Normalize(); }
84
85 operator f32*() { return &P.x; }
86 operator const f32*() const { return &P.x; }
87 bool operator==(const self_type& rhs) const { return P == rhs.P && d == rhs.d; }
88 bool operator!=(const self_type& rhs) const { return P != rhs.P || d != rhs.d; }
89
90 // 線分を、線分の始点を始点とする線に変換する。
91 void Set(const SEGMENT3* S);
NormalizeLINE392 void Normalize() { (void)VEC3Normalize(&d, &d); }
93 public:
94 VEC3 P;
95 VEC3 d; // 直接代入する場合は正規化しておくこと
96 };
97
98 /* ------------------------------------------------------------------------
99 RAY3
100
101 R: P + td (ただし、t >= 0)
102 起点からdの方向だけに向かう線である。Pが起点でdが線の方向である。
103 使用時にdは正規化されていることが前提となっている。
104 ------------------------------------------------------------------------ */
105 struct RAY3
106 {
107 public:
108 typedef RAY3 self_type;
109 public:
RAY3RAY3110 RAY3() {}
111 RAY3(const f32* p, bool isNormalized = false)
PRAY3112 : P(p), d(p + 3)
113 { if (!isNormalized) Normalize(); }
114 RAY3(const VEC3& Pt, const VEC3& dir, bool isNormalized = false)
PRAY3115 : P(Pt), d(dir)
116 { if (!isNormalized) Normalize(); }
117
118 operator f32*() { return &P.x; }
119 operator const f32*() const { return &P.x; }
120 bool operator==(const self_type& rhs) const { return P == rhs.P && d == rhs.d; }
121 bool operator!=(const self_type& rhs) const { return P != rhs.P || d != rhs.d; }
122
NormalizeRAY3123 void Normalize() { (void)VEC3Normalize(&d, &d); }
124 public:
125 VEC3 P;
126 VEC3 d; // 直接代入する場合は正規化しておくこと
127 };
128
129
130 /* ------------------------------------------------------------------------
131 SEGMENT3
132
133 S: (1 - t)P0 + tP1 (ただし、0 <= t <= 1)
134 P0とP1を繋ぐ線分である。
135 ------------------------------------------------------------------------ */
136 struct SEGMENT3
137 {
138 public:
139 typedef SEGMENT3 self_type;
140 public:
SEGMENT3SEGMENT3141 SEGMENT3() {}
SEGMENT3SEGMENT3142 SEGMENT3(const f32* p) : P0(p), P1(p + 3) {}
SEGMENT3SEGMENT3143 SEGMENT3(const VEC3& pt0, const VEC3& pt1) : P0(pt0), P1(pt1) {}
144
145 operator f32*() { return &P0.x; }
146 operator const f32*() const { return &P0.x; }
147 bool operator==(const self_type& rhs) const { return P0 == rhs.P0 && P1 == rhs.P1; }
148 bool operator!=(const self_type& rhs) const { return P0 != rhs.P0 || P1 == rhs.P1; }
149 public:
150 VEC3 P0;
151 VEC3 P1;
152 };
153
154 inline void
Set(const SEGMENT3 * S)155 LINE3::Set(const SEGMENT3* S)
156 {
157 P = S->P0;
158 VEC3Sub(&d, &S->P1, &S->P0);
159 Normalize();
160 }
161
162
163 /* ------------------------------------------------------------------------
164 SPHERE
165
166 S: |P - C| <= r
167 Cを中心の位置、rを半径とする球である。
168 ------------------------------------------------------------------------ */
169 struct SPHERE
170 {
171 public:
172 typedef SPHERE self_type;
173 public:
SPHERESPHERE174 SPHERE() {}
SPHERESPHERE175 SPHERE(const f32* p) : C(p), r(*(p + 3)) {}
SPHERESPHERE176 SPHERE(const VEC3& center, f32 radius) : C(center), r(radius) {}
177
178 operator f32*() { return &C.x; }
179 operator const f32*() const { return &C.x; }
180 bool operator==(const self_type& rhs) const { return C == rhs.C && r == rhs.r; }
181 bool operator!=(const self_type& rhs) const { return C != rhs.C || r != rhs.r; }
182
183 // 点の集合を包含する球をセットする。
184 void Set(const VEC3* arrayPoint, unsigned int numPoints);
185 public:
186 VEC3 C;
187 f32 r;
188 };
189
190
191 /* ------------------------------------------------------------------------
192 PLANE
193
194 (N.x)x + (N.y)y + (N.z)z + d = 0
195
196 平面の陰関数表現をパラメータとして持っている。
197 法線ベクトルNは正規化されている必要がある。
198 ------------------------------------------------------------------------ */
199 struct PLANE
200 {
201 public:
202 typedef PLANE self_type;
203 public:
PLANEPLANE204 PLANE() {}
205 PLANE(const f32* p, bool isNormalized = false)
NPLANE206 : N(p), d(*(p + 3))
207 { if (!isNormalized) Normalize(); }
208 PLANE(f32 A, f32 B, f32 C, f32 D, bool isNormalized = false)
NPLANE209 : N(A, B, C), d(D)
210 { if (!isNormalized) Normalize(); }
211
PLANEPLANE212 PLANE(const VEC3& P0, const VEC3& P1, const VEC3& P2)
213 {
214 Set(&P0, &P1, &P2);
215 }
216
217 operator f32*() { return &N.x; }
218 operator const f32*() const { return &N.x; }
219 bool operator==(const self_type& rhs) const { return N == rhs.N && d == rhs.d; }
220 bool operator!=(const self_type& rhs) const { return N != rhs.N || d != rhs.d; }
221
222 // Pが平面の法線方向にある場合は正に、そうでない場合は負になります。
TestPLANE223 f32 Test(const VEC3& P) const
224 {
225 return d + VEC3Dot(&N, &P);
226 }
227
NormalizePLANE228 void Normalize()
229 {
230 f32 r = FrSqrt(VEC3SquareLen(&N));
231 (void)VEC3Scale(&N, &N, r);
232 d *= r;
233 }
234
235 void Set(const VEC3* P0, const VEC3* P1, const VEC3* P2);
236 public:
237 VEC3 N; // 直接代入する場合は正規化しておくこと
238 f32 d;
239 };
240
241
242 /* ------------------------------------------------------------------------
243 CAPSULE
244
245 線分と線分に対する距離でカプセルが定義される。
246 ------------------------------------------------------------------------ */
247 struct CAPSULE
248 {
249 public:
250 typedef CAPSULE self_type;
251 public:
CAPSULECAPSULE252 CAPSULE() {}
CAPSULECAPSULE253 CAPSULE(const f32* p) : S(p), r(*(p + 6)) {}
CAPSULECAPSULE254 CAPSULE(const SEGMENT3& S_, f32 r_) : S(S_), r(r_) {}
CAPSULECAPSULE255 CAPSULE(const VEC3& P0, const VEC3& P1, f32 r_) : S(P0, P1), r(r_) {}
256
257 operator f32*() { return &S.P0.x; }
258 operator const f32*() const { return &S.P0.x; }
259 bool operator==(const self_type& rhs) const { return S == rhs.S && r == rhs.r; }
260 bool operator!=(const self_type& rhs) const { return S != rhs.S || r != rhs.r; }
261 public:
262 SEGMENT3 S;
263 f32 r;
264 };
265
266
267 /* ------------------------------------------------------------------------
268 AABB
269
270 xyz軸に沿ったボックスです。2つの点PminとPmaxで定義されます。
271 Pminのそれぞれの座標はPmaxの座標よりも小さい必要があります。
272 ------------------------------------------------------------------------ */
273 struct AABB
274 {
275 public:
276 typedef AABB self_type;
277 public:
AABBAABB278 AABB() {}
279 AABB(const f32* p, bool isNormalized = false)
PminAABB280 : Pmin(p), Pmax(p + 3)
281 { if (!isNormalized) Normalize(); }
282 AABB(const VEC3& min, const VEC3& max, bool isNormalized = false)
PminAABB283 : Pmin(min), Pmax(max)
284 { if (!isNormalized) Normalize(); }
285
286 operator f32*() { return &Pmin.x; }
287 operator const f32*() const { return &Pmin.x; }
288 bool operator==(const self_type& rhs) const { return Pmin == rhs.Pmin && Pmax == rhs.Pmax; }
289 bool operator!=(const self_type& rhs) const { return Pmin != rhs.Pmin || Pmax != rhs.Pmax; }
290
291 void Set(const VEC3* arrayPoint, unsigned int numPoints);
292 void Set(const AABB* box, const MTX34* M);
293 void Normalize();
294 public:
295 VEC3 Pmin;
296 VEC3 Pmax;
297 };
298
299
300
301
302 /* ------------------------------------------------------------------------
303 CYLINDER
304
305 半径rで原点からZ軸にhだけの高さを持つ円柱と解釈される。
306 lineやplaneとの交差判定は座標変換してから行う必要がある。
307 ------------------------------------------------------------------------ */
308 struct CYLINDER
309 {
310 public:
311 typedef CYLINDER self_type;
312 public:
CYLINDERCYLINDER313 CYLINDER() {}
CYLINDERCYLINDER314 CYLINDER(const f32* p)
315 : r(*p), h(*(p + 1)) {}
CYLINDERCYLINDER316 CYLINDER(f32 radius, f32 height)
317 : r(radius), h(height) {}
318 public:
319 f32 r;
320 f32 h;
321 };
322
323
324 /* ------------------------------------------------------------------------
325 CONE
326
327 半径rで原点からZ軸にhだけの高さを持つ円錐と解釈される。
328 lineやplaneとの交差判定は座標変換してから行う必要がある。
329 ------------------------------------------------------------------------ */
330 struct CONE
331 {
332 public:
333 typedef CONE self_type;
334 public:
CONECONE335 CONE() {}
CONECONE336 CONE(const f32* p)
337 : r(*p), h(*(p + 1)) {}
CONECONE338 CONE(f32 radius, f32 height)
339 : r(radius), h(height) {}
340 public:
341 f32 r;
342 f32 h;
343 };
344
345
346
347 /* ------------------------------------------------------------------------
348 FRUSTUM
349
350 主にカリングに使用するためのフラスタムの定義
351 ------------------------------------------------------------------------ */
352 class FRUSTUM
353 {
354 public:
355 typedef FRUSTUM self_type;
356 public:
357 //---------------------------------------------------------------------------
358 //! @brief コンストラクタです。
359 //---------------------------------------------------------------------------
FRUSTUM()360 FRUSTUM() {}
361
362 //---------------------------------------------------------------------------
363 //! @brief コンストラクタです。
364 //!
365 //! @param[in] fovyRad 縦方向の視野角(Radian)。
366 //! @param[in] aspect アスペクト比(幅/高さ)
367 //! @param[in] n ニアクリッピング面までの距離。
368 //! @param[in] f ファークリッピング面までの距離。
369 //! @param[in] camera カメラ行列。
370 //---------------------------------------------------------------------------
FRUSTUM(f32 fovyRad,f32 aspect,f32 n,f32 f,const MTX34 & camera)371 FRUSTUM(f32 fovyRad, f32 aspect, f32 n, f32 f, const MTX34& camera)
372 {
373 Set(fovyRad, aspect, n, f, camera);
374 }
375
376 //---------------------------------------------------------------------------
377 //! @brief コンストラクタです。
378 //!
379 //! @param[in] top ニアクリッピング面での視錐台上辺の Y 座標。
380 //! @param[in] bottom ニアクリッピング面での視錐台下辺の Y 座標。
381 //! @param[in] left ニアクリッピング面での視錐台左辺の X 座標。
382 //! @param[in] right ニアクリッピング面での視錐台右辺の X 座標。
383 //! @param[in] n ニアクリッピング面までの距離。
384 //! @param[in] f ファークリッピング面までの距離。
385 //! @param[in] camera カメラ行列。
386 //---------------------------------------------------------------------------
FRUSTUM(f32 top,f32 bottom,f32 left,f32 right,f32 n,f32 f,const MTX34 & camera)387 FRUSTUM(f32 top, f32 bottom, f32 left, f32 right, f32 n, f32 f, const MTX34& camera)
388 {
389 Set(top, bottom, left, right, n, f, camera);
390 }
391 private:
392 MTX34 cam;
393
394 /* ビュー座標系用のデータメンバ */
395 PLANE leftPlane;
396 PLANE rightPlane;
397 PLANE topPlane;
398 PLANE bottomPlane;
399 f32 znear;
400 f32 zfar;
401
402 /* ワールド座標系用のデータメンバ */
403 AABB box; // フラスタムを包含するAABBで粗い判定に用いる
404 PLANE planes[6]; // left, right, near, far, up, downの順(Optimized View Frustum Culling Algorithmより)
405 public:
406 //---------------------------------------------------------------------------
407 //! @brief FRUSTUM に設定を反映する Set 関数です。
408 //!
409 //! @param[in] top ニアクリッピング面での視錐台上辺の Y 座標。
410 //! @param[in] bottom ニアクリッピング面での視錐台下辺の Y 座標。
411 //! @param[in] left ニアクリッピング面での視錐台左辺の X 座標。
412 //! @param[in] right ニアクリッピング面での視錐台右辺の X 座標。
413 //! @param[in] n ニアクリッピング面までの距離。
414 //! @param[in] f ファークリッピング面までの距離。
415 //! @param[in] camera カメラ行列。
416 //---------------------------------------------------------------------------
417 void Set(f32 top, f32 bottom, f32 left, f32 right, f32 n, f32 f, const MTX34& camera);
418
419 //---------------------------------------------------------------------------
420 //! @brief FRUSTUM に設定を反映する Set 関数です。
421 //!
422 //! @param[in] fovyRad 縦方向の視野角(Radian)。
423 //! @param[in] aspect アスペクト比(幅/高さ)
424 //! @param[in] n ニアクリッピング面までの距離。
425 //! @param[in] f ファークリッピング面までの距離。
426 //! @param[in] camera カメラ行列。
427 //---------------------------------------------------------------------------
Set(f32 fovyRad,f32 aspect,f32 n,f32 f,const MTX34 & camera)428 void Set(f32 fovyRad, f32 aspect, f32 n, f32 f, const MTX34& camera)
429 {
430 f32 tanRad = TanRad(0.5f * fovyRad);
431 f32 ny = tanRad * n;
432 f32 nx = ny * aspect;
433 Set(ny, -ny, -nx, nx, n, f, camera);
434 }
435
436 public:
437 // SPHEREはワールド座標系
438 bool IntersectSphere(const SPHERE* S) const;
439
440 // AABBはワールド座標系
441 bool IntersectAABB(const AABB* B) const;
442
443 // AABBはワールド座標系
444 IntersectionResult IntersectAABB_Ex(const AABB* B) const;
445 };
446
447
448 //
449 // 3Dジオメトリ間の距離
450 //
451
452 // 点
453 f32 DistSqPoint3ToLine3(const VEC3* P, const LINE3* L, f32* t);
454 f32 DistSqPoint3ToRay3(const VEC3* P, const RAY3* R, f32* t);
455 f32 DistSqPoint3ToSegment3(const VEC3* P, const SEGMENT3* S, f32* t);
456 f32 DistSqPoint3ToPlane(const VEC3* P, const PLANE* J, VEC3* Q);
457 f32 DistSqSphereToPlane(const SPHERE* S, const PLANE* J);
458 f32 DistSqPoint3ToPolyline3(const VEC3* P, const VEC3* vertices, unsigned int nVertices);
459 f32 DistSqPoint3ToAABB(const VEC3* P, const AABB* B, VEC3* q);
460
461 // 線・レイ・線分
462 f32 DistSqLine3ToLine3(const LINE3* L0, const LINE3* L1, f32* s, f32* t);
463 f32 DistSqSegment3ToSegment3(const SEGMENT3* S0, const SEGMENT3* S1, f32* s, f32* t);
464 f32 DistSqLine3ToRay3(const LINE3* L, const RAY3* R, f32* s, f32* t);
465 f32 DistSqLine3ToSegment3(const LINE3* L0, const SEGMENT3* S, f32* s, f32* t);
466 f32 DistSqRay3ToRay3(const RAY3* R0, const RAY3* R1, f32* s, f32* t);
467 f32 DistSqRay3ToSegment3(const RAY3* R0, const SEGMENT3* S, f32* s, f32* t);
468
469
470
471
472 //
473 // 3Dジオメトリ間の交差
474 //
475
476
477 IntersectionResult IntersectionLine3Plane(const LINE3* L, const PLANE* J, f32* t, VEC3* I);
478 IntersectionResult IntersectionRay3Plane(const RAY3* R, const PLANE* J, f32* t, VEC3* I);
479 IntersectionResult IntersectionSegment3Plane(const SEGMENT3* S, const PLANE* J, f32* t, VEC3* I);
480
481 IntersectionResult IntersectionLine3Sphere(const LINE3* L, const SPHERE* sphere, f32* t0, f32* t1);
482 IntersectionResult IntersectionRay3Sphere(const RAY3* R, const SPHERE* sphere, f32* t0, f32* t1);
483 bool IntersectionRay3Sphere(const RAY3* R, const SPHERE* sphere);
484 IntersectionResult IntersectionSegment3Sphere(const SEGMENT3* S, const SPHERE* sphere, f32* t0, f32* t1);
485
486 bool IntersectionRay3AABB(const RAY3* R, const AABB* box, f32* t);
487 bool IntersectionAABB(const AABB* a, const AABB* b);
488 bool IntersectionSphereAABB(const SPHERE* sphere, const AABB* aabb);
489 bool IntersectionSphere(const SPHERE* s0, const SPHERE* s1);
490 bool IntersectionPlaneAABB(const PLANE* J, const AABB* B);
491
492 bool IntersectionCapsule(const CAPSULE* C0, const CAPSULE* C1);
493 bool IntersectionRay3Capsule(const RAY3* R, const CAPSULE* C);
494 bool IntersectionLine3Capsule(const LINE3* L, const CAPSULE* C);
495 bool IntersectionPlaneCapsule(const PLANE* J, const CAPSULE* C);
496
497 inline bool
IntersectionSphereFrustum(const SPHERE * S,const FRUSTUM * F)498 IntersectionSphereFrustum(const SPHERE* S, const FRUSTUM* F)
499 {
500 return F->IntersectSphere(S);
501 }
502
503 inline bool
IntersectionAABBFrustum(const AABB * B,const FRUSTUM * F)504 IntersectionAABBFrustum(const AABB* B, const FRUSTUM* F)
505 {
506 return F->IntersectAABB(B);
507 }
508
509
510 inline IntersectionResult
IntersectionAABBFrustumEx(const AABB * B,const FRUSTUM * F)511 IntersectionAABBFrustumEx(const AABB* B, const FRUSTUM* F)
512 {
513 return F->IntersectAABB_Ex(B);
514 }
515
516 //
517 // 3Dジオメトリのマージ
518 //
519 SPHERE* MergeSphere(SPHERE* s2, const SPHERE* s0, const SPHERE* s1);
520 AABB* MergeAABB(AABB* a2, const AABB* a0, const AABB* a1);
521
522
523
524
525
526
527
528
529
530
531
532 }} // nn::math
533
534 #endif
535
536