Cocos2d-x 3.3 的3D开发功能介绍

前端之家收集整理的这篇文章主要介绍了Cocos2d-x 3.3 的3D开发功能介绍前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

昨天去成都参加GMGDC 全球移动游戏开发者大会,据蓝港互动CEO王峰谈到《手机游戏开发如何走好第一步》时谈到

目前手游公司有10000家,没错,红海,都快变黑海了

这么多公司和产品如何竞争,大量的同质化产品,(王峰给我的建议是与其在红海中厮杀不如想象未来的蓝海在哪,听明白的请举起右手)

先不管这些了,作为程序员来讲我们看到了20万的人才缺口(如果每家公司招20个人,听明白的请举起左手)

今天下载了Cocos2d-x 3.3,3D功能果然强大

主要有以下功能

1. 基本的Sprite3D使用,加载静态模型和动态模型,看 Sprite3DBasicTest

2.Sprite3D对象的旋转,缩放等Action操作

3.Sprite3D中使用Shader特效,实现outLine

4.Animate3D来创建3D动画

5.动态增加3D骨骼,实现怪物添加手持武器功能

6,动态修改骨骼皮肤实现换装功能Sprite3DReskinTest

7.通过包围盒实现3D模型碰撞,Sprite3DWithOBBPerfromanceTest

8.实现水平镜像3D模型,Sprite3DMirrorTest


下面介绍一下Sprite3DTest里面的源码



#include"Sprite3DTest.h"

#include"3d/CCAnimation3D.h"

#include"3d/CCAnimate3D.h"

#include"3d/CCAttachNode.h"

#include"3d/CCRay.h"

#include"3d/CCSprite3D.h"

#include"renderer/CCVertexIndexBuffer.h"

#include"DrawNode3D.h"

1.在Scene中添加3D模型

voidSprite3DBasicTest::addNewSpriteWithCoords(Vec2p)

{

//这里的obj可以使用3dmax直接导出

// //option 1: load a obj that contain the texture in it 第一种方法是在模型文件中包含了纹理

// auto sprite = Sprite3D::create("sprite3dTest/scene01.obj");

//option 2: load obj and assign the texture 第二种方法是在模型文件中不包含纹理

autosprite =Sprite3D::create("Sprite3DTest/boss1.obj");

sprite->setScale(3.f);

sprite->setTexture("Sprite3DTest/boss.png");

//在Sprite3D中包含了一些基本的Shader特效,下面是让3D模型实现outline

//sprite->setEffect(cocos2d::EFFECT_OUTLINE);

//add to scene

addChild( sprite );

sprite->setPosition(Vec2( p.x,p.y) );

ActionInterval* action;

floatrandom =CCRANDOM_0_1();

if( random <0.20)

action =ScaleBy::create(3,2);

elseif(random <0.40)

action =RotateBy::create(3,360);

elseif( random <0.60)

action =Blink::create(1,3);

elseif( random <0.8)

action =TintBy::create(2,0,-255,-255);

else

action =FadeOut::create(2);

autoaction_back = action->reverse();

autoseq =Sequence::create( action,action_back,nullptr);

sprite->runAction(RepeatForever::create(seq) );

//以上大家看到Sprite3D起始和Sprite类似都可以实现各种Action

}

voidSprite3DBasicTest::onTouchesEnded(conststd::vector<Touch*>& touches,Event* event)

for(autotouch: touches)

{

autolocation = touch->getLocation();

//触摸屏幕添加3D模型

addNewSpriteWithCoords( location );

}

}

2.透过触摸屏幕拖动模型移动


Sprite3DHitTest::Sprite3DHitTest()

{

autos =Director::getInstance()->getWinSize();

autosprite1 =Sprite3D::create("Sprite3DTest/boss1.obj");

sprite1->setScale(4.f);

sprite1->setTexture("Sprite3DTest/boss.png");

sprite1->setPosition(Vec2(s.width/2,s.height/2) );

addChild( sprite1 );

sprite1->runAction(RepeatForever::create(RotateBy::create(3,360)));

autosprite2 =Sprite3D::create("Sprite3DTest/boss1.obj");

sprite2->setScale(4.f);

sprite2->setTexture("Sprite3DTest/boss.png");

sprite2->setPosition(Vec2(s.width/2,s.height/2) );

sprite2->setAnchorPoint(Vec2(0.5,0.5));

addChild( sprite2 );

sprite2->runAction(RepeatForever::create(RotateBy::create(3,-360)));

// Make sprite1 touchable

autolistener1 =EventListenerTouchOneByOne::create();

listener1->setSwallowTouches(true);

listener1->onTouchBegan= [](Touch* touch,Event* event){

autotarget =static_cast<Sprite3D*>(event->getCurrentTarget());

Rectrect = target->getBoundingBox();

if(rect.containsPoint(touch->getLocation()))

{

log("sprite3d began... x = %f,y = %f",touch->getLocation().x,touch->getLocation().y);

target->setOpacity(100);

returntrue;

}

returnfalse;

};

listener1->onTouchMoved= [](Touch* touch,51); font-family:Arial; font-size:14px; line-height:26px"> autotarget =static_cast<Sprite3D*>(event->getCurrentTarget());

target->setPosition(target->getPosition() + touch->getDelta());

listener1->onTouchEnded= [=](Touch* touch,Event* event){

autotarget =static_cast<Sprite3D*>(event->getCurrentTarget());

log("sprite3d onTouchesEnded.. ");

target->setOpacity(255);

};

_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener1,sprite1);

