加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Cocos2d-x3.3RC0 Cpp-test分析之Camera3DDemo

发布时间:2020-12-14 19:28:14 所属栏目:百科 来源:网络整理
导读:1、Camera3DDemo //.h#include "cocos2d.h"#include stringUSING_NS_CC;#include stringnamespace cocos2d { class Sprite3D; class Delay;}enum State{ State_None = 0,State_Idle = 0x01,State_Move = 0x02,State_Rotate = 0x04,State_Speak = 0x08,State_

1、Camera3DDemo

//.h
#include "cocos2d.h"
#include <string>
USING_NS_CC;

#include <string>
namespace cocos2d {
    class Sprite3D;
    class Delay;
}
enum State
{
    State_None = 0,State_Idle = 0x01,State_Move = 0x02,State_Rotate = 0x04,State_Speak = 0x08,State_MeleeAttack = 0x10,State_RemoteAttack = 0x20,State_Attack = 0x40,};
enum class CameraType
{
    FreeCamera=0,FirstCamera=1,ThirdCamera=2,};
class Camera3DTestDemo : public Layer
{
public:
    CREATE_FUNC(Camera3DTestDemo);
    Camera3DTestDemo(void);
    virtual ~Camera3DTestDemo(void);
    
    virtual void onEnter() override;
    virtual void onExit() override;

    void addNewSpriteWithCoords(Vec3 p,std::string fileName,bool playAnimation=false,float scale=1.0f,bool bindCamera=false);
    void onTouchesBegan(const std::vector<Touch*>& touches,cocos2d::Event  *event);
    void onTouchesMoved(const std::vector<Touch*>& touches,cocos2d::Event  *event);
    void onTouchesEnded(const std::vector<Touch*>& touches,cocos2d::Event  *event);
    void SwitchViewCallback(Ref* sender,CameraType cameraType);
    void updateCamera(float fDelta);
    void move3D(float elapsedTime);
    void updateState(float elapsedTime);
    bool isState(unsigned int state,unsigned int bit) const;
    
    bool onTouchesZoomOut(Touch* touch,Event* event);
    void onTouchesZoomOutEnd(Touch* touch,Event* event);
    bool onTouchesZoomIn(Touch* touch,Event* event);
    void onTouchesZoomInEnd(Touch* touch,Event* event);
    
    bool onTouchesRotateLeft(Touch* touch,Event* event);
    void onTouchesRotateLeftEnd(Touch* touch,Event* event);
    bool onTouchesRotateRight(Touch* touch,Event* event);
    void onTouchesRotateRightEnd(Touch* touch,Event* event);
protected:
    std::string    _title;
    Layer*         _layer3D;
    Sprite3D*      _sprite3D;
    Vec3           _targetPos;
    CameraType     _cameraType;
    MenuItem*      _incRot;
    MenuItem*      _decRot;
    unsigned int   _curState;
    Camera*      _camera;
    MoveTo* _moveAction;
    bool _bZoomOut;
    bool _bZoomIn;
    bool _bRotateLeft;
    bool _bRotateRight;
    Label* _RotateRightlabel;
    Label* _RotateLeftlabel;
    Label* _ZoomInlabel;
    Label* _ZoomOutlabel;
};
.cpp
#include "Camera3DDemo.h"
#include <algorithm>//包含STL库的算法
#include "VisibleRect.h"

class DrawLine3D: public Node
{
public:
    //静态创建函数
    static DrawLine3D* create();
    //画线函数,参数1:起点;参数2:终点;参数3:线段颜色
    void drawLine(const Vec3 &from,const Vec3 &to,const Color4F &color);
    void clear()
    {
        _buffer.clear();
    }
    //真正的绘图函数
    void onDraw(const Mat4 &transform,uint32_t flags);
    //绘制节点
    virtual void draw(Renderer *renderer,const Mat4 &transform,uint32_t flags) override;
    
CC_CONSTRUCTOR_ACCESS:
    DrawLine3D()
    {
        
    }
    virtual ~DrawLine3D()
    {
        
    }
    virtual bool init();
    
protected:
    //自定义线段存放的结构体
    struct V3F_C4B
    {
        Vec3     vertices;//线段端点坐标
        Color4B  colors;  //线段颜色
    };
    //存放线段数据的容器
    std::vector<V3F_C4B> _buffer;
    //启动自定义绘图
    CustomCommand _customCommand;
    
private:
    //CC_DISALLOW_COPY_AND_ASSIGN宏的作用是定义一个类,禁止拷贝和赋值(=)运算符重载功能。
    CC_DISALLOW_COPY_AND_ASSIGN(DrawLine3D);
};

