Merge pull request #11159 from super626/v3

node animation support
This commit is contained in:
minggo 2015-03-30 09:32:36 +08:00
commit 30db8ab7fa
12 changed files with 13884 additions and 36 deletions

View File

@ -29,9 +29,9 @@
NS_CC_BEGIN
std::unordered_map<Sprite3D*, Animate3D*> Animate3D::s_fadeInAnimates;
std::unordered_map<Sprite3D*, Animate3D*> Animate3D::s_fadeOutAnimates;
std::unordered_map<Sprite3D*, Animate3D*> Animate3D::s_runningAnimates;
std::unordered_map<Node*, Animate3D*> Animate3D::s_fadeInAnimates;
std::unordered_map<Node*, Animate3D*> Animate3D::s_fadeOutAnimates;
std::unordered_map<Node*, Animate3D*> Animate3D::s_runningAnimates;
float Animate3D::_transTime = 0.1f;
//create Animate3D using Animation.
@ -120,26 +120,98 @@ Animate3D* Animate3D::reverse() const
return animate;
}
Node* findChildByNameRecursively(Node* node, const std::string &childName)
{
const std::string& name = node->getName();
if (name == childName)
return node;
const Vector<Node*>& children = node->getChildren();
for (const auto& child : children)
{
Node* findNode = findChildByNameRecursively(child, childName);
if (findNode)
return findNode;
}
return nullptr;
}
//! called before the action start. It will also set the target.
void Animate3D::startWithTarget(Node *target)
{
Sprite3D* sprite = dynamic_cast<Sprite3D*>(target);
CCASSERT(sprite && sprite->getSkeleton() && _animation, "Animate3D apply to Sprite3D only");
ActionInterval::startWithTarget(target);
_boneCurves.clear();
auto skin = sprite->getSkeleton();
_nodeCurves.clear();
bool hasCurve = false;
for (int i = 0; i < skin->getBoneCount(); i++) {
auto bone = skin->getBoneByIndex(static_cast<unsigned int>(i));
auto curve = _animation->getBoneCurveByName(bone->getName());
if (curve)
Sprite3D* sprite = dynamic_cast<Sprite3D*>(target);
if(sprite)
{
if (_animation)
{
const std::unordered_map<std::string, Animation3D::Curve*>& boneCurves = _animation->getBoneCurves();
for (const auto& iter: boneCurves)
{
const std::string& boneName = iter.first;
auto skin = sprite->getSkeleton();
if(skin)
{
auto bone = skin->getBoneByName(boneName);
if (bone)
{
auto curve = _animation->getBoneCurveByName(boneName);
_boneCurves[bone] = curve;
hasCurve = true;
}
else
{
Node* node = nullptr;
if (target->getName() == boneName)
node = target;
else
node = findChildByNameRecursively(target, boneName);
if (node)
{
auto curve = _animation->getBoneCurveByName(boneName);
if (curve)
{
_nodeCurves[node] = curve;
hasCurve = true;
}
}
}
}
}
}
}
else
{
const std::unordered_map<std::string, Animation3D::Curve*>& boneCurves = _animation->getBoneCurves();
for (const auto& iter: boneCurves)
{
const std::string& boneName = iter.first;
Node* node = nullptr;
if (target->getName() == boneName)
node = target;
else
node = findChildByNameRecursively(target, boneName);
if (node)
{
auto curve = _animation->getBoneCurveByName(boneName);
if (curve)
{
_nodeCurves[node] = curve;
hasCurve = true;
}
}
}
}
if (!hasCurve)
{
CCLOG("warning: no animation finde for the skeleton");
@ -238,6 +310,8 @@ void Animate3D::update(float t)
t = 1 - t;
t = _start + t * _last;
for (const auto& it : _boneCurves)
{
for (const auto& it : _boneCurves) {
auto bone = it.first;
auto curve = it.second;
@ -259,6 +333,31 @@ void Animate3D::update(float t)
bone->setAnimationValue(trans, rot, scale, this, _weight);
}
}
for (const auto& it : _nodeCurves)
{
auto node = it.first;
auto curve = it.second;
Mat4 transform;
if (curve->translateCurve)
{
curve->translateCurve->evaluate(t, transDst, EvaluateType::INT_LINEAR);
transform.translate(transDst[0], transDst[1], transDst[2]);
}
if (curve->rotCurve)
{
curve->rotCurve->evaluate(t, rotDst, EvaluateType::INT_QUAT_SLERP);
Quaternion qua(rotDst[0], rotDst[1], rotDst[2], rotDst[3]);
transform.rotate(qua);
}
if (curve->scaleCurve)
{
curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR);
transform.scale(scaleDst[0], scaleDst[1], scaleDst[2]);
}
node->setAdditionalTransform(&transform);
}
}
}
}