_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener1->clone(),sprite2);

3.在一个Sprite3D上使用Shader

Effect3D继承REF封装了Shader的处理

Effect3DOutline继承了Effect3D,封装了Outline类型的Shader

EffectSprite3D继承了Sprite3D封装了对Effect3DOutline的调用

classEffect3D :publicRef

{

public:

virtualvoiddraw(constMat4&transform) =0;

virtualvoidsetTarget(EffectSprite3D*sprite) =0;

protected:

Effect3D() :_glProgramState(nullptr) {}

virtual~Effect3D()

{

CC_SAFE_RELEASE(_glProgramState);

}

GLProgramState* _glProgramState;

};


classEffect3DOutline:publicEffect3D

staticEffect3DOutline* create();

voidsetOutlineColor(constVec3& color);

voidsetOutlineWidth(floatwidth);

virtualvoiddraw(constMat4&transform) override;

virtualvoidsetTarget(EffectSprite3D*sprite) override;

protected:

Effect3DOutline();

virtual~Effect3DOutline();

boolinit();

Vec3 _outlineColor;

float_outlineWidth;

//weak reference

EffectSprite3D* _sprite;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

EventListenerCustom* _backToForegroundListener;

#endif

staticconststd::string_vertShaderFile;

staticconststd::string_fragShaderFile;

staticconststd::string_keyInGLProgramCache;

staticconststd::string_vertSkinnedShaderFile;

staticconststd::string_fragSkinnedShaderFile;

staticconststd::string_keySkinnedInGLProgramCache;

staticGLProgram* getOrCreateProgram(boolisSkinned =false);

};

classEffectSprite3D :publicSprite3D

staticEffectSprite3D* createFromObjFileAndTexture(conststd::string& objFilePath,conststd::string& textureFilePath);

staticEffectSprite3D* create(conststd::string& path);

voidsetEffect3D(Effect3D* effect);

voidaddEffect(Effect3DOutline* effect,ssize_torder);

virtualvoiddraw(Renderer*renderer,constMat4&transform,uint32_tflags) override;

EffectSprite3D();

virtual~EffectSprite3D();

std::vector<std::tuple<ssize_t,Effect3D*,CustomCommand>> _effects;

Effect3D* _defaultEffect;

CustomCommand_command;

};

classSprite3DEffectTest :publicSprite3DTestDemo

public:

CREATE_FUNC(Sprite3DEffectTest);

Sprite3DEffectTest();

virtualstd::stringtitle()constoverride;

virtualstd::stringsubtitle()constoverride;

voidaddNewSpriteWithCoords(Vec2p);

voidonTouchesEnded(conststd::vector<Touch*>& touches,Event* event);

};


conststd::stringEffect3DOutline::_vertShaderFile ="Shaders3D/OutLine.vert";

conststd::stringEffect3DOutline::_fragShaderFile ="Shaders3D/OutLine.frag";

conststd::stringEffect3DOutline::_keyInGLProgramCache ="Effect3DLibrary_Outline";

conststd::stringEffect3DOutline::_vertSkinnedShaderFile ="Shaders3D/SkinnedOutline.vert";

conststd::stringEffect3DOutline::_fragSkinnedShaderFile ="Shaders3D/OutLine.frag";

conststd::stringEffect3DOutline::_keySkinnedInGLProgramCache ="Effect3DLibrary_Outline";

GLProgram*Effect3DOutline::getOrCreateProgram(boolisSkinned/* = false */)

if(isSkinned)

autoprogram =GLProgramCache::getInstance()->getGLProgram(_keySkinnedInGLProgramCache);

if(program ==nullptr)

{

program =GLProgram::createWithFilenames(_vertSkinnedShaderFile,_fragSkinnedShaderFile);

GLProgramCache::getInstance()->addGLProgram(program,_keySkinnedInGLProgramCache);

}

returnprogram;

autoprogram =GLProgramCache::getInstance()->getGLProgram(_keyInGLProgramCache);

program =GLProgram::createWithFilenames(_vertShaderFile,_fragShaderFile);

_keyInGLProgramCache);

}


Effect3DOutline*Effect3DOutline::create()

