mirror of https://github.com/axmolengine/axmol.git
commit
30db8ab7fa
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
@ -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]
|
||||
|
||||
|
|
Loading…
Reference in New Issue