Cocos2d x-sprite3d

31
Sprite3D Tips @5cocos2d-x勉強会 株式会社アカツキ 河野 洋志

Transcript of Cocos2d x-sprite3d

Page 1: Cocos2d x-sprite3d

Sprite3D Tips@第5回cocos2d-x勉強会 株式会社アカツキ 河野 洋志

Page 2: Cocos2d x-sprite3d

自己紹介• 河野 洋志(こうの ひろし)

• 株式会社アカツキ エンジニア

• サウザンドメモリーズを担当

• 主にサーバサイド

• Ruby on Rails, MySQL, Redis, AWS, etc…

• cocos2d-x…? C++…?

Page 3: Cocos2d x-sprite3d

残念ながら…

• サウザンドメモリーズはcocos2d-x製ではありません

• 弊社ではcocos2d-xを利用した別のプロジェクトが進行中です!

Page 4: Cocos2d x-sprite3d

!?

Page 5: Cocos2d x-sprite3d

• ということで…

• 本来開発・運用で得られた知見をお話できればベストだったのですが知見ゼロ

• cocos2d-x界隈で最近おもしろそうなものないかなーということで ver 3.1 で新しく追加されたSprite3Dについて簡単にご紹介したいと思います

Page 6: Cocos2d x-sprite3d

目次• cocos2d-x Ver 3.1で追加されたSprite3Dクラスの紹介

• Sprite3Dの使い方

• シェーダー拡張

• Sprite3Dで(まだ?)できないこと

Page 7: Cocos2d x-sprite3d

目次• cocos2d-x Ver 3.1で追加されたSprite3Dクラスの紹介

• Sprite3Dの使い方

• シェーダー拡張

• Sprite3Dで(まだ?)できないこと

Page 8: Cocos2d x-sprite3d

Sprite3Dとは

• 3Dモデルをスプライトとして扱うことができるクラス

• 対応フォーマットは .obj

• 呼び出し時にテクスチャ画像をsetするauto model3d = Sprite3D::create("sample.obj");!model3d->setTexture(“sample.png”);

Page 9: Cocos2d x-sprite3d

API

• 3D APIはもちろん、これまでの2Dスプライトで使えたAPIはほとんど使える

• Sprite3DクラスはSpriteクラス同様Nodeクラスを継承しているため

• 移動、拡縮、その他アクションなど

Page 10: Cocos2d x-sprite3d

Position3D• z軸は手前が正、奥が負

• パースがかかっているので、設定したx, yよりも手前側は画面縁に、奥側は画面中央寄りに配置される

auto model_a = Sprite3D::create("sample.obj");!model_a->setTexture("sample.png");!model_a->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height * 2 / 3, 400));!this->addChild(model_a);!!auto model_b = Sprite3D::create("samle.obj");!model3_b->setTexture("samle.png");!model3_b->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height / 2, 0));!this->addChild(model_b);!!auto model_c = Sprite3D::create("samle.obj");!model3_c->setTexture("samle.png");!model3_c->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height * 1 / 3, -400));!this->addChild(model_c);

model_a

model_b

model_c

Page 11: Cocos2d x-sprite3d

Rotation3D• Vec3を渡して3次元的なrotationを設定できる

auto model_a = Sprite3D::create("sample.obj");!model_a->setTexture("sample.png");!model_a->setRotation3D(Vec3(90.0f, 0.0f, 0.0f));!model_a->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height * 2 / 3, 0));!model_a->setScale(15);!this->addChild(model_a);!!auto model_b = Sprite3D::create("sample.obj");!model_b->setTexture("sample.png");!model_b->setRotation3D(Vec3(0.0f, 90.0f, 0.0f));!model_b->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height / 2, 0));!model_b->setScale(15);!this->addChild(model_b);!!auto model_c = Sprite3D::create("sample.obj");!model_c->setTexture("sample.png");!model_c->setRotation3D(Vec3(0.0f, 0.0f, 90.0f));!model_c->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height / 3, 0));!model_c->setScale(15);!this->addChild(model_c);

Page 12: Cocos2d x-sprite3d

移動・拡縮• 移動

!

!

• 拡縮

