zoukankan      html  css  js  c++  java
  • 3D中的相机

    3D中的相机 - 投影矩阵和视图矩阵
    3d游戏中,一般通过相机的设置来计算投影矩阵和视图矩阵,比如untiy和cocos,一般情况下我们不用关注如何计算,
    可以直接在可视化的编辑器中调整参数就可以了,但是了解下总是好的。
    具体计算可以参考:
    可以参考现在cocos2dx的代码中的Camera源码,里面有根据相机的设置(位置等)计算上面两个矩阵的代码。
    也可以参考下面这个,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);
        }
    }
    ```
  • 相关阅读:
    SPOJ distinct subtrings
    OI题目类型总结整理
    emacs 考场配置
    SDOI2013 费用流
    HAOI2011 problem a
    BZOJ3438 小M的作物(和拓展)
    APIO2014 连珠线
    NOI2009 管道取珠
    HNOI2013 切糕
    NOI2009 植物大战僵尸
  • 原文地址:https://www.cnblogs.com/ZhYQ-Note/p/5941975.html
Copyright © 2011-2022 走看看