{

Effect3DOutline* effect =new(std::nothrow)Effect3DOutline();

if(effect && effect->init())

effect->autorelease();

returneffect;

CC_SAFE_DELETE(effect);

returnnullptr;

boolEffect3DOutline::init()

{

returntrue;

Effect3DOutline::Effect3DOutline()

:_outlineWidth(1.0f)

,_outlineColor(1,1,1)

(nullptr)

{

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

_backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED,

[this](EventCustom*)

{

autoglProgram = _glProgramState->getGLProgram();

glProgram->reset();

glProgram->initWithFilenames(_vertShaderFile,_fragShaderFile);

glProgram->link();

glProgram->updateUniforms();

}

);

Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener,-1);

#endif

Effect3DOutline::~Effect3DOutline()

Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);

voidEffect3DOutline::setOutlineColor(constVec3& color)

if(_outlineColor!= color)

_outlineColor= color;

if(_glProgramState)

_glProgramState->setUniformVec3("OutLineColor",_outlineColor);

voidEffect3DOutline::setOutlineWidth(floatwidth)

if(_outlineWidth!= width)

_outlineWidth= width;

_glProgramState->setUniformFloat("OutlineWidth",_outlineWidth);

voidEffect3DOutline::setTarget(EffectSprite3D*sprite)

{

CCASSERT(nullptr!= sprite &&nullptr!= sprite->getMesh(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D");

if(sprite !=_sprite)

GLProgram* glprogram;

if(!sprite->getMesh()->getSkin())

glprogram =GLProgram::createWithFilenames(_vertShaderFile,_fragShaderFile);

else

glprogram =GLProgram::createWithFilenames(_vertSkinnedShaderFile,_fragSkinnedShaderFile);

_glProgramState=GLProgramState::create(glprogram);


_glProgramState->retain();

_glProgramState->setUniformVec3("OutLineColor",_outlineColor);

_glProgramState->setUniformFloat("OutlineWidth",_outlineWidth);

_sprite= sprite;

automesh = sprite->getMesh();

longoffset =0;

for(autoi =0; i < mesh->getMeshVertexAttribCount(); i++)

{

automeshvertexattrib = mesh->getMeshVertexAttribute(i);

_glProgramState->setVertexAttribPointer(s_attributeNames[meshvertexattrib.vertexAttrib],

meshvertexattrib.size,51); font-family:Arial; font-size:14px; line-height:26px"> meshvertexattrib.type,51); font-family:Arial; font-size:14px; line-height:26px"> GL_FALSE,51); font-family:Arial; font-size:14px; line-height:26px"> mesh->getVertexSizeInBytes(),51); font-family:Arial; font-size:14px; line-height:26px"> (void*)offset);

offset += meshvertexattrib.attribSizeBytes;

}

Color4Fcolor(_sprite->getDisplayedColor());

color.a=_sprite->getDisplayedOpacity() /255.0f;

_glProgramState->setUniformVec4("u_color",Vec4(color.r,color.g,color.b,color.a));

staticvoidMatrixPalleteCallBack(GLProgram* glProgram,Uniform* uniform,intpaletteSize,constfloat* palette)

glUniform4fv( uniform->location,(GLsizei)paletteSize,(constfloat*)palette );

voidEffect3DOutline::draw(constMat4&transform)

{

//draw

Color4Fcolor(_sprite->getDisplayedColor());

color.a=_sprite->getDisplayedOpacity() /255.0f;

_glProgramState->setUniformVec4("u_color",51); font-family:Arial; font-size:14px; line-height:26px"> if(_sprite&&_sprite->getMesh())

{

glEnable(GL_CULL_FACE);

glCullFace(GL_FRONT);

glEnable(GL_DEPTH_TEST);

automesh =_sprite->getMesh();

glBindBuffer(GL_ARRAY_BUFFER,mesh->getVertexBuffer());

autoskin =_sprite->getMesh()->getSkin();

if(_sprite&& skin)

autofunction =std::bind(MatrixPalleteCallBack,std::placeholders::_1,std::placeholders::_2,51); font-family:Arial; font-size:14px; line-height:26px"> skin->getMatrixPaletteSize(),(float*)skin->getMatrixPalette());

_glProgramState->setUniformCallback("u_matrixPalette",function);

if(_sprite)

_glProgramState->apply(transform);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mesh->getIndexBuffer());

glDrawElements(mesh->getPrimitiveType(),mesh->getIndexCount(),mesh->getIndexFormat(),0);

CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,mesh->getIndexCount());

glBindBuffer(GL_ARRAY_BUFFER,51); font-family:Arial; font-size:14px; line-height:26px"> glDisable(GL_DEPTH_TEST);

glCullFace(GL_BACK);

glDisable(GL_CULL_FACE);

voidEffectSprite3D::draw(cocos2d::Renderer*renderer,constcocos2d::Mat4&transform,uint32_tflags)

for(auto&effect : _effects)

if(std::get<0>(effect) >=0)

break;

CustomCommand&cc =std::get<2>(effect);

cc.func=CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform);

renderer->addCommand(&cc);

if(!_defaultEffect)

Sprite3D::draw(renderer,transform,flags);