View File

@ -138,11 +138,12 @@ protected:
float _lastTime; // last t (0 - 1)
float _originInterval;// save origin interval time
std::unordered_map<Bone3D*, Animation3D::Curve*> _boneCurves; //weak ref
std::unordered_map<Node*, Animation3D::Curve*> _nodeCurves;
//sprite animates
static std::unordered_map<Sprite3D*, Animate3D*> s_fadeInAnimates;
static std::unordered_map<Sprite3D*, Animate3D*> s_fadeOutAnimates;
static std::unordered_map<Sprite3D*, Animate3D*> s_runningAnimates;
static std::unordered_map<Node*, Animate3D*> s_fadeInAnimates;
static std::unordered_map<Node*, Animate3D*> s_fadeOutAnimates;
static std::unordered_map<Node*, Animate3D*> s_runningAnimates;
};
// end of actions group

View File

@ -73,6 +73,8 @@ public:
/**get bone curve*/
Curve* getBoneCurveByName(const std::string& name) const;
const std::unordered_map<std::string, Curve*>& getBoneCurves() const {return _boneCurves;}
CC_CONSTRUCTOR_ACCESS:
Animation3D();
virtual ~Animation3D();

View File

@ -1616,7 +1616,7 @@ bool Bundle3D::loadNodesJson(NodeDatas& nodedatas)
{
const rapidjson::Value& jnode = nodes[i];
std::string id = jnode[ID].GetString();
NodeData* nodedata = parseNodesRecursivelyJson(jnode);
NodeData* nodedata = parseNodesRecursivelyJson(jnode, nodes.Size() == 1);
bool isSkeleton = jnode[SKELETON].GetBool();
if (isSkeleton)
@ -1626,22 +1626,24 @@ bool Bundle3D::loadNodesJson(NodeDatas& nodedatas)
}
return true;
}
NodeData* Bundle3D::parseNodesRecursivelyJson(const rapidjson::Value& jvalue)
NodeData* Bundle3D::parseNodesRecursivelyJson(const rapidjson::Value& jvalue, bool singleSprite)
{
NodeData* nodedata = new (std::nothrow) NodeData();;
// id
nodedata->id = jvalue[ID].GetString();
// transform
Mat4 tranform;
Mat4 transform;
const rapidjson::Value& jtransform = jvalue[TRANSFORM];
for (rapidjson::SizeType j = 0; j < jtransform.Size(); j++)
{
tranform.m[j] = jtransform[j].GetDouble();
transform.m[j] = jtransform[j].GetDouble();
}
nodedata->transform = tranform;
nodedata->transform = transform;
bool isSkin = false;
// parts
if (jvalue.HasMember(PARTS))
@ -1690,11 +1692,31 @@ NodeData* Bundle3D::parseNodesRecursivelyJson(const rapidjson::Value& jvalue)
//invbindpos.inverse();
modelnodedata->invBindPose.push_back(invbindpos);
}
if (bones.Size() > 0)
isSkin = true;
}
nodedata->modelNodeDatas.push_back(modelnodedata);
}
}
// set transform
if(_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || _version == "0.6")
{
if(isSkin || singleSprite)
{
nodedata->transform = Mat4::IDENTITY;
}
else
{
nodedata->transform = transform;
}
}
else
{
nodedata->transform = transform;
}
if (jvalue.HasMember(CHILDREN))
{
const rapidjson::Value& children = jvalue[CHILDREN];
@ -1702,7 +1724,7 @@ NodeData* Bundle3D::parseNodesRecursivelyJson(const rapidjson::Value& jvalue)
{
const rapidjson::Value& child = children[i];
NodeData* tempdata = parseNodesRecursivelyJson(child);
NodeData* tempdata = parseNodesRecursivelyJson(child, singleSprite);
nodedata->children.push_back(tempdata);
}
}
@ -1725,7 +1747,7 @@ bool Bundle3D::loadNodesBinary(NodeDatas& nodedatas)
for (rapidjson::SizeType i = 0; i < nodeSize; i++)
{
bool skeleton = false;
NodeData* nodedata = parseNodesRecursivelyBinary(skeleton);
NodeData* nodedata = parseNodesRecursivelyBinary(skeleton, nodeSize == 1);
if (skeleton)
nodedatas.skeleton.push_back(nodedata);
@ -1734,7 +1756,7 @@ bool Bundle3D::loadNodesBinary(NodeDatas& nodedatas)
}
return true;
}
NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton)
NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton, bool singleSprite)
{
// id
std::string id = _binaryReader.readString();
@ -1765,7 +1787,9 @@ NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton)
NodeData* nodedata = new (std::nothrow) NodeData();
nodedata->id = id;
nodedata->transform = transform;
bool isSkin = false;
if (partsSize > 0)
{
for (unsigned int i = 0; i < partsSize; i++)
@ -1804,6 +1828,7 @@ NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton)
modelnodedata->invBindPose.push_back(invbindpos);
}
isSkin = true;
}
unsigned int uvMapping = 0;
if (_binaryReader.read(&uvMapping, 4, 1) != 1)
@ -1832,6 +1857,23 @@ NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton)
}
}
// set transform
if(_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || _version == "0.6")
{
if(isSkin || singleSprite)
{
nodedata->transform = Mat4::IDENTITY;
}
else
{
nodedata->transform = transform;
}
}
else
{
nodedata->transform = transform;
}
unsigned int childrenSize = 0;
if (_binaryReader.read(&childrenSize, 4, 1) != 1)
{
@ -1842,7 +1884,7 @@ NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton)
{
for (unsigned int i = 0; i < childrenSize; i++)
{
NodeData* tempdata = parseNodesRecursivelyBinary(skeleton);
NodeData* tempdata = parseNodesRecursivelyBinary(skeleton, singleSprite);
nodedata->children.push_back(tempdata);
}
}

