3D中的相机 - 投影矩阵和视图矩阵

3D中的相机 - 投影矩阵和视图矩阵
3d游戏中,一般通过相机的设置来计算投影矩阵和视图矩阵,比如untiy和cocos,一般情况下我们不用关注如何计算,
可以直接在可视化的编辑器中调整参数就可以了,但是了解下总是好的。
具体计算可以参考:

1、
可以参考现在cocos2dx的代码中的Camera源码,里面有根据相机的设置(位置等)计算上面两个矩阵的代码。

2、
也可以参考下面这个,github上面一个项目,这个项目有很好的参考价值:
https://github.com/wantnon2/3DToolKit-2-for-cocos2dx/blob/master/c3dToolKit/core/c3dCamera.h
```
//
// c3dCamera.h
// HelloCpp
//
// Created by Yang Chao (wantnon) on 14-1-7.
//
//
#ifndef __HelloCpp__c3dCamera__
#define __HelloCpp__c3dCamera__

#include <iostream>
using namespace std;
#include "cocos2d.h"
using namespace cocos2d;
#include "c3dVector.h"
#include "c3dMatrix.h"
#include "c3dGLMath.h"
#include "c3dCommonFunc.h"
#include "c3dMatrixStackInfoGetor.h"
#include "c3dRange.h"
class Cc3dCamera:public CCCamera
{
public:
Cc3dCamera(){
CCSize winSize=CCDirector::sharedDirector()->getWinSize();
m_fovy=60;
m_aspect=winSize.width/winSize.height;
m_zNear=1;//554/2;//0.5;
m_zFar=1500;

const float w=winSize.width;//11;
const float h=winSize.height;//w*winSize.height/winSize.width;
m_range.init(-w/2, -w/2+w, -h/2, -h/2+h,
-1024,//yeah, better to use negative value
1024);
m_projectionMode=ec3dPerspectiveMode;
m_isViewMatDirty=false;
m_isViewMatInverseDirty=false;

}
virtual ~Cc3dCamera(){

}


Cc3dVector4 getEyePos()const;
Cc3dVector4 getCenter()const;
Cc3dVector4 getUp()const;
void setEyePos(const Cc3dVector4&eyePos);
void setCenter(const Cc3dVector4&center);
void setUp(const Cc3dVector4&up);
float getFovy()const {return m_fovy;}
float getAspect()const {return m_aspect;}
float getzNear()const {return m_zNear;}
float getzFar()const {return m_zFar;}
void setFovy(float fovy){m_fovy=fovy;}
void setAspect(float aspect){m_aspect=aspect;}
void setzNear(float zNear){m_zNear=zNear;}
void setzFar(float zFar){m_zFar=zFar;}
Cc3dRange getRange()const {return m_range;}
void setRange(const Cc3dRange&range){m_range=range;}
Cc3dMatrix4 calculateViewMat();
Cc3dMatrix4 calculateViewMatInverse();
Cc3dMatrix4 calculateProjectionMat();
Ec3dProjectionMode getProjectionMode(){return m_projectionMode;}
void setProjectionMode(Ec3dProjectionMode projectionMode){m_projectionMode=projectionMode;}
void applyProjection();
void printProjectionMode()const;
protected:
//projection mode type
Ec3dProjectionMode m_projectionMode;
//perspective projection mode params
float m_fovy;
float m_aspect;
float m_zNear;
float m_zFar;
//Ortho projection mode params
Cc3dRange m_range;//in the camera space
protected:
//cache viewMat
Cc3dMatrix4 m_viewMatCache;
bool m_isViewMatDirty;
Cc3dMatrix4 m_viewMatInverseCache;
bool m_isViewMatInverseDirty;


};
#endif /* defined(__HelloCpp__c3dCamera__) */

//
// c3dCamera.cpp
// HelloCpp
//
// Created by Yang Chao (wantnon) on 14-1-7.
//
//

#include "c3dCamera.h"

Cc3dVector4 Cc3dCamera::getEyePos()const{
//getEyeXYZ is not const, but i want getEyePos to be const
//so i convert this from const to nonconst
float eyex,eyey,eyez;
((Cc3dCamera*)this)->getEyeXYZ(&eyex, &eyey, &eyez);
return Cc3dVector4(eyex,eyey,eyez,1);
}
Cc3dVector4 Cc3dCamera::getCenter()const{
//getCenterXYZ is not const, but i want getCenter to be const
//so i convert this from const to nonconst
float centerX,centerY,centerZ;
((Cc3dCamera*)this)->getCenterXYZ(&centerX, &centerY, &centerZ);
return Cc3dVector4(centerX,centerY,centerZ,1);
}
Cc3dVector4 Cc3dCamera::getUp()const{
//getUpXYZ is not const, but i want getUp to be const
//so i convert this from const to nonconst
float upX,upY,upZ;
((Cc3dCamera*)this)->getUpXYZ(&upX, &upY, &upZ);
return Cc3dVector4(upX,upY,upZ,0);
}
void Cc3dCamera::setEyePos(const Cc3dVector4&eyePos){
this->setEyeXYZ(eyePos.x(), eyePos.y(), eyePos.z());
m_isViewMatDirty=true;
m_isViewMatInverseDirty=true;

}
void Cc3dCamera::setCenter(const Cc3dVector4&center){
this->setCenterXYZ(center.x(), center.y(), center.z());
m_isViewMatDirty=true;
m_isViewMatInverseDirty=true;

}
void Cc3dCamera::setUp(const Cc3dVector4&up){
this->setUpXYZ(up.x(), up.y(), up.z());
m_isViewMatDirty=true;
m_isViewMatInverseDirty=true;
}

Cc3dMatrix4 Cc3dCamera::calculateViewMat(){
//why we not just return CCCamera::m_lookupMatrix?
//because m_lookupMatrix may be dirty (m_lookupMatrix got updated only when locate is called)
//so we calculate view matrix ourselves.
Cc3dMatrix4 ret;
if(m_isViewMatDirty){//dirty
//calculate and cache
ret=::calculateViewMatrix(getEyePos(), getCenter(), getUp());
m_viewMatCache=ret;
}else{//not dirty
//get from cache
ret=m_viewMatCache;
}
return ret;

};
Cc3dMatrix4 Cc3dCamera::calculateViewMatInverse(){
Cc3dMatrix4 ret;
if(m_isViewMatInverseDirty){
ret=::calculateViewMatrixInverse(getEyePos(), getCenter(), getUp());
m_viewMatInverseCache=ret;
}else{
ret=m_viewMatInverseCache;
}
return ret;
}
Cc3dMatrix4 Cc3dCamera::calculateProjectionMat(){
Cc3dMatrix4 projectionMat;
switch (m_projectionMode) {
case ec3dPerspectiveMode:
projectionMat=::calculatePerspectiveProjectionMatrix(m_fovy, m_aspect, m_zNear, m_zFar);
break;
case ec3dOrthographicMode:
projectionMat=::calculateOrthoProjectionMatrix(m_range.getMinX(), m_range.getMaxX(), m_range.getMinY(), m_range.getMaxY(), m_range.getMinZ(), m_range.getMaxZ());
break;
default:
assert(false);
break;
}
return projectionMat;
}
void Cc3dCamera::applyProjection()
//note: after apply projection matrix, will be back to modelview matrix stack
{
Cc3dMatrix4 projectionMat=calculateProjectionMat();
kmGLMatrixMode(KM_GL_PROJECTION);
kmGLLoadIdentity();
kmMat4 projMat;
memcpy(projMat.mat, projectionMat.getArray(), 16*sizeof(float));
kmGLMultMatrix(&projMat);
//restore to model view stack
kmGLMatrixMode(KM_GL_MODELVIEW);

};
void Cc3dCamera::printProjectionMode()const{
if(m_projectionMode==ec3dPerspectiveMode){
C3DLOG("projectionMode: perspectiveMode");
}else if(m_projectionMode==ec3dOrthographicMode){
C3DLOG("projectionMode: orthographic");
}else{
assert(false);
}
}
```

posted on 2016-09-13 17:23  ZhYQ_note  阅读(873)  评论(0编辑  收藏  举报

导航