{

_command.init(_globalZOrder);

_command.func=CC_CALLBACK_0(Effect3D::draw,_defaultEffect,51); font-family:Arial; font-size:14px; line-height:26px"> renderer->addCommand(&_command);

if(std::get<0>(effect) <=0)

continue;

//Sprite3DEffectTest中实现了对Sprite3DEffect的加载

Sprite3DEffectTest::Sprite3DEffectTest()

autos =Director::getInstance()->getWinSize();

addNewSpriteWithCoords(Vec2(s.width/2,s.height/2) );

autolistener =EventListenerTouchAllAtOnce::create();

listener->onTouchesEnded=CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded,this);

_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,this);

voidSprite3DEffectTest::addNewSpriteWithCoords(Vec2p)

//option 2: load obj and assign the texture

autosprite =EffectSprite3D::createFromObjFileAndTexture("Sprite3DTest/boss1.obj","Sprite3DTest/boss.png");

Effect3DOutline* effect =Effect3DOutline::create();

sprite->addEffect(effect,-1);

effect->setOutlineColor(Vec3(1,0));

effect->setOutlineWidth(0.01f);

Effect3DOutline* effect2 =Effect3DOutline::create();

sprite->addEffect(effect2,-2);

effect2->setOutlineWidth(0.02f);

effect2->setOutlineColor(Vec3(1,1,0));

//sprite->setEffect3D(effect);

sprite->setScale(6.f);

addChild( sprite );

y) );

nullptr);

voidSprite3DEffectTest::onTouchesEnded(conststd::vector<Touch*>& touches,51); font-family:Arial; font-size:14px; line-height:26px">

4.加载包含了3D纹理和动画的C3B文件,具体转化方法为在tools下使用fbx-conv.exe将3dmax导出的文件转化为c3b

用Sprite3D来加载c3b,用Animation3D,和Animate3D来创建动画

autoanimation =Animation3D::create(fileName);

if(animation)

{

autoanimate =Animate3D::create(animation);

sprite->runAction(RepeatForever::create(animate));

}


voidSprite3DWithSkinTest::addNewSpriteWithCoords(Vec2p)

std::stringfileName ="Sprite3DTest/orc.c3b";

autosprite =EffectSprite3D::create(fileName);

sprite->setScale(3);

sprite->setRotation3D(Vec3(0,180,0));

addChild(sprite);

sprite->setPosition(Vec2( p.x,p.y) );

boolinverse = (std::rand() %3==0);

intrand2 =std::rand();

floatspeed =1.0f;

if(rand2 %3==1)

speed = animate->getSpeed() +CCRANDOM_0_1();

elseif(rand2 %3==2)

speed = animate->getSpeed() -0.5*CCRANDOM_0_1();

animate->setSpeed(inverse ? -speed : speed);

sprite->runAction(RepeatForever::create(animate));

5.在以上模型和动画中添加特效(方法和在静态模型上一样)

voidSprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2p)

std::stringfileName ="Sprite3DTest/orc.c3b";

autosprite =EffectSprite3D::create(fileName);

Effect3DOutline* effect =Effect3DOutline::create();