View File

@ -121,13 +121,13 @@ protected:
* load nodes of json
*/
bool loadNodesJson(NodeDatas& nodedatas);
NodeData* parseNodesRecursivelyJson(const rapidjson::Value& jvalue);
NodeData* parseNodesRecursivelyJson(const rapidjson::Value& jvalue, bool singleSprite);
/**
* load nodes of binary
*/
bool loadNodesBinary(NodeDatas& nodedatas);
NodeData* parseNodesRecursivelyBinary(bool& skeleton);
NodeData* parseNodesRecursivelyBinary(bool& skeleton, bool singleSprite);
/**
* get define data type

View File

@ -613,6 +613,8 @@ std::string ObjLoader::LoadObj(shapes_t& shapes, const char* filename, const cha
// use mtl
if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6])))
{
exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name);
faceGroup.clear();
char namebuf[4096];
token += 7;

View File

@ -478,6 +478,7 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m
{
if(it->bones.size() > 0 || singleSprite)
{
this->setName(nodedata->id);
auto mesh = Mesh::create(nodedata->id, getMeshIndexData(it->subMeshId));
if(mesh)
{
@ -518,6 +519,17 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m
}
}
}
Vec3 pos;
Quaternion qua;
Vec3 scale;
nodedata->transform.decompose(&scale, &qua, &pos);
setPosition3D(pos);
setRotationQuat(qua);
setScaleX(scale.x);
setScaleY(scale.y);
setScaleZ(scale.z);
}
}
else

View File

@ -74,7 +74,8 @@ static std::function<Layer*()> createFunctions[] =
CL(Sprite3DEmptyTest),
CL(UseCaseSprite3D),
CL(Sprite3DForceDepthTest),
CL(Sprite3DCubeMapTest)
CL(Sprite3DCubeMapTest),
CL(NodeAnimationTest)
};
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
@ -2340,6 +2341,104 @@ void UseCaseSprite3D::update(float delta)
}
}
/////////////////////////////////////////////
// Node Frame Animation
NodeAnimationTest::NodeAnimationTest()
:_vectorIndex(0)
{
auto s = Director::getInstance()->getWinSize();
auto itemPrev = MenuItemImage::create("Images/b1.png", "Images/b2.png",
[&](Ref *sender) {
_sprites[_vectorIndex]->setVisible(false);
int tIndex = _vectorIndex - 1;
if(tIndex < 0)
_vectorIndex = _sprites.size()-1;
else
_vectorIndex--;
_sprites[_vectorIndex]->setVisible(true);
});
auto itemNext = MenuItemImage::create("Images/f1.png", "Images/f2.png",
[&](Ref *sender) {
_sprites[_vectorIndex]->setVisible(false);
int tIndex = _vectorIndex + 1;
if(tIndex >= _sprites.size())
_vectorIndex = 0;
else
_vectorIndex++;
_sprites[_vectorIndex]->setVisible(true);
});
auto menu = Menu::create(itemPrev, itemNext, nullptr);
menu->alignItemsHorizontally();
menu->setScale(0.5);
menu->setAnchorPoint(Vec2(0,0));
menu->setPosition(Vec2(s.width/2,70));
addChild(menu);
addNewSpriteWithCoords(Vec2(s.width / 2.f, s.height / 2.f));
}
std::string NodeAnimationTest::title() const
{
return "Node Animation Test";
}
std::string NodeAnimationTest::subtitle() const
{
return "Jumping animation";
}
void NodeAnimationTest::addNewSpriteWithCoords(Vec2 p)
{
auto s = Director::getInstance()->getWinSize();
// add jumping ball
std::string fileName = "Sprite3DTest/ball.c3b";
auto sprite = Sprite3D::create(fileName);
sprite->setRotation3D(Vec3(0, 180, 0));
sprite->setScale(3);
sprite->setPosition(Vec2(s.width / 2.f, s.height / 3.f));
sprite->setTexture("Sprite3DTest/teapot.png");
auto light1 = PointLight::create(Vec3(s.width * 0.2f, s.height * 0.8f, 100.0f), Color3B(200, 200, 200), 10000.0f);
addChild(light1);
auto light2 = AmbientLight::create(Color3B(100, 100, 100));
addChild(light2);
auto animation = Animation3D::create(fileName);
if (animation)
{
auto animate = Animate3D::create(animation);
auto act = RepeatForever::create(animate);
act->setTag(0);
sprite->runAction(act);
}
addChild(sprite);
_sprites.push_back(sprite);
// add jumping orc
fileName = "Sprite3DTest/orc_jump.c3t";
sprite = Sprite3D::create(fileName);
sprite->setRotation3D(Vec3(0, 180, 0));
sprite->setScale(3);
sprite->setPosition(Vec2(s.width / 2.f, s.height / 3.f));
sprite->setVisible(false);
animation = Animation3D::create(fileName);
if (animation)
{
auto animate = Animate3D::create(animation);
auto act = RepeatForever::create(animate);
act->setTag(0);
sprite->runAction(act);
}
addChild(sprite);
_sprites.push_back(sprite);
}
Sprite3DCubeMapTest::Sprite3DCubeMapTest() :
_textureCube(nullptr),
_skyBox(nullptr),

View File

@ -491,6 +491,21 @@ protected:
std::string _useCaseTitles[(int)USECASE::MAX_CASE_NUM];
};
// node animation test, cocos2d-x supports both skeletal animation and node animation
class NodeAnimationTest : public Sprite3DTestDemo
{
public:
CREATE_FUNC(NodeAnimationTest);
NodeAnimationTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
void addNewSpriteWithCoords(Vec2 p);
protected:
std::vector<Sprite3D*> _sprites;
int _vectorIndex;
};
class Sprite3DTestScene : public TestScene
{
public:

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ classes = Animate3D Sprite3D Animation3D Skeleton3D ^Mesh$ AttachNode BillBoard
skip = Mesh::[create getAABB getVertexBuffer hasVertexAttrib getSkin getMeshIndexData getGLProgramState getPrimitiveType getIndexCount getIndexFormat getIndexBuffer],
Sprite3D::[getSkin getAABB getMeshArrayByName createAsync],
Skeleton3D::[create],
Animation3D::[getBoneCurveByName],
Animation3D::[getBoneCurveByName getBoneCurves],
BillBoard::[draw],
Sprite3DCache::[addSprite3DData getSpriteData]