void HelloWorld::onTouchesEnded(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event)!{! for (auto touch: touches) {! auto location = touch->getLocation();! auto action = MoveTo::create(0.5f, location);! model3d->runAction(action);! }!}

void HelloWorld::onTouchesEnded(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event)!{! for (auto touch: touches) {! auto location = touch->getLocation();! auto seq = Sequence::create(ScaleTo::create(0.1f, 75.f),! ScaleTo::create(0.1f, 30.f),! ScaleTo::create(0.1f, 45.f), NULL);! model3d->runAction(seq);! }!}

Page 13: Cocos2d x-sprite3d

回転• z軸方向にしか回転してくれない

!

!

• Vec3クラスを渡すと3次元的に回転できる

void HelloWorld::onTouchesEnded(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event)!{! for (auto touch: touches) {! auto location = touch->getLocation();! auto action = RotateBy::create(0.5f, 360);! model3d->runAction(action);! }!}

void HelloWorld::onTouchesEnded(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event)!{! for (auto touch: touches) {! auto location = touch->getLocation();! auto action = RotateBy::create(0.5f, Vec3(location.x, location.y, 30));! model3d->runAction(action);! }!}

Page 14: Cocos2d x-sprite3d

回転(余談)!

• 上記メソッドを使うとペラペラになって面白い

RotateBy::create(float duration, float deltaAngleZ_X, float deltaAngleZ_Y);

Page 15: Cocos2d x-sprite3d

目次• cocos2d-x Ver 3.1で追加されたSprite3Dクラスの紹介

• Sprite3Dの使い方

• シェーダー拡張

• Sprite3Dで(まだ?)できないこと

Page 16: Cocos2d x-sprite3d

シェーダー拡張• シェーダーを拡張することでトゥーンレンダリング(っぽいこと)などができるようになる

Page 17: Cocos2d x-sprite3d

シェーダ拡張• cpp-testの中に含まれるEffect3DOutlineクラスについて解説していきます

• cocos2d-x/tests/cpp-tests/Classes/Sprite3DTest

• 3Dプログラミングについては詳しくないので詳しいところまでソースは追いません…(追えませんでした)

• 間違いがあれば是非指摘してください

Page 18: Cocos2d x-sprite3d

3DEffectクラス• 3Dエフェクトに関する抽象クラス

class Effect3D : public Ref!{!public:! virtual void drawWithSprite(EffectSprite3D* sprite, const Mat4 &transform) = 0;!protected:! Effect3D() : _glProgramState(nullptr) {}! virtual ~Effect3D()! {! CC_SAFE_RELEASE(_glProgramState);! }!protected:! GLProgramState* _glProgramState;!};!

• OpenGLシェーダを格納する _glProgramState プロパティを持つ

• シェーダを描画する drawWithSprite() メソッド

Page 19: Cocos2d x-sprite3d

3DEffectOutlineクラス• シェーダーを読み込んで描画を実行するクラス

class Effect3DOutline: public Effect3D!{!public:! static Effect3DOutline* create();! ! void setOutlineColor(const Vec3& color);! ! void setOutlineWidth(float width);! ! void drawWithSprite(EffectSprite3D* sprite, const Mat4 &transform);! !protected:! ! Effect3DOutline();! virtual ~Effect3DOutline();! ! bool init();! ! Vec3 _outlineColor;! float _outlineWidth;!public:! static const std::string _vertShaderFile;! static const std::string _fragShaderFile;! static const std::string _keyInGLProgramCache;! static GLProgram* getOrCreateProgram();! !};!

• 初期化時にシェーダーを読み込む

• drawWithSprite()の実装もこのクラスにあります

Page 20: Cocos2d x-sprite3d

シェーダ• Resources/Shaders3D 以下に配置

• OutLine.frag

• OutLine.vert

uniform vec3 OutLineColor;!uniform vec4 u_color;!!void main(void)!{! gl_FragColor = vec4(OutLineColor,1.0) * u_color;!}

attribute vec4 a_position;!attribute vec3 a_normal;!uniform float OutlineWidth;!!void main(void)!{! vec4 pos = CC_MVPMatrix * a_position;! vec4 normalproj = CC_MVPMatrix * vec4(a_normal, 0);! normalproj = normalize(normalproj);! pos.xy += normalproj.xy * (OutlineWidth * (pos.z * 0.5 + 0.5));! ! gl_Position = pos;!}