effect->setOutlineColor(Vec3(1,51); font-family:Arial; font-size:14px; line-height:26px"> effect->setOutlineWidth(0.01f);

sprite->addEffect(effect,-1);


Effect3DOutline* effect2 =Effect3DOutline::create();

effect2->setOutlineWidth(0.02f);

effect2->setOutlineColor(Vec3(1,51); font-family:Arial; font-size:14px; line-height:26px"> sprite->addEffect(effect2,-2);

sprite->setScale(3);

sprite->setRotation3D(Vec3(0,51); font-family:Arial; font-size:14px; line-height:26px"> addChild(sprite);

autoanimation =Animation3D::create(fileName);

if(animation)

autoanimate =Animate3D::create(animation);

6.动画的切换

既然每个3D动画是Action就可以通过切换每个Sprite3D的Action来切换动画,下面是一个小乌龟的2个动画之间的切换

Animate3DTest::Animate3DTest()

:_hurt(nullptr)

_swim(nullptr)

(nullptr)

(nullptr)

(0.f)

{//添加小乌龟

addSprite3D();

listener->onTouchesEnded=CC_CALLBACK_2(Animate3DTest::onTouchesEnded,this);

scheduleUpdate();

Animate3DTest::~Animate3DTest()

{

CC_SAFE_RELEASE(_moveAction);

CC_SAFE_RELEASE(_hurt);

CC_SAFE_RELEASE(_swim);

voidAnimate3DTest::update(floatdt)

{

if(_state==State::HURT_TO_SWIMMING)

_elapseTransTime+= dt;

if(_elapseTransTime>=Animate3D::getTransitionTime())

_sprite->stopAction(_hurt);

_state=State::SWIMMING;

}

elseif(_state==State::SWIMMING_TO_HURT)

_elapseTransTime+= dt;

_sprite->stopAction(_swim);

_state=State::HURT;

voidAnimate3DTest::addSprite3D()

std::stringfileName ="Sprite3DTest/tortoise.c3b";

autosprite =Sprite3D::create(fileName);

sprite->setScale(0.1f);

autos =Director::getInstance()->getWinSize();

sprite->setPosition(Vec2(s.width*4.f/5.f,s.height/2.f));

_sprite= sprite;

{ //2个动画的时间不同,这些在3Dmax中定义

autoanimate =Animate3D::create(animation,0.f,1.933f);

_swim=RepeatForever::create(animate);

sprite->runAction(_swim);

_swim->retain();

_hurt=Animate3D::create(animation,1.933f,2.8f);

_hurt->retain();

_state=State::SWIMMING;

_moveAction=MoveTo::create(4.f,Vec2(s.width/5.f,s.height/2.f));

_moveAction->retain();

autoseq =Sequence::create(_moveAction,CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack,this)),nullptr);

seq->setTag(100);

sprite->runAction(seq);

//当触摸小乌龟则改变动画

voidAnimate3DTest::reachEndCallBack()

{

_sprite->stopActionByTag(100);

autoinverse = (MoveTo*)_moveAction->reverse();

inverse->retain();

_moveAction->release();

_moveAction= inverse;

autorot =RotateBy::create(1.f,Vec3(0.f,180.f,0.f));

autoseq =Sequence::create(rot,_moveAction,nullptr);

seq->setTag(100);

_sprite->runAction(seq);

}

voidAnimate3DTest::renewCallBack()

//rerun swim action

_sprite->runAction(_swim);

_state=State::HURT_TO_SWIMMING;

_elapseTransTime=0.0f;

voidAnimate3DTest::onTouchesEnded(conststd::vector<Touch*>& touches,51); font-family:Arial; font-size:14px; line-height:26px"> floatlen = (_sprite->getPosition() - location).length();

if(len <40)

{

//hurt the tortoise 在游动状态改变为被抓住的动画

if(_state==State::SWIMMING)

{

_elapseTransTime=0.0f;

_state=State::SWIMMING_TO_HURT;

_sprite->stopAction(_hurt);

_sprite->runAction(_hurt);

autodelay =DelayTime::create(_hurt->getDuration() -Animate3D::getTransitionTime());

autoseq =Sequence::create(delay,CallFunc::create(CC_CALLBACK_0(Animate3DTest::renewCallBack,51); font-family:Arial; font-size:14px; line-height:26px"> seq->setTag(101);

_sprite->runAction(seq);

}

return;

}

7.动态添加武器

AttachmentTest::AttachmentTest()

:_hasWeapon(false)

height/2) );

listener->onTouchesEnded=CC_CALLBACK_2(AttachmentTest::onTouchesEnded,51); font-family:Arial; font-size:14px; line-height:26px"> }

voidAttachmentTest::addNewSpriteWithCoords(Vec2p)

sprite->setScale(5);

y) );

//test attach 亮点在这里,获取某个骨骼,Bip001 R Hand是在3Dmax定义的

autosp =Sprite3D::create("Sprite3DTest/axe.c3b");

sprite->getAttachNode("Bip001 R Hand")->addChild(sp);

autoanimate =Animate3D::create(animation);

_sprite= sprite;

_hasWeapon=true;

voidAttachmentTest::onTouchesEnded(conststd::vector<Touch*>& touches,51); font-family:Arial; font-size:14px; line-height:26px"> {

if(_hasWeapon)

{

_sprite->removeAllAttachNode(); //去掉新骨骼节点

}

else

{

autosp = Sprite3D::create("Sprite3DTest/axe.c3b");

_sprite->getAttachNode("Bip001 R Hand")->addChild(sp);

_hasWeapon = !_hasWeapon;

8.动态修改材质Mesh(这个demo好,美女的模型超赞)

Sprite3DReskinTest::Sprite3DReskinTest()

: _sprite(nullptr)

autos = Director::getInstance()->getWinSize();

addNewSpriteWithCoords( Vec2(s.width/2,s.height/2) );

autolistener = EventListenerTouchAllAtOnce::create();

listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded,this);

_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,51); font-family:Arial; font-size:14px; line-height:26px"> TTFConfig ttfConfig("fonts/arial.ttf",20);

autolabel1 = Label::createWithTTF(ttfConfig,"Hair");

autoitem1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchHair,this) );

autolabel2 = Label::createWithTTF(ttfConfig,"Glasses");

autoitem2 = MenuItemLabel::create(label2,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchGlasses,51); font-family:Arial; font-size:14px; line-height:26px"> autolabel3 = Label::createWithTTF(ttfConfig,"Coat");

autoitem3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchCoat,51); font-family:Arial; font-size:14px; line-height:26px"> autolabel4 = Label::createWithTTF(ttfConfig,"Pants");

autoitem4 = MenuItemLabel::create(label4,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchPants,51); font-family:Arial; font-size:14px; line-height:26px"> autolabel5 = Label::createWithTTF(ttfConfig,"Shoes");