DrawLine3D* DrawLine3D::create()
{
    //nothrow创建对象失败返回0
    auto ret = new (std::nothrow) DrawLine3D();
    //对象创建成功
    if (ret && ret->init())
        return ret;
    //对象创建失败
    CC_SAFE_DELETE(ret);
    return nullptr;
}

bool DrawLine3D::init()
{
    //设置节点着色程序
    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_COLOR));
    return true;
}
//画线函数
void DrawLine3D::drawLine(const Vec3 &from,const Color4F &color)
{
    Color4B col = Color4B(color);//线段颜色
    DrawLine3D::V3F_C4B vertex;
    vertex.vertices = from;//起点信息
    vertex.colors = col;
    _buffer.push_back(vertex);
    vertex.vertices = to;//终点信息
    _buffer.push_back(vertex);
}
//绘制节点函数
void DrawLine3D::draw(Renderer *renderer,uint32_t flags)
{
    _customCommand.init(_globalZOrder);
    ////调用真正的绘图函数onDraw
    _customCommand.func = CC_CALLBACK_0(DrawLine3D::onDraw,this,transform,flags);
    //将着色器程序加入renderer对象
    renderer->addCommand(&_customCommand);
}
//真正的调用OpenGL接口绘图,涉及OpenGL知识,暂不了解
void DrawLine3D::onDraw(const Mat4 &transform,uint32_t flags)
{
    auto glProgram = getGLProgram();//返回当前节点的GLProgram (shader)
    glProgram->use();//调用glUseProgram()函数,使用shader绘图
    glProgram->setUniformsForBuiltins(transform);
    glEnable(GL_DEPTH_TEST);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,3,GL_FLOAT,GL_FALSE,sizeof(V3F_C4B),&(_buffer[0].vertices));
    
    glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,GL_UNSIGNED_BYTE,GL_TRUE,&(_buffer[0].colors));
    glDrawArrays(GL_LINES,static_cast<int>(_buffer.size()));
    glDisable(GL_DEPTH_TEST);
}

////////////////////////////////////////////////////////////////////////////////

enum
{
    IDC_NEXT = 100,IDC_BACK,IDC_RESTART
};

