狠狠撸

狠狠撸Share a Scribd company logo
Sprite3D Tips
@第5回cocos2d-x勉強会
株式会社アカツキ 河野 洋志
自己紹介
? 河野 洋志(こうの ひろし)
? 株式会社アカツキ エンジニア
? サウザンドメモリーズを担当
? 主にサーバサイド
? Ruby on Rails, MySQL, Redis, AWS, etc…
? cocos2d-x…? C++…?
残念ながら…
? サウザンドメモリーズはcocos2d-x製ではありま
せん
? 弊社ではcocos2d-xを利用した別のプロジェクト
が進行中です!
!?
? ということで…
? 本来開発?運用で得られた知見をお話できれば
ベストだったのですが知見ゼロ
? cocos2d-x界隈で最近おもしろそうなものないか
なーということで ver 3.1 で新しく追加された
Sprite3Dについて簡単にご紹介したいと思います
目次
? cocos2d-x Ver 3.1で追加されたSprite3Dクラス
の紹介
? Sprite3Dの使い方
? シェーダー拡張
? Sprite3Dで(まだ?)できないこと
目次
? cocos2d-x Ver 3.1で追加されたSprite3Dクラス
の紹介
? Sprite3Dの使い方
? シェーダー拡張
? Sprite3Dで(まだ?)できないこと
Sprite3Dとは
? 3Dモデルをスプライトとして扱うことができる
クラス
? 対応フォーマットは .obj
? 呼び出し時にテクスチャ画像をsetする
auto model3d = Sprite3D::create("sample.obj");!
model3d->setTexture(“sample.png”);
API
? 3D APIはもちろん、これまでの2Dスプライトで
使えたAPIはほとんど使える
? Sprite3DクラスはSpriteクラス同様Nodeクラス
を継承しているため
? 移動、拡縮、その他アクションなど
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
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);
移動?拡縮
? 移動
!
!
? 拡縮
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);!
}!
}
回転
? 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);!
}!
}
回転(余談)
!
? 上記メソッドを使うとペラペラになって面白い
RotateBy::create(float duration, float deltaAngleZ_X, float deltaAngleZ_Y);
目次
? cocos2d-x Ver 3.1で追加されたSprite3Dクラス
の紹介
? Sprite3Dの使い方
? シェーダー拡張
? Sprite3Dで(まだ?)できないこと
シェーダー拡張
? シェーダーを拡張することでトゥーンレンダリン
グ(っぽいこと)などができるようになる
シェーダ拡張
? cpp-testの中に含まれるEffect3DOutlineクラスにつ
いて解説していきます
? cocos2d-x/tests/cpp-tests/Classes/Sprite3DTest
? 3Dプログラミングについては詳しくないので詳しい
ところまでソースは追いません…(追えませんでした)
? 間違いがあれば是非指摘してください
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() メソッド
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()の実装
もこのクラスにあります
シェーダ
? 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;!
}
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;!
};!
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);
目次
? cocos2d-x Ver 3.1で追加されたSprite3Dクラス
の紹介
? Sprite3Dの使い方
? シェーダー拡張
? 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
おや、肠辞肠辞蝉2诲-虫のようすが…
期待ag…と思ったらマージされてた
https://github.com/cocos2d/cocos2d-x/pull/7085
こいつ…动くぞ!
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));!
}
まとめ
? Sprite3Dについて簡単に紹介しました
? Position, Rotate, Action, etc…
? つい先日アニメーションもマージされたので、
今後に期待
? でもここまでやるならUni(ry
参考
? cocos2d-x公式のサンプルプロジェクト
? https://github.com/cocos2d/cocos2d-x/tree/
v3/tests/cpp-tests/Classes/Sprite3DTest
? EarthWarrior3D
? https://github.com/chukong/EarthWarrior3D
ご清聴ありがとうございました

More Related Content

Cocos2d x-sprite3d