autoitem5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchShoes,51); font-family:Arial; font-size:14px; line-height:26px"> item1->setPosition( Vec2(VisibleRect::left().x+50,VisibleRect::bottom().y+item1->getContentSize().height*4) );

item2->setPosition( Vec2(VisibleRect::left().x+50,VisibleRect::bottom().y+item1->getContentSize().height *5) );

item3->setPosition( Vec2(VisibleRect::left().x+50,VisibleRect::bottom().y+item1->getContentSize().height*6) );

item4->setPosition( Vec2(VisibleRect::left().x+50,VisibleRect::bottom().y+item1->getContentSize().height *7) );

item5->setPosition( Vec2(VisibleRect::left().x+50,VisibleRect::bottom().y+item1->getContentSize().height *8) );

autopMenu1 = CCMenu::create(item1,item2,item3,item4,item5,NULL);

pMenu1->setPosition(Vec2(0,51); font-family:Arial; font-size:14px; line-height:26px"> this->addChild(pMenu1,10);

voidSprite3DReskinTest::menuCallback_switchHair(Ref* sender)

_useHairId++;

if(_useHairId >1)

_useHairId =0;

if(_useHairId >=0 && _sprite)

for(inti =0; i <2; i++ )

{ // 获取材质 可见3.3支持了多套材质

autosubMesh = _sprite->getMeshByName(_girlHair[i]);

if(subMesh)

{

if(i == _useHairId )

subMesh->setVisible(true);

else

subMesh->setVisible(false);

}

voidSprite3DReskinTest::menuCallback_switchGlasses(Ref* sender)

autosubMesh = _sprite->getMeshByName("Girl_Glasses01");

if(subMesh)

if(subMesh->isVisible())

subMesh->setVisible(false);

else

subMesh->setVisible(true);

voidSprite3DReskinTest::menuCallback_switchCoat(Ref* sender)

_useUpBodyId++;

if(_useUpBodyId >1)

_useUpBodyId =0;

if(_useUpBodyId >=0 && _sprite)

autosubMesh = _sprite->getMeshByName(_girlUpperBody[i]);

if(subMesh)

{

if(i == _useUpBodyId )

{

subMesh->setVisible(true);

}

else

subMesh->setVisible(false);

voidSprite3DReskinTest::menuCallback_switchPants(Ref* sender)

_usePantsId++;

if(_usePantsId >1)

_usePantsId =0;

if(_usePantsId >=0 && _sprite)

autosubMesh = _sprite->getMeshByName(_girlPants[i]);

if(i == _usePantsId )

voidSprite3DReskinTest::menuCallback_switchShoes(Ref* sender)

_useShoesId++;

if(_useShoesId >1)

_useShoesId =0;

if(_useShoesId >=0 && _sprite)

for(inti =0; i <2; i++ )

autosubMesh = _sprite->getMeshByName(_girlShoes[i]);

if(subMesh)

if(i == _useShoesId )

{

subMesh->setVisible(true);

}

else

subMesh->setVisible(false);

std::string Sprite3DReskinTest::title()const

return"Testing Sprite3D Reskin";

std::string Sprite3DReskinTest::subtitle()const

return"";

voidSprite3DReskinTest::addNewSpriteWithCoords(Vec2 p)

_girlPants[0]="Girl_LowerBody01";

_girlPants[1]="Girl_LowerBody02";

_girlUpperBody[0] ="Girl_UpperBody01";

_girlUpperBody[1] ="Girl_UpperBody02";

_girlShoes[0] ="Girl_Shoes01";

_girlShoes[1] ="Girl_Shoes02";

_girlHair[0]="Girl_Hair01";

_girlHair[1]="Girl_Hair02";

_usePantsId =0;

_useUpBodyId =0;

_useShoesId =0;

_useHairId =0;

std::string fileName ="Sprite3DTest/ReskinGirl.c3b";

autosprite = Sprite3D::create(fileName);

sprite->setScale(4);

sprite->setRotation3D(Vec3(0,51); font-family:Arial; font-size:14px; line-height:26px"> autogirlPants = sprite->getMeshByName(_girlPants[1]);

if(girlPants)

girlPants->setVisible(false);

autogirlShoes = sprite->getMeshByName(_girlShoes[1]);

if(girlShoes)

girlShoes->setVisible(false);

autogirlHair = sprite->getMeshByName(_girlHair[1]);

if(girlHair)

girlHair->setVisible(false);

autogirlUpBody = sprite->getMeshByName( _girlUpperBody[1]);

if(girlUpBody)

girlUpBody->setVisible(false);

addChild(sprite);

sprite->setPosition( Vec2( p.x,p.y-60) );

autoanimation = Animation3D::create(fileName);

autoanimate = Animate3D::create(animation);

sprite->runAction(RepeatForever::create(animate));

_sprite = sprite;

9.包围盒与3D模型碰撞的实现

AABB碰撞原理参考以下网址

http://cn.cocos2d-x.org/tutorial/show?id=1572

Sprite3DWithOBBPerfromanceTest::Sprite3DWithOBBPerfromanceTest()

listener->onTouchesBegan = CC_CALLBACK_2(Sprite3DWithOBBPerfromanceTest::onTouchesBegan,51); font-family:Arial; font-size:14px; line-height:26px"> listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithOBBPerfromanceTest::onTouchesEnded,51); font-family:Arial; font-size:14px; line-height:26px"> listener->onTouchesMoved = CC_CALLBACK_2(Sprite3DWithOBBPerfromanceTest::onTouchesMoved,51); font-family:Arial; font-size:14px; line-height:26px"> initDrawBox();

addNewSpriteWithCoords(Vec2(s.width/2,s.height/2));

MenuItemFont::setFontName("fonts/arial.ttf");

MenuItemFont::setFontSize(65);

autodecrease = MenuItemFont::create(" - ",CC_CALLBACK_1(Sprite3DWithOBBPerfromanceTest::delOBBCallback,this));

decrease->setColor(Color3B(0,200,20));

autoincrease = MenuItemFont::create(" + ",CC_CALLBACK_1(Sprite3DWithOBBPerfromanceTest::addOBBCallback,51); font-family:Arial; font-size:14px; line-height:26px"> increase->setColor(Color3B(0,20));

automenu = Menu::create(decrease,increase,51); font-family:Arial; font-size:14px; line-height:26px"> menu->alignItemsHorizontally();

menu->setPosition(Vec2(s.width/2,s.height-65));

addChild(menu,1);

TTFConfig ttfCount("fonts/Marker Felt.ttf",30);

_labelCubeCount = Label::createWithTTF(ttfCount,"0 cubes");

_labelCubeCount->setColor(Color3B(0,51); font-family:Arial; font-size:14px; line-height:26px"> _labelCubeCount->setPosition(Vec2(s.width/2,s.height-90));

addChild(_labelCubeCount);

_hasCollider =false;

addOBBCallback(nullptr);

scheduleUpdate();

std::string Sprite3DWithOBBPerfromanceTest::title()const

return"OBB Collison Perfromance Test";

std::string Sprite3DWithOBBPerfromanceTest::subtitle()const

voidSprite3DWithOBBPerfromanceTest::addNewOBBWithCoords(Vec2 p)

Vec3 extents = Vec3(10,10,10);

AABB aabb(-extents,extents);

autoobb = OBB(aabb);

obb._center = Vec3(p.x,p.y,0);

_obb.push_back(obb);

voidSprite3DWithOBBPerfromanceTest::onTouchesBegan(conststd::vector<Touch*>& touches,Event* event)

autolocation = touch->getLocationInView();

if(_obb.size() >0)

_intersetList.clear();

Ray ray;

calculateRayByLocationInView(&ray,location);

for(inti =0; i < _obb.size(); i++)

if(ray.intersects(_obb[i]))

_intersetList.insert(i);

return;

voidSprite3DWithOBBPerfromanceTest::onTouchesEnded(conststd::vector<Touch*>& touches,51); font-family:Arial; font-size:14px; line-height:26px"> voidSprite3DWithOBBPerfromanceTest::onTouchesMoved(conststd::vector<Touch*>& touches,51); font-family:Arial; font-size:14px; line-height:26px"> autolocation = touch->getLocation();

for(inti =0; i < _obb.size(); i++)

if(_intersetList.find(i) != _intersetList.end())

_obb[i]._center = Vec3(location.x,location.y,51); font-family:Arial; font-size:14px; line-height:26px"> voidSprite3DWithOBBPerfromanceTest::update(floatdt)

charszText[16];

sprintf(szText,"%lu cubes",_obb.size());

_labelCubeCount->setString(szText);

if(_drawDebug)

_drawDebug->clear();

Mat4 mat = _sprite->getNodeToWorldTransform();

mat.getRightVector(&_obbt._xAxis);

_obbt._xAxis.normalize();

mat.getUpVector(&_obbt._yAxis);

_obbt._yAxis.normalize();

mat.getForwardVector(&_obbt._zAxis);

_obbt._zAxis.normalize();

_obbt._center = _sprite->getPosition3D();

Vec3 corners[8] = {};

_obbt.getCorners(corners);

_drawDebug->drawCube(corners,Color4F(0,1));

if(_obb.size() >0)

_drawOBB->clear();

Vec3 corners[8] = {};

_obb[i].getCorners(corners);

_drawOBB->drawCube(corners,_obbt.intersects(_obb[i])?Color4F(1,1):Color4F(0,51); font-family:Arial; font-size:14px; line-height:26px"> voidSprite3DWithOBBPerfromanceTest::initDrawBox()

_drawOBB = DrawNode3D::create();

addChild(_drawOBB);

voidSprite3DWithOBBPerfromanceTest::addNewSpriteWithCoords(Vec2 p)

std::string fileName ="Sprite3DTest/tortoise.c3b";

sprite->setScale(0.1f);

sprite->setPosition(Vec2(s.width *4.f/5.f,s.height /2.f));

autoanimate = Animate3D::create(animation,1.933f);

_moveAction = MoveTo::create(4.f,Vec2(s.width /5.f,51); font-family:Arial; font-size:14px; line-height:26px"> _moveAction->retain();

autoseq = Sequence::create(_moveAction,CallFunc::create(CC_CALLBACK_0(Sprite3DWithOBBPerfromanceTest::reachEndCallBack,51); font-family:Arial; font-size:14px; line-height:26px"> seq->setTag(100);

sprite->runAction(seq);

AABB aabb = _sprite->getAABB();

_obbt = OBB(aabb);

_drawDebug = DrawNode3D::create();

addChild(_drawDebug);

voidSprite3DWithOBBPerfromanceTest::reachEndCallBack()

_sprite->stopActionByTag(100);

autoinverse = (MoveTo*)_moveAction->reverse();

inverse->retain();

_moveAction->release();

_moveAction = inverse;

autorot = RotateBy::create(1.0f,Vec3(0.f,0.f));

autoseq = Sequence::create(rot,_moveAction,51); font-family:Arial; font-size:14px; line-height:26px"> _sprite->runAction(seq);

voidSprite3DWithOBBPerfromanceTest::addOBBCallback(Ref* sender)

addOBBWithCount(10);

voidSprite3DWithOBBPerfromanceTest::addOBBWithCount(floatvalue)

for(inti =0; i < value; i++)

Vec2 randompos = Vec2(CCRANDOM_0_1() * Director::getInstance()->getWinSize().width,CCRANDOM_0_1() * Director::getInstance()->getWinSize().height);

Vec3 extents = Vec3(10,51); font-family:Arial; font-size:14px; line-height:26px"> AABB aabb(-extents,51); font-family:Arial; font-size:14px; line-height:26px"> autoobb = OBB(aabb);

obb._center = Vec3(randompos.x,randompos.y,51); font-family:Arial; font-size:14px; line-height:26px"> _obb.push_back(obb);

voidSprite3DWithOBBPerfromanceTest::delOBBCallback(Ref* sender)

delOBBWithCount(10);

voidSprite3DWithOBBPerfromanceTest::delOBBWithCount(floatvalue)

if(_obb.size() >=10)

_obb.erase(_obb.begin(),_obb.begin() + value);

return;

voidSprite3DWithOBBPerfromanceTest::unproject(constMat4& viewProjection,constSize* viewport,Vec3* src,Vec3* dst)

assert(dst);

assert(viewport->width !=0.0f&& viewport->height !=0.0f);

Vec4 screen(src->x / viewport->width,((viewport->height - src->y)) / viewport->height,src->z,1.0f);

screen.x = screen.x *2.0f-1.0f;

screen.y = screen.y *2.0f-1.0f;

screen.z = screen.z *2.0f-1.0f;

viewProjection.getInversed().transformVector(screen,&screen);

if(screen.w !=0.0f)

screen.x /= screen.w;

screen.y /= screen.w;

screen.z /= screen.w;

dst->set(screen.x,screen.y,screen.z);

voidSprite3DWithOBBPerfromanceTest::calculateRayByLocationInView(Ray* ray,constVec2& location)

autodir = Director::getInstance();

autoview = dir->getWinSize();

Mat4 mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);

Vec3 src = Vec3(location.x,51); font-family:Arial; font-size:14px; line-height:26px"> Vec3 nearPoint;

unproject(mat,&view,&src,&nearPoint);

src = Vec3(location.x,1);

Vec3 farPoint;

Vec3 direction;

Vec3::subtract(farPoint,nearPoint,&direction);

direction.normalize();

ray->_origin = nearPoint;

ray->_direction = direction;

10.3D模型的镜像

Sprite3DMirrorTest::Sprite3DMirrorTest()

,_mirrorSprite(nullptr)

2) );

std::string Sprite3DMirrorTest::title()const

return"Sprite3D Mirror Test";

std::string Sprite3DMirrorTest::subtitle()const

voidSprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p)

std::string fileName ="Sprite3DTest/orc.c3b";

sprite->setScale(5);

sprite->setPosition( Vec2( p.x -80,p.y) );

//test attach

autosp = Sprite3D::create("Sprite3DTest/axe.c3b");

sprite->getAttachNode("Bip001 R Hand")->addChild(sp);

_hasWeapon =true;

//create mirror Sprite3D 镜像

sprite = Sprite3D::create(fileName);

sprite->setScale(5);

sprite->setScaleX(-5);

sprite->setCullFace(GL_FRONT);

sprite->setRotation3D(Vec3(0,51); font-family:Arial; font-size:14px; line-height:26px"> addChild(sprite);

sprite->setPosition( Vec2( p.x +80,p.y) );

sp = Sprite3D::create("Sprite3DTest/axe.c3b");

animation = Animation3D::create(fileName);

_mirrorSprite = sprite;

}

猜你在找的Cocos2d-x相关文章