Page 21: Cocos2d x-sprite3d

EffectSprite3Dクラス• Sprite3Dクラスを継承して3DEffectを追加できるように拡張

class EffectSprite3D : public Sprite3D!{!public:! static EffectSprite3D* createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath);! void setEffect3D(Effect3D* effect);! void addEffect(Effect3D* effect, ssize_t order);! void eraseEffect(Effect3D* effect);! ssize_t getEffectCount() const;! Effect3D* getEffect(ssize_t index) const;! virtual void draw(Renderer *renderer, const Mat4 &transform, bool transformUpdated) override;!protected:! EffectSprite3D();! virtual ~EffectSprite3D();! ! std::vector<std::tuple<ssize_t,Effect3D*,CustomCommand>> _effects;! Effect3D* _defaultEffect;! CustomCommand _command;!};!

Page 22: Cocos2d x-sprite3d

EffectSprite3Dクラス• 使い方

auto model = EffectSprite3D::createFromObjFileAndTexture("sample.obj", "sample.png");!model->setScale(45);!model->setRotation3D(Vec3(265.0f, 265.0f, 265.0f));!model->setPosition3D(Vec3(visibleSize.width / 2, visibleSize.height / 2, 0));!!auto effect = Effect3DOutline::create();!effect->setOutlineColor(Vec3(1,1,0));!effect->setOutlineWidth(0.03f);!model->addEffect(effect, 1);! !this->addChild(model);

Page 23: Cocos2d x-sprite3d

目次• cocos2d-x Ver 3.1で追加されたSprite3Dクラスの紹介

• Sprite3Dの使い方

• シェーダー拡張

• Sprite3Dで(まだ?)できないこと

Page 24: Cocos2d x-sprite3d

できないこと• タップイベントの取得

• getBoundBox()でRectが取得できない

• 物理演算

• アニメーション

• モデルの表示、アクション以上のことはできない

auto position = model3d->getPosition3D();!CCLOG("position: X:%f Y:%f Z:%f", position.x, position.y, position.z);!auto rect = model3d->getBoundingBox();!CCLOG("bounding box: MinX:%f MaxX:%f MinY:%f MaxY:%f", rect.getMinX(), rect.getMaxX(), rect.getMinY(), rect.getMaxY());!!// cocos2d: position: X:320.000000 Y:480.000000 Z:0.000000!// cocos2d: bounding box: MinX:320.000000 MaxX:320.000000 MinY:480.000000 MaxY:480.000000

Page 25: Cocos2d x-sprite3d

おや、cocos2d-xのようすが…

Page 26: Cocos2d x-sprite3d

期待ag…と思ったらマージされてたhttps://github.com/cocos2d/cocos2d-x/pull/7085

Page 27: Cocos2d x-sprite3d

こいつ…動くぞ!

Page 28: Cocos2d x-sprite3d

Animation3D• Animate3DクラスはActionとして実装されている

• Animation3DからAction(Animate3D)をcreateする

• .c3t フォーマットに対応

auto animation = Animation3D::getOrCreate("Sprite3DTest/girl.c3t");!if (animation)!{! auto animate = Animate3D::create(animation); ! auto spawn = Spawn::create(animate, RotateBy::create(animation->getDuration(), Vec3(0.0f, 90.0f, 0.0f)), NULL);! sprite->runAction(RepeatForever::create(spawn));!}

Page 29: Cocos2d x-sprite3d

まとめ• Sprite3Dについて簡単に紹介しました

• Position, Rotate, Action, etc…

• つい先日アニメーションもマージされたので、今後に期待

• でもここまでやるならUni(ry

Page 30: Cocos2d x-sprite3d

参考

• cocos2d-x公式のサンプルプロジェクト

• https://github.com/cocos2d/cocos2d-x/tree/v3/tests/cpp-tests/Classes/Sprite3DTest

• EarthWarrior3D

• https://github.com/chukong/EarthWarrior3D

Page 31: Cocos2d x-sprite3d

ご清聴ありがとうございました