00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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 }
00245