主要有以下功能:
1. 基本的Sprite3D使用,加载静态模型和动态模型,看 Sprite3DBasicTest
2.Sprite3D对象的旋转,缩放等Action操作
3.Sprite3D中使用Shader特效,实现outLine
4.Animate3D来创建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");
@H_502_82@ //option 2: load obj and assign the texture 第二种方法是在模型文件中不包含纹理
@H_502_82@ auto@H_502_82@sprite =Sprite3D@H_502_82@::create@H_502_82@("Sprite3DTest/boss1.obj"@H_502_82@);
sprite->setScale(3.f);
@H_502_82@ sprite->setTexture@H_502_82@("Sprite3DTest/boss.png"@H_502_82@);
//在Sprite3D中包含了一些基本的Shader特效,下面是让3D模型实现outline
@H_502_82@ //sprite->setEffect(cocos2d::EFFECT_OUTLINE);
@H_502_82@ //add to scene
addChild( sprite );
sprite->setPosition(Vec2( p.x,p.y) );
@H_502_82@ ActionInterval@H_502_82@* 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模型
@H_502_82@ addNewSpriteWithCoords@H_502_82@( location );
}
}
2.透过触摸屏幕拖动模型移动
Sprite3DHitTest::Sprite3DHitTest()
{
@H_502_82@ auto@H_502_82@s =Director@H_502_82@::getInstance@H_502_82@()->getWinSize@H_502_82@();
@H_502_82@ auto@H_502_82@sprite1 =Sprite3D@H_502_82@::create@H_502_82@("Sprite3DTest/boss1.obj"@H_502_82@);
sprite1->setScale(4.f);
@H_502_82@ sprite1->setTexture@H_502_82@("Sprite3DTest/boss.png"@H_502_82@);
sprite1->setPosition(Vec2(s.width/2,s.height/2) );
addChild( sprite1 );
sprite1->runAction(RepeatForever::create(RotateBy::create(3,360)));
@H_502_82@ auto@H_502_82@sprite2 =Sprite3D@H_502_82@::create@H_502_82@("Sprite3DTest/boss1.obj"@H_502_82@);
sprite2->setScale(4.f);
@H_502_82@ sprite2->setTexture@H_502_82@("Sprite3DTest/boss.png"@H_502_82@);
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)));
@H_502_82@ // Make sprite1 touchable
@H_502_82@ auto@H_502_82@listener1 =EventListenerTouchOneByOne@H_502_82@::create@H_502_82@();
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;
}
@H_502_82@ return@H_502_82@false@H_502_82@;
};
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());
@H_502_82@ log@H_502_82@("sprite3d onTouchesEnded.. "@H_502_82@);
target->setOpacity(255);
};
@H_502_82@ _eventDispatcher@H_502_82@->addEventListenerWithSceneGraPHPriority@H_502_82@(listener1,sprite1);
@H_502_82@ _eventDispatcher@H_502_82@->addEventListenerWithSceneGraPHPriority@H_502_82@(listener1->clone@H_502_82@(),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)
{
@H_502_82@ program =GLProgram@H_502_82@::createWithFilenames@H_502_82@(_vertSkinnedShaderFile@H_502_82@,_fragSkinnedShaderFile@H_502_82@);
GLProgramCache::getInstance()->addGLProgram(program,_keySkinnedInGLProgramCache);
}
returnprogram;
autoprogram =GLProgramCache::getInstance()->getGLProgram(_keyInGLProgramCache);
@H_502_82@ program =GLProgram@H_502_82@::createWithFilenames@H_502_82@(_vertShaderFile@H_502_82@,_fragShaderFile@H_502_82@);
_keyInGLProgramCache);
}
Effect3DOutline@H_502_82@*Effect3DOutline@H_502_82@::create()
{
@H_502_82@ Effect3DOutline@H_502_82@* effect =new@H_502_82@(std@H_502_82@::nothrow@H_502_82@)Effect3DOutline@H_502_82@();
if(effect && effect->init())
effect->autorelease();
returneffect;
CC_SAFE_DELETE(effect);
@H_502_82@ return@H_502_82@nullptr@H_502_82@;
bool@H_502_82@Effect3DOutline@H_502_82@::init()
{
@H_502_82@ return@H_502_82@true@H_502_82@;
Effect3DOutline::Effect3DOutline()
@H_502_82@:_outlineWidth@H_502_82@(1.0f@H_502_82@)
@H_502_82@,_outlineColor@H_502_82@(1@H_502_82@,1@H_502_82@,1@H_502_82@)
502_82@(nullptr@H_502_82@)
{
#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;
@H_502_82@ if@H_502_82@(_glProgramState@H_502_82@)
@H_502_82@ _glProgramState@H_502_82@->setUniformVec3@H_502_82@("OutLineColor"@H_502_82@,_outlineColor@H_502_82@);
voidEffect3DOutline::setOutlineWidth(floatwidth)
if(_outlineWidth!= width)
_outlineWidth= width;
@H_502_82@ _glProgramState@H_502_82@->setUniformFloat@H_502_82@("OutlineWidth"@H_502_82@,_outlineWidth@H_502_82@);
void@H_502_82@Effect3DOutline@H_502_82@::setTarget(EffectSprite3D@H_502_82@*sprite)
{
@H_502_82@ CCASSERT@H_502_82@(nullptr@H_502_82@!= sprite &&nullptr@H_502_82@!= sprite->getMesh@H_502_82@(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D"@H_502_82@);
if(sprite !=_sprite)
GLProgram* glprogram;
if(!sprite->getMesh()->getSkin())
glprogram =GLProgram::createWithFilenames(_vertShaderFile,_fragShaderFile);
else
@H_502_82@ glprogram =GLProgram@H_502_82@::createWithFilenames@H_502_82@(_vertSkinnedShaderFile@H_502_82@,_fragSkinnedShaderFile@H_502_82@);
_glProgramState=GLProgramState::create(glprogram);
@H_502_82@ _glProgramState@H_502_82@->retain@H_502_82@();
@H_502_82@ _glProgramState@H_502_82@->setUniformVec3@H_502_82@("OutLineColor"@H_502_82@,_outlineColor@H_502_82@);
@H_502_82@ _glProgramState@H_502_82@->setUniformFloat@H_502_82@("OutlineWidth"@H_502_82@,_outlineWidth@H_502_82@);
_sprite= sprite;
automesh = sprite->getMesh();
longoffset =0;
for(autoi =0; i < mesh->getMeshVertexAttribCount(); i++)
{
automeshvertexattrib = mesh->getMeshVertexAttribute(i);
@H_502_82@ _glProgramState@H_502_82@->setVertexAttribPointer@H_502_82@(s_attributeNames@H_502_82@[meshvertexattrib.vertexAttrib@H_502_82@],
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)
{
@H_502_82@ //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())
{
@H_502_82@ glEnable@H_502_82@(GL_CULL_FACE@H_502_82@);
glCullFace(GL_FRONT);
@H_502_82@ glEnable@H_502_82@(GL_DEPTH_TEST@H_502_82@);
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);
@H_502_82@ glBindBuffer@H_502_82@(GL_ELEMENT_ARRAY_BUFFER@H_502_82@,mesh->getIndexBuffer@H_502_82@());
@H_502_82@ glDrawElements@H_502_82@(mesh->getPrimitiveType@H_502_82@(),mesh->getIndexCount@H_502_82@(),mesh->getIndexFormat@H_502_82@(),0@H_502_82@);
@H_502_82@ CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES@H_502_82@(1@H_502_82@,mesh->getIndexCount@H_502_82@());
@H_502_82@ glBindBuffer@H_502_82@(GL_ARRAY_BUFFER@H_502_82@,51); font-family:Arial; font-size:14px; line-height:26px"> @H_502_82@ glDisable@H_502_82@(GL_DEPTH_TEST@H_502_82@);
glCullFace(GL_BACK);
@H_502_82@ glDisable@H_502_82@(GL_CULL_FACE@H_502_82@);
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);
@H_502_82@ if@H_502_82@(!_defaultEffect@H_502_82@)
Sprite3D::draw(renderer,transform,flags);
{
@H_502_82@ _command@H_502_82@.init@H_502_82@(_globalZOrder@H_502_82@);
_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()
@H_502_82@ auto@H_502_82@s =Director@H_502_82@::getInstance@H_502_82@()->getWinSize@H_502_82@();
@H_502_82@ addNewSpriteWithCoords@H_502_82@(Vec2@H_502_82@(s.width@H_502_82@/2@H_502_82@,s.height@H_502_82@/2@H_502_82@) );
@H_502_82@ auto@H_502_82@listener =EventListenerTouchAllAtOnce@H_502_82@::create@H_502_82@();
listener->onTouchesEnded=CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded,this);
@H_502_82@ _eventDispatcher@H_502_82@->addEventListenerWithSceneGraPHPriority@H_502_82@(listener,this@H_502_82@);
voidSprite3DEffectTest::addNewSpriteWithCoords(Vec2p)
@H_502_82@ //option 2: load obj and assign the texture
@H_502_82@ auto@H_502_82@sprite =EffectSprite3D@H_502_82@::createFromObjFileAndTexture@H_502_82@("Sprite3DTest/boss1.obj"@H_502_82@,"Sprite3DTest/boss.png"@H_502_82@);
@H_502_82@ Effect3DOutline@H_502_82@* effect =Effect3DOutline@H_502_82@::create@H_502_82@();
sprite->addEffect(effect,-1);
effect->setOutlineColor(Vec3(1,0));
effect->setOutlineWidth(0.01f);
@H_502_82@ Effect3DOutline@H_502_82@* effect2 =Effect3DOutline@H_502_82@::create@H_502_82@();
sprite->addEffect(effect2,-2);
effect2->setOutlineWidth(0.02f);
effect2->setOutlineColor(Vec3(1,1,0));
@H_502_82@ //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_365_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)
@H_502_82@ std@H_502_82@::string@H_502_82@fileName ="Sprite3DTest/orc.c3b"@H_502_82@;
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));
void@H_502_82@Sprite3DWithSkinOutlineTest@H_502_82@::addNewSpriteWithCoords(Vec2@H_502_82@p)
@H_502_82@ std@H_502_82@::string@H_502_82@fileName ="Sprite3DTest/orc.c3b"@H_502_82@;
autosprite =EffectSprite3D::create(fileName);
@H_502_82@ Effect3DOutline@H_502_82@* effect =Effect3DOutline@H_502_82@::create@H_502_82@();
effect->setOutlineColor(Vec3(1,51); font-family:Arial; font-size:14px; line-height:26px"> effect->setOutlineWidth(0.01f);
sprite->addEffect(effect,-1);
@H_502_82@ Effect3DOutline@H_502_82@* effect2 =Effect3DOutline@H_502_82@::create@H_502_82@();
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 =
原文链接:https://www.f2er.com/cocos2dx/341137.html