#include "BillBoardTest.h"
BillBoardDemo::BillBoardDemo()
:_camera(nullptr)
{
}
bool BillBoardDemo::init()
{
bool bRet = false;
do{
CC_BREAK_IF(!Layer::init());
//注册事件监听
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesMoved = CC_CALLBACK_2(BillBoardDemo::onTouchesMoved,this);//事件回调
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(listener,this);
//添加层
auto layer3D = Layer::create();
addChild(layer3D,0);
_layerBillBoard = layer3D;
auto winSize = Director::getInstance()->getWinSize();
//创建摄像机
if(_camera == nullptr)
{
//参数1:透视相机的视野。参数2:相机的长宽比。参数3:近点平面距离。参数4:远点平面距离
_camera = Camera::createPerspective(60,(GLfloat)winSize.width / winSize.height,1,500);
_camera->setCameraFlag(CameraFlag::USER1);//设置相机Flag,便于相机识别节点
_layerBillBoard->addChild(_camera);//相机加入层
}
std::string imgs[3] = {"Icon.png","r2.png"};
for(unsigned int i = 0; i < 4; i++)
{
Layer* layer = Layer::create();
//随机创建BillBoard对象
auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1()*1+0.5)]);
billboard->setScale(0.5);//设置缩放
//CCRANDOM_MINUS1_1返回一个-1到1的float值
billboard->setPosition3D(Vec3(0.0f,0.0f,CCRANDOM_MINUS1_1()*150.0f));//设置3D坐标
//ALPHA_NON_PREMULTIPLIED混合方式 {GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA}
//源因子使用源颜色的透明度,目标因子使用减去源颜色的透明度
billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合
billboard->setOpacity(CCRANDOM_0_1()*128+128);//设置可见性
_billboards.push_back(billboard);
layer->addChild(billboard);
//1,层对象加入层
_layerBillBoard->addChild(layer);//加入层
layer->runAction(RepeatForever::create(RotateBy::create(CCRANDOM_0_1(),Vec3(0.0f,45.0f,0.0f))));//层执行翻转动作
}
{
auto billboard = BillBoard::create("Icon.png");
billboard->setScale(0.2f);
billboard->setPosition3D(Vec3(0.0f,30.0f,0.0f));
auto billboard2 = BillBoard::create("r2.png");
billboard2->setPosition3D(Vec3(0.0f,100.0f));
billboard->addChild(billboard2);
_billboards.push_back(billboard);
_billboards.push_back(billboard2);
auto sprite3D = Sprite3D::create("orc.c3t");
sprite3D->setScale(2.0f);
sprite3D->addChild(billboard);
sprite3D->runAction(RepeatForever::create(RotateBy::create(10.0f,360.0f,0.0f))));
//2,Sprite3D对象加入层
_layerBillBoard->addChild(sprite3D);
}
//添加新的billboard
addNewBillBoardWithCoords(Vec3(20,5,0));
addNewBillBoardWithCoords(Vec3(60,0));
addNewBillBoardWithCoords(Vec3(100,0));
addNewBillBoardWithCoords(Vec3(140,0));
addNewBillBoardWithCoords(Vec3(180,0));
addNewAniBillBoardWithCoords(Vec3(-20,0));
addNewAniBillBoardWithCoords(Vec3(-60,0));
addNewAniBillBoardWithCoords(Vec3(-100,0));
addNewAniBillBoardWithCoords(Vec3(-140,0));
addNewAniBillBoardWithCoords(Vec3(-180,0));
_camera->setPosition3D(Vec3(0,100,230));//设置相机的3D位置
_camera->lookAt(Vec3(0,0),Vec3(0,0));//设置相机的,参数1:目标的中心位置,参数2:向上的向量
//添加菜单
TTFConfig ttfConfig("fonts/arial.ttf",30);
auto label1 = Label::createWithTTF(ttfConfig,"rotate+");
auto menuItem1 = MenuItemLabel::create(label1,CC_CALLBACK_1(BillBoardDemo::rotateCameraCallback,this,10));
auto label2 = Label::createWithTTF(ttfConfig,"rotate-");
auto menuItem2 = MenuItemLabel::create(label2,-10));
auto menu = Menu::create(menuItem1,menuItem2,nullptr);
menu->setPosition(Vec2::ZERO);
menuItem1->setPosition(Vec2(winSize.width - 80,VisibleRect::top().y - 160));
menuItem2->setPosition(Vec2(winSize.width - 80,VisibleRect::top().y - 190));
addChild(menu,0);
_layerBillBoard->setCameraMask(2);//设置mask使得对相机可见
//设置billboard观察模式
label1 = Label::createWithTTF(ttfConfig,"Point Oriented");
menuItem1 = MenuItemLabel::create(label1,CC_CALLBACK_1(BillBoardDemo::menuCallback_orientedPoint,this));
label2 = Label::createWithTTF(ttfConfig,"Plane Oriented");
menuItem2 = MenuItemLabel::create(label2,CC_CALLBACK_1(BillBoardDemo::menuCallback_orientedPlane,this));
menuItem1->setPosition(Vec2(winSize.width -80,VisibleRect::top().y - 100));
menuItem2->setPosition(Vec2(winSize.width -80,VisibleRect::top().y - 130));
menu = Menu::create(menuItem1,nullptr);
menu->setPosition(Vec2::ZERO);
this->addChild(menu,10);
menuCallback_orientedPoint(nullptr);
bRet = true;
}while(0);
return bRet;
}
void BillBoardDemo::menuCallback_orientedPoint(cocos2d::Ref *sender)
{
for(auto& billboard : _billboards)
{
billboard->setMode(BillBoard::Mode::VIEW_POINT_ORIENTED);
}
}
void BillBoardDemo::menuCallback_orientedPlane(cocos2d::Ref *sender)
{
for(auto& billboard : _billboards)
{
billboard->setMode(BillBoard::Mode::VIEW_PLANE_ORIENTED);
}
}
BillBoardDemo::~BillBoardDemo()
{
if(_camera)
{
_camera = nullptr;
}
}
//创建新的BillBoard
void BillBoardDemo::addNewBillBoardWithCoords(Vec3 p)
{
std::string imgs[3] = {"Icon.png","r2.png"};
for(unsigned int i = 0; i < 10; i++)
{
//随机图片
auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1()*1+0.5)]);
billboard->setScale(0.5f);
billboard->setPosition3D(Vec3(p.x,p.y,-150.0f+30*i));//Z轴值越来越大
billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合方式
billboard->setOpacity(CCRANDOM_0_1()*128+128);
_layerBillBoard->addChild(billboard);//3,加入新的billboard对象
_billboards.push_back(billboard);
}
}
//创建新的BillBoard
void BillBoardDemo::addNewAniBillBoardWithCoords(cocos2d::Vec3 p)
{
for(unsigned i = 0; i < 10; i++)
{
auto billboardAni = BillBoard::create("grossini.png");
billboardAni->setScale(0.5);
billboardAni->setPosition3D(Vec3(p.x,-150.0f+30*i));
_layerBillBoard->addChild(billboardAni);//4,加入新的billboard对象
//使用帧动画
auto animation = Animation::create();
for(int i = 1; i < 15; i++)
{
char szName1[100] = {0};
sprintf(szName1,"grossini_dance_%02d.png",i);
animation->addSpriteFrameWithFile(szName1);
}
animation->setDelayPerUnit(2.8f/14.0f);//设置一帧的时间
animation->setRestoreOriginalFrame(true);//重复播放
auto action = Animate::create(animation);
billboardAni->runAction(RepeatForever::create(action));
billboardAni->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合方式
billboardAni->setOpacity(CCRANDOM_0_1()*128+128);
_billboards.push_back(billboardAni);
}
}
void BillBoardDemo::update(float dt)
{
}
//触摸事件,改变摄像机的坐标
void BillBoardDemo::onTouchesMoved(const std::vector<Touch *> &touches,cocos2d::Event *event)
{
if(touches.size() == 1)
{
auto touch = touches[0];
auto location = touch->getLocation();
auto PrevIoUsLocation = touch->getPrevIoUsLocation();
Vec2 newPos = PrevIoUsLocation - location;
Vec3 cameraDir;
Vec3 cameraRightDir;
_camera->getNodeToWorldTransform().getForwardVector(&cameraDir);
cameraDir.normalize();
cameraDir.y = 0;
_camera->getNodeToWorldTransform().getRightVector(&cameraRightDir);
cameraRightDir.normalize();
cameraRightDir.y = 0;
Vec3 cameraPos = _camera->getPosition3D();
cameraPos+= cameraDir*newPos.y*0.5;
cameraPos+= cameraRightDir*newPos.x*0.5;
_camera->setPosition3D(cameraPos);
}
}
//翻转摄像机
void BillBoardDemo::rotateCameraCallback(cocos2d::Ref *sender,float value)
{
Vec3 rotation3D = _camera->getRotation3D();
rotation3D.y += value;
_camera->setRotation3D(rotation3D);
}
3、使用