Camera3DTestDemo::Camera3DTestDemo(void)
: Layer(),_camera(nullptr),_incRot(nullptr),_decRot(nullptr),_bZoomOut(false),_bZoomIn(false),_bRotateLeft(false),_bRotateRight(false)
{

}
Camera3DTestDemo::~Camera3DTestDemo(void)
{
}
//旋转视角回调函数
void Camera3DTestDemo::SwitchViewCallback(Ref* sender,CameraType cameraType)
{
    //如果当前视角等于要转换的视角,则直接返回
    if(_cameraType==cameraType)
    {
        return ;
    }
    _cameraType = cameraType;
    
    //如果摄像机类型等于自由视角
    if(_cameraType==CameraType::FreeCamera)
    {
        _camera->setPosition3D(Vec3(0,130,130) + _sprite3D->getPosition3D());
        _camera->lookAt(_sprite3D->getPosition3D(),Vec3(0,1,0));
        
        _RotateRightlabel->setColor(Color3B::WHITE);
        _RotateLeftlabel->setColor(Color3B::WHITE);
        _ZoomInlabel->setColor(Color3B::WHITE);
        _ZoomOutlabel->setColor(Color3B::WHITE);
    }
    //如果摄像机类型为第一视角
    else if(_cameraType==CameraType::FirstCamera)
    {
        Vec3 newFaceDir;
        //返回逆世界仿射变换矩阵。像素的矩阵。并获取Forward矩阵,参数为目标向量
        _sprite3D->getWorldToNodeTransform().getForwardVector(&newFaceDir);
        //目标向量标准化,将Vec3对象的x,y,z转化为分数,且x的平方+y的平方+z的平方=1
        newFaceDir.normalize();
        _camera->setPosition3D(Vec3(0,35,0) + _sprite3D->getPosition3D());
        //设置相机的视图矩阵,参数1:target位置,参数2:向上的向量
        _camera->lookAt(_sprite3D->getPosition3D() + newFaceDir*50,0));
        
        _RotateRightlabel->setColor(Color3B::WHITE);
        _RotateLeftlabel->setColor(Color3B::WHITE);
        _ZoomInlabel->setColor(Color3B::GRAY);
        _ZoomOutlabel->setColor(Color3B::GRAY);
    }
    //如果摄像机的类型为第三视角
    else if(_cameraType==CameraType::ThirdCamera)
    {
        _camera->setPosition3D(Vec3(0,130) + _sprite3D->getPosition3D());
        //设置相机的视图矩阵。
        _camera->lookAt(_sprite3D->getPosition3D(),0));
        _RotateRightlabel->setColor(Color3B::GRAY);
        _RotateLeftlabel->setColor(Color3B::GRAY);
        _ZoomInlabel->setColor(Color3B::WHITE);
        _ZoomOutlabel->setColor(Color3B::WHITE);
    }
}
void Camera3DTestDemo::onEnter()
{
    Layer::onEnter();
    _sprite3D=nullptr;
    //注册事件
    auto s = Director::getInstance()->getWinSize();
    auto listener = EventListenerTouchAllAtOnce::create();
    listener->onTouchesBegan = CC_CALLBACK_2(Camera3DTestDemo::onTouchesBegan,this);
    listener->onTouchesMoved = CC_CALLBACK_2(Camera3DTestDemo::onTouchesMoved,this);
    listener->onTouchesEnded = CC_CALLBACK_2(Camera3DTestDemo::onTouchesEnded,this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
    //创建新的层,用于加载3D精灵和线段
    auto layer3D=Layer::create();
    addChild(layer3D,0);
    _layer3D=layer3D;
    _curState=State_None;
    //添加精灵参数依次为:Vec3向量,精灵文件路径,是否执行动作,缩放系数,是否绑定摄像机
    addNewSpriteWithCoords( Vec3(0,0),"girl.c3b",true,0.2f,true);
    TTFConfig ttfConfig("fonts/arial.ttf",30);
    //依次添加4个Label对象到对应的Node节点上,并对4个Label对象注册监听事件
    auto containerForLabel1 = Node::create();
    _ZoomOutlabel = Label::createWithTTF(ttfConfig,"zoom out");
    _ZoomOutlabel->setPosition(s.width-150,VisibleRect::top().y-30);
    containerForLabel1->addChild(_ZoomOutlabel);
    addChild(containerForLabel1,10);
    
    auto listener1 = EventListenerTouchOneByOne::create();
    listener1->setSwallowTouches(true);
    
    listener1->onTouchBegan = CC_CALLBACK_2(Camera3DTestDemo::onTouchesZoomOut,this);
    listener1->onTouchEnded = CC_CALLBACK_2(Camera3DTestDemo::onTouchesZoomOutEnd,this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,_ZoomOutlabel);
    
    auto containerForLabel2 = Node::create();
    _ZoomInlabel = Label::createWithTTF(ttfConfig,"zoom in");
    _ZoomInlabel->setPosition(s.width-150,VisibleRect::top().y-100);
    containerForLabel2->addChild(_ZoomInlabel);
    addChild(containerForLabel2,10);
    
    auto listener2 = EventListenerTouchOneByOne::create();
    listener2->setSwallowTouches(true);
    
    listener2->onTouchBegan = CC_CALLBACK_2(Camera3DTestDemo::onTouchesZoomIn,this);
    listener2->onTouchEnded = CC_CALLBACK_2(Camera3DTestDemo::onTouchesZoomInEnd,this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener2,_ZoomInlabel);
    
    auto containerForLabel3 = Node::create();
    _RotateLeftlabel = Label::createWithTTF(ttfConfig,"rotate left");
    _RotateLeftlabel->setPosition(s.width-150,VisibleRect::top().y-170);
    containerForLabel3->addChild(_RotateLeftlabel);
    addChild(containerForLabel3,10);
    
    auto listener3 = EventListenerTouchOneByOne::create();
    listener3->setSwallowTouches(true);
    
    listener3->onTouchBegan = CC_CALLBACK_2(Camera3DTestDemo::onTouchesRotateLeft,this);
    listener3->onTouchEnded = CC_CALLBACK_2(Camera3DTestDemo::onTouchesRotateLeftEnd,this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener3,_RotateLeftlabel);
    
    auto containerForLabel4 = Node::create();
    _RotateRightlabel = Label::createWithTTF(ttfConfig,"rotate right");
    _RotateRightlabel->setPosition(s.width-150,VisibleRect::top().y-240);
    containerForLabel4->addChild(_RotateRightlabel);
    addChild(containerForLabel4,10);
    
    auto listener4 = EventListenerTouchOneByOne::create();
    listener4->setSwallowTouches(true);
    
    listener4->onTouchBegan = CC_CALLBACK_2(Camera3DTestDemo::onTouchesRotateRight,this);
    listener4->onTouchEnded = CC_CALLBACK_2(Camera3DTestDemo::onTouchesRotateRightEnd,this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener4,_RotateRightlabel);
    
    //设置摄像机视角菜单选项,并回调转换视角函数
    auto label1 = Label::createWithTTF(ttfConfig,"free ");
    auto menuItem1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Camera3DTestDemo::SwitchViewCallback,CameraType::FreeCamera));
    auto label2 = Label::createWithTTF(ttfConfig,"third person");
    auto menuItem2 = MenuItemLabel::create(label2,CameraType::ThirdCamera));
    auto label3 = Label::createWithTTF(ttfConfig,"first person");
    auto menuItem3 = MenuItemLabel::create(label3,CameraType::FirstCamera));
    auto menu = Menu::create(menuItem1,menuItem2,menuItem3,nullptr);
    
    menu->setPosition(Vec2::ZERO);
    
    menuItem1->setPosition(VisibleRect::left().x+100,VisibleRect::top().y-50);
    menuItem2->setPosition(VisibleRect::left().x+100,VisibleRect::top().y -100);
    menuItem3->setPosition(VisibleRect::left().x+100,VisibleRect::top().y -150);
    addChild(menu,0);
    //设置自定义更新器,时间间隔为0.0秒
    schedule(CC_SCHEDULE_SELECTOR(Camera3DTestDemo::updateCamera),0.0f);
    if (_camera == nullptr)
    {
        //初始化相机
        _camera=Camera::createPerspective(60,(GLfloat)s.width/s.height,1000);
        _camera->setCameraFlag(CameraFlag::USER1);
        _layer3D->addChild(_camera);
    }
    //首先执行视角切换回调函数,先切换到第三视角
    SwitchViewCallback(this,CameraType::ThirdCamera);
    
    //创建3D画线类对象
    DrawLine3D* line =DrawLine3D::create();
    //draw x
    for( int j =-20; j<=20 ;j++)
    {
        //将线段信息存入vector,调用draw绘图,实质是onDraw进行绘制
        line->drawLine(Vec3(-100,5*j),Vec3(100,Color4F(1,1));
    }
    //draw z
    for( int j =-20; j<=20 ;j++)
    {
        //将线段信息存入vector,调用draw绘图,实质是onDraw进行绘制
        line->drawLine(Vec3(5*j,-100),Vec3(5*j,100),Color4F(0,1));
    }
    //draw y //绘制y轴方向的两条线段
    line->drawLine(Vec3(0,-50,0.5,1));
    line->drawLine(Vec3(0,50,1));
    _layer3D->addChild(line);
    //设置mask,使得其对相机可见
    _layer3D->setCameraMask(2);
}
//onExit函数,退出当前层时执行
void Camera3DTestDemo::onExit()
{
    Layer::onExit();
    if (_camera)
    {
        _camera = nullptr;
    }
}
//添加精灵,参数1:精灵坐标,参数2:精灵文件路径,参数3:是否执行动作,参数4:缩放系数,参数5:是否绑定摄像机
void Camera3DTestDemo::addNewSpriteWithCoords(Vec3 p,bool playAnimation,float scale,bool bindCamera)
{
    //创建3D精灵
    auto sprite = Sprite3D::create(fileName);
    _layer3D->addChild(sprite);
    float globalZOrder=sprite->getGlobalZOrder();
    //设置精灵的坐标和全局Z轴顺序
    sprite->setPosition3D( Vec3( p.x,p.y,p.z) );
    sprite->setGlobalZOrder(globalZOrder);
    if(playAnimation)
    {
        //首先通过骨骼节点创建骨骼动画
        auto animation = Animation3D::create(fileName,"Take 001");
        if (animation)
        {
            //执行3D动画
            auto animate = Animate3D::create(animation);
            sprite->runAction(RepeatForever::create(animate));
        }
    }
    //如果绑定摄像机,将sprite赋值给_sprite3D对象
    if(bindCamera)
    {
        _sprite3D=sprite;
    }
    sprite->setScale(scale);
    
}
//多点触摸
void Camera3DTestDemo::onTouchesBegan(const std::vector<Touch*>& touches,cocos2d::Event  *event)
{
    for ( auto &item: touches )
    {
        auto touch = item;
        auto location = touch->getLocation();
    }
}
//多点触摸移动,即点击线段区域,精灵移动过去
void Camera3DTestDemo::onTouchesMoved(const std::vector<Touch*>& touches,cocos2d::Event  *event)
{
    if(touches.size()==1)
    {
        auto touch = touches[0];
        //获取第一个触摸点的OpenGL坐标系的坐标,原点在屏幕左下角。
        //补充:屏幕坐标系,原点在屏幕左上角
        //世界坐标系:与OpenGL坐标系一致,位于屏幕左下角
        //节点坐标系:父节点的左下角,与OpenGL一致
        auto location = touch->getLocation();
        Point newPos = touch->getPreviousLocation()-location;
        if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
        {
            Vec3 cameraDir;
            Vec3 cameraRightDir;
            //返回世界仿射变换矩阵。矩阵单位是像素。并获取Forward矩阵,参数为目标向量。注意逆世界仿射变换矩阵
            _camera->getNodeToWorldTransform().getForwardVector(&cameraDir);
            //将返回的矩阵向量规范化
            cameraDir.normalize();
            //将返回的矩阵向量y轴赋值为0
            cameraDir.y=0;
            //返回正确的举证向量的世界仿射变化矩阵
            _camera->getNodeToWorldTransform().getRightVector(&cameraRightDir);
            //向量规范化
            cameraRightDir.normalize();
            //向量y轴赋值0
            cameraRightDir.y=0;
            Vec3 cameraPos=  _camera->getPosition3D();
            cameraPos+=cameraDir*newPos.y*0.1f;
            cameraPos+=cameraRightDir*newPos.x*0.1f;
            //重新设置摄像机的3D坐标
            _camera->setPosition3D(cameraPos);
            //如果精灵存在,且相机的类型为第一视角,执行下面代码
            if(_sprite3D &&  _cameraType==CameraType::FirstCamera)
            {
                //设置精灵的3D坐标,并保存当前精灵坐标值,用于更新任务运动状态
                _sprite3D->setPosition3D(Vec3(_camera->getPositionX(),_camera->getPositionZ()));
                _targetPos=_sprite3D->getPosition3D();
            }
        }
    }
}
//3D精灵移动
void Camera3DTestDemo::move3D(float elapsedTime)
{
    if(_sprite3D)
    {
        //获取当前精灵的3D坐标
        Vec3 curPos=  _sprite3D->getPosition3D();
        //计算原来坐标与新坐标的向量
        Vec3 newFaceDir = _targetPos - curPos;
        //将y轴赋值为0,并将新向量规范化
        newFaceDir.y = 0.0f;
        newFaceDir.normalize();
        //计算偏移
        Vec3 offset = newFaceDir * 25.0f * elapsedTime;
        curPos+=offset;
        //设置精灵的新坐标
        _sprite3D->setPosition3D(curPos);
        offset.x=offset.x;
        offset.z=offset.z;
        if(_cameraType==CameraType::ThirdCamera)
        {
            //如果摄像机的类型为第三视角,同时更新摄像机的3D坐标
            Vec3 cameraPos= _camera->getPosition3D();
            cameraPos.x+=offset.x;
            cameraPos.z+=offset.z;
            _camera->setPosition3D(cameraPos);
        }
    }
}
//判断精灵的状态
void Camera3DTestDemo::updateState(float elapsedTime)
{
    if(_sprite3D)
    {
        Vec3 curPos=  _sprite3D->getPosition3D();
        Vec3 curFaceDir;
        //返回世界仿射变换矩阵。矩阵单位是像素。并获取Forward矩阵,参数为目标向量。注意逆世界仿射变换矩阵
        _sprite3D->getNodeToWorldTransform().getForwardVector(&curFaceDir);
        curFaceDir=-curFaceDir;
        curFaceDir.normalize();
        Vec3 newFaceDir = _targetPos - curPos;
        newFaceDir.y = 0.0f;
        newFaceDir.normalize();
        //计算两个向量的点积,通过返回的值判断精灵运动方向和是否停止
        float cosAngle = std::fabs(Vec3::dot(curFaceDir,newFaceDir) - 1.0f);
        //返回两个向量的平方距离
        float dist = curPos.distanceSquared(_targetPos);
        if(dist<=4.0f)
        {
            if(cosAngle<=0.01f)
                _curState = State_Idle;
            else
                _curState = State_Rotate;
        }
        else
        {
            if(cosAngle>0.01f)
                _curState = State_Rotate | State_Move;
            else
                _curState = State_Move;
        }
    }
}
void Camera3DTestDemo::onTouchesEnded(const std::vector<Touch*>& touches,cocos2d::Event  *event)
{
    for ( auto &item: touches )
    {
        auto touch = item;
        auto location = touch->getLocationInView();
        if(_camera)
        {
            if(_sprite3D && _cameraType==CameraType::ThirdCamera && _bZoomOut == false && _bZoomIn == false && _bRotateLeft == false && _bRotateRight == false)
            {
                Vec3 nearP(location.x,location.y,-1.0f),farP(location.x,1.0f);
                
                auto size = Director::getInstance()->getWinSize();
                _camera->unproject(size,&nearP,&nearP);
                _camera->unproject(size,&farP,&farP);
                Vec3 dir(farP - nearP);
                float dist=0.0f;
                float ndd = Vec3::dot(Vec3(0,dir);
                if(ndd == 0)
                    dist=0.0f;
                float ndo = Vec3::dot(Vec3(0,nearP);
                dist= (0 - ndo) / ndd;
                Vec3 p =   nearP + dist *  dir;
                
                if( p.x > 100)
                    p.x = 100;
                if( p.x < -100)
                    p.x = -100;
                if( p.z > 100)
                    p.z = 100;
                if( p.z < -100)
                    p.z = -100;
                
                _targetPos=p;
            }
        }
    }
}
void onTouchesCancelled(const std::vector<Touch*>& touches,cocos2d::Event  *event)
{
}
//更新视图
void Camera3DTestDemo::updateCamera(float fDelta)
{
    if(_sprite3D)
    {
        if( _cameraType==CameraType::ThirdCamera)
        {
            //摄像机类型为第三视角,判断精灵的运动状态
            updateState(fDelta);
            //如果精灵正在行走
            if(isState(_curState,State_Move))
            {
                //使精灵和相机为行走状态
                move3D(fDelta);
                //如果行走在转身
                if(isState(_curState,State_Rotate))
                {
                    Vec3 curPos = _sprite3D->getPosition3D();
                    
                    Vec3 newFaceDir = _targetPos - curPos;
                    newFaceDir.y = 0;
                    newFaceDir.normalize();
                    Vec3 up;
                    _sprite3D->getNodeToWorldTransform().getUpVector(&up);
                    up.normalize();
                    Vec3 right;
                    Vec3::cross(-newFaceDir,up,&right);
                    right.normalize();
                    Vec3 pos = Vec3(0,0);
                    Mat4 mat;
                    mat.m[0] = right.x;
                    mat.m[1] = right.y;
                    mat.m[2] = right.z;
                    mat.m[3] = 0.0f;
                    
                    mat.m[4] = up.x;
                    mat.m[5] = up.y;
                    mat.m[6] = up.z;
                    mat.m[7] = 0.0f;
                    
                    mat.m[8]  = newFaceDir.x;
                    mat.m[9]  = newFaceDir.y;
                    mat.m[10] = newFaceDir.z;
                    mat.m[11] = 0.0f;
                    
                    mat.m[12] = pos.x;
                    mat.m[13] = pos.y;
                    mat.m[14] = pos.z;
                    mat.m[15] = 1.0f;
                    //设置额外的节点变换矩阵
                    _sprite3D->setAdditionalTransform(&mat);
                }
            }
        }
        //如果执行缩小动作
        if(_bZoomOut == true)
        {
            if(_camera)
            {
                //摄像机类型为第三视角
                if(_cameraType == CameraType::ThirdCamera)
                {
                    Vec3 lookDir = _camera->getPosition3D() - _sprite3D->getPosition3D();
                    Vec3 cameraPos = _camera->getPosition3D();
                    //求得相机与精灵的空间距离
                    if(lookDir.length() <= 300)
                    {
                        //相机位置增加,且不改变相机与精灵的相对位置
                        cameraPos += lookDir.getNormalized();
                        _camera->setPosition3D(cameraPos);
                    }
                }
                //如果是自由视角
                else if(_cameraType == CameraType::FreeCamera)
                {
                    Vec3 cameraPos = _camera->getPosition3D();
                    if(cameraPos.length() <= 300)
                    {
                        //相机距离增加
                        cameraPos += cameraPos.getNormalized();
                        _camera->setPosition3D(cameraPos);
                    }
                }
            }
        }
        //如果是放大效果
        if(_bZoomIn == true)
        {
            if(_camera)
            {
                //相机是第三视角
                if(_cameraType == CameraType::ThirdCamera)
                {
                    Vec3 lookDir = _camera->getPosition3D() - _sprite3D->getPosition3D();
                    Vec3 cameraPos = _camera->getPosition3D();
                    if(lookDir.length() >= 50)
                    {
                        //相机与精灵的距离大于50,才会执行下面操作
                        //相机位置增加
                        cameraPos -= lookDir.getNormalized();
                        _camera->setPosition3D(cameraPos);
                    }
                }
                //如果为自由视角
                else if(_cameraType == CameraType::FreeCamera)
                {
                    Vec3 cameraPos = _camera->getPosition3D();
                    if(cameraPos.length() >= 50)
                    {
                        //相机位置增加
                        cameraPos -= cameraPos.getNormalized();
                        _camera->setPosition3D(cameraPos);
                    }
                }
            }
        }
        //如果是左转效果
        if(_bRotateLeft == true)
        {
            //如果相机类型为自由视角和第一视角
            if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
            {
                //y轴增加旋转
                Vec3  rotation3D= _camera->getRotation3D();
                rotation3D.y+= 1;
                _camera->setRotation3D(rotation3D);
            }
        }
        //如果是右转效果
        if(_bRotateRight == true)
        {
            if(_cameraType==CameraType::FreeCamera || _cameraType==CameraType::FirstCamera)
            {
                //摄像机类型为自由视角和第一视角,y轴减少旋转
                Vec3  rotation3D= _camera->getRotation3D();
                rotation3D.y-= 1;
                _camera->setRotation3D(rotation3D);
            }
        }
    }
}
//判断精灵的运动状态
bool Camera3DTestDemo::isState(unsigned int state,unsigned int bit) const
{
    return (state & bit) == bit;
}
//缩小触摸事件
bool Camera3DTestDemo::onTouchesZoomOut(Touch* touch,Event* event)
{
    auto target = static_cast<Label*>(event->getCurrentTarget());
    //将触摸点的位置转化为节点坐标位置
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    Size s = target->getContentSize();
    Rect rect = Rect(0,s.width,s.height);
    //如果触摸在节点内
    if (rect.containsPoint(locationInNode))
    {
        _bZoomOut = true;
        return true;
    }
    return false;
}
//缩小触摸结束
void Camera3DTestDemo::onTouchesZoomOutEnd(Touch* touch,Event* event)
{
    _bZoomOut = false;
}
//放大触摸事件
bool Camera3DTestDemo::onTouchesZoomIn(Touch* touch,Event* event)
{
    auto target = static_cast<Label*>(event->getCurrentTarget());
    
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    Size s = target->getContentSize();
    Rect rect = Rect(0,s.height);
    //如果在节点内,设置放大判断值为true
    if (rect.containsPoint(locationInNode))
    {
        _bZoomIn = true;
        return true;
    }
    return false;
}
//放大触摸结束
void Camera3DTestDemo::onTouchesZoomInEnd(Touch* touch,Event* event)
{
    _bZoomIn = false;
}
//左转触摸
bool Camera3DTestDemo::onTouchesRotateLeft(Touch* touch,s.height);
    //设置左转触摸为true
    if (rect.containsPoint(locationInNode))
    {
        
        _bRotateLeft = true;
        return true;
    }
    return false;
}
void Camera3DTestDemo::onTouchesRotateLeftEnd(Touch* touch,Event* event)
{
    //左转触摸结束,恢复判断值为false
    _bRotateLeft = false;
}
//右转触摸
bool Camera3DTestDemo::onTouchesRotateRight(Touch* touch,s.height);
    //设置右转触摸判断值为true;
    if (rect.containsPoint(locationInNode))
    {
        _bRotateRight = true;
        return true;
    }
    return false;
}
//触摸结束,恢复右转判断触摸值为false
void Camera3DTestDemo::onTouchesRotateRightEnd(Touch* touch,Event* event)
{
    _bRotateRight = false;
}

2、使用

在HelloWorld的createScene中,直接创建Camera3DDemo的Layer对象,加入Scene

3、运行效果

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读