mirror of https://github.com/axmolengine/axmol.git
commit
7f28e81d09
|
@ -1025,6 +1025,10 @@
|
|||
373B912A187891FB00198F86 /* CCComBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 373B910718787C0B00198F86 /* CCComBase.h */; };
|
||||
3EA0FB6B191C841D00B170C8 /* UIVideoPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA0FB69191C841D00B170C8 /* UIVideoPlayer.h */; };
|
||||
3EA0FB6C191C841D00B170C8 /* UIVideoPlayerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3EA0FB6A191C841D00B170C8 /* UIVideoPlayerIOS.mm */; };
|
||||
3EA47870195478E00068D9D1 /* CCBundleReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3EA4786E195478E00068D9D1 /* CCBundleReader.cpp */; };
|
||||
3EA47871195478E00068D9D1 /* CCBundleReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3EA4786E195478E00068D9D1 /* CCBundleReader.cpp */; };
|
||||
3EA47872195478E00068D9D1 /* CCBundleReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA4786F195478E00068D9D1 /* CCBundleReader.h */; };
|
||||
3EA47873195478E00068D9D1 /* CCBundleReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA4786F195478E00068D9D1 /* CCBundleReader.h */; };
|
||||
460E468118080832000CDD6D /* cocos-ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A167D21807AF4D005B8026 /* cocos-ext.h */; };
|
||||
460E468218080836000CDD6D /* cocos-ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A167D21807AF4D005B8026 /* cocos-ext.h */; };
|
||||
460E477B180808F5000CDD6D /* ExtensionMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A168321807AF4E005B8026 /* ExtensionMacros.h */; };
|
||||
|
@ -2339,6 +2343,8 @@
|
|||
37936A3E1869B76800E974DD /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = "<group>"; };
|
||||
3EA0FB69191C841D00B170C8 /* UIVideoPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIVideoPlayer.h; sourceTree = "<group>"; };
|
||||
3EA0FB6A191C841D00B170C8 /* UIVideoPlayerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIVideoPlayerIOS.mm; sourceTree = "<group>"; };
|
||||
3EA4786E195478E00068D9D1 /* CCBundleReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCBundleReader.cpp; sourceTree = "<group>"; };
|
||||
3EA4786F195478E00068D9D1 /* CCBundleReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBundleReader.h; sourceTree = "<group>"; };
|
||||
46A15FCC1807A544005B8026 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; name = AUTHORS; path = ../AUTHORS; sourceTree = "<group>"; };
|
||||
46A15FCE1807A544005B8026 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = "<group>"; };
|
||||
46A15FE11807A56F005B8026 /* Export.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Export.h; sourceTree = "<group>"; };
|
||||
|
@ -4912,6 +4918,8 @@
|
|||
B29594B81926D61F003EEF37 /* 3d */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA4786E195478E00068D9D1 /* CCBundleReader.cpp */,
|
||||
3EA4786F195478E00068D9D1 /* CCBundleReader.h */,
|
||||
B6AAF83F19404E0D0069DE01 /* CCBundle3D.cpp */,
|
||||
B6AAF84019404E0D0069DE01 /* CCBundle3D.h */,
|
||||
B6ACD89C193DC0CC005E0B8A /* CCAnimate3D.cpp */,
|
||||
|
@ -5218,6 +5226,7 @@
|
|||
1AD71EE3180E26E600808F54 /* SlotData.h in Headers */,
|
||||
0634A4E2194B19E400E608AF /* CCTimeLine.h in Headers */,
|
||||
1AD71EE7180E26E600808F54 /* spine-cocos2dx.h in Headers */,
|
||||
3EA47872195478E00068D9D1 /* CCBundleReader.h in Headers */,
|
||||
1AD71EE9180E26E600808F54 /* spine.h in Headers */,
|
||||
1AAF536C180E3374000584C8 /* HttpClient.h in Headers */,
|
||||
50ABBD9D1925AB4100A911A9 /* ccGLStateCache.h in Headers */,
|
||||
|
@ -5774,6 +5783,7 @@
|
|||
50ABC0201926664800A911A9 /* CCThread.h in Headers */,
|
||||
1A01C69318F57BE800EFE3A6 /* CCDouble.h in Headers */,
|
||||
50ABBE221925AB6F00A911A9 /* atitc.h in Headers */,
|
||||
3EA47873195478E00068D9D1 /* CCBundleReader.h in Headers */,
|
||||
1A8C59DA180E930E00EF57C3 /* CCDisplayFactory.h in Headers */,
|
||||
1A8C59DE180E930E00EF57C3 /* CCDisplayManager.h in Headers */,
|
||||
50FCEBB618C72017004AD434 /* SliderReader.h in Headers */,
|
||||
|
@ -6314,6 +6324,7 @@
|
|||
1A57034B180BD09B0088DEC7 /* tinyxml2.cpp in Sources */,
|
||||
1A570354180BD0B00088DEC7 /* ioapi.cpp in Sources */,
|
||||
1A570358180BD0B00088DEC7 /* unzip.cpp in Sources */,
|
||||
3EA47870195478E00068D9D1 /* CCBundleReader.cpp in Sources */,
|
||||
1AD71DA9180E26E600808F54 /* CCBAnimationManager.cpp in Sources */,
|
||||
1AD71DAD180E26E600808F54 /* CCBFileLoader.cpp in Sources */,
|
||||
50E6D33418E174130051CA34 /* UIHBox.cpp in Sources */,
|
||||
|
@ -6634,6 +6645,7 @@
|
|||
50ABC01A1926664800A911A9 /* CCSAXParser.cpp in Sources */,
|
||||
503DD8EE1926736A00CD74DD /* CCImage.mm in Sources */,
|
||||
50FCEBC818C72017004AD434 /* WidgetReader.cpp in Sources */,
|
||||
3EA47871195478E00068D9D1 /* CCBundleReader.cpp in Sources */,
|
||||
46A170FC1807CECB005B8026 /* CCPhysicsBody.cpp in Sources */,
|
||||
50ABBD941925AB4100A911A9 /* CCGLProgramState.cpp in Sources */,
|
||||
50ABBE281925AB6F00A911A9 /* CCAutoreleasePool.cpp in Sources */,
|
||||
|
|
|
@ -182,6 +182,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
|
|||
<ClCompile Include="..\3d\CCAnimate3D.cpp" />
|
||||
<ClCompile Include="..\3d\CCAnimation3D.cpp" />
|
||||
<ClCompile Include="..\3d\CCBundle3D.cpp" />
|
||||
<ClCompile Include="..\3d\CCBundleReader.cpp" />
|
||||
<ClCompile Include="..\3d\CCMesh.cpp" />
|
||||
<ClCompile Include="..\3d\CCMeshSkin.cpp" />
|
||||
<ClCompile Include="..\3d\CCObjLoader.cpp" />
|
||||
|
@ -360,6 +361,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
|
|||
<ClInclude Include="..\3d\CCAnimationCurve.h" />
|
||||
<ClInclude Include="..\3d\CCBundle3D.h" />
|
||||
<ClInclude Include="..\3d\CCBundle3DData.h" />
|
||||
<ClInclude Include="..\3d\CCBundleReader.h" />
|
||||
<ClInclude Include="..\3d\CCMesh.h" />
|
||||
<ClInclude Include="..\3d\CCMeshSkin.h" />
|
||||
<ClInclude Include="..\3d\CCObjLoader.h" />
|
||||
|
|
|
@ -580,6 +580,9 @@
|
|||
<ClCompile Include="..\3d\CCSprite3DMaterial.cpp">
|
||||
<Filter>3d</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3d\CCBundleReader.cpp">
|
||||
<Filter>3d</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\physics\CCPhysicsBody.h">
|
||||
|
@ -1180,6 +1183,9 @@
|
|||
<ClInclude Include="..\3d\CCSprite3DMaterial.h">
|
||||
<Filter>3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\3d\CCBundleReader.h">
|
||||
<Filter>3d</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\math\Mat4.inl">
|
||||
|
|
|
@ -45,16 +45,34 @@ Animate3D* Animate3D::create(Animation3D* animation)
|
|||
return animate;
|
||||
}
|
||||
|
||||
Animate3D* Animate3D::create(Animation3D* animation, float fromTime, float duration)
|
||||
{
|
||||
auto animate = Animate3D::create(animation);
|
||||
|
||||
float fullDuration = animation->getDuration();
|
||||
if (duration > fullDuration - fromTime)
|
||||
duration = fullDuration - fromTime;
|
||||
|
||||
animate->_start = fromTime / fullDuration;
|
||||
animate->_last = duration / fullDuration;
|
||||
animate->setDuration(duration);
|
||||
|
||||
return animate;
|
||||
}
|
||||
|
||||
/** returns a clone of action */
|
||||
Animate3D* Animate3D::clone() const
|
||||
{
|
||||
|
||||
auto animate = const_cast<Animate3D*>(this);
|
||||
auto copy = Animate3D::create(animate->_animation);
|
||||
|
||||
copy->_speed = _speed;
|
||||
copy->_weight = _weight;
|
||||
copy->_elapsed = _elapsed;
|
||||
copy->_start = _start;
|
||||
copy->_last = _last;
|
||||
copy->_playBack = _playBack;
|
||||
copy->setDuration(animate->getDuration());
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
@ -106,6 +124,7 @@ void Animate3D::update(float t)
|
|||
if (_playBack)
|
||||
t = 1 - t;
|
||||
|
||||
t = _start + t * _last;
|
||||
for (const auto& it : _boneCurves) {
|
||||
auto bone = it.first;
|
||||
auto curve = it.second;
|
||||
|
@ -124,7 +143,7 @@ void Animate3D::update(float t)
|
|||
curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR);
|
||||
scale = &scaleDst[0];
|
||||
}
|
||||
bone->setAnimationValue(trans, rot, scale, _weight);
|
||||
bone->setAnimationValue(trans, rot, scale, this, _weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +152,8 @@ void Animate3D::update(float t)
|
|||
Animate3D::Animate3D()
|
||||
: _speed(1)
|
||||
, _weight(1.f)
|
||||
, _start(0.f)
|
||||
, _last(1.f)
|
||||
, _animation(nullptr)
|
||||
, _playBack(false)
|
||||
{
|
||||
|
|
|
@ -39,15 +39,23 @@ NS_CC_BEGIN
|
|||
class Animation3D;
|
||||
class Bone;
|
||||
/**
|
||||
* Animate3D
|
||||
* Animate3D, Animates a Sprite3D given with an Animation3D
|
||||
*/
|
||||
class Animate3D: public ActionInterval
|
||||
{
|
||||
public:
|
||||
|
||||
//create Animate3D using Animation.
|
||||
/**create Animate3D using Animation.*/
|
||||
static Animate3D* create(Animation3D* animation);
|
||||
|
||||
/**
|
||||
* create Animate3D
|
||||
* @param animation used to generate animate3D
|
||||
* @param formTime
|
||||
* @param duration Time the Animate3D lasts
|
||||
* @return Animate3D created using animate
|
||||
*/
|
||||
static Animate3D* create(Animation3D* animation, float fromTime, float duration);
|
||||
//
|
||||
// Overrides
|
||||
//
|
||||
|
@ -58,9 +66,15 @@ public:
|
|||
|
||||
virtual void update(float t) override;
|
||||
|
||||
/**get & set speed */
|
||||
float getSpeed() const { return _speed; }
|
||||
void setSpeed(float speed) { _speed = speed; }
|
||||
|
||||
/**get & set blend weight*/
|
||||
float getWeight() const { return _weight; }
|
||||
void setWeight(float weight) { _weight = weight; }
|
||||
|
||||
/**get & set play back*/
|
||||
bool getPlayBack() const { return _playBack; }
|
||||
void setPlayBack(bool playBack) { _playBack = playBack; }
|
||||
|
||||
|
@ -69,11 +83,14 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
Animate3D();
|
||||
virtual ~Animate3D();
|
||||
|
||||
Animation3D* _animation;
|
||||
protected:
|
||||
Animation3D* _animation; //animation data
|
||||
|
||||
float _speed;
|
||||
float _weight;
|
||||
bool _playBack;
|
||||
float _speed; //playing speed
|
||||
float _weight; //blend weight
|
||||
float _start; //start time 0 - 1, used to generate sub Animate3D
|
||||
float _last; //last time 0 - 1, used to generate sub Animate3D
|
||||
bool _playBack; // is playing back
|
||||
std::map<Bone*, Animation3D::Curve*> _boneCurves; //weak ref
|
||||
};
|
||||
|
||||
|
|
|
@ -43,31 +43,36 @@ class Animation3D: public Ref
|
|||
{
|
||||
friend class Bundle3D;
|
||||
public:
|
||||
/**
|
||||
* animation curve, translation, rotation, and scale
|
||||
*/
|
||||
class Curve
|
||||
{
|
||||
public:
|
||||
typedef AnimationCurve<3> AnimationCurveVec3;
|
||||
typedef AnimationCurve<4> AnimationCurveQuat;
|
||||
AnimationCurveVec3* translateCurve;
|
||||
AnimationCurveQuat* rotCurve;
|
||||
AnimationCurveVec3* scaleCurve;
|
||||
AnimationCurveVec3* translateCurve; //translate curve
|
||||
AnimationCurveQuat* rotCurve;//rotation curve
|
||||
AnimationCurveVec3* scaleCurve;//scale curve
|
||||
|
||||
Curve();
|
||||
~Curve();
|
||||
};
|
||||
|
||||
//read all animation or only the animation with given animationName? animationName == "" read all.
|
||||
/**read all animation or only the animation with given animationName? animationName == "" read all.*/
|
||||
static Animation3D* getOrCreate(const std::string& filename, const std::string& animationName = "");
|
||||
|
||||
|
||||
/**get duration*/
|
||||
float getDuration() const { return _duration; }
|
||||
|
||||
/**get bone curve*/
|
||||
Curve* getBoneCurveByName(const std::string& name) const;
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
||||
Animation3D();
|
||||
virtual ~Animation3D();
|
||||
|
||||
/**init Animation3D from bundle data*/
|
||||
bool init(const Animation3DData& data);
|
||||
|
||||
protected:
|
||||
|
@ -78,26 +83,34 @@ protected:
|
|||
float _duration; //animation duration
|
||||
};
|
||||
|
||||
/**
|
||||
* Animation3D Cache
|
||||
*/
|
||||
class Animation3DCache
|
||||
{
|
||||
public:
|
||||
/**get and destroy instance*/
|
||||
static Animation3DCache* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
/**get animation by key*/
|
||||
Animation3D* getAnimation(const std::string& key);
|
||||
|
||||
/**add animation to cache*/
|
||||
void addAnimation(const std::string& key, Animation3D* animation);
|
||||
|
||||
/**remove all animation*/
|
||||
void removeAllAnimations();
|
||||
/**remove unused animation*/
|
||||
void removeUnusedAnimation();
|
||||
|
||||
protected:
|
||||
Animation3DCache();
|
||||
~Animation3DCache();
|
||||
|
||||
static Animation3DCache* _cacheInstance;
|
||||
static Animation3DCache* _cacheInstance; //cache instance
|
||||
|
||||
std::unordered_map<std::string, Animation3D*> _animations;
|
||||
std::unordered_map<std::string, Animation3D*> _animations; //cached animations
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -38,9 +38,12 @@
|
|||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* Evaluate Type
|
||||
*/
|
||||
enum class EvaluateType
|
||||
{
|
||||
INT_LINEAR,
|
||||
INT_LINEAR,
|
||||
INT_NEAR,
|
||||
INT_QUAT_SLERP,
|
||||
INT_USER_FUNCTION,
|
||||
|
@ -54,15 +57,24 @@ class AnimationCurve: public Ref
|
|||
{
|
||||
public:
|
||||
|
||||
//create animation curve
|
||||
/**create animation curve*/
|
||||
static AnimationCurve* create(float* keytime, float* value, int count);
|
||||
|
||||
/**
|
||||
* evalute value of time
|
||||
* @param time Time to be estimated
|
||||
* @param dst Estimated value of that time
|
||||
* @param type EvaluateType
|
||||
*/
|
||||
void evaluate(float time, float* dst, EvaluateType type) const;
|
||||
|
||||
/**set evaluate function, allow the user use own function*/
|
||||
void setEvaluateFun(std::function<void(float time, float* dst)> fun);
|
||||
|
||||
/**get start time*/
|
||||
float getStartTime() const;
|
||||
|
||||
/**get end time*/
|
||||
float getEndTime() const;
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
@ -82,7 +94,7 @@ protected:
|
|||
int _count;
|
||||
int _componentSizeByte; //component size in byte, position and scale 3 * sizeof(float), rotation 4 * sizeof(float)
|
||||
|
||||
std::function<void(float time, float* dst)> _evaluateFun;
|
||||
std::function<void(float time, float* dst)> _evaluateFun; //user defined function
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -27,55 +27,114 @@
|
|||
#include "base/ccMacros.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "renderer/CCGLProgram.h"
|
||||
#include "CCBundleReader.h"
|
||||
#include "base/CCData.h"
|
||||
#include "json/document.h"
|
||||
|
||||
|
||||
#define BUNDLE_TYPE_SCENE 1
|
||||
#define BUNDLE_TYPE_NODE 2
|
||||
#define BUNDLE_TYPE_ANIMATIONS 3
|
||||
#define BUNDLE_TYPE_ANIMATION 4
|
||||
#define BUNDLE_TYPE_ANIMATION_CHANNEL 5
|
||||
#define BUNDLE_TYPE_MODEL 10
|
||||
#define BUNDLE_TYPE_MATERIAL 16
|
||||
#define BUNDLE_TYPE_EFFECT 18
|
||||
#define BUNDLE_TYPE_CAMERA 32
|
||||
#define BUNDLE_TYPE_LIGHT 33
|
||||
#define BUNDLE_TYPE_MESH 34
|
||||
#define BUNDLE_TYPE_MESHPART 35
|
||||
#define BUNDLE_TYPE_MESHSKIN 36
|
||||
|
||||
static const char* ID = "id";
|
||||
|
||||
static const char* MESHDATA_MESH = "mesh";
|
||||
static const char* MESHDATA_DEFAULTPART = "body";
|
||||
static const char* MESHDATA_VERTEXSIZE = "vertexsize";
|
||||
static const char* MESHDATA_VERTICES = "vertices";
|
||||
static const char* MESHDATA_INDEXNUM = "indexnum";
|
||||
static const char* MESHDATA_INDICES = "indices";
|
||||
static const char* MESHDATA_ATTRIBUTES = "attributes";
|
||||
static const char* MESHDATA_SIZE = "size";
|
||||
static const char* MESHDATA_TYPE = "type";
|
||||
static const char* MESHDATA_ATTRIBUTE = "attribute";
|
||||
|
||||
static const char* SKINDATA_SKIN = "skin";
|
||||
static const char* SKINDATA_BONES = "bones";
|
||||
static const char* SKINDATA_NODE = "node";
|
||||
static const char* SKINDATA_BINDSHAPE = "bindshape";
|
||||
static const char* SKINDATA_CHILDREN = "children";
|
||||
static const char* SKINDATA_TRANSFORM = "tansform";
|
||||
|
||||
static const char* MATERIALDATA_MATERIAL = "material";
|
||||
static const char* MATERIALDATA_BASE = "base";
|
||||
static const char* MATERIALDATA_FILENAME = "filename";
|
||||
|
||||
static const char* ANIMATIONDATA_ANIMATION = "animation";
|
||||
static const char* ANIMATIONDATA_LENGTH = "length";
|
||||
static const char* ANIMATIONDATA_BONES = "bones";
|
||||
static const char* ANIMATIONDATA_BONEID = "boneId";
|
||||
static const char* ANIMATIONDATA_KEYFRAMES = "keyframes";
|
||||
static const char* ANIMATIONDATA_TRANSLATION = "translation";
|
||||
static const char* ANIMATIONDATA_ROTATION = "rotation";
|
||||
static const char* ANIMATIONDATA_SCALE = "scale";
|
||||
static const char* ANIMATIONDATA_KEYTIME = "keytime";
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
void getChildMap(std::map<int, std::vector<int> >& map, SkinData* skinData, const rapidjson::Value& val)
|
||||
{
|
||||
if (!skinData)
|
||||
return;
|
||||
|
||||
if (!val.HasMember("children"))
|
||||
return;
|
||||
|
||||
std::string parent_name = val["id"].GetString();
|
||||
int parent_name_index = skinData->getBoneNameIndex(parent_name);
|
||||
|
||||
const rapidjson::Value& children = val["children"];
|
||||
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
|
||||
|
||||
// get transform matrix
|
||||
Mat4 transform;
|
||||
const rapidjson::Value& parent_tranform = val[SKINDATA_TRANSFORM];
|
||||
for (rapidjson::SizeType j = 0; j < parent_tranform.Size(); j++)
|
||||
{
|
||||
const rapidjson::Value& child = children[i];
|
||||
std::string child_name = child["id"].GetString();
|
||||
|
||||
int child_name_index = skinData->getBoneNameIndex(child_name);
|
||||
if (child_name_index >= 0)
|
||||
{
|
||||
map[parent_name_index].push_back(child_name_index);
|
||||
|
||||
getChildMap(map, skinData, child);
|
||||
}
|
||||
transform.m[j] = parent_tranform[j].GetDouble();
|
||||
}
|
||||
}
|
||||
|
||||
void getChildMapT(std::map<std::string, std::vector<std::string> >& map, const SkinData* skinData, const rapidjson::Value& val)
|
||||
{
|
||||
if (!skinData)
|
||||
|
||||
// set origin matrices
|
||||
std::string parent_name = val[ID].GetString();
|
||||
int parent_name_index = skinData->getSkinBoneNameIndex(parent_name);
|
||||
if (parent_name_index < 0)
|
||||
{
|
||||
skinData->addNodeBoneNames(parent_name);
|
||||
skinData->nodeBoneOriginMatrices.push_back(transform);
|
||||
parent_name_index = skinData->getBoneNameIndex(parent_name);
|
||||
}
|
||||
else if (parent_name_index < skinData->skinBoneNames.size())
|
||||
{
|
||||
skinData->skinBoneOriginMatrices[parent_name_index] = (transform);
|
||||
}
|
||||
|
||||
// set root bone index
|
||||
if(skinData->rootBoneIndex < 0)
|
||||
skinData->rootBoneIndex = parent_name_index;
|
||||
|
||||
if (!val.HasMember(SKINDATA_CHILDREN))
|
||||
return;
|
||||
|
||||
if (!val.HasMember("children"))
|
||||
return;
|
||||
|
||||
std::string parent_name = val["id"].GetString();
|
||||
const rapidjson::Value& children = val["children"];
|
||||
|
||||
const rapidjson::Value& children = val[SKINDATA_CHILDREN];
|
||||
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
|
||||
{
|
||||
// get child bone name
|
||||
const rapidjson::Value& child = children[i];
|
||||
std::string child_name = child["id"].GetString();
|
||||
|
||||
map[parent_name].push_back(child_name);
|
||||
|
||||
getChildMapT(map, skinData, child);
|
||||
|
||||
std::string child_name = child[ID].GetString();
|
||||
int child_name_index = skinData->getSkinBoneNameIndex(child_name);
|
||||
if (child_name_index < 0)
|
||||
{
|
||||
skinData->addNodeBoneNames(child_name);
|
||||
child_name_index = skinData->getBoneNameIndex(child_name);
|
||||
|
||||
}
|
||||
|
||||
map[parent_name_index].push_back(child_name_index);
|
||||
|
||||
getChildMap(map, skinData, child);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,184 +152,276 @@ void Bundle3D::destroyInstance()
|
|||
CC_SAFE_DELETE(_instance);
|
||||
}
|
||||
|
||||
void Bundle3D::clear()
|
||||
{
|
||||
if (_isBinary)
|
||||
{
|
||||
CC_SAFE_DELETE(_binaryBuffer);
|
||||
CC_SAFE_DELETE_ARRAY(_references);
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle3D::load(const std::string& path)
|
||||
{
|
||||
if (_path == path)
|
||||
return true;
|
||||
|
||||
getModelPath(path);
|
||||
std::string strFileString = FileUtils::getInstance()->getStringFromFile(path);
|
||||
ssize_t size = strFileString.length();
|
||||
CC_SAFE_DELETE_ARRAY(_documentBuffer);
|
||||
_documentBuffer = new char[size + 1];
|
||||
memcpy(_documentBuffer, strFileString.c_str(), size);
|
||||
_documentBuffer[size] = '\0';
|
||||
if (_document.ParseInsitu<0>(_documentBuffer).HasParseError())
|
||||
getModelRelativePath(path);
|
||||
|
||||
bool ret = false;
|
||||
std::string ext = path.substr(path.length() - 4, 4);
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
|
||||
if (ext == ".c3t")
|
||||
{
|
||||
_isBinary = false;
|
||||
ret = loadJson(path);
|
||||
}
|
||||
else if (ext == ".c3b")
|
||||
{
|
||||
_isBinary = true;
|
||||
ret = loadBinary(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOGINFO("%s is invalid file formate", path);
|
||||
}
|
||||
|
||||
ret?(_path = path):(_path = "");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
|
||||
{
|
||||
if (_isBinary)
|
||||
{
|
||||
return loadMeshDataBinary(meshdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
return loadMeshDataJson(meshdata);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
|
||||
{
|
||||
if (_isBinary)
|
||||
{
|
||||
return loadSkinDataBinary(skindata);
|
||||
}
|
||||
else
|
||||
{
|
||||
return loadSkinDataJson(skindata);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdata)
|
||||
{
|
||||
if (_isBinary)
|
||||
{
|
||||
return loadMaterialDataBinary(materialdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
return loadMaterialDataJson(materialdata);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animationdata)
|
||||
{
|
||||
if (_isBinary)
|
||||
{
|
||||
return loadAnimationDataBinary(animationdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
return loadAnimationDataJson(animationdata);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle3D::loadJson(const std::string& path)
|
||||
{
|
||||
clear();
|
||||
|
||||
Data data = FileUtils::getInstance()->getDataFromFile(path);
|
||||
ssize_t size = data.getSize();
|
||||
|
||||
// json need null-terminated string.
|
||||
_jsonBuffer = new char[size + 1];
|
||||
memcpy(_jsonBuffer, data.getBytes(), size);
|
||||
_jsonBuffer[size] = '\0';
|
||||
if (_jsonReader.ParseInsitu<0>(_jsonBuffer).HasParseError())
|
||||
{
|
||||
assert(0);
|
||||
CC_SAFE_DELETE_ARRAY(_documentBuffer);
|
||||
_path = "";
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
_path = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
|
||||
bool Bundle3D::loadMeshDataJson(MeshData* meshdata)
|
||||
{
|
||||
meshdata->resetData();
|
||||
|
||||
assert(_document.HasMember("mesh"));
|
||||
const rapidjson::Value& mash_data_array = _document["mesh"];
|
||||
assert(_jsonReader.HasMember(MESHDATA_MESH));
|
||||
const rapidjson::Value& mash_data_array = _jsonReader[MESHDATA_MESH];
|
||||
|
||||
assert(mash_data_array.IsArray());
|
||||
const rapidjson::Value& mash_data_val = mash_data_array[(rapidjson::SizeType)0];
|
||||
|
||||
assert(mash_data_val.HasMember("body"));
|
||||
const rapidjson::Value& mesh_data_body_array = mash_data_val["body"];
|
||||
assert(mash_data_val.HasMember(MESHDATA_DEFAULTPART));
|
||||
const rapidjson::Value& mesh_data_body_array = mash_data_val[MESHDATA_DEFAULTPART];
|
||||
|
||||
assert(mesh_data_body_array.IsArray());
|
||||
const rapidjson::Value& mesh_data_body_array_0 = mesh_data_body_array[(rapidjson::SizeType)0];
|
||||
|
||||
// vertex_size
|
||||
assert(mesh_data_body_array_0.HasMember("vertexsize"));
|
||||
meshdata->vertexSizeInFloat = mesh_data_body_array_0["vertexsize"].GetInt();
|
||||
assert(mesh_data_body_array_0.HasMember(MESHDATA_VERTEXSIZE));
|
||||
meshdata->vertexSizeInFloat = mesh_data_body_array_0[MESHDATA_VERTEXSIZE].GetInt();
|
||||
|
||||
// vertices
|
||||
meshdata->vertex.resize(meshdata->vertexSizeInFloat);
|
||||
const rapidjson::Value& mesh_data_body_vertices = mesh_data_body_array_0["vertices"];
|
||||
const rapidjson::Value& mesh_data_body_vertices = mesh_data_body_array_0[MESHDATA_VERTICES];
|
||||
for (rapidjson::SizeType i = 0; i < mesh_data_body_vertices.Size(); i++)
|
||||
meshdata->vertex[i] = mesh_data_body_vertices[i].GetDouble();
|
||||
|
||||
// index_number
|
||||
meshdata->numIndex = mesh_data_body_array_0["indexnum"].GetUint();
|
||||
meshdata->numIndex = mesh_data_body_array_0[MESHDATA_INDEXNUM].GetUint();
|
||||
|
||||
// indices
|
||||
meshdata->indices.resize(meshdata->numIndex);
|
||||
const rapidjson::Value& mesh_data_body_indices_val = mesh_data_body_array_0["indices"];
|
||||
const rapidjson::Value& mesh_data_body_indices_val = mesh_data_body_array_0[MESHDATA_INDICES];
|
||||
for (rapidjson::SizeType i = 0; i < mesh_data_body_indices_val.Size(); i++)
|
||||
meshdata->indices[i] = (unsigned short)mesh_data_body_indices_val[i].GetUint();
|
||||
|
||||
// mesh_vertex_attribute
|
||||
const rapidjson::Value& mesh_vertex_attribute = mash_data_val["attributes"];
|
||||
const rapidjson::Value& mesh_vertex_attribute = mash_data_val[MESHDATA_ATTRIBUTES];
|
||||
meshdata->attribCount = mesh_vertex_attribute.Size();
|
||||
meshdata->attribs.resize(meshdata->attribCount);
|
||||
for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); i++)
|
||||
{
|
||||
const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[i];
|
||||
|
||||
meshdata->attribs[i].size = mesh_vertex_attribute_val["size"].GetUint();
|
||||
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * parseGLTypeSize(mesh_vertex_attribute_val["type"].GetString());
|
||||
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val["type"].GetString());
|
||||
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val["attribute"].GetString());
|
||||
meshdata->attribs[i].size = mesh_vertex_attribute_val[MESHDATA_SIZE].GetUint();
|
||||
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * 4;
|
||||
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val[MESHDATA_TYPE].GetString());
|
||||
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[MESHDATA_ATTRIBUTE].GetString());
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
|
||||
bool Bundle3D::loadSkinDataJson(SkinData* skindata)
|
||||
{
|
||||
if (!_document.HasMember("skin")) return false;
|
||||
|
||||
if (!_jsonReader.HasMember(SKINDATA_SKIN )) return false;
|
||||
|
||||
skindata->resetData();
|
||||
|
||||
const rapidjson::Value& skin_data_array = _document["skin"];
|
||||
|
||||
|
||||
const rapidjson::Value& skin_data_array = _jsonReader[SKINDATA_SKIN ];
|
||||
|
||||
assert(skin_data_array.IsArray());
|
||||
const rapidjson::Value& skin_data_array_val_0 = skin_data_array[(rapidjson::SizeType)0];
|
||||
|
||||
if (!skin_data_array_val_0.HasMember("bones"))
|
||||
|
||||
if (!skin_data_array_val_0.HasMember(SKINDATA_BONES))
|
||||
return false;
|
||||
|
||||
const rapidjson::Value& skin_data_bones = skin_data_array_val_0["bones"];
|
||||
|
||||
const rapidjson::Value& skin_data_bones = skin_data_array_val_0[SKINDATA_BONES];
|
||||
for (rapidjson::SizeType i = 0; i < skin_data_bones.Size(); i++)
|
||||
{
|
||||
const rapidjson::Value& skin_data_bone = skin_data_bones[i];
|
||||
std::string name = skin_data_bone["node"].GetString();
|
||||
skindata->boneNames.push_back(name);
|
||||
std::string name = skin_data_bone[SKINDATA_NODE].GetString();
|
||||
skindata->addSkinBoneNames(name);
|
||||
|
||||
Mat4 mat_bind_pos;
|
||||
const rapidjson::Value& bind_pos = skin_data_bone["bindshape"];
|
||||
const rapidjson::Value& bind_pos = skin_data_bone[SKINDATA_BINDSHAPE];
|
||||
for (rapidjson::SizeType j = 0; j < bind_pos.Size(); j++)
|
||||
{
|
||||
mat_bind_pos.m[j] = bind_pos[j].GetDouble();
|
||||
}
|
||||
skindata->inverseBindPoseMatrices.push_back(mat_bind_pos);
|
||||
}
|
||||
|
||||
|
||||
// set root bone infomation
|
||||
const rapidjson::Value& skin_data_1 = skin_data_array[1];
|
||||
const rapidjson::Value& bone_array_0 = skin_data_1["children"][(rapidjson::SizeType)0];
|
||||
skindata->rootBoneIndex = skindata->getBoneNameIndex(bone_array_0["id"].GetString());
|
||||
getChildMap(skindata->boneChild, skindata, bone_array_0);
|
||||
|
||||
// parent and child relationship map
|
||||
skindata->skinBoneOriginMatrices.resize(skindata->skinBoneNames.size());
|
||||
//skindata->nodeBoneOriginMatrices.resize(skindata->nodeBoneNames.size());
|
||||
getChildMap(skindata->boneChild, skindata, skin_data_1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdata)
|
||||
bool Bundle3D::loadMaterialDataJson(MaterialData* materialdata)
|
||||
{
|
||||
if (!_document.HasMember("material"))
|
||||
if (!_jsonReader.HasMember(MATERIALDATA_MATERIAL))
|
||||
return false;
|
||||
|
||||
const rapidjson::Value& material_data_array = _document["material"];
|
||||
const rapidjson::Value& material_data_array = _jsonReader[MATERIALDATA_MATERIAL];
|
||||
|
||||
const rapidjson::Value& material_data_array_0 = material_data_array[(rapidjson::SizeType)0];
|
||||
|
||||
const rapidjson::Value& material_data_base_array = material_data_array_0["base"];
|
||||
const rapidjson::Value& material_data_base_array = material_data_array_0[MATERIALDATA_BASE];
|
||||
|
||||
const rapidjson::Value& material_data_base_array_0 = material_data_base_array[(rapidjson::SizeType)0];
|
||||
|
||||
materialdata->texturePath = _modelRelativePath + material_data_base_array_0["filename"].GetString();
|
||||
materialdata->texturePath = _modelRelativePath + material_data_base_array_0[MATERIALDATA_FILENAME].GetString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animationdata)
|
||||
bool Bundle3D::loadAnimationDataJson(Animation3DData* animationdata)
|
||||
{
|
||||
if (!_document.HasMember("animation")) return false;
|
||||
if (!_jsonReader.HasMember(ANIMATIONDATA_ANIMATION)) return false;
|
||||
|
||||
animationdata->_rotationKeys.clear();
|
||||
animationdata->_scaleKeys.clear();
|
||||
animationdata->_translationKeys.clear();
|
||||
|
||||
const rapidjson::Value& animation_data_array = _document["animation"];
|
||||
const rapidjson::Value& animation_data_array = _jsonReader[ANIMATIONDATA_ANIMATION];
|
||||
if (animation_data_array.Size()==0) return false;
|
||||
|
||||
const rapidjson::Value& animation_data_array_val_0 = animation_data_array[(rapidjson::SizeType)0];
|
||||
|
||||
animationdata->_totalTime = animation_data_array_val_0["length"].GetDouble();
|
||||
animationdata->_totalTime = animation_data_array_val_0[ANIMATIONDATA_LENGTH].GetDouble();
|
||||
|
||||
const rapidjson::Value& bones = animation_data_array_val_0["bones"];
|
||||
const rapidjson::Value& bones = animation_data_array_val_0[ANIMATIONDATA_BONES];
|
||||
for (rapidjson::SizeType i = 0; i < bones.Size(); i++)
|
||||
{
|
||||
const rapidjson::Value& bone = bones[i];
|
||||
std::string bone_name = bone["boneId"].GetString();
|
||||
std::string bone_name = bone[ANIMATIONDATA_BONEID].GetString();
|
||||
|
||||
if ( bone.HasMember("keyframes"))
|
||||
if ( bone.HasMember(ANIMATIONDATA_KEYFRAMES))
|
||||
{
|
||||
const rapidjson::Value& bone_keyframes = bone["keyframes"];
|
||||
for (rapidjson::SizeType j = 0; j < bone_keyframes.Size(); j++)
|
||||
const rapidjson::Value& bone_keyframes = bone[ANIMATIONDATA_KEYFRAMES];
|
||||
rapidjson::SizeType keyframe_size = bone_keyframes.Size();
|
||||
for (rapidjson::SizeType j = 0; j < keyframe_size; j++)
|
||||
{
|
||||
const rapidjson::Value& bone_keyframe = bone_keyframes[j];
|
||||
|
||||
if ( bone_keyframe.HasMember("translation"))
|
||||
if ( bone_keyframe.HasMember(ANIMATIONDATA_TRANSLATION))
|
||||
{
|
||||
const rapidjson::Value& bone_keyframe_translation = bone_keyframe["translation"];
|
||||
float keytime = bone_keyframe["keytime"].GetDouble();
|
||||
const rapidjson::Value& bone_keyframe_translation = bone_keyframe[ANIMATIONDATA_TRANSLATION];
|
||||
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
|
||||
Vec3 val = Vec3(bone_keyframe_translation[(rapidjson::SizeType)0].GetDouble(), bone_keyframe_translation[1].GetDouble(), bone_keyframe_translation[2].GetDouble());
|
||||
animationdata->_translationKeys[bone_name].push_back(Animation3DData::Vec3Key(keytime,val));
|
||||
}
|
||||
|
||||
if ( bone_keyframe.HasMember("rotation"))
|
||||
if ( bone_keyframe.HasMember(ANIMATIONDATA_ROTATION))
|
||||
{
|
||||
const rapidjson::Value& bone_keyframe_rotation = bone_keyframe["rotation"];
|
||||
float keytime = bone_keyframe["keytime"].GetDouble();
|
||||
const rapidjson::Value& bone_keyframe_rotation = bone_keyframe[ANIMATIONDATA_ROTATION];
|
||||
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
|
||||
Quaternion val = Quaternion(bone_keyframe_rotation[(rapidjson::SizeType)0].GetDouble(),bone_keyframe_rotation[1].GetDouble(),bone_keyframe_rotation[2].GetDouble(),bone_keyframe_rotation[3].GetDouble());
|
||||
animationdata->_rotationKeys[bone_name].push_back(Animation3DData::QuatKey(keytime,val));
|
||||
}
|
||||
|
||||
if ( bone_keyframe.HasMember("scale"))
|
||||
if ( bone_keyframe.HasMember(ANIMATIONDATA_SCALE))
|
||||
{
|
||||
const rapidjson::Value& bone_keyframe_scale = bone_keyframe["scale"];
|
||||
float keytime = bone_keyframe["keytime"].GetDouble();
|
||||
const rapidjson::Value& bone_keyframe_scale = bone_keyframe[ANIMATIONDATA_SCALE];
|
||||
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
|
||||
Vec3 val = Vec3(bone_keyframe_scale[(rapidjson::SizeType)0].GetDouble(), bone_keyframe_scale[1].GetDouble(), bone_keyframe_scale[2].GetDouble());
|
||||
animationdata->_scaleKeys[bone_name].push_back(Animation3DData::Vec3Key(keytime,val));
|
||||
}
|
||||
|
@ -281,6 +432,330 @@ bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animati
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadBinary(const std::string& path)
|
||||
{
|
||||
clear();
|
||||
|
||||
// get file data
|
||||
CC_SAFE_DELETE(_binaryBuffer);
|
||||
_binaryBuffer = new Data();
|
||||
*_binaryBuffer = FileUtils::getInstance()->getDataFromFile(path);
|
||||
if (_binaryBuffer->isNull())
|
||||
{
|
||||
clear();
|
||||
CCLOGINFO(false, "Failed to read file: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create bundle reader
|
||||
//CC_SAFE_DELETE(_bundleReader);
|
||||
_binaryReader.init( (char*)_binaryBuffer->getBytes(), _binaryBuffer->getSize() );
|
||||
|
||||
// Read identifier info
|
||||
char identifier[] = { 'C', '3', 'B', '\0'};
|
||||
char sig[4];
|
||||
if (_binaryReader.read(sig, 1, 4) != 4 || memcmp(sig, identifier, 4) != 0)
|
||||
{
|
||||
clear();
|
||||
CCLOGINFO(false, "Invalid identifier: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read version
|
||||
unsigned char ver[2];
|
||||
if (_binaryReader.read(ver, 1, 2) != 2 || ver[0] != 0 || ver[1] != 1)
|
||||
{
|
||||
clear();
|
||||
CCLOGINFO(false, "Unsupported version: (%d, %d)", ver[0], ver[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read ref table size
|
||||
if (_binaryReader.read(&_referenceCount, 4, 1) != 1)
|
||||
{
|
||||
clear();
|
||||
CCLOGINFO("Failed to read ref table size '%s'.", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read all refs
|
||||
CC_SAFE_DELETE_ARRAY(_references);
|
||||
_references = new Reference[_referenceCount];
|
||||
for (ssize_t i = 0; i < _referenceCount; ++i)
|
||||
{
|
||||
if ((_references[i].id = _binaryReader.readString()).empty() ||
|
||||
_binaryReader.read(&_references[i].type, 4, 1) != 1 ||
|
||||
_binaryReader.read(&_references[i].offset, 4, 1) != 1)
|
||||
{
|
||||
clear();
|
||||
CCLOGINFO("Failed to read ref number %d for bundle '%s'.", i, path.c_str());
|
||||
CC_SAFE_DELETE_ARRAY(_references);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
|
||||
{
|
||||
if (!seekToFirstType(BUNDLE_TYPE_MESH))
|
||||
return false;
|
||||
|
||||
meshdata->resetData();
|
||||
|
||||
// read mesh data
|
||||
if (_binaryReader.read(&meshdata->attribCount, 4, 1) != 1 || meshdata->attribCount < 1)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: attribCount '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
meshdata->attribs.resize(meshdata->attribCount);
|
||||
for (ssize_t i = 0; i < meshdata->attribCount; i++)
|
||||
{
|
||||
unsigned int vUsage, vSize;
|
||||
if (_binaryReader.read(&vUsage, 4, 1) != 1 || _binaryReader.read(&vSize, 4, 1) != 1)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: usage or size '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
meshdata->attribs[i].size = vSize;
|
||||
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * 4;
|
||||
meshdata->attribs[i].type = GL_FLOAT;
|
||||
meshdata->attribs[i].vertexAttrib = vUsage;
|
||||
}
|
||||
|
||||
// Read vertex data
|
||||
if (_binaryReader.read(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: vertexSizeInFloat '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
meshdata->vertex.resize(meshdata->vertexSizeInFloat);
|
||||
if (_binaryReader.read(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: vertex element '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read index data
|
||||
ssize_t meshPartCount = 1;
|
||||
//_binaryReader.read(&meshPartCount, 4, 1);
|
||||
|
||||
for (ssize_t i = 0; i < meshPartCount; ++i)
|
||||
{
|
||||
ssize_t nIndexCount;
|
||||
if (_binaryReader.read(&nIndexCount, 4, 1) != 1)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: nIndexCount '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
meshdata->numIndex = nIndexCount;
|
||||
meshdata->indices.resize(meshdata->numIndex);
|
||||
if (_binaryReader.read(&meshdata->indices[0], 2, meshdata->numIndex) != nIndexCount)
|
||||
{
|
||||
CCLOGINFO("Failed to read meshdata: indices '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadSkinDataBinary(SkinData* skindata)
|
||||
{
|
||||
if (!seekToFirstType(BUNDLE_TYPE_MESHSKIN))
|
||||
return false;
|
||||
|
||||
skindata->resetData();
|
||||
|
||||
std::string boneName = _binaryReader.readString();
|
||||
|
||||
// transform
|
||||
float bindShape[16];
|
||||
if (!_binaryReader.readMatrix(bindShape))
|
||||
{
|
||||
CCLOGINFO("Failed to read SkinData: bindShape matrix '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// bone count
|
||||
unsigned int boneNum;
|
||||
if (!_binaryReader.read(&boneNum))
|
||||
{
|
||||
CCLOGINFO("Failed to read SkinData: boneNum '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// bone names and bind pos
|
||||
float bindpos[16];
|
||||
for (unsigned int i = 0; i < boneNum; i++)
|
||||
{
|
||||
std::string skinBoneName = _binaryReader.readString();
|
||||
skindata->skinBoneNames.push_back(skinBoneName);
|
||||
if (!_binaryReader.readMatrix(bindpos))
|
||||
{
|
||||
CCLOGINFO("Failed to load SkinData: bindpos '%s'.", _path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
skindata->inverseBindPoseMatrices.push_back(bindpos);
|
||||
}
|
||||
|
||||
skindata->skinBoneOriginMatrices.resize(boneNum);
|
||||
|
||||
boneName = _binaryReader.readString();
|
||||
|
||||
// bind shape
|
||||
_binaryReader.readMatrix(bindShape);
|
||||
int rootIndex = skindata->getSkinBoneNameIndex(boneName);
|
||||
if(rootIndex < 0)
|
||||
{
|
||||
skindata->addNodeBoneNames(boneName);
|
||||
rootIndex = skindata->getBoneNameIndex(boneName);
|
||||
skindata->nodeBoneOriginMatrices.push_back(bindShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
skindata->skinBoneOriginMatrices[rootIndex] = bindShape;
|
||||
}
|
||||
|
||||
// set root bone index
|
||||
skindata->rootBoneIndex = rootIndex;
|
||||
|
||||
// read parent and child relationship map
|
||||
float transform[16];
|
||||
unsigned int linkNum;
|
||||
_binaryReader.read(&linkNum);
|
||||
for (unsigned int i = 0; i < linkNum; ++i)
|
||||
{
|
||||
std::string id = _binaryReader.readString();
|
||||
int index = skindata->getSkinBoneNameIndex(id);
|
||||
|
||||
|
||||
std::string parentid = _binaryReader.readString();
|
||||
|
||||
if (!_binaryReader.readMatrix(transform))
|
||||
{
|
||||
CCLOGINFO("Failed to load SkinData: transform '%s'.", _path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(index < 0)
|
||||
{
|
||||
skindata->addNodeBoneNames(id);
|
||||
index = skindata->getBoneNameIndex(id);
|
||||
skindata->nodeBoneOriginMatrices.push_back(transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
skindata->skinBoneOriginMatrices[index] = transform;
|
||||
}
|
||||
|
||||
int parentIndex = skindata->getSkinBoneNameIndex(parentid);
|
||||
if(parentIndex < 0)
|
||||
{
|
||||
skindata->addNodeBoneNames(parentid);
|
||||
parentIndex = skindata->getBoneNameIndex(parentid);
|
||||
}
|
||||
|
||||
skindata->boneChild[parentIndex].push_back(index);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadMaterialDataBinary(MaterialData* materialdata)
|
||||
{
|
||||
if (!seekToFirstType(BUNDLE_TYPE_MATERIAL))
|
||||
return false;
|
||||
|
||||
std::string texturePath = _binaryReader.readString();
|
||||
if (texturePath.empty())
|
||||
{
|
||||
CCLOGINFO("Failed to read Materialdata: texturePath is empty '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
materialdata->texturePath = _modelRelativePath + texturePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bundle3D::loadAnimationDataBinary(Animation3DData* animationdata)
|
||||
{
|
||||
if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS))
|
||||
return false;
|
||||
|
||||
animationdata->_rotationKeys.clear();
|
||||
animationdata->_scaleKeys.clear();
|
||||
animationdata->_translationKeys.clear();
|
||||
|
||||
_binaryReader.readString();
|
||||
|
||||
if (!_binaryReader.read(&animationdata->_totalTime))
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: totalTime '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t animNum;
|
||||
if (!_binaryReader.read(&animNum))
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: animNum '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ssize_t i = 0; i < animNum; ++i)
|
||||
{
|
||||
std::string boneName = _binaryReader.readString();
|
||||
ssize_t keyframeNum;
|
||||
if (!_binaryReader.read(&keyframeNum))
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: keyframeNum '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ssize_t j = 0; j < keyframeNum; ++j)
|
||||
{
|
||||
float keytime;
|
||||
if (!_binaryReader.read(&keytime))
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: keytime '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Quaternion rotate;
|
||||
if (_binaryReader.read(&rotate, 4, 4) != 4)
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: rotate '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
animationdata->_rotationKeys[boneName].push_back(Animation3DData::QuatKey(keytime, rotate));
|
||||
|
||||
Vec3 scale;
|
||||
if (_binaryReader.read(&scale, 4, 3) != 3)
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: scale '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
animationdata->_scaleKeys[boneName].push_back(Animation3DData::Vec3Key(keytime, scale));
|
||||
|
||||
Vec3 position;
|
||||
if (_binaryReader.read(&position, 4, 3) != 3)
|
||||
{
|
||||
CCLOGINFO("Failed to read AnimationData: position '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
animationdata->_translationKeys[boneName].push_back(Animation3DData::Vec3Key(keytime, position));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GLenum Bundle3D::parseGLType(const std::string& str)
|
||||
{
|
||||
if (str == "GL_FLOAT")
|
||||
|
@ -298,23 +773,6 @@ GLenum Bundle3D::parseGLType(const std::string& str)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int Bundle3D::parseGLTypeSize(const std::string& str)
|
||||
{
|
||||
if (str == "GL_FLOAT")
|
||||
{
|
||||
return sizeof(float);
|
||||
}
|
||||
else if (str == "GL_UNSIGNED_INT")
|
||||
{
|
||||
return sizeof(unsigned int);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Bundle3D::parseGLProgramAttribute(const std::string& str)
|
||||
{
|
||||
if (str == "VERTEX_ATTRIB_POSITION")
|
||||
|
@ -348,7 +806,7 @@ unsigned int Bundle3D::parseGLProgramAttribute(const std::string& str)
|
|||
}
|
||||
}
|
||||
|
||||
void Bundle3D::getModelPath(const std::string& path)
|
||||
void Bundle3D::getModelRelativePath(const std::string& path)
|
||||
{
|
||||
int index = path.find_last_of('/');
|
||||
std::string fullModelPath;
|
||||
|
@ -365,19 +823,41 @@ void Bundle3D::getModelPath(const std::string& path)
|
|||
}
|
||||
}
|
||||
|
||||
Reference* Bundle3D::seekToFirstType(unsigned int type)
|
||||
{
|
||||
// for each Reference
|
||||
for (unsigned int i = 0; i < _referenceCount; ++i)
|
||||
{
|
||||
Reference* ref = &_references[i];
|
||||
if (ref->type == type)
|
||||
{
|
||||
// Found a match
|
||||
if (_binaryReader.seek(ref->offset, SEEK_SET) == false)
|
||||
{
|
||||
CCLOGINFO("Failed to seek to object '%s' in bundle '%s'.", ref->id.c_str(), _path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bundle3D::Bundle3D()
|
||||
:_isBinary(false)
|
||||
,_modelRelativePath("")
|
||||
,_documentBuffer(nullptr)
|
||||
,_path("")
|
||||
:_isBinary(false),
|
||||
_modelRelativePath(""),
|
||||
_path(""),
|
||||
_jsonBuffer(nullptr),
|
||||
_binaryBuffer(nullptr),
|
||||
_referenceCount(0),
|
||||
_references(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
Bundle3D::~Bundle3D()
|
||||
{
|
||||
CC_SAFE_DELETE_ARRAY(_documentBuffer);
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -34,10 +34,18 @@
|
|||
#include "base/ccTypes.h"
|
||||
|
||||
#include "json/document.h"
|
||||
#include "CCBundleReader.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class Animation3D;
|
||||
class Data;
|
||||
|
||||
/**
|
||||
* Defines a bundle file that contains a collection of assets. Mesh, Material, MeshSkin, Animation
|
||||
* There are two types of bundle files, c3t and c3b.
|
||||
* c3t text file
|
||||
* c3b binary file
|
||||
*/
|
||||
class Bundle3D
|
||||
{
|
||||
public:
|
||||
|
@ -46,6 +54,13 @@ public:
|
|||
|
||||
static void destroyInstance();
|
||||
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* load a file. You must load a file first, then call loadMeshData, loadSkinData, and so on
|
||||
* @param path File to be loaded
|
||||
* @return result of load
|
||||
*/
|
||||
bool load(const std::string& path);
|
||||
|
||||
/**
|
||||
|
@ -71,17 +86,75 @@ public:
|
|||
* @param id The ID of the animation, load the first animation in the bundle if it is empty
|
||||
*/
|
||||
bool loadAnimationData(const std::string& id, Animation3DData* animationdata);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool loadJson(const std::string& path);
|
||||
|
||||
bool loadMeshDataJson(MeshData* meshdata);
|
||||
|
||||
bool loadSkinDataJson(SkinData* skindata);
|
||||
|
||||
bool loadMaterialDataJson(MaterialData* materialdata);
|
||||
|
||||
bool loadAnimationDataJson(Animation3DData* animationdata);
|
||||
|
||||
/**
|
||||
* load data in binary
|
||||
* @param path The c3b file path
|
||||
*/
|
||||
bool loadBinary(const std::string& path);
|
||||
|
||||
/**
|
||||
* load mesh data in binary
|
||||
* @param meshdata The mesh data pointer
|
||||
*/
|
||||
bool loadMeshDataBinary(MeshData* meshdata);
|
||||
|
||||
/**
|
||||
* load skin data in binary
|
||||
* @param skindata The skin data pointer
|
||||
*/
|
||||
bool loadSkinDataBinary(SkinData* skindata);
|
||||
|
||||
/**
|
||||
* load material data in binary
|
||||
* @param materialdata The material pointer
|
||||
*/
|
||||
bool loadMaterialDataBinary(MaterialData* materialdata);
|
||||
|
||||
/**
|
||||
* load animation data in binary
|
||||
* @param animationdata The animation data pointer
|
||||
*/
|
||||
bool loadAnimationDataBinary(Animation3DData* animationdata);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* get define data type
|
||||
* @param str The type in string
|
||||
*/
|
||||
GLenum parseGLType(const std::string& str);
|
||||
|
||||
unsigned int parseGLTypeSize(const std::string& str);
|
||||
|
||||
/**
|
||||
* get vertex attribute type
|
||||
* @param str The type in string
|
||||
*/
|
||||
unsigned int parseGLProgramAttribute(const std::string& str);
|
||||
|
||||
// get model path
|
||||
void getModelPath(const std::string& path);
|
||||
/*
|
||||
* get model path
|
||||
* @param str Full path of model file
|
||||
*/
|
||||
void getModelRelativePath(const std::string& path);
|
||||
|
||||
/*
|
||||
* set the read position in buffer to the target type
|
||||
* @param The data type
|
||||
*/
|
||||
Reference* seekToFirstType(unsigned int type);
|
||||
|
||||
protected:
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
Bundle3D();
|
||||
~Bundle3D();
|
||||
|
@ -91,11 +164,17 @@ protected:
|
|||
static Bundle3D* _instance;
|
||||
|
||||
std::string _modelRelativePath;
|
||||
|
||||
char* _documentBuffer;
|
||||
std::string _path;
|
||||
|
||||
// for json reading
|
||||
char* _jsonBuffer;
|
||||
rapidjson::Document _jsonReader;
|
||||
|
||||
rapidjson::Document _document;
|
||||
// for binary reading
|
||||
Data* _binaryBuffer;
|
||||
BundleReader _binaryReader;
|
||||
size_t _referenceCount;
|
||||
Reference* _references;
|
||||
|
||||
bool _isBinary;
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
NS_CC_BEGIN
|
||||
|
||||
//mesh vertex attribute
|
||||
/**mesh vertex attribute*/
|
||||
struct MeshVertexAttrib
|
||||
{
|
||||
//attribute size
|
||||
|
@ -47,6 +47,7 @@ struct MeshVertexAttrib
|
|||
int attribSizeBytes;
|
||||
};
|
||||
|
||||
/**mesh data*/
|
||||
struct MeshData
|
||||
{
|
||||
std::vector<float> vertex;
|
||||
|
@ -78,41 +79,90 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**skin data*/
|
||||
struct SkinData
|
||||
{
|
||||
std::vector<std::string> boneNames;
|
||||
std::vector<Mat4> inverseBindPoseMatrices; //bind pose of bone
|
||||
std::vector<std::string> skinBoneNames; //skin bones affect skin
|
||||
std::vector<std::string> nodeBoneNames; //node bones don't affect skin, all bones [skinBone, nodeBone]
|
||||
std::vector<Mat4> inverseBindPoseMatrices; //bind pose of skin bone, only for skin bone
|
||||
std::vector<Mat4> skinBoneOriginMatrices; // original bone transform, for skin bone
|
||||
std::vector<Mat4> nodeBoneOriginMatrices; // original bone transform, for node bone
|
||||
|
||||
//bone child info, both skinbone and node bone
|
||||
std::map<int, std::vector<int> > boneChild;//key parent, value child
|
||||
int rootBoneIndex;
|
||||
void resetData()
|
||||
{
|
||||
boneNames.clear();
|
||||
skinBoneNames.clear();
|
||||
nodeBoneNames.clear();
|
||||
inverseBindPoseMatrices.clear();
|
||||
skinBoneOriginMatrices.clear();
|
||||
nodeBoneOriginMatrices.clear();
|
||||
boneChild.clear();
|
||||
rootBoneIndex = -1;
|
||||
}
|
||||
|
||||
void addSkinBoneNames(const std::string& name)
|
||||
{
|
||||
for (auto iter : skinBoneNames)
|
||||
{
|
||||
if ((iter) == name)
|
||||
return;
|
||||
}
|
||||
|
||||
skinBoneNames.push_back(name);
|
||||
}
|
||||
|
||||
void addNodeBoneNames(const std::string& name)
|
||||
{
|
||||
for (auto iter : nodeBoneNames)
|
||||
{
|
||||
if ((iter) == name)
|
||||
return;
|
||||
}
|
||||
|
||||
nodeBoneNames.push_back(name);
|
||||
}
|
||||
|
||||
int getSkinBoneNameIndex(const std::string& name)const
|
||||
{
|
||||
int i = 0;
|
||||
for (auto iter : skinBoneNames)
|
||||
{
|
||||
if ((iter) == name)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getBoneNameIndex(const std::string& name)const
|
||||
{
|
||||
std::vector<std::string>::const_iterator iter = boneNames.begin();
|
||||
for (int i = 0; iter != boneNames.end(); ++iter, ++i)
|
||||
int i = 0;
|
||||
for (auto iter : skinBoneNames)
|
||||
{
|
||||
if ((*iter) == name)
|
||||
{
|
||||
if ((iter) == name)
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for(auto iter : nodeBoneNames)
|
||||
{
|
||||
if (iter == name)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**material data*/
|
||||
struct MaterialData
|
||||
{
|
||||
std::string texturePath;
|
||||
};
|
||||
|
||||
/**animation data*/
|
||||
struct Animation3DData
|
||||
{
|
||||
public:
|
||||
|
@ -182,6 +232,19 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**reference data*/
|
||||
struct Reference
|
||||
{
|
||||
public:
|
||||
std::string id;
|
||||
unsigned int type;
|
||||
unsigned int offset;
|
||||
|
||||
Reference(){}
|
||||
|
||||
~Reference(){}
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif //__CC_BUNDLE_3D_DATA_H__
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#include "CCBundleReader.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
BundleReader::BundleReader()
|
||||
{
|
||||
m_buffer = NULL;
|
||||
m_position = 0;
|
||||
m_length = 0;
|
||||
};
|
||||
|
||||
BundleReader::~BundleReader()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void BundleReader::init(char* lpbuffer, unsigned int length)
|
||||
{
|
||||
m_position = 0;
|
||||
m_buffer = lpbuffer;
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
ssize_t BundleReader::read(void* ptr, ssize_t size, ssize_t count)
|
||||
{
|
||||
if (!m_buffer || eof())
|
||||
return 0;
|
||||
|
||||
ssize_t validCount;
|
||||
ssize_t validLength = m_length - m_position;
|
||||
ssize_t needLength = size*count;
|
||||
char* ptr1 = (char*)ptr;
|
||||
if(validLength <= needLength)
|
||||
{
|
||||
validCount = validLength/size;
|
||||
ssize_t readLength = size*validCount;
|
||||
memcpy(ptr1,(char*)m_buffer+m_position,readLength);
|
||||
ptr1 += readLength;
|
||||
m_position += readLength;
|
||||
readLength = validLength - readLength;
|
||||
if(readLength>0)
|
||||
{
|
||||
memcpy(ptr1,(char*)m_buffer+m_position,readLength);
|
||||
m_position += readLength;
|
||||
validCount+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ptr1,(char*)m_buffer+m_position,needLength);
|
||||
m_position += needLength;
|
||||
validCount = count;
|
||||
}
|
||||
|
||||
return validCount;
|
||||
}
|
||||
|
||||
char* BundleReader::readLine(int num,char* line)
|
||||
{
|
||||
if (!m_buffer)
|
||||
return 0;
|
||||
|
||||
char* buffer = (char*)m_buffer+m_position;
|
||||
char* p = line;
|
||||
char c;
|
||||
ssize_t readNum = 0;
|
||||
while((c=*buffer) != 10 && readNum < (ssize_t)num && m_position<(long int)m_length)
|
||||
{
|
||||
*p = c;
|
||||
p++;
|
||||
buffer++;
|
||||
m_position++;
|
||||
readNum++;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool BundleReader::eof()
|
||||
{
|
||||
if (!m_buffer)
|
||||
return true;
|
||||
|
||||
return ((ssize_t)tell()) >= length();
|
||||
}
|
||||
|
||||
ssize_t BundleReader::length()
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
long int BundleReader::tell()
|
||||
{
|
||||
if (!m_buffer)
|
||||
return -1;
|
||||
return m_position;
|
||||
}
|
||||
|
||||
bool BundleReader::seek(long int offset, int origin)
|
||||
{
|
||||
if (!m_buffer)
|
||||
return false;
|
||||
|
||||
if(origin == SEEK_CUR)
|
||||
{
|
||||
m_position += offset;
|
||||
}
|
||||
else if(origin == SEEK_SET)
|
||||
{
|
||||
m_position = offset;
|
||||
}
|
||||
else if(origin == SEEK_END)
|
||||
{
|
||||
m_position = m_length+offset;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BundleReader::rewind()
|
||||
{
|
||||
if (m_buffer != NULL)
|
||||
{
|
||||
m_position = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string BundleReader::readString()
|
||||
{
|
||||
unsigned int length;
|
||||
if(read(&length, 4, 1) != 1)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string str;
|
||||
if (length > 0)
|
||||
{
|
||||
str.resize(length);
|
||||
if (read(&str[0], 1, length) != length)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
bool BundleReader::readMatrix(float* m)
|
||||
{
|
||||
return (read(m, sizeof(float), 16) == 16);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CC_BUNDLE_READER_H__
|
||||
#define __CC_BUNDLE_READER_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/CCRef.h"
|
||||
#include "base/CCPlatformMacros.h"
|
||||
#include "base/CCConsole.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* BundleReader is an interface for reading sequence of bytes.
|
||||
*/
|
||||
class BundleReader: public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Structor
|
||||
*/
|
||||
BundleReader();
|
||||
|
||||
/**
|
||||
* inicial
|
||||
*/
|
||||
~BundleReader();
|
||||
|
||||
/**
|
||||
* initialise
|
||||
* @param lpbuffer The data buffer pointer
|
||||
* @param length The data buffer size
|
||||
*/
|
||||
void init(char* lpbuffer, unsigned int length);
|
||||
|
||||
/**
|
||||
* Reads an array of elements.
|
||||
*
|
||||
* @param ptr The pointer to the memory to copy into.
|
||||
* The available size should be at least bytes.
|
||||
* @param size The size of each element to be read, in bytes.
|
||||
* @param count The number of elements to read.
|
||||
*
|
||||
* @return The number of elements read.
|
||||
*/
|
||||
ssize_t read(void* ptr, ssize_t size, ssize_t count);
|
||||
|
||||
/**
|
||||
* Reads a line from the buffer.
|
||||
*/
|
||||
char* readLine(int num, char* line);
|
||||
|
||||
/**
|
||||
* Returns true if the end of the buffer has been reached.
|
||||
*/
|
||||
bool eof();
|
||||
|
||||
/**
|
||||
* Returns the length of the buffer in bytes.
|
||||
*/
|
||||
ssize_t length();
|
||||
|
||||
/**
|
||||
* Returns the position of the file pointer.
|
||||
*/
|
||||
long int tell();
|
||||
|
||||
/**
|
||||
* Sets the position of the file pointer.
|
||||
*/
|
||||
bool seek(long int offset, int origin);
|
||||
|
||||
/**
|
||||
* Sets the file pointer at the start of the file.
|
||||
*/
|
||||
bool rewind();
|
||||
|
||||
/**
|
||||
* read binary typed value.
|
||||
*/
|
||||
template<typename T> bool read(T* ptr);
|
||||
template<typename T> bool readArray(unsigned int* length, std::vector<T>* values);
|
||||
|
||||
/**
|
||||
* first read length, then read string text
|
||||
*/
|
||||
std::string readString();
|
||||
bool readMatrix(float* m);
|
||||
|
||||
private:
|
||||
long int m_position;
|
||||
ssize_t m_length;
|
||||
char* m_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* template read routines
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool BundleReader::read(T *ptr)
|
||||
{
|
||||
return (read(ptr, sizeof(T), 1) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* template function to read array of value.
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool BundleReader::readArray(unsigned int *length, std::vector<T> *values)
|
||||
{
|
||||
if (!read(length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*length > 0 && values)
|
||||
{
|
||||
values->resize(*length);
|
||||
if (read(&(*values)[0], sizeof(T), *length) != *length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* specalization for char
|
||||
*/
|
||||
template<>
|
||||
inline bool BundleReader::read<char>(char *ptr)
|
||||
{
|
||||
if (read(ptr, sizeof(char), 1) == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* specalization for std::string
|
||||
*/
|
||||
template<>
|
||||
inline bool BundleReader::read<std::string>(std::string *ptr)
|
||||
{
|
||||
CCLOG("can not read std::string, use readString() instead");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* template function to read array of value.
|
||||
*/
|
||||
template<>
|
||||
inline bool BundleReader::readArray<std::string>(unsigned int *length, std::vector<std::string> *values)
|
||||
{
|
||||
if (!read(length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
values->clear();
|
||||
if (*length > 0 && values)
|
||||
{
|
||||
for (int i = 0; i < (int)*length; ++i)
|
||||
{
|
||||
values->push_back(readString());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif
|
|
@ -62,7 +62,10 @@ protected:
|
|||
std::vector<MeshVertexAttrib> _vertexAttribs;
|
||||
};
|
||||
|
||||
/** Mesh: TODO, add description of Mesh */
|
||||
/**
|
||||
* Mesh: Geometry with a collection of vertex.
|
||||
* Supporting various vertex formats.
|
||||
*/
|
||||
class Mesh : public Ref
|
||||
{
|
||||
public:
|
||||
|
@ -83,41 +86,49 @@ public:
|
|||
POINTS = GL_POINTS
|
||||
};
|
||||
|
||||
//create
|
||||
/**create mesh from positions, normals, and so on*/
|
||||
static Mesh* create(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const std::vector<unsigned short>& indices);
|
||||
|
||||
/**create mesh with vertex attributes*/
|
||||
static Mesh* create(const std::vector<float>& vertices, int vertexSizeInFloat, const std::vector<unsigned short>& indices, int numIndex, const std::vector<MeshVertexAttrib>& attribs, int attribCount);
|
||||
|
||||
//get vertex buffer
|
||||
/**get vertex buffer*/
|
||||
inline GLuint getVertexBuffer() const { return _vertexBuffer; }
|
||||
|
||||
//get mesh vertex attribute count
|
||||
/**get mesh vertex attribute count*/
|
||||
ssize_t getMeshVertexAttribCount() const { return _renderdata._vertexAttribs.size(); }
|
||||
//get MeshVertexAttribute by index
|
||||
/**get MeshVertexAttribute by index*/
|
||||
const MeshVertexAttrib& getMeshVertexAttribute(int idx) const { return _renderdata._vertexAttribs[idx]; }
|
||||
//has vertex attribute?
|
||||
/**has vertex attribute?*/
|
||||
bool hasVertexAttrib(int attrib) { return _renderdata.hasVertexAttrib(attrib); }
|
||||
//get per vertex size in bytes
|
||||
/**get per vertex size in bytes*/
|
||||
int getVertexSizeInBytes() const { return _renderdata._vertexsizeBytes; }
|
||||
|
||||
/** get primitive type*/
|
||||
PrimitiveType getPrimitiveType() const { return _primitiveType; }
|
||||
/**get index count*/
|
||||
ssize_t getIndexCount() const { return _indexCount; }
|
||||
/**get index format*/
|
||||
IndexFormat getIndexFormat() const { return _indexFormat; }
|
||||
/**get index buffer*/
|
||||
GLuint getIndexBuffer() const {return _indexBuffer; }
|
||||
|
||||
//build vertex buffer from renderdata
|
||||
/**build vertex buffer from renderdata*/
|
||||
void restore();
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
||||
Mesh();
|
||||
virtual ~Mesh();
|
||||
/**init mesh*/
|
||||
bool init(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const std::vector<unsigned short>& indices);
|
||||
|
||||
/**init mesh*/
|
||||
bool init(const std::vector<float>& vertices, int vertexSizeInFloat, const std::vector<unsigned short>& indices, int numIndex, const std::vector<MeshVertexAttrib>& attribs, int attribCount);
|
||||
|
||||
//build buffer
|
||||
/**build buffer*/
|
||||
void buildBuffer();
|
||||
/**free buffer*/
|
||||
void cleanAndFreeBuffers();
|
||||
|
||||
protected:
|
||||
|
@ -131,20 +142,25 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* MeshCache
|
||||
* Mesh Cache
|
||||
*/
|
||||
class MeshCache
|
||||
{
|
||||
public:
|
||||
/**get & destroy*/
|
||||
static MeshCache* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
/**get mesh from cache*/
|
||||
Mesh* getMesh(const std::string& key) const;
|
||||
|
||||
/**add mesh to cache*/
|
||||
bool addMesh(const std::string& key, Mesh* mesh);
|
||||
|
||||
/**remove all meshes*/
|
||||
void removeAllMeshes();
|
||||
|
||||
/**remove unused meshes*/
|
||||
void removeUnusedMesh();
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
|
@ -158,9 +174,9 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
|
||||
protected:
|
||||
|
||||
static MeshCache* _cacheInstance;
|
||||
static MeshCache* _cacheInstance;//instance
|
||||
|
||||
std::unordered_map<std::string, Mesh*> _meshes;
|
||||
std::unordered_map<std::string, Mesh*> _meshes; //cached meshes
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
EventListenerCustom* _backToForegroundlistener;
|
||||
|
|
|
@ -46,6 +46,20 @@ const Mat4& Bone::getInverseBindPose()
|
|||
return _invBindPose;
|
||||
}
|
||||
|
||||
void Bone::setOriPose(const Mat4& m)
|
||||
{
|
||||
_oriPose = m;
|
||||
}
|
||||
|
||||
void Bone::resetPose()
|
||||
{
|
||||
_local =_oriPose;
|
||||
|
||||
for (auto it : _children) {
|
||||
it->resetPose();
|
||||
}
|
||||
}
|
||||
|
||||
void Bone::setWorldMatDirty(bool dirty)
|
||||
{
|
||||
_worldDirty = dirty;
|
||||
|
@ -81,8 +95,21 @@ const Mat4& Bone::getWorldMat()
|
|||
return _world;
|
||||
}
|
||||
|
||||
void Bone::setAnimationValue(float* trans, float* rot, float* scale, float weight)
|
||||
void Bone::setAnimationValue(float* trans, float* rot, float* scale, void* tag, float weight)
|
||||
{
|
||||
for (auto& it : _blendStates) {
|
||||
if (it.tag == tag)
|
||||
{
|
||||
if (trans)
|
||||
it.localTranslate.set(trans);
|
||||
if (rot)
|
||||
it.localRot.set(rot);
|
||||
if (scale)
|
||||
it.localScale.set(scale);
|
||||
it.weight = weight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
BoneBlendState state;
|
||||
if (trans)
|
||||
state.localTranslate.set(trans);
|
||||
|
@ -92,9 +119,9 @@ void Bone::setAnimationValue(float* trans, float* rot, float* scale, float weigh
|
|||
state.localScale.set(scale);
|
||||
|
||||
state.weight = weight;
|
||||
state.tag = tag;
|
||||
|
||||
_blendStates.push_back(state);
|
||||
_localDirty = true;
|
||||
}
|
||||
|
||||
void Bone::clearBoneBlendState()
|
||||
|
@ -115,13 +142,6 @@ Bone* Bone::create(const std::string& id)
|
|||
return bone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates the joint matrix.
|
||||
*
|
||||
* @param matrixPalette The matrix palette to update.
|
||||
*/
|
||||
void Bone::updateJointMatrix(Vec4* matrixPalette)
|
||||
{
|
||||
{
|
||||
|
@ -134,12 +154,11 @@ void Bone::updateJointMatrix(Vec4* matrixPalette)
|
|||
}
|
||||
}
|
||||
|
||||
//bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.
|
||||
Bone* Bone::getParentBone()
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
int Bone::getChildBoneCount() const
|
||||
ssize_t Bone::getChildBoneCount() const
|
||||
{
|
||||
return _children.size();
|
||||
}
|
||||
|
@ -168,15 +187,11 @@ void Bone::removeAllChildBone()
|
|||
Bone::Bone(const std::string& id)
|
||||
: _name(id)
|
||||
, _parent(nullptr)
|
||||
, _localDirty(true)
|
||||
, _worldDirty(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
Bone::~Bone()
|
||||
{
|
||||
removeAllChildBone();
|
||||
|
@ -186,8 +201,8 @@ void Bone::updateLocalMat()
|
|||
{
|
||||
if (_blendStates.size())
|
||||
{
|
||||
Vec3 translate(Vec3::ZERO), scale(Vec3::ONE);
|
||||
Quaternion quat(Quaternion::identity());
|
||||
Vec3 translate(Vec3::ZERO), scale(Vec3::ZERO);
|
||||
Quaternion quat(Quaternion::zero());
|
||||
|
||||
float total = 0.f;
|
||||
for (auto it: _blendStates) {
|
||||
|
@ -195,13 +210,12 @@ void Bone::updateLocalMat()
|
|||
}
|
||||
if (total)
|
||||
{
|
||||
//if (_blendStates.size() == 1)
|
||||
if (true)
|
||||
if (_blendStates.size() == 1)
|
||||
{
|
||||
int cnt = _blendStates.size();
|
||||
translate = _blendStates[cnt - 1].localTranslate;
|
||||
scale = _blendStates[cnt - 1].localScale;
|
||||
quat = _blendStates[cnt - 1].localRot;
|
||||
auto& state = _blendStates[0];
|
||||
translate = state.localTranslate;
|
||||
scale = state.localScale;
|
||||
quat = state.localRot;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -209,24 +223,18 @@ void Bone::updateLocalMat()
|
|||
for (auto it : _blendStates) {
|
||||
float weight = (it.weight * invTotal);
|
||||
translate += it.localTranslate * weight;
|
||||
if (!it.localScale.isZero())
|
||||
scale.x += it.localScale.x * weight;
|
||||
scale.y += it.localScale.y * weight;
|
||||
scale.z += it.localScale.z * weight;
|
||||
if (!quat.isZero())
|
||||
{
|
||||
scale.x *= it.localScale.x * weight;
|
||||
scale.y *= it.localScale.y * weight;
|
||||
scale.z *= it.localScale.z * weight;
|
||||
}
|
||||
if (!it.localRot.isZero())
|
||||
{
|
||||
if (!quat.isZero())
|
||||
{
|
||||
Quaternion& q = _blendStates[0].localRot;
|
||||
if (q.x * quat.x + q.y * quat.y + q.z * quat.z + q.w * quat.w < 0)
|
||||
Quaternion& q = _blendStates[0].localRot;
|
||||
if (q.x * quat.x + q.y * quat.y + q.z * quat.z + q.w * quat.w < 0)
|
||||
weight = -weight;
|
||||
}
|
||||
quat = Quaternion(it.localRot.x * weight + quat.x, it.localRot.y * weight + quat.y, it.localRot.z * weight + quat.z, it.localRot.w * weight + quat.w);
|
||||
}
|
||||
quat = Quaternion(it.localRot.x * weight + quat.x, it.localRot.y * weight + quat.y, it.localRot.z * weight + quat.z, it.localRot.w * weight + quat.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mat4::createTranslation(translate, &_local);
|
||||
|
@ -234,13 +242,7 @@ void Bone::updateLocalMat()
|
|||
_local.scale(scale);
|
||||
|
||||
_blendStates.clear();
|
||||
_localDirty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("use cached local");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -295,11 +297,17 @@ MeshSkin* MeshSkin::create(const std::string& filename, const std::string& name)
|
|||
|
||||
bool MeshSkin::initFromSkinData(const SkinData& skindata)
|
||||
{
|
||||
setBoneCount((int)skindata.boneNames.size());
|
||||
for (size_t i = 0; i < skindata.boneNames.size(); i++) {
|
||||
auto bone = Bone::create(skindata.boneNames[i]);
|
||||
ssize_t i = 0;
|
||||
for (; i < skindata.skinBoneNames.size(); i++) {
|
||||
auto bone = Bone::create(skindata.skinBoneNames[i]);
|
||||
bone->_invBindPose = skindata.inverseBindPoseMatrices[i];
|
||||
addBone(bone);
|
||||
bone->setOriPose(skindata.skinBoneOriginMatrices[i]);
|
||||
addSkinBone(bone);
|
||||
}
|
||||
for (i = 0; i < skindata.nodeBoneNames.size(); i++) {
|
||||
auto bone = Bone::create(skindata.nodeBoneNames[i]);
|
||||
bone->setOriPose(skindata.nodeBoneOriginMatrices[i]);
|
||||
addNodeBone(bone);
|
||||
}
|
||||
for (auto it : skindata.boneChild) {
|
||||
auto parent = getBoneByIndex(it.first);
|
||||
|
@ -311,29 +319,42 @@ bool MeshSkin::initFromSkinData(const SkinData& skindata)
|
|||
}
|
||||
|
||||
setRootBone(getBoneByIndex(skindata.rootBoneIndex));
|
||||
_rootBone->resetPose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int MeshSkin::getBoneCount() const
|
||||
ssize_t MeshSkin::getBoneCount() const
|
||||
{
|
||||
return _bones.size();
|
||||
return _skinBones.size() + _nodeBones.size();
|
||||
}
|
||||
|
||||
//get bone
|
||||
Bone* MeshSkin::getBoneByIndex(unsigned int index) const
|
||||
{
|
||||
return _bones.at(index);
|
||||
if (index < _skinBones.size())
|
||||
return _skinBones.at(index);
|
||||
index -= _skinBones.size();
|
||||
if (index < _nodeBones.size())
|
||||
return _nodeBones.at(index);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
Bone* MeshSkin::getBoneByName(const std::string& id) const
|
||||
{
|
||||
for (auto it : _bones) {
|
||||
//search from skin bones
|
||||
for (auto it : _skinBones) {
|
||||
if (it->getName() == id)
|
||||
return it;
|
||||
}
|
||||
//search from node bones
|
||||
for (auto it : _nodeBones) {
|
||||
if (it->getName() == id )
|
||||
return it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//get & set root bone
|
||||
Bone* MeshSkin::getRootBone() const
|
||||
{
|
||||
return _rootBone;
|
||||
|
@ -345,36 +366,16 @@ void MeshSkin::setRootBone(Bone* joint)
|
|||
_rootBone = joint;
|
||||
}
|
||||
|
||||
void MeshSkin::setBoneCount(int boneCount)
|
||||
int MeshSkin::getBoneIndex(Bone* bone) const
|
||||
{
|
||||
removeAllBones();
|
||||
|
||||
// Resize the joints vector and initialize to NULL
|
||||
_bones.reserve(boneCount);
|
||||
// for (auto i = 0; i < boneCount; i++)
|
||||
// {
|
||||
// _bones.pushBack(nullptr);
|
||||
// }
|
||||
|
||||
// Rebuild the matrix palette. Each matrix is 3 rows of Vec4.
|
||||
CC_SAFE_DELETE_ARRAY(_matrixPalette);
|
||||
|
||||
if (boneCount > 0)
|
||||
{
|
||||
_matrixPalette = new Vec4[boneCount * PALETTE_ROWS];
|
||||
for (unsigned int i = 0; i < boneCount * PALETTE_ROWS; i+=PALETTE_ROWS)
|
||||
{
|
||||
_matrixPalette[i+0].set(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
_matrixPalette[i+1].set(0.0f, 1.0f, 0.0f, 0.0f);
|
||||
_matrixPalette[i+2].set(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
int i = 0;
|
||||
for (; i < _skinBones.size(); i++) {
|
||||
if (_skinBones.at(i) == bone)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
int MeshSkin::getBoneIndex(Bone* joint) const
|
||||
{
|
||||
for (auto i = 0; i < _bones.size(); i++) {
|
||||
if (_bones.at(i) == joint)
|
||||
int index = 0;
|
||||
for (; index < _nodeBones.size(); index++, i++) {
|
||||
if (_nodeBones.at(index) == bone)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
|
@ -385,8 +386,12 @@ Vec4* MeshSkin::getMatrixPalette()
|
|||
{
|
||||
updateBoneMatrix();
|
||||
|
||||
if (_matrixPalette == nullptr)
|
||||
{
|
||||
_matrixPalette = new Vec4[_skinBones.size() * PALETTE_ROWS];
|
||||
}
|
||||
int i = 0;
|
||||
for (auto it : _bones )
|
||||
for (auto it : _skinBones )
|
||||
{
|
||||
it->updateJointMatrix(&_matrixPalette[i++ * PALETTE_ROWS]);
|
||||
}
|
||||
|
@ -394,10 +399,9 @@ Vec4* MeshSkin::getMatrixPalette()
|
|||
return _matrixPalette;
|
||||
}
|
||||
|
||||
//getBoneCount() * 3
|
||||
unsigned int MeshSkin::getMatrixPaletteSize() const
|
||||
ssize_t MeshSkin::getMatrixPaletteSize() const
|
||||
{
|
||||
return _bones.size() * PALETTE_ROWS;
|
||||
return _skinBones.size() * PALETTE_ROWS;
|
||||
}
|
||||
|
||||
//refresh bone world matrix
|
||||
|
@ -409,14 +413,20 @@ void MeshSkin::updateBoneMatrix()
|
|||
|
||||
void MeshSkin::removeAllBones()
|
||||
{
|
||||
_bones.clear();
|
||||
_skinBones.clear();
|
||||
_nodeBones.clear();
|
||||
CC_SAFE_DELETE_ARRAY(_matrixPalette);
|
||||
CC_SAFE_RELEASE(_rootBone);
|
||||
}
|
||||
|
||||
void MeshSkin::addBone(Bone* bone)
|
||||
void MeshSkin::addSkinBone(Bone* bone)
|
||||
{
|
||||
_bones.pushBack(bone);
|
||||
_skinBones.pushBack(bone);
|
||||
}
|
||||
|
||||
void MeshSkin::addNodeBone(Bone* bone)
|
||||
{
|
||||
_nodeBones.pushBack(bone);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -52,17 +52,26 @@ public:
|
|||
*/
|
||||
const Mat4& getInverseBindPose();
|
||||
|
||||
//update own world matrix and children's
|
||||
/**update own world matrix and children's*/
|
||||
void updateWorldMat();
|
||||
|
||||
void setWorldMatDirty(bool dirty = true);
|
||||
|
||||
/**get wrod matrix*/
|
||||
const Mat4& getWorldMat();
|
||||
|
||||
/**get bone name*/
|
||||
const std::string& getName() const { return _name; }
|
||||
|
||||
void setAnimationValue(float* trans, float* rot, float* scale, float weight = 1.0f);
|
||||
/**
|
||||
* set animation value
|
||||
* @param trans translate vec3
|
||||
* @param rot rotation quaternion
|
||||
* @param scale scale vec3
|
||||
* @param tag, unique tag, only blend animation between different tags
|
||||
* @param weight, blend weight
|
||||
*/
|
||||
void setAnimationValue(float* trans, float* rot, float* scale, void* tag = nullptr, float weight = 1.0f);
|
||||
|
||||
/**clear bone blend states*/
|
||||
void clearBoneBlendState();
|
||||
/**
|
||||
* Creates C3DBone.
|
||||
|
@ -72,10 +81,22 @@ public:
|
|||
/**
|
||||
* Sets the inverse bind pose matrix.
|
||||
*
|
||||
* @param m C3DMatrix representing the inverse bind pose for this Bone.
|
||||
* @param m Mat4 representing the inverse bind pose for this Bone.
|
||||
*/
|
||||
void setInverseBindPose(const Mat4& m);
|
||||
|
||||
/**
|
||||
* Sets the bone's original pose.
|
||||
*
|
||||
* @param m Mat4 representing the original pose for this Bone.
|
||||
*/
|
||||
void setOriPose(const Mat4& m);
|
||||
|
||||
/**
|
||||
* reset pose to origin
|
||||
*/
|
||||
void resetPose();
|
||||
|
||||
/**
|
||||
* Updates the joint matrix.
|
||||
*
|
||||
|
@ -83,13 +104,19 @@ public:
|
|||
*/
|
||||
void updateJointMatrix(Vec4* matrixPalette);
|
||||
|
||||
//bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.
|
||||
/**bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.*/
|
||||
Bone* getParentBone();
|
||||
int getChildBoneCount() const;
|
||||
/**get child bone count*/
|
||||
ssize_t getChildBoneCount() const;
|
||||
/**get child bone by index*/
|
||||
Bone* getChildBoneByIndex(int index);
|
||||
/**add child bone*/
|
||||
void addChildBone(Bone* bone);
|
||||
/**remove child bone by index*/
|
||||
void removeChildBoneByIndex(int index);
|
||||
/**remove child bone*/
|
||||
void removeChildBone(Bone* bone);
|
||||
/**remove all child bone*/
|
||||
void removeAllChildBone();
|
||||
|
||||
|
||||
|
@ -102,11 +129,13 @@ protected:
|
|||
Quaternion localRot;
|
||||
Vec3 localScale;
|
||||
float weight;
|
||||
void* tag; //
|
||||
BoneBlendState()
|
||||
: localTranslate(Vec3::ZERO)
|
||||
, localRot(Quaternion::identity())
|
||||
, localScale(Vec3::ONE)
|
||||
, weight(1.f)
|
||||
, tag(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -126,17 +155,21 @@ protected:
|
|||
*/
|
||||
void updateLocalMat();
|
||||
|
||||
std::string _name;
|
||||
/**set world matrix dirty flag*/
|
||||
void setWorldMatDirty(bool dirty = true);
|
||||
|
||||
std::string _name; // bone name
|
||||
/**
|
||||
* The Mat4 representation of the Joint's bind pose.
|
||||
*/
|
||||
Mat4 _invBindPose;
|
||||
|
||||
Bone* _parent;
|
||||
Mat4 _oriPose; //original bone pose
|
||||
|
||||
Bone* _parent; //parent bone
|
||||
|
||||
Vector<Bone*> _children;
|
||||
|
||||
bool _localDirty;
|
||||
bool _worldDirty;
|
||||
Mat4 _world;
|
||||
Mat4 _local;
|
||||
|
@ -145,35 +178,38 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* MeshSkin, A class maintain a collection of bones that affect Mesh vertex.
|
||||
* And it is responsible for computing matrix palletes that used by skin mesh rendering.
|
||||
*/
|
||||
class MeshSkin: public Ref
|
||||
{
|
||||
public:
|
||||
|
||||
//create a new meshskin if do not want to share meshskin
|
||||
/**create a new meshskin if do not want to share meshskin*/
|
||||
static MeshSkin* create(const std::string& filename, const std::string& name);
|
||||
|
||||
unsigned int getBoneCount() const;
|
||||
/**get total bone count, skin bone + node bone*/
|
||||
ssize_t getBoneCount() const;
|
||||
|
||||
void setBoneCount(int boneCount);
|
||||
|
||||
//get bone
|
||||
/**get bone*/
|
||||
Bone* getBoneByIndex(unsigned int index) const;
|
||||
Bone* getBoneByName(const std::string& id) const;
|
||||
|
||||
//get & set root bone
|
||||
/**get & set root bone*/
|
||||
Bone* getRootBone() const;
|
||||
void setRootBone(Bone* joint);
|
||||
void setRootBone(Bone* bone);
|
||||
|
||||
int getBoneIndex(Bone* joint) const;
|
||||
/**get bone index*/
|
||||
int getBoneIndex(Bone* bone) const;
|
||||
|
||||
//compute matrix palette used by gpu skin
|
||||
/**compute matrix palette used by gpu skin*/
|
||||
Vec4* getMatrixPalette();
|
||||
|
||||
//getBoneCount() * 3
|
||||
unsigned int getMatrixPaletteSize() const;
|
||||
/**getSkinBoneCount() * 3*/
|
||||
ssize_t getMatrixPaletteSize() const;
|
||||
|
||||
//refresh bone world matrix
|
||||
/**refresh bone world matrix*/
|
||||
void updateBoneMatrix();
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
@ -182,43 +218,58 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
|
||||
~MeshSkin();
|
||||
|
||||
/**init from skin data*/
|
||||
bool initFromSkinData(const SkinData& skindata);
|
||||
|
||||
/**remove all bones*/
|
||||
void removeAllBones();
|
||||
|
||||
void addBone(Bone* bone);
|
||||
/**add skin bone*/
|
||||
void addSkinBone(Bone* bone);
|
||||
|
||||
/**add Node bone*/
|
||||
void addNodeBone(Bone* bone);
|
||||
|
||||
protected:
|
||||
|
||||
Vector<Bone*> _bones;
|
||||
Vector<Bone*> _skinBones; // bones with skin
|
||||
Vector<Bone*> _nodeBones; //bones without skin, only used to compute transform of children
|
||||
|
||||
Bone* _rootBone;
|
||||
|
||||
// Pointer to the array of palette matrices.
|
||||
// This array is passed to the vertex shader as a uniform.
|
||||
// Each 4x3 row-wise matrix is represented as 3 Vec4's.
|
||||
// The number of Vec4's is (_joints.size() * 3).
|
||||
// The number of Vec4's is (_skinBones.size() * 3).
|
||||
Vec4* _matrixPalette;
|
||||
};
|
||||
|
||||
/**
|
||||
* MeshSkinData Cache
|
||||
*/
|
||||
class MeshSkinDataCache
|
||||
{
|
||||
public:
|
||||
/**get & destroy*/
|
||||
static MeshSkinDataCache* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
/**get mesh skin data from cache*/
|
||||
const SkinData* getMeshSkinData(const std::string& key) const;
|
||||
|
||||
/**add mesh skin data to cache*/
|
||||
bool addMeshSkinData(const std::string& key, const SkinData& skinData);
|
||||
|
||||
/**remove all mesh skin data*/
|
||||
void removeAllMeshSkinData();
|
||||
|
||||
protected:
|
||||
MeshSkinDataCache();
|
||||
~MeshSkinDataCache();
|
||||
|
||||
static MeshSkinDataCache* _cacheInstance;
|
||||
static MeshSkinDataCache* _cacheInstance; // instance
|
||||
|
||||
std::unordered_map<std::string, SkinData> _skinDatas;
|
||||
std::unordered_map<std::string, SkinData> _skinDatas; //cached skindatas
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -273,6 +273,8 @@ void Sprite3D::genGLProgramState()
|
|||
}
|
||||
|
||||
setGLProgramState(programstate);
|
||||
GLuint texID = _texture ? _texture->getName() : 0;
|
||||
_meshCommand.genMaterialID(texID, programstate, _mesh, _blend);
|
||||
}
|
||||
|
||||
GLProgram* Sprite3D::getDefaultGLProgram(bool textured)
|
||||
|
@ -296,11 +298,12 @@ GLProgram* Sprite3D::getDefaultGLProgram(bool textured)
|
|||
void Sprite3D::setTexture(const std::string& texFile)
|
||||
{
|
||||
auto tex = Director::getInstance()->getTextureCache()->addImage(texFile);
|
||||
if( tex && _texture != tex ) {
|
||||
CC_SAFE_RETAIN(tex);
|
||||
CC_SAFE_RELEASE_NULL(_texture);
|
||||
_texture = tex;
|
||||
}
|
||||
// if( tex && _texture != tex ) {
|
||||
// CC_SAFE_RETAIN(tex);
|
||||
// CC_SAFE_RELEASE_NULL(_texture);
|
||||
// _texture = tex;
|
||||
// }
|
||||
setTexture(tex);
|
||||
}
|
||||
|
||||
void Sprite3D::setTexture(Texture2D* texture)
|
||||
|
@ -309,6 +312,11 @@ void Sprite3D::setTexture(Texture2D* texture)
|
|||
CC_SAFE_RETAIN(texture);
|
||||
CC_SAFE_RELEASE_NULL(_texture);
|
||||
_texture = texture;
|
||||
if (getGLProgramState() && _mesh)
|
||||
{
|
||||
GLuint texID = _texture ? _texture->getName() : 0;
|
||||
_meshCommand.genMaterialID(texID, getGLProgramState(), _mesh, _blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,22 +40,24 @@ class Mesh;
|
|||
class Texture2D;
|
||||
class MeshSkin;
|
||||
|
||||
/** Sprite3D: TODO add description */
|
||||
/** Sprite3D: A sprite can be loaded from 3D model files, .obj, .c3t, .c3b, then can be drawed as sprite */
|
||||
class Sprite3D : public Node, public BlendProtocol
|
||||
{
|
||||
public:
|
||||
/// creates a Sprite3D
|
||||
/** creates a Sprite3D*/
|
||||
static Sprite3D* create(const std::string &modelPath);
|
||||
|
||||
// creates a Sprite3D. It only supports one texture, and overrides the internal texture with 'texturePath'
|
||||
static Sprite3D* create(const std::string &modelPath, const std::string &texturePath);
|
||||
|
||||
//set texture
|
||||
/**set texture*/
|
||||
void setTexture(const std::string& texFile);
|
||||
void setTexture(Texture2D* texture);
|
||||
|
||||
/**get mesh*/
|
||||
Mesh* getMesh() const { return _mesh; }
|
||||
|
||||
/**get skin*/
|
||||
MeshSkin* getSkin() const { return _skin; }
|
||||
|
||||
// overrides
|
||||
|
@ -68,28 +70,31 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
virtual ~Sprite3D();
|
||||
bool initWithFile(const std::string &path);
|
||||
|
||||
//.mtl file should at the same directory with the same name if exist
|
||||
/**.mtl file should at the same directory with the same name if exist*/
|
||||
bool loadFromObj(const std::string& path);
|
||||
|
||||
//load from .c3b or .c3t
|
||||
/**load from .c3b or .c3t*/
|
||||
bool loadFromC3x(const std::string& path);
|
||||
|
||||
/**draw*/
|
||||
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
|
||||
|
||||
/**get default shader*/
|
||||
virtual GLProgram* getDefaultGLProgram(bool textured = true);
|
||||
|
||||
/**generate default GLProgramState*/
|
||||
void genGLProgramState();
|
||||
|
||||
protected:
|
||||
Mesh *_mesh;
|
||||
MeshSkin *_skin;
|
||||
Mesh* _mesh;//mesh
|
||||
MeshSkin* _skin;//skin
|
||||
|
||||
MeshCommand _meshCommand;
|
||||
MeshCommand _meshCommand; //render command
|
||||
Texture2D* _texture;
|
||||
BlendFunc _blend;
|
||||
BlendFunc _blend;
|
||||
};
|
||||
|
||||
extern std::string s_attributeNames[];
|
||||
extern std::string s_attributeNames[];//attribute names array
|
||||
|
||||
NS_CC_END
|
||||
#endif // __SPRITE3D_H_
|
||||
|
|
|
@ -44,15 +44,19 @@ class Texture2D;
|
|||
class Sprite3DMaterialCache
|
||||
{
|
||||
public:
|
||||
|
||||
/**get & destroy cache*/
|
||||
static Sprite3DMaterialCache* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
/**add to cache*/
|
||||
bool addSprite3DMaterial(const std::string& key, Texture2D* tex);
|
||||
|
||||
/**get material from cache*/
|
||||
Texture2D* getSprite3DMaterial(const std::string& key);
|
||||
|
||||
/**remove all spritematerial*/
|
||||
void removeAllSprite3DMaterial();
|
||||
/**remove unused spritematerial*/
|
||||
void removeUnusedSprite3DMaterial();
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
@ -61,8 +65,8 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
~Sprite3DMaterialCache();
|
||||
|
||||
protected:
|
||||
static Sprite3DMaterialCache* _cacheInstance;
|
||||
std::unordered_map<std::string, Texture2D*> _materials; //
|
||||
static Sprite3DMaterialCache* _cacheInstance;//instance
|
||||
std::unordered_map<std::string, Texture2D*> _materials; //cached material
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -7,5 +7,6 @@ set(COCOS_3D_SRC
|
|||
3d/CCAnimation3D.cpp
|
||||
3d/CCBundle3D.cpp
|
||||
3d/CCMeshSkin.cpp
|
||||
3d/CCBundleReader.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ cocos2d.cpp \
|
|||
3d/CCAnimate3D.cpp \
|
||||
3d/CCAnimation3D.cpp \
|
||||
3d/CCBundle3D.cpp \
|
||||
3d/CCBundleReader.cpp \
|
||||
3d/CCMesh.cpp \
|
||||
3d/CCMeshSkin.cpp \
|
||||
3d/CCSprite3DMaterial.cpp \
|
||||
|
|
|
@ -326,6 +326,15 @@ void GLProgramState::resetGLProgram()
|
|||
}
|
||||
|
||||
void GLProgramState::apply(const Mat4& modelView)
|
||||
{
|
||||
applyGLProgram(modelView);
|
||||
|
||||
applyAttributes();
|
||||
|
||||
applyUniforms();
|
||||
}
|
||||
|
||||
void GLProgramState::applyGLProgram(const Mat4& modelView)
|
||||
{
|
||||
CCASSERT(_glprogram, "invalid glprogram");
|
||||
if(_uniformAttributeValueDirty)
|
||||
|
@ -349,19 +358,24 @@ void GLProgramState::apply(const Mat4& modelView)
|
|||
// set shader
|
||||
_glprogram->use();
|
||||
_glprogram->setUniformsForBuiltins(modelView);
|
||||
|
||||
}
|
||||
void GLProgramState::applyAttributes(bool applyAttribFlags)
|
||||
{
|
||||
// Don't set attributes if they weren't set
|
||||
// Use Case: Auto-batching
|
||||
if(_vertexAttribsFlags) {
|
||||
// enable/disable vertex attribs
|
||||
GL::enableVertexAttribs(_vertexAttribsFlags);
|
||||
if (applyAttribFlags)
|
||||
GL::enableVertexAttribs(_vertexAttribsFlags);
|
||||
// set attributes
|
||||
for(auto &attribute : _attributes)
|
||||
{
|
||||
attribute.second.apply();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void GLProgramState::applyUniforms()
|
||||
{
|
||||
// set uniforms
|
||||
for(auto& uniform : _uniforms) {
|
||||
uniform.second.apply();
|
||||
|
|
|
@ -157,7 +157,16 @@ public:
|
|||
/** gets-or-creates an instance of GLProgramState for a given GLProgramName */
|
||||
static GLProgramState* getOrCreateWithGLProgramName(const std::string &glProgramName );
|
||||
|
||||
// apply GLProgram, attributes and uniforms
|
||||
void apply(const Mat4& modelView);
|
||||
|
||||
void applyGLProgram(const Mat4& modelView);
|
||||
/**
|
||||
* apply vertex attributes
|
||||
* @param applyAttribFlags Call GL::enableVertexAttribs(_vertexAttribsFlags) or not
|
||||
*/
|
||||
void applyAttributes(bool applyAttribFlags = true);
|
||||
void applyUniforms();
|
||||
|
||||
void setGLProgram(GLProgram* glprogram);
|
||||
GLProgram* getGLProgram() const { return _glprogram; }
|
||||
|
|
|
@ -23,7 +23,12 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/CCConfiguration.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCEventCustom.h"
|
||||
#include "base/CCEventListenerCustom.h"
|
||||
#include "base/CCEventDispatcher.h"
|
||||
#include "base/CCEventType.h"
|
||||
#include "renderer/CCMeshCommand.h"
|
||||
#include "renderer/ccGLStateCache.h"
|
||||
#include "renderer/CCGLProgram.h"
|
||||
|
@ -32,6 +37,7 @@
|
|||
#include "renderer/CCTextureAtlas.h"
|
||||
#include "renderer/CCTexture2D.h"
|
||||
#include "renderer/ccGLStateCache.h"
|
||||
#include "xxhash.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -46,8 +52,15 @@ MeshCommand::MeshCommand()
|
|||
, _displayColor(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
, _matrixPalette(nullptr)
|
||||
, _matrixPaletteSize(0)
|
||||
, _materialID(0)
|
||||
, _vao(0)
|
||||
{
|
||||
_type = RenderCommand::Type::MESH_COMMAND;
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
// listen the event when app go to foreground
|
||||
_backToForegroundlistener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(MeshCommand::listenBackToForeground, this));
|
||||
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundlistener, -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MeshCommand::init(float globalOrder,
|
||||
|
@ -103,6 +116,10 @@ void MeshCommand::setDisplayColor(const Vec4& color)
|
|||
|
||||
MeshCommand::~MeshCommand()
|
||||
{
|
||||
releaseVAO();
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundlistener);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MeshCommand::applyRenderState()
|
||||
|
@ -138,16 +155,85 @@ void MeshCommand::restoreRenderState()
|
|||
}
|
||||
}
|
||||
|
||||
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, void* mesh, const BlendFunc& blend)
|
||||
{
|
||||
int* intstate = static_cast<int*>(glProgramState);
|
||||
int* intmesh = static_cast<int*>(mesh);
|
||||
|
||||
int statekey[] = {intstate[0], 0}, meshkey[] = {intmesh[0], 0};
|
||||
if (sizeof(void*) > sizeof(int))
|
||||
{
|
||||
statekey[1] = intstate[1];
|
||||
meshkey[1] = intmesh[1];
|
||||
}
|
||||
int intArray[] = {(int)texID, statekey[0], statekey[1], meshkey[0], meshkey[1], (int)blend.src, (int)blend.dst};
|
||||
_materialID = XXH32((const void*)intArray, sizeof(intArray), 0);
|
||||
}
|
||||
|
||||
void MeshCommand::MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform)
|
||||
{
|
||||
glProgram->setUniformLocationWith4fv(uniform->location, (const float*)_matrixPalette, _matrixPaletteSize);
|
||||
}
|
||||
|
||||
void MeshCommand::preBatchDraw()
|
||||
{
|
||||
// set render state
|
||||
applyRenderState();
|
||||
// Set material
|
||||
GL::bindTexture2D(_textureID);
|
||||
GL::blendFunc(_blendType.src, _blendType.dst);
|
||||
|
||||
if (_vao == 0)
|
||||
buildVAO();
|
||||
if (_vao)
|
||||
{
|
||||
GL::bindVAO(_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
|
||||
_glProgramState->applyAttributes();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
|
||||
}
|
||||
}
|
||||
void MeshCommand::batchDraw()
|
||||
{
|
||||
_glProgramState->setUniformVec4("u_color", _displayColor);
|
||||
|
||||
if (_matrixPaletteSize && _matrixPalette)
|
||||
{
|
||||
_glProgramState->setUniformCallback("u_matrixPalette", CC_CALLBACK_2(MeshCommand::MatrixPalleteCallBack, this));
|
||||
|
||||
}
|
||||
|
||||
_glProgramState->applyGLProgram(_mv);
|
||||
_glProgramState->applyUniforms();
|
||||
|
||||
// Draw
|
||||
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
|
||||
|
||||
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
|
||||
}
|
||||
void MeshCommand::postBatchDraw()
|
||||
{
|
||||
//restore render state
|
||||
restoreRenderState();
|
||||
if (_vao)
|
||||
{
|
||||
GL::bindVAO(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshCommand::execute()
|
||||
{
|
||||
// set render state
|
||||
applyRenderState();
|
||||
|
||||
// Set material
|
||||
GL::bindTexture2D(_textureID);
|
||||
GL::blendFunc(_blendType.src, _blendType.dst);
|
||||
|
@ -172,9 +258,49 @@ void MeshCommand::execute()
|
|||
|
||||
//restore render state
|
||||
restoreRenderState();
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void MeshCommand::buildVAO()
|
||||
{
|
||||
releaseVAO();
|
||||
if (Configuration::getInstance()->supportsShareableVAO())
|
||||
{
|
||||
glGenVertexArrays(1, &_vao);
|
||||
GL::bindVAO(_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
|
||||
auto flags = _glProgramState->getVertexAttribsFlags();
|
||||
for (int i = 0; flags > 0; i++) {
|
||||
int flag = 1 << i;
|
||||
if (flag & flags)
|
||||
glEnableVertexAttribArray(i);
|
||||
flags &= ~flag;
|
||||
}
|
||||
_glProgramState->applyAttributes(false);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
|
||||
|
||||
GL::bindVAO(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
void MeshCommand::releaseVAO()
|
||||
{
|
||||
if (Configuration::getInstance()->supportsShareableVAO() && _vao)
|
||||
{
|
||||
glDeleteVertexArrays(1, &_vao);
|
||||
_vao = 0;
|
||||
GL::bindVAO(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
void MeshCommand::listenBackToForeground(EventCustom* event)
|
||||
{
|
||||
releaseVAO();
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef _CC_MESHCOMMAND_H_
|
||||
#define _CC_MESHCOMMAND_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include "CCRenderCommand.h"
|
||||
#include "renderer/CCGLProgram.h"
|
||||
#include "math/CCMath.h"
|
||||
|
@ -35,6 +36,8 @@ NS_CC_BEGIN
|
|||
class GLProgramState;
|
||||
class GLProgram;
|
||||
struct Uniform;
|
||||
class EventListenerCustom;
|
||||
class EventCustom;
|
||||
|
||||
//it is a common mesh
|
||||
class MeshCommand : public RenderCommand
|
||||
|
@ -59,10 +62,27 @@ public:
|
|||
void setMatrixPalette(const Vec4* matrixPalette) { _matrixPalette = matrixPalette; }
|
||||
|
||||
void setMatrixPaletteSize(int size) { _matrixPaletteSize = size; }
|
||||
|
||||
|
||||
void execute();
|
||||
|
||||
//used for bath
|
||||
void preBatchDraw();
|
||||
void batchDraw();
|
||||
void postBatchDraw();
|
||||
|
||||
void genMaterialID(GLuint texID, void* glProgramState, void* mesh, const BlendFunc& blend);
|
||||
|
||||
uint32_t getMaterialID() const { return _materialID; }
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
void listenBackToForeground(EventCustom* event);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//build & release vao
|
||||
void buildVAO();
|
||||
void releaseVAO();
|
||||
|
||||
// apply renderstate
|
||||
void applyRenderState();
|
||||
|
||||
|
@ -83,6 +103,10 @@ protected:
|
|||
const Vec4* _matrixPalette;
|
||||
int _matrixPaletteSize;
|
||||
|
||||
uint32_t _materialID; //material ID
|
||||
|
||||
GLuint _vao; //use vao if possible
|
||||
|
||||
GLuint _vertexBuffer;
|
||||
GLuint _indexBuffer;
|
||||
GLenum _primitive;
|
||||
|
@ -97,7 +121,12 @@ protected:
|
|||
|
||||
// ModelView transform
|
||||
Mat4 _mv;
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
EventListenerCustom* _backToForegroundlistener;
|
||||
#endif
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif //_CC_MESHCOMMAND_H_
|
||||
|
|
|
@ -108,6 +108,7 @@ static const int DEFAULT_RENDER_QUEUE = 0;
|
|||
//
|
||||
Renderer::Renderer()
|
||||
:_lastMaterialID(0)
|
||||
,_lastBatchedMeshCommand(nullptr)
|
||||
,_numQuads(0)
|
||||
,_glViewAssigned(false)
|
||||
,_isRendering(false)
|
||||
|
@ -283,6 +284,7 @@ void Renderer::visitRenderQueue(const RenderQueue& queue)
|
|||
auto commandType = command->getType();
|
||||
if(RenderCommand::Type::QUAD_COMMAND == commandType)
|
||||
{
|
||||
flush3D();
|
||||
auto cmd = static_cast<QuadCommand*>(command);
|
||||
//Batch quads
|
||||
if(_numQuads + cmd->getQuadCount() > VBO_SIZE)
|
||||
|
@ -321,9 +323,19 @@ void Renderer::visitRenderQueue(const RenderQueue& queue)
|
|||
}
|
||||
else if (RenderCommand::Type::MESH_COMMAND == commandType)
|
||||
{
|
||||
flush();
|
||||
flush2D();
|
||||
auto cmd = static_cast<MeshCommand*>(command);
|
||||
cmd->execute();
|
||||
if (_lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())
|
||||
{
|
||||
flush3D();
|
||||
cmd->preBatchDraw();
|
||||
cmd->batchDraw();
|
||||
_lastBatchedMeshCommand = cmd;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->batchDraw();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -376,6 +388,7 @@ void Renderer::clean()
|
|||
_numQuads = 0;
|
||||
|
||||
_lastMaterialID = 0;
|
||||
_lastBatchedMeshCommand = nullptr;
|
||||
}
|
||||
|
||||
void Renderer::convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView)
|
||||
|
@ -505,11 +518,26 @@ void Renderer::drawBatchedQuads()
|
|||
}
|
||||
|
||||
void Renderer::flush()
|
||||
{
|
||||
flush2D();
|
||||
flush3D();
|
||||
}
|
||||
|
||||
void Renderer::flush2D()
|
||||
{
|
||||
drawBatchedQuads();
|
||||
_lastMaterialID = 0;
|
||||
}
|
||||
|
||||
void Renderer::flush3D()
|
||||
{
|
||||
if (_lastBatchedMeshCommand)
|
||||
{
|
||||
_lastBatchedMeshCommand->postBatchDraw();
|
||||
_lastBatchedMeshCommand = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
|
||||
|
|
|
@ -38,6 +38,7 @@ NS_CC_BEGIN
|
|||
|
||||
class EventListenerCustom;
|
||||
class QuadCommand;
|
||||
class MeshCommand;
|
||||
|
||||
/** Class that knows how to sort `RenderCommand` objects.
|
||||
Since the commands that have `z == 0` are "pushed back" in
|
||||
|
@ -132,6 +133,10 @@ protected:
|
|||
//Draw the previews queued quads and flush previous context
|
||||
void flush();
|
||||
|
||||
void flush2D();
|
||||
|
||||
void flush3D();
|
||||
|
||||
void visitRenderQueue(const RenderQueue& queue);
|
||||
|
||||
void convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView);
|
||||
|
@ -142,6 +147,7 @@ protected:
|
|||
|
||||
uint32_t _lastMaterialID;
|
||||
|
||||
MeshCommand* _lastBatchedMeshCommand;
|
||||
std::vector<QuadCommand*> _batchedQuadCommands;
|
||||
|
||||
V3F_C4B_T2F_Quad _quads[VBO_SIZE];
|
||||
|
|
|
@ -29,38 +29,47 @@ uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
|
|||
// Varyings
|
||||
varying vec2 TextureCoordOut;
|
||||
|
||||
vec4 _skinnedPosition;
|
||||
|
||||
vec4 getPosition()
|
||||
{
|
||||
vec4 matrixPalette1 = vec4(0.0);
|
||||
vec4 matrixPalette2 = vec4(0.0);
|
||||
vec4 matrixPalette3 = vec4(0.0);
|
||||
|
||||
float blendWeight = a_blendWeight[0];
|
||||
|
||||
int matrixIndex = int (a_blendIndex[0]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
vec4 matrixPalette1 = u_matrixPalette[matrixIndex] * blendWeight;
|
||||
vec4 matrixPalette2 = u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
vec4 matrixPalette3 = u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[1];
|
||||
matrixIndex = int(a_blendIndex[1]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[1]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[2];
|
||||
matrixIndex = int(a_blendIndex[2]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[2]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[3];
|
||||
matrixIndex = int(a_blendIndex[3]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[3]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
vec4 _skinnedPosition;
|
||||
_skinnedPosition.x = dot(a_position, matrixPalette1);
|
||||
_skinnedPosition.y = dot(a_position, matrixPalette2);
|
||||
_skinnedPosition.z = dot(a_position, matrixPalette3);
|
||||
|
|
|
@ -194,7 +194,9 @@
|
|||
"cocos/3d/CCAnimationCurve.h",
|
||||
"cocos/3d/CCAnimationCurve.inl",
|
||||
"cocos/3d/CCBundle3D.cpp",
|
||||
"cocos/3d/CCBundle3D.h",
|
||||
"cocos/3d/CCBundle3D.h",
|
||||
"cocos/3d/CCBundleReader.cpp",
|
||||
"cocos/3d/CCBundleReader.h",
|
||||
"cocos/3d/CCBundle3DData.h",
|
||||
"cocos/3d/CCMesh.cpp",
|
||||
"cocos/3d/CCMesh.h",
|
||||
|
|
|
@ -44,7 +44,8 @@ static std::function<Layer*()> createFunctions[] =
|
|||
{
|
||||
CL(Sprite3DBasicTest),
|
||||
CL(Sprite3DEffectTest),
|
||||
CL(Sprite3DWithSkinTest)
|
||||
CL(Sprite3DWithSkinTest),
|
||||
CL(Animate3DTest)
|
||||
};
|
||||
|
||||
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
|
||||
|
@ -532,7 +533,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest()
|
|||
}
|
||||
std::string Sprite3DWithSkinTest::title() const
|
||||
{
|
||||
return "Testing Sprite3D for animation from c3t";
|
||||
return "Testing Sprite3D";
|
||||
}
|
||||
std::string Sprite3DWithSkinTest::subtitle() const
|
||||
{
|
||||
|
@ -541,12 +542,14 @@ std::string Sprite3DWithSkinTest::subtitle() const
|
|||
|
||||
void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p)
|
||||
{
|
||||
auto sprite = Sprite3D::create("Sprite3DTest/girl.c3t");
|
||||
std::string fileName = "Sprite3DTest/orc.c3b";
|
||||
auto sprite = Sprite3D::create(fileName);
|
||||
sprite->setScale(3);
|
||||
sprite->setRotation3D(Vec3(0,180,0));
|
||||
addChild(sprite);
|
||||
sprite->setRotation3D(Vec3(-90.f, 0.f, 0.f));
|
||||
sprite->setPosition( Vec2( p.x, p.y) );
|
||||
|
||||
auto animation = Animation3D::getOrCreate("Sprite3DTest/girl.c3t");
|
||||
auto animation = Animation3D::getOrCreate(fileName);
|
||||
if (animation)
|
||||
{
|
||||
auto animate = Animate3D::create(animation);
|
||||
|
@ -578,3 +581,141 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector<Touch*>& touches, Ev
|
|||
addNewSpriteWithCoords( location );
|
||||
}
|
||||
}
|
||||
|
||||
Animate3DTest::Animate3DTest()
|
||||
: _hurt(nullptr)
|
||||
, _swim(nullptr)
|
||||
, _sprite(nullptr)
|
||||
, _moveAction(nullptr)
|
||||
, _transTime(0.1f)
|
||||
, _elapseTransTime(0.f)
|
||||
{
|
||||
addSprite3D();
|
||||
|
||||
auto listener = EventListenerTouchAllAtOnce::create();
|
||||
listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this);
|
||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
|
||||
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
Animate3DTest::~Animate3DTest()
|
||||
{
|
||||
CC_SAFE_RELEASE(_moveAction);
|
||||
CC_SAFE_RELEASE(_hurt);
|
||||
CC_SAFE_RELEASE(_swim);
|
||||
}
|
||||
|
||||
std::string Animate3DTest::title() const
|
||||
{
|
||||
return "Testing Animate3D";
|
||||
}
|
||||
|
||||
std::string Animate3DTest::subtitle() const
|
||||
{
|
||||
return "Touch to beat the tortoise";
|
||||
}
|
||||
|
||||
void Animate3DTest::update(float dt)
|
||||
{
|
||||
if (_state == State::HURT_TO_SWIMMING)
|
||||
{
|
||||
_elapseTransTime += dt;
|
||||
float t = _elapseTransTime / _transTime;
|
||||
|
||||
if (t >= 1.f)
|
||||
{
|
||||
t = 1.f;
|
||||
_sprite->stopAction(_hurt);
|
||||
_state = State::SWIMMING;
|
||||
}
|
||||
_swim->setWeight(t);
|
||||
_hurt->setWeight(1.f - t);
|
||||
}
|
||||
else if (_state == State::SWIMMING_TO_HURT)
|
||||
{
|
||||
_elapseTransTime += dt;
|
||||
float t = _elapseTransTime / _transTime;
|
||||
if (t >= 1.f)
|
||||
{
|
||||
t = 1.f;
|
||||
_state = State::HURT;
|
||||
}
|
||||
_swim->setWeight(1.f - t);
|
||||
_hurt->setWeight(t);
|
||||
}
|
||||
}
|
||||
|
||||
void Animate3DTest::addSprite3D()
|
||||
{
|
||||
std::string fileName = "Sprite3DTest/tortoise.c3b";
|
||||
auto sprite = Sprite3D::create(fileName);
|
||||
sprite->setScale(0.1f);
|
||||
auto s = Director::getInstance()->getWinSize();
|
||||
sprite->setPosition(Vec2(s.width * 4.f / 5.f, s.height / 2.f));
|
||||
addChild(sprite);
|
||||
_sprite = sprite;
|
||||
auto animation = Animation3D::getOrCreate(fileName);
|
||||
if (animation)
|
||||
{
|
||||
auto animate = Animate3D::create(animation, 0.f, 1.933f);
|
||||
sprite->runAction(RepeatForever::create(animate));
|
||||
_swim = animate;
|
||||
_swim->retain();
|
||||
_hurt = Animate3D::create(animation, 1.933f, 2.8f);
|
||||
_hurt->retain();
|
||||
_state = State::SWIMMING;
|
||||
}
|
||||
|
||||
_moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f));
|
||||
_moveAction->retain();
|
||||
auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr);
|
||||
seq->setTag(100);
|
||||
sprite->runAction(seq);
|
||||
}
|
||||
|
||||
void Animate3DTest::reachEndCallBack()
|
||||
{
|
||||
_sprite->stopActionByTag(100);
|
||||
auto inverse = (MoveTo*)_moveAction->reverse();
|
||||
inverse->retain();
|
||||
_moveAction->release();
|
||||
_moveAction = inverse;
|
||||
auto rot = RotateBy::create(1.f, Vec3(0.f, 180.f, 0.f));
|
||||
auto seq = Sequence::create(rot, _moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr);
|
||||
seq->setTag(100);
|
||||
_sprite->runAction(seq);
|
||||
}
|
||||
|
||||
void Animate3DTest::renewCallBack()
|
||||
{
|
||||
_sprite->stopActionByTag(101);
|
||||
_state = State::HURT_TO_SWIMMING;
|
||||
}
|
||||
|
||||
void Animate3DTest::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
|
||||
{
|
||||
for (auto touch: touches)
|
||||
{
|
||||
auto location = touch->getLocation();
|
||||
|
||||
if (_sprite)
|
||||
{
|
||||
float len = (_sprite->getPosition() - location).length();
|
||||
if (len < 40)
|
||||
{
|
||||
//hurt the tortoise
|
||||
if (_state == State::SWIMMING)
|
||||
{
|
||||
_sprite->runAction(_hurt);
|
||||
auto delay = DelayTime::create(_hurt->getDuration() - 0.1f);
|
||||
auto seq = Sequence::create(delay, CallFunc::create(CC_CALLBACK_0(Animate3DTest::renewCallBack, this)), NULL);
|
||||
seq->setTag(101);
|
||||
_sprite->runAction(seq);
|
||||
_state = State::SWIMMING_TO_HURT;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,12 @@
|
|||
#include "../BaseTest.h"
|
||||
#include <string>
|
||||
|
||||
namespace cocos2d {
|
||||
class Animate3D;
|
||||
class Sprite3D;
|
||||
class Delay;
|
||||
}
|
||||
|
||||
class Sprite3DTestDemo : public BaseTest
|
||||
{
|
||||
public:
|
||||
|
@ -151,6 +157,46 @@ public:
|
|||
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
|
||||
};
|
||||
|
||||
class Animate3DTest : public Sprite3DTestDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(Animate3DTest);
|
||||
Animate3DTest();
|
||||
~Animate3DTest();
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
|
||||
|
||||
virtual void update(float dt) override;
|
||||
|
||||
protected:
|
||||
void addSprite3D();
|
||||
|
||||
enum class State
|
||||
{
|
||||
SWIMMING,
|
||||
SWIMMING_TO_HURT,
|
||||
HURT,
|
||||
HURT_TO_SWIMMING,
|
||||
};
|
||||
|
||||
void reachEndCallBack();
|
||||
|
||||
void renewCallBack();
|
||||
|
||||
cocos2d::Sprite3D* _sprite;
|
||||
|
||||
cocos2d::Animate3D* _swim;
|
||||
cocos2d::Animate3D* _hurt;
|
||||
float _transTime;
|
||||
float _elapseTransTime;
|
||||
|
||||
State _state;
|
||||
|
||||
MoveTo* _moveAction;
|
||||
};
|
||||
|
||||
class Sprite3DTestScene : public TestScene
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -34,6 +34,7 @@ Controller g_aTestNames[] = {
|
|||
// TESTS MUST BE ORDERED ALPHABETICALLY
|
||||
// violators will be prosecuted
|
||||
//
|
||||
{ "3D: Sprite3D", [](){ return new Sprite3DTestScene(); }},
|
||||
{ "ActionManager", [](){return new ActionManagerTestScene(); } },
|
||||
{ "Actions - Basic", [](){ return new ActionsTestScene(); } },
|
||||
{ "Actions - Ease", [](){return new ActionsEaseTestScene();} },
|
||||
|
@ -83,7 +84,6 @@ Controller g_aTestNames[] = {
|
|||
{ "Node: Scene", [](){return new SceneTestScene();} },
|
||||
{ "Node: Spine", []() { return new SpineTestScene(); } },
|
||||
{ "Node: Sprite", [](){return new SpriteTestScene(); } },
|
||||
{ "Node: Sprite3D", [](){ return new Sprite3DTestScene(); }},
|
||||
{ "Node: TileMap", [](){return new TileMapTestScene(); } },
|
||||
{ "Node: Text Input", [](){return new TextInputTestScene(); } },
|
||||
{ "Node: UI", [](){ return new UITestScene(); }},
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 256 KiB |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
Loading…
Reference in New Issue