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

Camera.cpp

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 #include "LampBasic.h"
00026 #include "Graphics/Camera/Camera.h"
00027 #include "Graphics/Scene/Scene.h"
00028 #include "Graphics/Camera/CameraManager.h"
00029 
00030 namespace Lamp{
00031 
00032 //------------------------------------------------------------------------------
00033 // コンストラクタ
00034 Camera::Camera(const String& name, Scene* scene) :
00035     SceneObject(name, scene),
00036     projectionMatrix_(Matrix44::unit), viewMatrix_(Matrix44::unit),
00037     left_(-0.76980036f), right_(0.76980036f),
00038     bottom_(-0.57735026f), top_(0.57735026f),
00039     nearClip_(1.f), farClip_(10000.f), isPerspective_(true){
00040     buildPerspectiveMatrix();
00041 }
00042 //------------------------------------------------------------------------------
00043 // デストラクタ
00044 Camera::~Camera(){
00045 }
00046 //------------------------------------------------------------------------------
00047 // コピー
00048 Camera* Camera::copy() const{
00049     CameraManager* manager = scene_->getCameraManager();
00050     Camera* copyCamera = manager->createCamera(manager->rename(name_));
00051     return copyCamera;
00052 }
00053 //------------------------------------------------------------------------------
00054 // 射影行列の構築
00055 void Camera::buildPerspectiveMatrix(){
00056     // 射影行列の構築
00057     if(isPerspective_){
00058         float zx = (right_ + left_) / (right_ - left_);
00059         float zy = (top_ + bottom_) / (top_ - bottom_);
00060         projectionMatrix_.set(
00061             2.f * nearClip_ / (right_ - left_), 0.f, zx, 0.f,
00062             0.f, 2.f * nearClip_ / (top_ - bottom_), zy, 0.f,
00063             0.f, 0.f, farClip_ / (nearClip_ - farClip_),
00064                 nearClip_ * farClip_ / (nearClip_ - farClip_),
00065             0.f, 0.f, -1.f, 0.f);
00066     }else{
00067         float wx = (left_ + right_) / (left_ - right_);
00068         float wy = (bottom_ + top_) / (bottom_ - top_);
00069         projectionMatrix_.set(
00070             2.f / (right_ - left_), 0.f, 0.f, wx,
00071             0.f, 2.f / (top_ - bottom_), 0.f, wy,
00072             0.f, 0.f, 1.f / (nearClip_ - farClip_),
00073                 nearClip_ / (nearClip_ - farClip_),
00074             0.f, 0.f, 0.f, 1.f);
00075     }
00076     clippingSetup();
00077 }
00078 //------------------------------------------------------------------------------
00079 // ビュー行列の設定
00080 void Camera::setViewMatrix(const Matrix44& viewMatrix){
00081     viewMatrix_ = viewMatrix;
00082     clippingSetup();
00083 }
00084 //------------------------------------------------------------------------------
00085 // トランスフォーメーションの設定
00086 void Camera::setTransformation(
00087     const Vector3& rotationXYZ, const Vector3& position){
00088     viewMatrix_.setTranslation(-position);
00089     viewMatrix_.addRotationZYX(-rotationXYZ);
00090     clippingSetup();
00091 }
00092 //------------------------------------------------------------------------------
00093 // トランスフォーメーションの設定
00094 void Camera::setTransformation(
00095     const Quaternion& rotation, const Vector3& position){
00096     viewMatrix_.setTranslation(-position);
00097     Quaternion invertRotation(rotation);
00098     invertRotation.unitInvert();
00099     viewMatrix_.addRotationQuaternion(invertRotation);
00100     clippingSetup();
00101 }
00102 //------------------------------------------------------------------------------
00103 // ルックアットの設定
00104 void Camera::setLookAt(
00105     const Vector3& position, const Vector3& target, const Vector3& up){
00106     Vector3 zAxis = position - target;
00107     zAxis.normalize();
00108     Vector3 xAxis = up.crossProduct(zAxis);
00109     xAxis.normalize();
00110     Vector3 yAxis = zAxis.crossProduct(xAxis);
00111     viewMatrix_.set(
00112         xAxis.x, xAxis.y, xAxis.z, -xAxis.dotProduct(position),
00113         yAxis.x, yAxis.y, yAxis.z, -yAxis.dotProduct(position),
00114         zAxis.x, zAxis.y, zAxis.z, -zAxis.dotProduct(position),
00115         0.f, 0.f, 0.f, 1.f);
00116     clippingSetup();
00117     Assert(position_.epsilonEquals(position, 0.001f));
00118 }
00119 //------------------------------------------------------------------------------
00120 // クリッピングのセットアップ
00121 void Camera::clippingSetup(){
00122     // コーナーの設定
00123     corner_[0].set(left_, bottom_, -nearClip_);
00124     corner_[1].set(left_, top_, -nearClip_);
00125     corner_[2].set(right_, top_, -nearClip_);
00126     corner_[3].set(right_, bottom_, -nearClip_);
00127     if(isPerspective_){
00128         float scale = farClip_ / nearClip_;
00129         corner_[4] = corner_[2] * scale;
00130         corner_[5] = corner_[1] * scale;
00131         corner_[6] = corner_[0] * scale;
00132         corner_[7] = corner_[3] * scale;
00133     }else{
00134         corner_[4].set(right_, top_, -farClip_);
00135         corner_[5].set(left_, top_, -farClip_);
00136         corner_[6].set(left_, bottom_, -farClip_);
00137         corner_[7].set(right_, bottom_, -farClip_);
00138     }
00139     Matrix44 inverseView(viewMatrix_);
00140     inverseView.invert();
00141     for(int i = 0; i < 8; i++){
00142         corner_[i] = inverseView * corner_[i];
00143     }
00144     // クリップ面の設定
00145     clipPlane_[0].set(corner_[0], corner_[1], corner_[2]);
00146     clipPlane_[1].set(corner_[4], corner_[5], corner_[6]);
00147     clipPlane_[2].set(corner_[0], corner_[6], corner_[5]);
00148     clipPlane_[3].set(corner_[2], corner_[4], corner_[7]);
00149     clipPlane_[4].set(corner_[0], corner_[3], corner_[7]);
00150     clipPlane_[5].set(corner_[1], corner_[5], corner_[4]);
00151 
00152     // 位置、回転の設定
00153     position_ = inverseView.getTranslation();
00154     inverseView.getRotationXYZ(&rotation_);
00155 
00156     // バウンディングスフィアの作成
00157     Vector3 center;
00158     float radius;
00159     if(isPerspective_){
00160         // パースペクティブな場合は中心がずれていることも考慮しないといけない
00161         Vector3 nearClip(Vector3::zero), farClip(Vector3::zero);
00162         for(int i = 0; i < 4; i++){ nearClip += corner_[i]; }
00163         for(int i = 4; i < 8; i++){ farClip += corner_[i]; }
00164         nearClip *= 0.25f;
00165         farClip *= 0.25f;
00166         // ニアクリップの中心とファークリップの中心の間を地道にしらべる
00167         int divisionNumber = 32;
00168         Vector3 divisionVector = (farClip - nearClip) * (1.f / divisionNumber);
00169         center = nearClip;
00170         radius = (corner_[0] - center).getSquaredLength();
00171         for(int i = 1; i < 8; i++){
00172             float squaredRadius = (corner_[i] - center).getSquaredLength();
00173             if(squaredRadius > radius){ radius = squaredRadius; }
00174         }
00175         for(int i = 1; i <= divisionNumber; i++){
00176             Vector3 position = nearClip + divisionVector * (float)i;
00177             float maxRadius = (corner_[0] - position).getSquaredLength();
00178             for(int j = 1; j < 8; j++){
00179                 float squaredRadius =
00180                     (corner_[j] - position).getSquaredLength();
00181                 if(squaredRadius > maxRadius){ maxRadius = squaredRadius; }
00182             }
00183             if(maxRadius < radius){
00184                 center = position;
00185                 radius = maxRadius;
00186             }
00187         }
00188         radius = Math::sqrt(radius);
00189     }else{
00190         // 並行投影ならどんな設定でも1頂点との距離をとればよい
00191         center = Vector3::zero;
00192         for(int i = 0; i < 8; i++){ center += corner_[i]; }
00193         center *= 0.125f;
00194         radius = (corner_[0] - center).getLength();
00195     }
00196     boundingSphere_.set(center, radius);
00197 }
00198 //------------------------------------------------------------------------------
00199 // クリッピング
00200 Clipping::State Camera::clipping(const Sphere& boundingSphere){
00201     // カメラのバウンディングスフィアと交差していなければ見えない
00202     if(!boundingSphere_.intersect(boundingSphere)){
00203         return Clipping::invisible;
00204     }
00205     bool intersect = false;
00206     Vector3 center = boundingSphere.getCenter();
00207     float radius = boundingSphere.getRadius();
00208     for(int i = 0; i < 6; i++){
00209         float distance = clipPlane_[i].getDistance(center);
00210         // 距離がマイナス半径未満ならば見えない
00211         if(distance < -radius){ return Clipping::invisible; }
00212         // 距離が半径未満なら一部しか見えない可能性がある
00213         if(distance < radius){ intersect = true; }
00214     }
00215     if(intersect){ return Clipping::intersect; }
00216     return Clipping::visible;
00217 }
00218 //------------------------------------------------------------------------------
00219 // クリッピング
00220 Clipping::State Camera::clipping(const AxisAlignedBox& boundingBox){
00221     // 完全ではない。視錐台の外側で平面に交差するボックスが残る。
00222     // 遅くなるかもしれないが、Segmentを使用すれば完全になるかも。
00223     // スフィアチェックのあとに使用する。
00224     Vector3 corner[8];
00225     boundingBox.getCornerArray(corner);
00226     int visibleCount = 0;
00227     for(int i = 0; i < 6; i++){
00228         bool visible = true;
00229         int invisibleCount = 0;
00230         for(int j = 0; j < 8; j++){
00231             float distance = clipPlane_[i].getDistance(corner[j]);
00232             if(distance < 0.f){
00233                 visible = false;
00234                 invisibleCount++;
00235             }
00236         }
00237         if(invisibleCount == 8){ return Clipping::invisible; }
00238         if(visible){ visibleCount++; }
00239     }
00240     if(visibleCount == 6){ return Clipping::visible; }
00241     return Clipping::intersect;
00242 }
00243 //------------------------------------------------------------------------------
00244 } // End of namespace Lamp
00245 //------------------------------------------------------------------------------

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