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

前端之家收集整理的这篇文章主要介绍了Cocos2d-x 的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下使用@H_840_2404@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 =

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