Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Sphere.h

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * 球ヘッダ
00022  * @author Junpee
00023  */
00024 
00025 #ifndef SPHERE_H_
00026 #define SPHERE_H_
00027 
00028 #include <Core/Primitive/Vector3.h>
00029 #include <Core/Primitive/Matrix33.h>
00030 #include <Core/Primitive/Matrix34.h>
00031 #include <Core/Primitive/Matrix44.h>
00032 
00033 namespace Lamp{
00034 
00035 class Intersection;
00036 class AxisAlignedBox;
00037 class Capsule;
00038 class Cone;
00039 class Line;
00040 class OrientedBox;
00041 class Plane;
00042 class Ray;
00043 class Segment;
00044 class Triangle;
00045 
00046 //------------------------------------------------------------------------------
00047 /**
00048  * 球
00049  *
00050  * このクラスは継承しないで下さい。
00051  */
00052 class Sphere{
00053 public:
00054     //--------------------------------------------------------------------------
00055     // 定数
00056     //--------------------------------------------------------------------------
00057     /// ゼロ球
00058     static const Sphere zero;
00059 
00060     /// 単位球
00061     static const Sphere unit;
00062 
00063     //--------------------------------------------------------------------------
00064     // コンストラクタ
00065     //--------------------------------------------------------------------------
00066     /**
00067      * コンストラクタ
00068      *
00069      * このコンストラクタは初期値の設定を行わないため値は不定です。
00070      */
00071     inline Sphere(){}
00072 
00073     /**
00074      * コンストラクタ
00075      * @param center 中心の初期値
00076      * @param radius 半径の初期値
00077      */
00078 
00079     inline Sphere(const Vector3& center, float radius) :
00080         center_(center), radius_(radius){
00081     }
00082 
00083     /**
00084      * コンストラクタ
00085      * @param centerX 中心Xの初期値
00086      * @param centerY 中心Yの初期値
00087      * @param centerZ 中心Zの初期値
00088      * @param radius 半径の初期値
00089      */
00090 
00091     inline Sphere(float centerX, float centerY, float centerZ, float radius) :
00092         center_(centerX, centerY, centerZ), radius_(radius){
00093     }
00094 
00095     /**
00096      * コンストラクタ
00097      * @param source 初期値配列
00098      */
00099     inline explicit Sphere(const float* const source) :
00100         center_(source[0], source[1], source[2]), radius_(source[3]){
00101     }
00102 
00103     //--------------------------------------------------------------------------
00104     // 値の設定
00105     //--------------------------------------------------------------------------
00106     /**
00107      * 値の設定
00108      * @param center 設定する中心
00109      * @param radius 設定する半径
00110      */
00111     inline void set(const Vector3& center, float radius){
00112         center_ = center;
00113         radius_ = radius;
00114     }
00115 
00116     /**
00117      * 値の設定
00118      * @param centerX 設定する中心X
00119      * @param centerY 設定する中心Y
00120      * @param centerZ 設定する中心Z
00121      * @param radius 設定する半径
00122      */
00123     inline void set(float centerX, float centerY, float centerZ, float radius){
00124         center_.set(centerX, centerY, centerZ);
00125         radius_ = radius;
00126     }
00127 
00128     /**
00129      * 値の設定
00130      * @param source 設定値配列
00131      */
00132     inline void set(const float* const source){
00133         center_.set(source[0], source[1], source[2]);
00134         radius_ = source[3];
00135     }
00136 
00137     /**
00138      * 中心の設定
00139      * @param centerX 設定する中心X
00140      * @param centerY 設定する中心Y
00141      * @param centerZ 設定する中心Z
00142      */
00143     inline void setCenter(float centerX, float centerY, float centerZ){
00144         center_.set(centerX, centerY, centerZ);
00145     }
00146 
00147     /**
00148      * 中心の設定
00149      * @param center 設定する中心
00150      */
00151     inline void setCenter(const Vector3& center){ center_ = center; }
00152 
00153     /**
00154      * 半径の設定
00155      * @param radius 設定する半径
00156      */
00157     inline void setRadius(float radius){ radius_ = radius; }
00158 
00159     //--------------------------------------------------------------------------
00160     // 値の取得
00161     //--------------------------------------------------------------------------
00162     /**
00163      * 中心の取得
00164      * @return 中心
00165      */
00166     inline const Vector3& getCenter() const{ return center_; }
00167 
00168     /**
00169      * 半径の取得
00170      * @return 半径
00171      */
00172     inline float getRadius() const{ return radius_; }
00173 
00174     //--------------------------------------------------------------------------
00175     // 球演算
00176     //--------------------------------------------------------------------------
00177     /**
00178      * マージ
00179      * @param target マージする球
00180      * @return マージされた球
00181      */
00182     inline const Sphere& merge(const Sphere& target){
00183         Vector3 direction = target.center_ - center_;
00184         // 同じ位置に存在する球
00185         if(direction.isZero()){
00186             if(target.radius_ > radius_){ radius_ = target.radius_; }
00187             return *this;
00188         }
00189         float distance = direction.getLength();
00190         // ターゲットが自球の内側にある
00191         if(radius_ >= target.radius_ + distance){ return *this; }
00192         // ターゲットの内側に自球がある
00193         if(target.radius_ >= radius_ + distance){
00194             *this = target;
00195             return *this;
00196         }
00197         // 球がお互い重なっていない
00198         direction *= (1.f / distance);
00199         center_ = ((center_ - direction * radius_) +
00200             (target.center_ + direction * target.radius_)) * 0.5f;
00201         radius_ = (radius_ + target.radius_ + distance) * 0.5f;
00202         return *this;
00203     }
00204 
00205     /**
00206      * マージ
00207      *
00208      * 中心が動く。
00209      * 適切な中心とappendを使用した場合と比べて、球が大きくなってしまう。
00210      * @param target マージするベクトル
00211      * @return マージされた球
00212      */
00213     inline const Sphere& merge(const Vector3& target){
00214         Vector3 direction = target - center_;
00215         // 中心と同じ位置に存在
00216         if(direction.isZero()){ return *this; }
00217         float distance = direction.getLength();
00218         // ベクトルが球内なら何もしない
00219         if(distance <= radius_){ return *this; }
00220         // ベクトルが球外にあるので中心を動かし、調整する
00221         direction *= (1.f / distance);
00222         center_ = ((center_ - direction * radius_) + target) * 0.5f;
00223         radius_ = (radius_ + distance) * 0.5f;
00224         return *this;
00225     }
00226 
00227     /**
00228      * 追加
00229      *
00230      * 中心は動かさない。適切な中心が設定されている状態で使用する。
00231      * @param target 追加するベクトル
00232      * @return 追加された球
00233      */
00234     inline const Sphere& append(const Vector3& target){
00235         Vector3 direction = target - center_;
00236         // 中心と同じ位置に存在
00237         if(direction.isZero()){ return *this; }
00238         float distance = direction.getLength();
00239         // 球外なら拡張。中心は動かさない
00240         if(distance > radius_){ radius_ = distance; }
00241         return *this;
00242     }
00243 
00244     //--------------------------------------------------------------------------
00245     /**
00246      * ゼロ球かどうか
00247      * @return ゼロ球ならtrueを返す
00248      */
00249     inline bool isZero() const{
00250         return (Math::abs(radius_) <= Math::epsilon);
00251     }
00252 
00253     /**
00254      * 単位球かどうか
00255      * @return 単位球ならtrueを返す
00256      */
00257     inline bool isUnit() const{
00258         return (Math::abs(radius_ - 1.f) <= Math::epsilon);
00259     }
00260 
00261     //--------------------------------------------------------------------------
00262     // トランスフォーム
00263     //--------------------------------------------------------------------------
00264     /**
00265      * トランスフォーム
00266      * @param matrix 乗算する行列
00267      * @return 変換後の球
00268      */
00269     inline Sphere transform(const Matrix33& matrix) const{
00270         return Sphere(matrix * center_, radius_);
00271     }
00272 
00273     /**
00274      * トランスフォーム
00275      * @param matrix 乗算する行列
00276      * @return 変換後の球
00277      */
00278     inline Sphere transform(const Matrix34& matrix) const{
00279         return Sphere(matrix * center_, radius_);
00280     }
00281 
00282     /**
00283      * トランスフォーム
00284      * @param matrix 乗算する行列
00285      * @return 変換後の球
00286      */
00287     inline Sphere transform(const Matrix44& matrix) const{
00288         return Sphere(matrix * center_, radius_);
00289     }
00290 
00291     //--------------------------------------------------------------------------
00292     /**
00293      * スケール有りトランスフォーム
00294      *
00295      * 一番スケールの大きな軸にあわせて半径が膨らみます。
00296      * @param matrix 乗算する行列
00297      * @return 変換後の球
00298      */
00299     inline Sphere scaledTransform(const Matrix33& matrix) const{
00300         // ベクトル(1,0,0),(0,1,0),(0,0,1)を変換して最長の長さを半径に乗算
00301         float maxSquardLength = 0.f;
00302         for(int i = 0; i < 3; i++){
00303             float squaredLength =
00304                 matrix.m[0][i] * matrix.m[0][i] +
00305                 matrix.m[1][i] * matrix.m[1][i] +
00306                 matrix.m[2][i] * matrix.m[2][i];
00307             if(squaredLength > maxSquardLength){
00308                 maxSquardLength = squaredLength;
00309             }
00310         }
00311         return Sphere(matrix * center_, radius_ * Math::sqrt(maxSquardLength));
00312     }
00313 
00314     /**
00315      * スケール有りトランスフォーム
00316      *
00317      * 一番スケールの大きな軸にあわせて半径が膨らみます。
00318      * @param matrix 乗算する行列
00319      * @return 変換後の球
00320      */
00321     inline Sphere scaledTransform(const Matrix34& matrix) const{
00322         // ベクトル(1,0,0),(0,1,0),(0,0,1)を変換して最長の長さを半径に乗算
00323         float maxSquardLength = 0.f;
00324         for(int i = 0; i < 3; i++){
00325             float squaredLength =
00326                 matrix.m[0][i] * matrix.m[0][i] +
00327                 matrix.m[1][i] * matrix.m[1][i] +
00328                 matrix.m[2][i] * matrix.m[2][i];
00329             if(squaredLength > maxSquardLength){
00330                 maxSquardLength = squaredLength;
00331             }
00332         }
00333         return Sphere(matrix * center_, radius_ * Math::sqrt(maxSquardLength));
00334     }
00335 
00336     /**
00337      * スケール有りトランスフォーム
00338      *
00339      * 一番スケールの大きな軸にあわせて半径が膨らみます。
00340      * @param matrix 乗算する行列
00341      * @return 変換後の球
00342      */
00343     inline Sphere scaledTransform(const Matrix44& matrix) const{
00344         // ベクトル(1,0,0),(0,1,0),(0,0,1)を変換して最長の長さを半径に乗算
00345         float maxSquardLength = 0.f;
00346         for(int i = 0; i < 3; i++){
00347             float squaredLength =
00348                 matrix.m[0][i] * matrix.m[0][i] +
00349                 matrix.m[1][i] * matrix.m[1][i] +
00350                 matrix.m[2][i] * matrix.m[2][i];
00351             if(squaredLength > maxSquardLength){
00352                 maxSquardLength = squaredLength;
00353             }
00354         }
00355         return Sphere(matrix * center_, radius_ * Math::sqrt(maxSquardLength));
00356     }
00357 
00358     //--------------------------------------------------------------------------
00359     // 距離
00360     //--------------------------------------------------------------------------
00361     /**
00362      * 点距離
00363      * @param point 距離判定する点
00364      * @return 距離
00365      */
00366     float getDistance(const Vector3& point) const{
00367         return Math::sqrt(getSquaredDistance(point));
00368     }
00369 
00370     /**
00371      * 点距離の二乗
00372      * @param point 距離判定する点
00373      * @return 距離の二乗
00374      */
00375     float getSquaredDistance(const Vector3& point) const;
00376 
00377     //--------------------------------------------------------------------------
00378     /**
00379      * 軸沿いボックス距離
00380      * @param axisAlignedBox 距離判定する軸沿いボックス
00381      * @return 距離
00382      */
00383     float getDistance(const AxisAlignedBox& axisAlignedBox) const{
00384         return Math::sqrt(getSquaredDistance(axisAlignedBox));
00385     }
00386 
00387     /**
00388      * 軸沿いボックス距離の二乗
00389      * @param axisAlignedBox 距離判定する軸沿いボックス
00390      * @return 距離の二乗
00391      */
00392     float getSquaredDistance(const AxisAlignedBox& axisAlignedBox) const;
00393 
00394     //--------------------------------------------------------------------------
00395     /**
00396      * カプセル距離
00397      * @param capsule 距離判定するカプセル
00398      * @return 距離
00399      */
00400     float getDistance(const Capsule& capsule) const{
00401         return Math::sqrt(getSquaredDistance(capsule));
00402     }
00403 
00404     /**
00405      * カプセル距離の二乗
00406      * @param capsule 距離判定するカプセル
00407      * @return 距離の二乗
00408      */
00409     float getSquaredDistance(const Capsule& capsule) const;
00410 
00411     //--------------------------------------------------------------------------
00412     /**
00413      * コーン距離
00414      * @param cone 距離判定するコーン
00415      * @return 距離
00416      */
00417     float getDistance(const Cone& cone) const{
00418         return Math::sqrt(getSquaredDistance(cone));
00419     }
00420 
00421     /**
00422      * コーン距離の二乗
00423      * @param cone 距離判定するコーン
00424      * @return 距離の二乗
00425      */
00426     float getSquaredDistance(const Cone& cone) const;
00427 
00428     //--------------------------------------------------------------------------
00429     /**
00430      * ライン距離
00431      * @param line 距離判定するライン
00432      * @return 距離
00433      */
00434     float getDistance(const Line& line) const{
00435         return Math::sqrt(getSquaredDistance(line));
00436     }
00437 
00438     /**
00439      * ライン距離の二乗
00440      * @param line 距離判定するライン
00441      * @return 距離の二乗
00442      */
00443     float getSquaredDistance(const Line& line) const;
00444 
00445     //--------------------------------------------------------------------------
00446     /**
00447      * 指向性ボックス距離
00448      * @param orientedBox 距離判定する指向性ボックス
00449      * @return 距離
00450      */
00451     float getDistance(const OrientedBox& orientedBox) const{
00452         return Math::sqrt(getSquaredDistance(orientedBox));
00453     }
00454 
00455     /**
00456      * 指向性ボックス距離の二乗
00457      * @param orientedBox 距離判定する指向性ボックス
00458      * @return 距離の二乗
00459      */
00460     float getSquaredDistance(const OrientedBox& orientedBox) const;
00461 
00462     //--------------------------------------------------------------------------
00463     /**
00464      * 平面距離
00465      * @param plane 距離判定する平面
00466      * @return 距離
00467      */
00468     float getDistance(const Plane& plane) const;
00469 
00470     /**
00471      * 平面距離の二乗
00472      * @param plane 距離判定する平面
00473      * @return 距離の二乗
00474      */
00475     float getSquaredDistance(const Plane& plane) const{
00476         float distance = getDistance(plane);
00477         return (distance * distance);
00478     }
00479 
00480     //--------------------------------------------------------------------------
00481     /**
00482      * レイ距離
00483      * @param ray 距離判定するレイ
00484      * @return 距離
00485      */
00486     float getDistance(const Ray& ray) const{
00487         return Math::sqrt(getSquaredDistance(ray));
00488     }
00489 
00490     /**
00491      * レイ距離の二乗
00492      * @param ray 距離判定するレイ
00493      * @return 距離の二乗
00494      */
00495     float getSquaredDistance(const Ray& ray) const;
00496 
00497     //--------------------------------------------------------------------------
00498     /**
00499      * セグメント距離
00500      * @param segment 距離判定するセグメント
00501      * @return 距離
00502      */
00503     float getDistance(const Segment& segment) const{
00504         return Math::sqrt(getSquaredDistance(segment));
00505     }
00506 
00507     /**
00508      * セグメント距離の二乗
00509      * @param segment 距離判定するセグメント
00510      * @return 距離の二乗
00511      */
00512     float getSquaredDistance(const Segment& segment) const;
00513 
00514     //--------------------------------------------------------------------------
00515     /**
00516      * 球距離
00517      * @param sphere 距離判定する球
00518      * @return 距離
00519      */
00520     float getDistance(const Sphere& sphere) const{
00521         return Math::sqrt(getSquaredDistance(sphere));
00522     }
00523 
00524     /**
00525      * 球距離の二乗
00526      * @param sphere 距離判定する球
00527      * @return 距離の二乗
00528      */
00529     float getSquaredDistance(const Sphere& sphere) const;
00530 
00531     //--------------------------------------------------------------------------
00532     /**
00533      * 三角距離
00534      * @param triangle 距離判定する三角
00535      * @return 距離
00536      */
00537     float getDistance(const Triangle& triangle) const{
00538         return Math::sqrt(getSquaredDistance(triangle));
00539     }
00540 
00541     /**
00542      * 三角距離の二乗
00543      * @param triangle 距離判定する三角
00544      * @return 距離の二乗
00545      */
00546     float getSquaredDistance(const Triangle& triangle) const;
00547 
00548     //--------------------------------------------------------------------------
00549     // 交差
00550     //--------------------------------------------------------------------------
00551     /**
00552      * 点交差
00553      * @param point 交差判定する点
00554      * @return 交差していればtrue
00555      */
00556     bool intersect(const Vector3& point) const;
00557 
00558     //--------------------------------------------------------------------------
00559     /**
00560      * 軸沿いボックス交差
00561      * @param axisAlignedBox 交差判定する軸沿いボックス
00562      * @return 交差していればtrue
00563      */
00564     bool intersect(const AxisAlignedBox& axisAlignedBox) const;
00565 
00566     //--------------------------------------------------------------------------
00567     /**
00568      * カプセル交差
00569      * @param capsule 交差判定するカプセル
00570      * @return 交差していればtrue
00571      */
00572     bool intersect(const Capsule& capsule) const;
00573 
00574     //--------------------------------------------------------------------------
00575     /**
00576      * コーン交差
00577      * @param cone 交差判定するコーン
00578      * @return 交差していればtrue
00579      */
00580     bool intersect(const Cone& cone) const;
00581 
00582     //--------------------------------------------------------------------------
00583     /**
00584      * ライン交差
00585      * @param line 交差判定するライン
00586      * @return 交差していればtrue
00587      */
00588     bool intersect(const Line& line) const;
00589 
00590     //--------------------------------------------------------------------------
00591     /**
00592      * 指向性ボックス交差
00593      * @param orientedBox 交差判定する指向性ボックス
00594      * @return 交差していればtrue
00595      */
00596     bool intersect(const OrientedBox& orientedBox) const;
00597 
00598     //--------------------------------------------------------------------------
00599     /**
00600      * 平面交差
00601      * @param plane 交差判定する平面
00602      * @return 交差していればtrue
00603      */
00604     bool intersect(const Plane& plane) const;
00605 
00606     //--------------------------------------------------------------------------
00607     /**
00608      * レイ交差
00609      * @param ray 交差判定するレイ
00610      * @return 交差していればtrue
00611      */
00612     bool intersect(const Ray& ray) const;
00613 
00614     //--------------------------------------------------------------------------
00615     /**
00616      * セグメント交差
00617      * @param segment 交差判定するセグメント
00618      * @return 交差していればtrue
00619      */
00620     bool intersect(const Segment& segment) const;
00621 
00622     //--------------------------------------------------------------------------
00623     /**
00624      * 球交差
00625      * @param sphere 交差判定する球
00626      * @return 交差していればtrue
00627      */
00628     bool intersect(const Sphere& sphere) const;
00629 
00630     /**
00631      * 球交差
00632      * @param intersection 交差、返り値がtrueなら設定されている
00633      * @param sphere 交差判定する球
00634      * @return 交差していればtrue
00635      */
00636     bool intersect(Intersection* intersection, const Sphere& sphere) const;
00637 
00638     //--------------------------------------------------------------------------
00639     /**
00640      * 三角交差
00641      * @param triangle 交差判定する三角
00642      * @return 交差していればtrue
00643      */
00644     bool intersect(const Triangle& triangle) const;
00645 
00646     /**
00647      * 三角交差
00648      * @param intersection 交差、返り値がtrueなら設定されている
00649      * @param triangle 交差判定する三角
00650      * @return 交差していればtrue
00651      */
00652     bool intersect(Intersection* intersection, const Triangle& triangle) const;
00653 
00654     //--------------------------------------------------------------------------
00655     // 論理演算
00656     //--------------------------------------------------------------------------
00657     /**
00658      * 球が同じかどうか
00659      * @param target 比較する球
00660      * @return 同じ値であればtrueを返す
00661      */
00662     inline bool operator ==(const Sphere& target) const{
00663         return ((center_ == target.center_) && (radius_ == target.radius_));
00664     }
00665 
00666     /**
00667      * 球が同じかどうか
00668      * @param target 比較する球
00669      * @param epsilon 誤差
00670      * @return 誤差の範囲内で同じ値であればtrueを返す
00671      */
00672     inline bool epsilonEquals(
00673         const Sphere& target, float epsilon) const{
00674         Assert(epsilon >= 0.f);
00675         return (center_.epsilonEquals(target.center_, epsilon) &&
00676             (Math::abs(radius_ - target.radius_) <= epsilon));
00677     }
00678 
00679     /**
00680      * 球が同じでないかどうか
00681      * @param target 比較する球
00682      * @return 同じでない値であればtrueを返す
00683      */
00684     inline bool operator !=(const Sphere& target) const{
00685         return ((center_ != target.center_) || (radius_ != target.radius_));
00686     }
00687 
00688     /**
00689      * 球が同じでないかどうか
00690      * @param target 比較する球
00691      * @param epsilon 誤差
00692      * @return 誤差の範囲内で同じでない値であればtrueを返す
00693      */
00694     inline bool notEpsilonEquals(
00695         const Sphere& target, float epsilon) const{
00696         Assert(epsilon >= 0.f);
00697         return (center_.notEpsilonEquals(target.center_, epsilon) ||
00698             (Math::abs(radius_ - target.radius_) > epsilon));
00699     }
00700 
00701     //--------------------------------------------------------------------------
00702     // その他
00703     //--------------------------------------------------------------------------
00704     /**
00705      * 文字列化
00706      * @return 球の文字列表記
00707      */
00708     inline String toString() const{
00709         String returnString;
00710         returnString.format("{ ( %.8f, %.8f, %.8f ) %.8f }",
00711             center_.x, center_.y, center_.z, radius_);
00712         return returnString;
00713     }
00714 
00715 private:
00716     //--------------------------------------------------------------------------
00717     // メンバ変数
00718     //--------------------------------------------------------------------------
00719     // 中心
00720     Vector3 center_;
00721     // 半径
00722     float radius_;
00723 
00724 };
00725 
00726 //------------------------------------------------------------------------------
00727 } // End of namespace Lamp
00728 #endif // End of SPHERE_H_
00729 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:36 2005 for Lamp by doxygen 1.3.2