Merge pull request #7226 from super626/v3

Animation3D
This commit is contained in:
minggo 2014-06-29 16:41:13 +08:00
commit 7f28e81d09
39 changed files with 15257 additions and 345 deletions

View File

@ -1025,6 +1025,10 @@
373B912A187891FB00198F86 /* CCComBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 373B910718787C0B00198F86 /* CCComBase.h */; }; 373B912A187891FB00198F86 /* CCComBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 373B910718787C0B00198F86 /* CCComBase.h */; };
3EA0FB6B191C841D00B170C8 /* UIVideoPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA0FB69191C841D00B170C8 /* UIVideoPlayer.h */; }; 3EA0FB6B191C841D00B170C8 /* UIVideoPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA0FB69191C841D00B170C8 /* UIVideoPlayer.h */; };
3EA0FB6C191C841D00B170C8 /* UIVideoPlayerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3EA0FB6A191C841D00B170C8 /* UIVideoPlayerIOS.mm */; }; 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 */; }; 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 */; }; 460E468218080836000CDD6D /* cocos-ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A167D21807AF4D005B8026 /* cocos-ext.h */; };
460E477B180808F5000CDD6D /* ExtensionMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A168321807AF4E005B8026 /* ExtensionMacros.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 46A15FE11807A56F005B8026 /* Export.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Export.h; sourceTree = "<group>"; };
@ -4912,6 +4918,8 @@
B29594B81926D61F003EEF37 /* 3d */ = { B29594B81926D61F003EEF37 /* 3d */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3EA4786E195478E00068D9D1 /* CCBundleReader.cpp */,
3EA4786F195478E00068D9D1 /* CCBundleReader.h */,
B6AAF83F19404E0D0069DE01 /* CCBundle3D.cpp */, B6AAF83F19404E0D0069DE01 /* CCBundle3D.cpp */,
B6AAF84019404E0D0069DE01 /* CCBundle3D.h */, B6AAF84019404E0D0069DE01 /* CCBundle3D.h */,
B6ACD89C193DC0CC005E0B8A /* CCAnimate3D.cpp */, B6ACD89C193DC0CC005E0B8A /* CCAnimate3D.cpp */,
@ -5218,6 +5226,7 @@
1AD71EE3180E26E600808F54 /* SlotData.h in Headers */, 1AD71EE3180E26E600808F54 /* SlotData.h in Headers */,
0634A4E2194B19E400E608AF /* CCTimeLine.h in Headers */, 0634A4E2194B19E400E608AF /* CCTimeLine.h in Headers */,
1AD71EE7180E26E600808F54 /* spine-cocos2dx.h in Headers */, 1AD71EE7180E26E600808F54 /* spine-cocos2dx.h in Headers */,
3EA47872195478E00068D9D1 /* CCBundleReader.h in Headers */,
1AD71EE9180E26E600808F54 /* spine.h in Headers */, 1AD71EE9180E26E600808F54 /* spine.h in Headers */,
1AAF536C180E3374000584C8 /* HttpClient.h in Headers */, 1AAF536C180E3374000584C8 /* HttpClient.h in Headers */,
50ABBD9D1925AB4100A911A9 /* ccGLStateCache.h in Headers */, 50ABBD9D1925AB4100A911A9 /* ccGLStateCache.h in Headers */,
@ -5774,6 +5783,7 @@
50ABC0201926664800A911A9 /* CCThread.h in Headers */, 50ABC0201926664800A911A9 /* CCThread.h in Headers */,
1A01C69318F57BE800EFE3A6 /* CCDouble.h in Headers */, 1A01C69318F57BE800EFE3A6 /* CCDouble.h in Headers */,
50ABBE221925AB6F00A911A9 /* atitc.h in Headers */, 50ABBE221925AB6F00A911A9 /* atitc.h in Headers */,
3EA47873195478E00068D9D1 /* CCBundleReader.h in Headers */,
1A8C59DA180E930E00EF57C3 /* CCDisplayFactory.h in Headers */, 1A8C59DA180E930E00EF57C3 /* CCDisplayFactory.h in Headers */,
1A8C59DE180E930E00EF57C3 /* CCDisplayManager.h in Headers */, 1A8C59DE180E930E00EF57C3 /* CCDisplayManager.h in Headers */,
50FCEBB618C72017004AD434 /* SliderReader.h in Headers */, 50FCEBB618C72017004AD434 /* SliderReader.h in Headers */,
@ -6314,6 +6324,7 @@
1A57034B180BD09B0088DEC7 /* tinyxml2.cpp in Sources */, 1A57034B180BD09B0088DEC7 /* tinyxml2.cpp in Sources */,
1A570354180BD0B00088DEC7 /* ioapi.cpp in Sources */, 1A570354180BD0B00088DEC7 /* ioapi.cpp in Sources */,
1A570358180BD0B00088DEC7 /* unzip.cpp in Sources */, 1A570358180BD0B00088DEC7 /* unzip.cpp in Sources */,
3EA47870195478E00068D9D1 /* CCBundleReader.cpp in Sources */,
1AD71DA9180E26E600808F54 /* CCBAnimationManager.cpp in Sources */, 1AD71DA9180E26E600808F54 /* CCBAnimationManager.cpp in Sources */,
1AD71DAD180E26E600808F54 /* CCBFileLoader.cpp in Sources */, 1AD71DAD180E26E600808F54 /* CCBFileLoader.cpp in Sources */,
50E6D33418E174130051CA34 /* UIHBox.cpp in Sources */, 50E6D33418E174130051CA34 /* UIHBox.cpp in Sources */,
@ -6634,6 +6645,7 @@
50ABC01A1926664800A911A9 /* CCSAXParser.cpp in Sources */, 50ABC01A1926664800A911A9 /* CCSAXParser.cpp in Sources */,
503DD8EE1926736A00CD74DD /* CCImage.mm in Sources */, 503DD8EE1926736A00CD74DD /* CCImage.mm in Sources */,
50FCEBC818C72017004AD434 /* WidgetReader.cpp in Sources */, 50FCEBC818C72017004AD434 /* WidgetReader.cpp in Sources */,
3EA47871195478E00068D9D1 /* CCBundleReader.cpp in Sources */,
46A170FC1807CECB005B8026 /* CCPhysicsBody.cpp in Sources */, 46A170FC1807CECB005B8026 /* CCPhysicsBody.cpp in Sources */,
50ABBD941925AB4100A911A9 /* CCGLProgramState.cpp in Sources */, 50ABBD941925AB4100A911A9 /* CCGLProgramState.cpp in Sources */,
50ABBE281925AB6F00A911A9 /* CCAutoreleasePool.cpp in Sources */, 50ABBE281925AB6F00A911A9 /* CCAutoreleasePool.cpp in Sources */,

View File

@ -182,6 +182,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
<ClCompile Include="..\3d\CCAnimate3D.cpp" /> <ClCompile Include="..\3d\CCAnimate3D.cpp" />
<ClCompile Include="..\3d\CCAnimation3D.cpp" /> <ClCompile Include="..\3d\CCAnimation3D.cpp" />
<ClCompile Include="..\3d\CCBundle3D.cpp" /> <ClCompile Include="..\3d\CCBundle3D.cpp" />
<ClCompile Include="..\3d\CCBundleReader.cpp" />
<ClCompile Include="..\3d\CCMesh.cpp" /> <ClCompile Include="..\3d\CCMesh.cpp" />
<ClCompile Include="..\3d\CCMeshSkin.cpp" /> <ClCompile Include="..\3d\CCMeshSkin.cpp" />
<ClCompile Include="..\3d\CCObjLoader.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\CCAnimationCurve.h" />
<ClInclude Include="..\3d\CCBundle3D.h" /> <ClInclude Include="..\3d\CCBundle3D.h" />
<ClInclude Include="..\3d\CCBundle3DData.h" /> <ClInclude Include="..\3d\CCBundle3DData.h" />
<ClInclude Include="..\3d\CCBundleReader.h" />
<ClInclude Include="..\3d\CCMesh.h" /> <ClInclude Include="..\3d\CCMesh.h" />
<ClInclude Include="..\3d\CCMeshSkin.h" /> <ClInclude Include="..\3d\CCMeshSkin.h" />
<ClInclude Include="..\3d\CCObjLoader.h" /> <ClInclude Include="..\3d\CCObjLoader.h" />

View File

@ -580,6 +580,9 @@
<ClCompile Include="..\3d\CCSprite3DMaterial.cpp"> <ClCompile Include="..\3d\CCSprite3DMaterial.cpp">
<Filter>3d</Filter> <Filter>3d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\3d\CCBundleReader.cpp">
<Filter>3d</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\physics\CCPhysicsBody.h"> <ClInclude Include="..\physics\CCPhysicsBody.h">
@ -1180,6 +1183,9 @@
<ClInclude Include="..\3d\CCSprite3DMaterial.h"> <ClInclude Include="..\3d\CCSprite3DMaterial.h">
<Filter>3d</Filter> <Filter>3d</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\3d\CCBundleReader.h">
<Filter>3d</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\math\Mat4.inl"> <None Include="..\math\Mat4.inl">

View File

@ -45,16 +45,34 @@ Animate3D* Animate3D::create(Animation3D* animation)
return animate; 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 */ /** returns a clone of action */
Animate3D* Animate3D::clone() const Animate3D* Animate3D::clone() const
{ {
auto animate = const_cast<Animate3D*>(this); auto animate = const_cast<Animate3D*>(this);
auto copy = Animate3D::create(animate->_animation); auto copy = Animate3D::create(animate->_animation);
copy->_speed = _speed; copy->_speed = _speed;
copy->_weight = _weight;
copy->_elapsed = _elapsed; copy->_elapsed = _elapsed;
copy->_start = _start;
copy->_last = _last;
copy->_playBack = _playBack; copy->_playBack = _playBack;
copy->setDuration(animate->getDuration());
return copy; return copy;
} }
@ -106,6 +124,7 @@ void Animate3D::update(float t)
if (_playBack) if (_playBack)
t = 1 - t; t = 1 - t;
t = _start + t * _last;
for (const auto& it : _boneCurves) { for (const auto& it : _boneCurves) {
auto bone = it.first; auto bone = it.first;
auto curve = it.second; auto curve = it.second;
@ -124,7 +143,7 @@ void Animate3D::update(float t)
curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR); curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR);
scale = &scaleDst[0]; 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() Animate3D::Animate3D()
: _speed(1) : _speed(1)
, _weight(1.f) , _weight(1.f)
, _start(0.f)
, _last(1.f)
, _animation(nullptr) , _animation(nullptr)
, _playBack(false) , _playBack(false)
{ {

View File

@ -39,15 +39,23 @@ NS_CC_BEGIN
class Animation3D; class Animation3D;
class Bone; class Bone;
/** /**
* Animate3D * Animate3D, Animates a Sprite3D given with an Animation3D
*/ */
class Animate3D: public ActionInterval class Animate3D: public ActionInterval
{ {
public: public:
//create Animate3D using Animation. /**create Animate3D using Animation.*/
static Animate3D* create(Animation3D* 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 // Overrides
// //
@ -58,9 +66,15 @@ public:
virtual void update(float t) override; virtual void update(float t) override;
/**get & set speed */
float getSpeed() const { return _speed; } float getSpeed() const { return _speed; }
void setSpeed(float speed) { _speed = 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; } bool getPlayBack() const { return _playBack; }
void setPlayBack(bool playBack) { _playBack = playBack; } void setPlayBack(bool playBack) { _playBack = playBack; }
@ -69,11 +83,14 @@ CC_CONSTRUCTOR_ACCESS:
Animate3D(); Animate3D();
virtual ~Animate3D(); virtual ~Animate3D();
Animation3D* _animation; protected:
Animation3D* _animation; //animation data
float _speed; float _speed; //playing speed
float _weight; float _weight; //blend weight
bool _playBack; 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 std::map<Bone*, Animation3D::Curve*> _boneCurves; //weak ref
}; };

View File

@ -43,31 +43,36 @@ class Animation3D: public Ref
{ {
friend class Bundle3D; friend class Bundle3D;
public: public:
/**
* animation curve, translation, rotation, and scale
*/
class Curve class Curve
{ {
public: public:
typedef AnimationCurve<3> AnimationCurveVec3; typedef AnimationCurve<3> AnimationCurveVec3;
typedef AnimationCurve<4> AnimationCurveQuat; typedef AnimationCurve<4> AnimationCurveQuat;
AnimationCurveVec3* translateCurve; AnimationCurveVec3* translateCurve; //translate curve
AnimationCurveQuat* rotCurve; AnimationCurveQuat* rotCurve;//rotation curve
AnimationCurveVec3* scaleCurve; AnimationCurveVec3* scaleCurve;//scale curve
Curve(); 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 = ""); static Animation3D* getOrCreate(const std::string& filename, const std::string& animationName = "");
/**get duration*/
float getDuration() const { return _duration; } float getDuration() const { return _duration; }
/**get bone curve*/
Curve* getBoneCurveByName(const std::string& name) const; Curve* getBoneCurveByName(const std::string& name) const;
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
Animation3D(); Animation3D();
virtual ~Animation3D(); virtual ~Animation3D();
/**init Animation3D from bundle data*/
bool init(const Animation3DData& data); bool init(const Animation3DData& data);
protected: protected:
@ -78,26 +83,34 @@ protected:
float _duration; //animation duration float _duration; //animation duration
}; };
/**
* Animation3D Cache
*/
class Animation3DCache class Animation3DCache
{ {
public: public:
/**get and destroy instance*/
static Animation3DCache* getInstance(); static Animation3DCache* getInstance();
static void destroyInstance(); static void destroyInstance();
/**get animation by key*/
Animation3D* getAnimation(const std::string& key); Animation3D* getAnimation(const std::string& key);
/**add animation to cache*/
void addAnimation(const std::string& key, Animation3D* animation); void addAnimation(const std::string& key, Animation3D* animation);
/**remove all animation*/
void removeAllAnimations(); void removeAllAnimations();
/**remove unused animation*/
void removeUnusedAnimation(); void removeUnusedAnimation();
protected: protected:
Animation3DCache(); Animation3DCache();
~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 NS_CC_END

View File

@ -38,9 +38,12 @@
NS_CC_BEGIN NS_CC_BEGIN
/**
* Evaluate Type
*/
enum class EvaluateType enum class EvaluateType
{ {
INT_LINEAR, INT_LINEAR,
INT_NEAR, INT_NEAR,
INT_QUAT_SLERP, INT_QUAT_SLERP,
INT_USER_FUNCTION, INT_USER_FUNCTION,
@ -54,15 +57,24 @@ class AnimationCurve: public Ref
{ {
public: public:
//create animation curve /**create animation curve*/
static AnimationCurve* create(float* keytime, float* value, int count); 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; 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); void setEvaluateFun(std::function<void(float time, float* dst)> fun);
/**get start time*/
float getStartTime() const; float getStartTime() const;
/**get end time*/
float getEndTime() const; float getEndTime() const;
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
@ -82,7 +94,7 @@ protected:
int _count; int _count;
int _componentSizeByte; //component size in byte, position and scale 3 * sizeof(float), rotation 4 * sizeof(float) 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 NS_CC_END

View File

@ -27,55 +27,114 @@
#include "base/ccMacros.h" #include "base/ccMacros.h"
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include "renderer/CCGLProgram.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 NS_CC_BEGIN
void getChildMap(std::map<int, std::vector<int> >& map, SkinData* skinData, const rapidjson::Value& val) void getChildMap(std::map<int, std::vector<int> >& map, SkinData* skinData, const rapidjson::Value& val)
{ {
if (!skinData) if (!skinData)
return; return;
if (!val.HasMember("children")) // get transform matrix
return; Mat4 transform;
const rapidjson::Value& parent_tranform = val[SKINDATA_TRANSFORM];
std::string parent_name = val["id"].GetString(); for (rapidjson::SizeType j = 0; j < parent_tranform.Size(); j++)
int parent_name_index = skinData->getBoneNameIndex(parent_name);
const rapidjson::Value& children = val["children"];
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
{ {
const rapidjson::Value& child = children[i]; transform.m[j] = parent_tranform[j].GetDouble();
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);
}
} }
}
// set origin matrices
void getChildMapT(std::map<std::string, std::vector<std::string> >& map, const SkinData* skinData, const rapidjson::Value& val) std::string parent_name = val[ID].GetString();
{ int parent_name_index = skinData->getSkinBoneNameIndex(parent_name);
if (!skinData) 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; return;
if (!val.HasMember("children")) const rapidjson::Value& children = val[SKINDATA_CHILDREN];
return;
std::string parent_name = val["id"].GetString();
const rapidjson::Value& children = val["children"];
for (rapidjson::SizeType i = 0; i < children.Size(); i++) for (rapidjson::SizeType i = 0; i < children.Size(); i++)
{ {
// get child bone name
const rapidjson::Value& child = children[i]; const rapidjson::Value& child = children[i];
std::string child_name = child["id"].GetString();
std::string child_name = child[ID].GetString();
map[parent_name].push_back(child_name); int child_name_index = skinData->getSkinBoneNameIndex(child_name);
if (child_name_index < 0)
getChildMapT(map, skinData, child); {
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); 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) bool Bundle3D::load(const std::string& path)
{ {
if (_path == path) if (_path == path)
return true; return true;
getModelPath(path); getModelRelativePath(path);
std::string strFileString = FileUtils::getInstance()->getStringFromFile(path);
ssize_t size = strFileString.length(); bool ret = false;
CC_SAFE_DELETE_ARRAY(_documentBuffer); std::string ext = path.substr(path.length() - 4, 4);
_documentBuffer = new char[size + 1]; std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
memcpy(_documentBuffer, strFileString.c_str(), size); if (ext == ".c3t")
_documentBuffer[size] = '\0'; {
if (_document.ParseInsitu<0>(_documentBuffer).HasParseError()) _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); assert(0);
CC_SAFE_DELETE_ARRAY(_documentBuffer); clear();
_path = "";
return false; return false;
} }
_path = path;
return true; return true;
} }
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata) bool Bundle3D::loadMeshDataJson(MeshData* meshdata)
{ {
meshdata->resetData(); meshdata->resetData();
assert(_document.HasMember("mesh")); assert(_jsonReader.HasMember(MESHDATA_MESH));
const rapidjson::Value& mash_data_array = _document["mesh"]; const rapidjson::Value& mash_data_array = _jsonReader[MESHDATA_MESH];
assert(mash_data_array.IsArray()); assert(mash_data_array.IsArray());
const rapidjson::Value& mash_data_val = mash_data_array[(rapidjson::SizeType)0]; const rapidjson::Value& mash_data_val = mash_data_array[(rapidjson::SizeType)0];
assert(mash_data_val.HasMember("body")); assert(mash_data_val.HasMember(MESHDATA_DEFAULTPART));
const rapidjson::Value& mesh_data_body_array = mash_data_val["body"]; const rapidjson::Value& mesh_data_body_array = mash_data_val[MESHDATA_DEFAULTPART];
assert(mesh_data_body_array.IsArray()); assert(mesh_data_body_array.IsArray());
const rapidjson::Value& mesh_data_body_array_0 = mesh_data_body_array[(rapidjson::SizeType)0]; const rapidjson::Value& mesh_data_body_array_0 = mesh_data_body_array[(rapidjson::SizeType)0];
// vertex_size // vertex_size
assert(mesh_data_body_array_0.HasMember("vertexsize")); assert(mesh_data_body_array_0.HasMember(MESHDATA_VERTEXSIZE));
meshdata->vertexSizeInFloat = mesh_data_body_array_0["vertexsize"].GetInt(); meshdata->vertexSizeInFloat = mesh_data_body_array_0[MESHDATA_VERTEXSIZE].GetInt();
// vertices // vertices
meshdata->vertex.resize(meshdata->vertexSizeInFloat); 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++) for (rapidjson::SizeType i = 0; i < mesh_data_body_vertices.Size(); i++)
meshdata->vertex[i] = mesh_data_body_vertices[i].GetDouble(); meshdata->vertex[i] = mesh_data_body_vertices[i].GetDouble();
// index_number // index_number
meshdata->numIndex = mesh_data_body_array_0["indexnum"].GetUint(); meshdata->numIndex = mesh_data_body_array_0[MESHDATA_INDEXNUM].GetUint();
// indices // indices
meshdata->indices.resize(meshdata->numIndex); 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++) 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(); meshdata->indices[i] = (unsigned short)mesh_data_body_indices_val[i].GetUint();
// mesh_vertex_attribute // 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->attribCount = mesh_vertex_attribute.Size();
meshdata->attribs.resize(meshdata->attribCount); meshdata->attribs.resize(meshdata->attribCount);
for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); i++) for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); i++)
{ {
const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[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].size = mesh_vertex_attribute_val[MESHDATA_SIZE].GetUint();
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * parseGLTypeSize(mesh_vertex_attribute_val["type"].GetString()); meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * 4;
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val["type"].GetString()); meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val[MESHDATA_TYPE].GetString());
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val["attribute"].GetString()); meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[MESHDATA_ATTRIBUTE].GetString());
} }
return true; 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(); skindata->resetData();
const rapidjson::Value& skin_data_array = _document["skin"]; const rapidjson::Value& skin_data_array = _jsonReader[SKINDATA_SKIN ];
assert(skin_data_array.IsArray()); assert(skin_data_array.IsArray());
const rapidjson::Value& skin_data_array_val_0 = skin_data_array[(rapidjson::SizeType)0]; 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; 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++) for (rapidjson::SizeType i = 0; i < skin_data_bones.Size(); i++)
{ {
const rapidjson::Value& skin_data_bone = skin_data_bones[i]; const rapidjson::Value& skin_data_bone = skin_data_bones[i];
std::string name = skin_data_bone["node"].GetString(); std::string name = skin_data_bone[SKINDATA_NODE].GetString();
skindata->boneNames.push_back(name); skindata->addSkinBoneNames(name);
Mat4 mat_bind_pos; 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++) for (rapidjson::SizeType j = 0; j < bind_pos.Size(); j++)
{ {
mat_bind_pos.m[j] = bind_pos[j].GetDouble(); mat_bind_pos.m[j] = bind_pos[j].GetDouble();
} }
skindata->inverseBindPoseMatrices.push_back(mat_bind_pos); skindata->inverseBindPoseMatrices.push_back(mat_bind_pos);
} }
// set root bone infomation
const rapidjson::Value& skin_data_1 = skin_data_array[1]; 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()); // parent and child relationship map
getChildMap(skindata->boneChild, skindata, bone_array_0); skindata->skinBoneOriginMatrices.resize(skindata->skinBoneNames.size());
//skindata->nodeBoneOriginMatrices.resize(skindata->nodeBoneNames.size());
getChildMap(skindata->boneChild, skindata, skin_data_1);
return true; 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; 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_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]; 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; 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->_rotationKeys.clear();
animationdata->_scaleKeys.clear(); animationdata->_scaleKeys.clear();
animationdata->_translationKeys.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; if (animation_data_array.Size()==0) return false;
const rapidjson::Value& animation_data_array_val_0 = animation_data_array[(rapidjson::SizeType)0]; 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++) for (rapidjson::SizeType i = 0; i < bones.Size(); i++)
{ {
const rapidjson::Value& bone = bones[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"]; const rapidjson::Value& bone_keyframes = bone[ANIMATIONDATA_KEYFRAMES];
for (rapidjson::SizeType j = 0; j < bone_keyframes.Size(); j++) rapidjson::SizeType keyframe_size = bone_keyframes.Size();
for (rapidjson::SizeType j = 0; j < keyframe_size; j++)
{ {
const rapidjson::Value& bone_keyframe = bone_keyframes[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"]; const rapidjson::Value& bone_keyframe_translation = bone_keyframe[ANIMATIONDATA_TRANSLATION];
float keytime = bone_keyframe["keytime"].GetDouble(); 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()); 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)); 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"]; const rapidjson::Value& bone_keyframe_rotation = bone_keyframe[ANIMATIONDATA_ROTATION];
float keytime = bone_keyframe["keytime"].GetDouble(); 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()); 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)); 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"]; const rapidjson::Value& bone_keyframe_scale = bone_keyframe[ANIMATIONDATA_SCALE];
float keytime = bone_keyframe["keytime"].GetDouble(); 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()); 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)); 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; 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) GLenum Bundle3D::parseGLType(const std::string& str)
{ {
if (str == "GL_FLOAT") 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) unsigned int Bundle3D::parseGLProgramAttribute(const std::string& str)
{ {
if (str == "VERTEX_ATTRIB_POSITION") 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('/'); int index = path.find_last_of('/');
std::string fullModelPath; 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() Bundle3D::Bundle3D()
:_isBinary(false) :_isBinary(false),
,_modelRelativePath("") _modelRelativePath(""),
,_documentBuffer(nullptr) _path(""),
,_path("") _jsonBuffer(nullptr),
_binaryBuffer(nullptr),
_referenceCount(0),
_references(nullptr)
{ {
} }
Bundle3D::~Bundle3D() Bundle3D::~Bundle3D()
{ {
CC_SAFE_DELETE_ARRAY(_documentBuffer); clear();
} }
NS_CC_END NS_CC_END

View File

@ -34,10 +34,18 @@
#include "base/ccTypes.h" #include "base/ccTypes.h"
#include "json/document.h" #include "json/document.h"
#include "CCBundleReader.h"
NS_CC_BEGIN NS_CC_BEGIN
class Animation3D; 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 class Bundle3D
{ {
public: public:
@ -46,6 +54,13 @@ public:
static void destroyInstance(); 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); 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 * @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); bool loadAnimationData(const std::string& id, Animation3DData* animationdata);
protected: 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); 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); 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: CC_CONSTRUCTOR_ACCESS:
Bundle3D(); Bundle3D();
~Bundle3D(); ~Bundle3D();
@ -91,11 +164,17 @@ protected:
static Bundle3D* _instance; static Bundle3D* _instance;
std::string _modelRelativePath; std::string _modelRelativePath;
char* _documentBuffer;
std::string _path; 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; bool _isBinary;
}; };

View File

@ -34,7 +34,7 @@
NS_CC_BEGIN NS_CC_BEGIN
//mesh vertex attribute /**mesh vertex attribute*/
struct MeshVertexAttrib struct MeshVertexAttrib
{ {
//attribute size //attribute size
@ -47,6 +47,7 @@ struct MeshVertexAttrib
int attribSizeBytes; int attribSizeBytes;
}; };
/**mesh data*/
struct MeshData struct MeshData
{ {
std::vector<float> vertex; std::vector<float> vertex;
@ -78,41 +79,90 @@ public:
} }
}; };
/**skin data*/
struct SkinData struct SkinData
{ {
std::vector<std::string> boneNames; std::vector<std::string> skinBoneNames; //skin bones affect skin
std::vector<Mat4> inverseBindPoseMatrices; //bind pose of bone 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 std::map<int, std::vector<int> > boneChild;//key parent, value child
int rootBoneIndex; int rootBoneIndex;
void resetData() void resetData()
{ {
boneNames.clear(); skinBoneNames.clear();
nodeBoneNames.clear();
inverseBindPoseMatrices.clear(); inverseBindPoseMatrices.clear();
skinBoneOriginMatrices.clear();
nodeBoneOriginMatrices.clear();
boneChild.clear(); boneChild.clear();
rootBoneIndex = -1; 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 int getBoneNameIndex(const std::string& name)const
{ {
std::vector<std::string>::const_iterator iter = boneNames.begin(); int i = 0;
for (int i = 0; iter != boneNames.end(); ++iter, ++i) for (auto iter : skinBoneNames)
{ {
if ((*iter) == name) if ((iter) == name)
{
return i; return i;
} i++;
}
for(auto iter : nodeBoneNames)
{
if (iter == name)
return i;
i++;
} }
return -1; return -1;
} }
}; };
/**material data*/
struct MaterialData struct MaterialData
{ {
std::string texturePath; std::string texturePath;
}; };
/**animation data*/
struct Animation3DData struct Animation3DData
{ {
public: 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 NS_CC_END
#endif //__CC_BUNDLE_3D_DATA_H__ #endif //__CC_BUNDLE_3D_DATA_H__

159
cocos/3d/CCBundleReader.cpp Normal file
View File

@ -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);
}
}

201
cocos/3d/CCBundleReader.h Normal file
View File

@ -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

View File

@ -62,7 +62,10 @@ protected:
std::vector<MeshVertexAttrib> _vertexAttribs; 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 class Mesh : public Ref
{ {
public: public:
@ -83,41 +86,49 @@ public:
POINTS = GL_POINTS 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); 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); 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; } inline GLuint getVertexBuffer() const { return _vertexBuffer; }
//get mesh vertex attribute count /**get mesh vertex attribute count*/
ssize_t getMeshVertexAttribCount() const { return _renderdata._vertexAttribs.size(); } 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]; } const MeshVertexAttrib& getMeshVertexAttribute(int idx) const { return _renderdata._vertexAttribs[idx]; }
//has vertex attribute? /**has vertex attribute?*/
bool hasVertexAttrib(int attrib) { return _renderdata.hasVertexAttrib(attrib); } 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; } int getVertexSizeInBytes() const { return _renderdata._vertexsizeBytes; }
/** get primitive type*/
PrimitiveType getPrimitiveType() const { return _primitiveType; } PrimitiveType getPrimitiveType() const { return _primitiveType; }
/**get index count*/
ssize_t getIndexCount() const { return _indexCount; } ssize_t getIndexCount() const { return _indexCount; }
/**get index format*/
IndexFormat getIndexFormat() const { return _indexFormat; } IndexFormat getIndexFormat() const { return _indexFormat; }
/**get index buffer*/
GLuint getIndexBuffer() const {return _indexBuffer; } GLuint getIndexBuffer() const {return _indexBuffer; }
//build vertex buffer from renderdata /**build vertex buffer from renderdata*/
void restore(); void restore();
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
Mesh(); Mesh();
virtual ~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); 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); 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(); void buildBuffer();
/**free buffer*/
void cleanAndFreeBuffers(); void cleanAndFreeBuffers();
protected: protected:
@ -131,20 +142,25 @@ protected:
}; };
/** /**
* MeshCache * Mesh Cache
*/ */
class MeshCache class MeshCache
{ {
public: public:
/**get & destroy*/
static MeshCache* getInstance(); static MeshCache* getInstance();
static void destroyInstance(); static void destroyInstance();
/**get mesh from cache*/
Mesh* getMesh(const std::string& key) const; Mesh* getMesh(const std::string& key) const;
/**add mesh to cache*/
bool addMesh(const std::string& key, Mesh* mesh); bool addMesh(const std::string& key, Mesh* mesh);
/**remove all meshes*/
void removeAllMeshes(); void removeAllMeshes();
/**remove unused meshes*/
void removeUnusedMesh(); void removeUnusedMesh();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
@ -158,9 +174,9 @@ CC_CONSTRUCTOR_ACCESS:
protected: 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) #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
EventListenerCustom* _backToForegroundlistener; EventListenerCustom* _backToForegroundlistener;

View File

@ -46,6 +46,20 @@ const Mat4& Bone::getInverseBindPose()
return _invBindPose; 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) void Bone::setWorldMatDirty(bool dirty)
{ {
_worldDirty = dirty; _worldDirty = dirty;
@ -81,8 +95,21 @@ const Mat4& Bone::getWorldMat()
return _world; 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; BoneBlendState state;
if (trans) if (trans)
state.localTranslate.set(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.localScale.set(scale);
state.weight = weight; state.weight = weight;
state.tag = tag;
_blendStates.push_back(state); _blendStates.push_back(state);
_localDirty = true;
} }
void Bone::clearBoneBlendState() void Bone::clearBoneBlendState()
@ -115,13 +142,6 @@ Bone* Bone::create(const std::string& id)
return bone; return bone;
} }
/**
* Updates the joint matrix.
*
* @param matrixPalette The matrix palette to update.
*/
void Bone::updateJointMatrix(Vec4* matrixPalette) 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() Bone* Bone::getParentBone()
{ {
return _parent; return _parent;
} }
int Bone::getChildBoneCount() const ssize_t Bone::getChildBoneCount() const
{ {
return _children.size(); return _children.size();
} }
@ -168,15 +187,11 @@ void Bone::removeAllChildBone()
Bone::Bone(const std::string& id) Bone::Bone(const std::string& id)
: _name(id) : _name(id)
, _parent(nullptr) , _parent(nullptr)
, _localDirty(true)
, _worldDirty(true) , _worldDirty(true)
{ {
} }
/**
* Destructor.
*/
Bone::~Bone() Bone::~Bone()
{ {
removeAllChildBone(); removeAllChildBone();
@ -186,8 +201,8 @@ void Bone::updateLocalMat()
{ {
if (_blendStates.size()) if (_blendStates.size())
{ {
Vec3 translate(Vec3::ZERO), scale(Vec3::ONE); Vec3 translate(Vec3::ZERO), scale(Vec3::ZERO);
Quaternion quat(Quaternion::identity()); Quaternion quat(Quaternion::zero());
float total = 0.f; float total = 0.f;
for (auto it: _blendStates) { for (auto it: _blendStates) {
@ -195,13 +210,12 @@ void Bone::updateLocalMat()
} }
if (total) if (total)
{ {
//if (_blendStates.size() == 1) if (_blendStates.size() == 1)
if (true)
{ {
int cnt = _blendStates.size(); auto& state = _blendStates[0];
translate = _blendStates[cnt - 1].localTranslate; translate = state.localTranslate;
scale = _blendStates[cnt - 1].localScale; scale = state.localScale;
quat = _blendStates[cnt - 1].localRot; quat = state.localRot;
} }
else else
{ {
@ -209,24 +223,18 @@ void Bone::updateLocalMat()
for (auto it : _blendStates) { for (auto it : _blendStates) {
float weight = (it.weight * invTotal); float weight = (it.weight * invTotal);
translate += it.localTranslate * weight; 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; Quaternion& q = _blendStates[0].localRot;
scale.y *= it.localScale.y * weight; if (q.x * quat.x + q.y * quat.y + q.z * quat.z + q.w * quat.w < 0)
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)
weight = -weight; 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); Mat4::createTranslation(translate, &_local);
@ -234,13 +242,7 @@ void Bone::updateLocalMat()
_local.scale(scale); _local.scale(scale);
_blendStates.clear(); _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) bool MeshSkin::initFromSkinData(const SkinData& skindata)
{ {
setBoneCount((int)skindata.boneNames.size()); ssize_t i = 0;
for (size_t i = 0; i < skindata.boneNames.size(); i++) { for (; i < skindata.skinBoneNames.size(); i++) {
auto bone = Bone::create(skindata.boneNames[i]); auto bone = Bone::create(skindata.skinBoneNames[i]);
bone->_invBindPose = skindata.inverseBindPoseMatrices[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) { for (auto it : skindata.boneChild) {
auto parent = getBoneByIndex(it.first); auto parent = getBoneByIndex(it.first);
@ -311,29 +319,42 @@ bool MeshSkin::initFromSkinData(const SkinData& skindata)
} }
setRootBone(getBoneByIndex(skindata.rootBoneIndex)); setRootBone(getBoneByIndex(skindata.rootBoneIndex));
_rootBone->resetPose();
return true; return true;
} }
unsigned int MeshSkin::getBoneCount() const ssize_t MeshSkin::getBoneCount() const
{ {
return _bones.size(); return _skinBones.size() + _nodeBones.size();
} }
//get bone //get bone
Bone* MeshSkin::getBoneByIndex(unsigned int index) const 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 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 ) if (it->getName() == id )
return it; return it;
} }
return nullptr; return nullptr;
} }
//get & set root bone
Bone* MeshSkin::getRootBone() const Bone* MeshSkin::getRootBone() const
{ {
return _rootBone; return _rootBone;
@ -345,36 +366,16 @@ void MeshSkin::setRootBone(Bone* joint)
_rootBone = joint; _rootBone = joint;
} }
void MeshSkin::setBoneCount(int boneCount) int MeshSkin::getBoneIndex(Bone* bone) const
{ {
removeAllBones(); int i = 0;
for (; i < _skinBones.size(); i++) {
// Resize the joints vector and initialize to NULL if (_skinBones.at(i) == bone)
_bones.reserve(boneCount); return i;
// 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 index = 0;
for (; index < _nodeBones.size(); index++, i++) {
int MeshSkin::getBoneIndex(Bone* joint) const if (_nodeBones.at(index) == bone)
{
for (auto i = 0; i < _bones.size(); i++) {
if (_bones.at(i) == joint)
return i; return i;
} }
return -1; return -1;
@ -385,8 +386,12 @@ Vec4* MeshSkin::getMatrixPalette()
{ {
updateBoneMatrix(); updateBoneMatrix();
if (_matrixPalette == nullptr)
{
_matrixPalette = new Vec4[_skinBones.size() * PALETTE_ROWS];
}
int i = 0; int i = 0;
for (auto it : _bones ) for (auto it : _skinBones )
{ {
it->updateJointMatrix(&_matrixPalette[i++ * PALETTE_ROWS]); it->updateJointMatrix(&_matrixPalette[i++ * PALETTE_ROWS]);
} }
@ -394,10 +399,9 @@ Vec4* MeshSkin::getMatrixPalette()
return _matrixPalette; return _matrixPalette;
} }
//getBoneCount() * 3 ssize_t MeshSkin::getMatrixPaletteSize() const
unsigned int MeshSkin::getMatrixPaletteSize() const
{ {
return _bones.size() * PALETTE_ROWS; return _skinBones.size() * PALETTE_ROWS;
} }
//refresh bone world matrix //refresh bone world matrix
@ -409,14 +413,20 @@ void MeshSkin::updateBoneMatrix()
void MeshSkin::removeAllBones() void MeshSkin::removeAllBones()
{ {
_bones.clear(); _skinBones.clear();
_nodeBones.clear();
CC_SAFE_DELETE_ARRAY(_matrixPalette); CC_SAFE_DELETE_ARRAY(_matrixPalette);
CC_SAFE_RELEASE(_rootBone); 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);
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////

View File

@ -52,17 +52,26 @@ public:
*/ */
const Mat4& getInverseBindPose(); const Mat4& getInverseBindPose();
//update own world matrix and children's /**update own world matrix and children's*/
void updateWorldMat(); void updateWorldMat();
void setWorldMatDirty(bool dirty = true); /**get wrod matrix*/
const Mat4& getWorldMat(); const Mat4& getWorldMat();
/**get bone name*/
const std::string& getName() const { return _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(); void clearBoneBlendState();
/** /**
* Creates C3DBone. * Creates C3DBone.
@ -72,10 +81,22 @@ public:
/** /**
* Sets the inverse bind pose matrix. * 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); 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. * Updates the joint matrix.
* *
@ -83,13 +104,19 @@ public:
*/ */
void updateJointMatrix(Vec4* matrixPalette); 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(); Bone* getParentBone();
int getChildBoneCount() const; /**get child bone count*/
ssize_t getChildBoneCount() const;
/**get child bone by index*/
Bone* getChildBoneByIndex(int index); Bone* getChildBoneByIndex(int index);
/**add child bone*/
void addChildBone(Bone* bone); void addChildBone(Bone* bone);
/**remove child bone by index*/
void removeChildBoneByIndex(int index); void removeChildBoneByIndex(int index);
/**remove child bone*/
void removeChildBone(Bone* bone); void removeChildBone(Bone* bone);
/**remove all child bone*/
void removeAllChildBone(); void removeAllChildBone();
@ -102,11 +129,13 @@ protected:
Quaternion localRot; Quaternion localRot;
Vec3 localScale; Vec3 localScale;
float weight; float weight;
void* tag; //
BoneBlendState() BoneBlendState()
: localTranslate(Vec3::ZERO) : localTranslate(Vec3::ZERO)
, localRot(Quaternion::identity()) , localRot(Quaternion::identity())
, localScale(Vec3::ONE) , localScale(Vec3::ONE)
, weight(1.f) , weight(1.f)
, tag(nullptr)
{ {
} }
@ -126,17 +155,21 @@ protected:
*/ */
void updateLocalMat(); 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. * The Mat4 representation of the Joint's bind pose.
*/ */
Mat4 _invBindPose; Mat4 _invBindPose;
Bone* _parent; Mat4 _oriPose; //original bone pose
Bone* _parent; //parent bone
Vector<Bone*> _children; Vector<Bone*> _children;
bool _localDirty;
bool _worldDirty; bool _worldDirty;
Mat4 _world; Mat4 _world;
Mat4 _local; 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 class MeshSkin: public Ref
{ {
public: 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); 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* getBoneByIndex(unsigned int index) const;
Bone* getBoneByName(const std::string& id) const; Bone* getBoneByName(const std::string& id) const;
//get & set root bone /**get & set root bone*/
Bone* getRootBone() const; 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(); Vec4* getMatrixPalette();
//getBoneCount() * 3 /**getSkinBoneCount() * 3*/
unsigned int getMatrixPaletteSize() const; ssize_t getMatrixPaletteSize() const;
//refresh bone world matrix /**refresh bone world matrix*/
void updateBoneMatrix(); void updateBoneMatrix();
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
@ -182,43 +218,58 @@ CC_CONSTRUCTOR_ACCESS:
~MeshSkin(); ~MeshSkin();
/**init from skin data*/
bool initFromSkinData(const SkinData& skindata); bool initFromSkinData(const SkinData& skindata);
/**remove all bones*/
void removeAllBones(); void removeAllBones();
void addBone(Bone* bone); /**add skin bone*/
void addSkinBone(Bone* bone);
/**add Node bone*/
void addNodeBone(Bone* bone);
protected: 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; Bone* _rootBone;
// Pointer to the array of palette matrices. // Pointer to the array of palette matrices.
// This array is passed to the vertex shader as a uniform. // This array is passed to the vertex shader as a uniform.
// Each 4x3 row-wise matrix is represented as 3 Vec4's. // 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; Vec4* _matrixPalette;
}; };
/**
* MeshSkinData Cache
*/
class MeshSkinDataCache class MeshSkinDataCache
{ {
public: public:
/**get & destroy*/
static MeshSkinDataCache* getInstance(); static MeshSkinDataCache* getInstance();
static void destroyInstance(); static void destroyInstance();
/**get mesh skin data from cache*/
const SkinData* getMeshSkinData(const std::string& key) const; const SkinData* getMeshSkinData(const std::string& key) const;
/**add mesh skin data to cache*/
bool addMeshSkinData(const std::string& key, const SkinData& skinData); bool addMeshSkinData(const std::string& key, const SkinData& skinData);
/**remove all mesh skin data*/
void removeAllMeshSkinData(); void removeAllMeshSkinData();
protected: protected:
MeshSkinDataCache(); MeshSkinDataCache();
~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 NS_CC_END

View File

@ -273,6 +273,8 @@ void Sprite3D::genGLProgramState()
} }
setGLProgramState(programstate); setGLProgramState(programstate);
GLuint texID = _texture ? _texture->getName() : 0;
_meshCommand.genMaterialID(texID, programstate, _mesh, _blend);
} }
GLProgram* Sprite3D::getDefaultGLProgram(bool textured) GLProgram* Sprite3D::getDefaultGLProgram(bool textured)
@ -296,11 +298,12 @@ GLProgram* Sprite3D::getDefaultGLProgram(bool textured)
void Sprite3D::setTexture(const std::string& texFile) void Sprite3D::setTexture(const std::string& texFile)
{ {
auto tex = Director::getInstance()->getTextureCache()->addImage(texFile); auto tex = Director::getInstance()->getTextureCache()->addImage(texFile);
if( tex && _texture != tex ) { // if( tex && _texture != tex ) {
CC_SAFE_RETAIN(tex); // CC_SAFE_RETAIN(tex);
CC_SAFE_RELEASE_NULL(_texture); // CC_SAFE_RELEASE_NULL(_texture);
_texture = tex; // _texture = tex;
} // }
setTexture(tex);
} }
void Sprite3D::setTexture(Texture2D* texture) void Sprite3D::setTexture(Texture2D* texture)
@ -309,6 +312,11 @@ void Sprite3D::setTexture(Texture2D* texture)
CC_SAFE_RETAIN(texture); CC_SAFE_RETAIN(texture);
CC_SAFE_RELEASE_NULL(_texture); CC_SAFE_RELEASE_NULL(_texture);
_texture = texture; _texture = texture;
if (getGLProgramState() && _mesh)
{
GLuint texID = _texture ? _texture->getName() : 0;
_meshCommand.genMaterialID(texID, getGLProgramState(), _mesh, _blend);
}
} }
} }

View File

@ -40,22 +40,24 @@ class Mesh;
class Texture2D; class Texture2D;
class MeshSkin; 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 class Sprite3D : public Node, public BlendProtocol
{ {
public: public:
/// creates a Sprite3D /** creates a Sprite3D*/
static Sprite3D* create(const std::string &modelPath); static Sprite3D* create(const std::string &modelPath);
// creates a Sprite3D. It only supports one texture, and overrides the internal texture with 'texturePath' // 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); static Sprite3D* create(const std::string &modelPath, const std::string &texturePath);
//set texture /**set texture*/
void setTexture(const std::string& texFile); void setTexture(const std::string& texFile);
void setTexture(Texture2D* texture); void setTexture(Texture2D* texture);
/**get mesh*/
Mesh* getMesh() const { return _mesh; } Mesh* getMesh() const { return _mesh; }
/**get skin*/
MeshSkin* getSkin() const { return _skin; } MeshSkin* getSkin() const { return _skin; }
// overrides // overrides
@ -68,28 +70,31 @@ CC_CONSTRUCTOR_ACCESS:
virtual ~Sprite3D(); virtual ~Sprite3D();
bool initWithFile(const std::string &path); 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); bool loadFromObj(const std::string& path);
//load from .c3b or .c3t /**load from .c3b or .c3t*/
bool loadFromC3x(const std::string& path); bool loadFromC3x(const std::string& path);
/**draw*/
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
/**get default shader*/
virtual GLProgram* getDefaultGLProgram(bool textured = true); virtual GLProgram* getDefaultGLProgram(bool textured = true);
/**generate default GLProgramState*/
void genGLProgramState(); void genGLProgramState();
protected: protected:
Mesh *_mesh; Mesh* _mesh;//mesh
MeshSkin *_skin; MeshSkin* _skin;//skin
MeshCommand _meshCommand; MeshCommand _meshCommand; //render command
Texture2D* _texture; Texture2D* _texture;
BlendFunc _blend; BlendFunc _blend;
}; };
extern std::string s_attributeNames[]; extern std::string s_attributeNames[];//attribute names array
NS_CC_END NS_CC_END
#endif // __SPRITE3D_H_ #endif // __SPRITE3D_H_

View File

@ -44,15 +44,19 @@ class Texture2D;
class Sprite3DMaterialCache class Sprite3DMaterialCache
{ {
public: public:
/**get & destroy cache*/
static Sprite3DMaterialCache* getInstance(); static Sprite3DMaterialCache* getInstance();
static void destroyInstance(); static void destroyInstance();
/**add to cache*/
bool addSprite3DMaterial(const std::string& key, Texture2D* tex); bool addSprite3DMaterial(const std::string& key, Texture2D* tex);
/**get material from cache*/
Texture2D* getSprite3DMaterial(const std::string& key); Texture2D* getSprite3DMaterial(const std::string& key);
/**remove all spritematerial*/
void removeAllSprite3DMaterial(); void removeAllSprite3DMaterial();
/**remove unused spritematerial*/
void removeUnusedSprite3DMaterial(); void removeUnusedSprite3DMaterial();
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
@ -61,8 +65,8 @@ CC_CONSTRUCTOR_ACCESS:
~Sprite3DMaterialCache(); ~Sprite3DMaterialCache();
protected: protected:
static Sprite3DMaterialCache* _cacheInstance; static Sprite3DMaterialCache* _cacheInstance;//instance
std::unordered_map<std::string, Texture2D*> _materials; // std::unordered_map<std::string, Texture2D*> _materials; //cached material
}; };

View File

@ -7,5 +7,6 @@ set(COCOS_3D_SRC
3d/CCAnimation3D.cpp 3d/CCAnimation3D.cpp
3d/CCBundle3D.cpp 3d/CCBundle3D.cpp
3d/CCMeshSkin.cpp 3d/CCMeshSkin.cpp
3d/CCBundleReader.cpp
) )

View File

@ -74,6 +74,7 @@ cocos2d.cpp \
3d/CCAnimate3D.cpp \ 3d/CCAnimate3D.cpp \
3d/CCAnimation3D.cpp \ 3d/CCAnimation3D.cpp \
3d/CCBundle3D.cpp \ 3d/CCBundle3D.cpp \
3d/CCBundleReader.cpp \
3d/CCMesh.cpp \ 3d/CCMesh.cpp \
3d/CCMeshSkin.cpp \ 3d/CCMeshSkin.cpp \
3d/CCSprite3DMaterial.cpp \ 3d/CCSprite3DMaterial.cpp \

View File

@ -326,6 +326,15 @@ void GLProgramState::resetGLProgram()
} }
void GLProgramState::apply(const Mat4& modelView) void GLProgramState::apply(const Mat4& modelView)
{
applyGLProgram(modelView);
applyAttributes();
applyUniforms();
}
void GLProgramState::applyGLProgram(const Mat4& modelView)
{ {
CCASSERT(_glprogram, "invalid glprogram"); CCASSERT(_glprogram, "invalid glprogram");
if(_uniformAttributeValueDirty) if(_uniformAttributeValueDirty)
@ -349,19 +358,24 @@ void GLProgramState::apply(const Mat4& modelView)
// set shader // set shader
_glprogram->use(); _glprogram->use();
_glprogram->setUniformsForBuiltins(modelView); _glprogram->setUniformsForBuiltins(modelView);
}
void GLProgramState::applyAttributes(bool applyAttribFlags)
{
// Don't set attributes if they weren't set // Don't set attributes if they weren't set
// Use Case: Auto-batching // Use Case: Auto-batching
if(_vertexAttribsFlags) { if(_vertexAttribsFlags) {
// enable/disable vertex attribs // enable/disable vertex attribs
GL::enableVertexAttribs(_vertexAttribsFlags); if (applyAttribFlags)
GL::enableVertexAttribs(_vertexAttribsFlags);
// set attributes // set attributes
for(auto &attribute : _attributes) for(auto &attribute : _attributes)
{ {
attribute.second.apply(); attribute.second.apply();
} }
} }
}
void GLProgramState::applyUniforms()
{
// set uniforms // set uniforms
for(auto& uniform : _uniforms) { for(auto& uniform : _uniforms) {
uniform.second.apply(); uniform.second.apply();

View File

@ -157,7 +157,16 @@ public:
/** gets-or-creates an instance of GLProgramState for a given GLProgramName */ /** gets-or-creates an instance of GLProgramState for a given GLProgramName */
static GLProgramState* getOrCreateWithGLProgramName(const std::string &glProgramName ); static GLProgramState* getOrCreateWithGLProgramName(const std::string &glProgramName );
// apply GLProgram, attributes and uniforms
void apply(const Mat4& modelView); 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); void setGLProgram(GLProgram* glprogram);
GLProgram* getGLProgram() const { return _glprogram; } GLProgram* getGLProgram() const { return _glprogram; }

View File

@ -23,7 +23,12 @@
****************************************************************************/ ****************************************************************************/
#include "base/ccMacros.h" #include "base/ccMacros.h"
#include "base/CCConfiguration.h"
#include "base/CCDirector.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/CCMeshCommand.h"
#include "renderer/ccGLStateCache.h" #include "renderer/ccGLStateCache.h"
#include "renderer/CCGLProgram.h" #include "renderer/CCGLProgram.h"
@ -32,6 +37,7 @@
#include "renderer/CCTextureAtlas.h" #include "renderer/CCTextureAtlas.h"
#include "renderer/CCTexture2D.h" #include "renderer/CCTexture2D.h"
#include "renderer/ccGLStateCache.h" #include "renderer/ccGLStateCache.h"
#include "xxhash.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -46,8 +52,15 @@ MeshCommand::MeshCommand()
, _displayColor(1.0f, 1.0f, 1.0f, 1.0f) , _displayColor(1.0f, 1.0f, 1.0f, 1.0f)
, _matrixPalette(nullptr) , _matrixPalette(nullptr)
, _matrixPaletteSize(0) , _matrixPaletteSize(0)
, _materialID(0)
, _vao(0)
{ {
_type = RenderCommand::Type::MESH_COMMAND; _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, void MeshCommand::init(float globalOrder,
@ -103,6 +116,10 @@ void MeshCommand::setDisplayColor(const Vec4& color)
MeshCommand::~MeshCommand() MeshCommand::~MeshCommand()
{ {
releaseVAO();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundlistener);
#endif
} }
void MeshCommand::applyRenderState() 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) void MeshCommand::MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform)
{ {
glProgram->setUniformLocationWith4fv(uniform->location, (const float*)_matrixPalette, _matrixPaletteSize); 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() void MeshCommand::execute()
{ {
// set render state // set render state
applyRenderState(); applyRenderState();
// Set material // Set material
GL::bindTexture2D(_textureID); GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst); GL::blendFunc(_blendType.src, _blendType.dst);
@ -172,9 +258,49 @@ void MeshCommand::execute()
//restore render state //restore render state
restoreRenderState(); restoreRenderState();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_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 NS_CC_END

View File

@ -25,6 +25,7 @@
#ifndef _CC_MESHCOMMAND_H_ #ifndef _CC_MESHCOMMAND_H_
#define _CC_MESHCOMMAND_H_ #define _CC_MESHCOMMAND_H_
#include <unordered_map>
#include "CCRenderCommand.h" #include "CCRenderCommand.h"
#include "renderer/CCGLProgram.h" #include "renderer/CCGLProgram.h"
#include "math/CCMath.h" #include "math/CCMath.h"
@ -35,6 +36,8 @@ NS_CC_BEGIN
class GLProgramState; class GLProgramState;
class GLProgram; class GLProgram;
struct Uniform; struct Uniform;
class EventListenerCustom;
class EventCustom;
//it is a common mesh //it is a common mesh
class MeshCommand : public RenderCommand class MeshCommand : public RenderCommand
@ -59,10 +62,27 @@ public:
void setMatrixPalette(const Vec4* matrixPalette) { _matrixPalette = matrixPalette; } void setMatrixPalette(const Vec4* matrixPalette) { _matrixPalette = matrixPalette; }
void setMatrixPaletteSize(int size) { _matrixPaletteSize = size; } void setMatrixPaletteSize(int size) { _matrixPaletteSize = size; }
void execute(); 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: protected:
//build & release vao
void buildVAO();
void releaseVAO();
// apply renderstate // apply renderstate
void applyRenderState(); void applyRenderState();
@ -83,6 +103,10 @@ protected:
const Vec4* _matrixPalette; const Vec4* _matrixPalette;
int _matrixPaletteSize; int _matrixPaletteSize;
uint32_t _materialID; //material ID
GLuint _vao; //use vao if possible
GLuint _vertexBuffer; GLuint _vertexBuffer;
GLuint _indexBuffer; GLuint _indexBuffer;
GLenum _primitive; GLenum _primitive;
@ -97,7 +121,12 @@ protected:
// ModelView transform // ModelView transform
Mat4 _mv; Mat4 _mv;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
EventListenerCustom* _backToForegroundlistener;
#endif
}; };
NS_CC_END NS_CC_END
#endif //_CC_MESHCOMMAND_H_ #endif //_CC_MESHCOMMAND_H_

View File

@ -108,6 +108,7 @@ static const int DEFAULT_RENDER_QUEUE = 0;
// //
Renderer::Renderer() Renderer::Renderer()
:_lastMaterialID(0) :_lastMaterialID(0)
,_lastBatchedMeshCommand(nullptr)
,_numQuads(0) ,_numQuads(0)
,_glViewAssigned(false) ,_glViewAssigned(false)
,_isRendering(false) ,_isRendering(false)
@ -283,6 +284,7 @@ void Renderer::visitRenderQueue(const RenderQueue& queue)
auto commandType = command->getType(); auto commandType = command->getType();
if(RenderCommand::Type::QUAD_COMMAND == commandType) if(RenderCommand::Type::QUAD_COMMAND == commandType)
{ {
flush3D();
auto cmd = static_cast<QuadCommand*>(command); auto cmd = static_cast<QuadCommand*>(command);
//Batch quads //Batch quads
if(_numQuads + cmd->getQuadCount() > VBO_SIZE) if(_numQuads + cmd->getQuadCount() > VBO_SIZE)
@ -321,9 +323,19 @@ void Renderer::visitRenderQueue(const RenderQueue& queue)
} }
else if (RenderCommand::Type::MESH_COMMAND == commandType) else if (RenderCommand::Type::MESH_COMMAND == commandType)
{ {
flush(); flush2D();
auto cmd = static_cast<MeshCommand*>(command); 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 else
{ {
@ -376,6 +388,7 @@ void Renderer::clean()
_numQuads = 0; _numQuads = 0;
_lastMaterialID = 0; _lastMaterialID = 0;
_lastBatchedMeshCommand = nullptr;
} }
void Renderer::convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView) void Renderer::convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView)
@ -505,11 +518,26 @@ void Renderer::drawBatchedQuads()
} }
void Renderer::flush() void Renderer::flush()
{
flush2D();
flush3D();
}
void Renderer::flush2D()
{ {
drawBatchedQuads(); drawBatchedQuads();
_lastMaterialID = 0; _lastMaterialID = 0;
} }
void Renderer::flush3D()
{
if (_lastBatchedMeshCommand)
{
_lastBatchedMeshCommand->postBatchDraw();
_lastBatchedMeshCommand = nullptr;
}
}
// helpers // helpers
bool Renderer::checkVisibility(const Mat4 &transform, const Size &size) bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)

View File

@ -38,6 +38,7 @@ NS_CC_BEGIN
class EventListenerCustom; class EventListenerCustom;
class QuadCommand; class QuadCommand;
class MeshCommand;
/** Class that knows how to sort `RenderCommand` objects. /** Class that knows how to sort `RenderCommand` objects.
Since the commands that have `z == 0` are "pushed back" in 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 //Draw the previews queued quads and flush previous context
void flush(); void flush();
void flush2D();
void flush3D();
void visitRenderQueue(const RenderQueue& queue); void visitRenderQueue(const RenderQueue& queue);
void convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView); void convertToWorldCoordinates(V3F_C4B_T2F_Quad* quads, ssize_t quantity, const Mat4& modelView);
@ -142,6 +147,7 @@ protected:
uint32_t _lastMaterialID; uint32_t _lastMaterialID;
MeshCommand* _lastBatchedMeshCommand;
std::vector<QuadCommand*> _batchedQuadCommands; std::vector<QuadCommand*> _batchedQuadCommands;
V3F_C4B_T2F_Quad _quads[VBO_SIZE]; V3F_C4B_T2F_Quad _quads[VBO_SIZE];

View File

@ -29,38 +29,47 @@ uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
// Varyings // Varyings
varying vec2 TextureCoordOut; varying vec2 TextureCoordOut;
vec4 _skinnedPosition;
vec4 getPosition() vec4 getPosition()
{ {
vec4 matrixPalette1 = vec4(0.0);
vec4 matrixPalette2 = vec4(0.0);
vec4 matrixPalette3 = vec4(0.0);
float blendWeight = a_blendWeight[0]; float blendWeight = a_blendWeight[0];
int matrixIndex = int (a_blendIndex[0]) * 3; int matrixIndex = int (a_blendIndex[0]) * 3;
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight; vec4 matrixPalette1 = u_matrixPalette[matrixIndex] * blendWeight;
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight; vec4 matrixPalette2 = u_matrixPalette[matrixIndex + 1] * blendWeight;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight; vec4 matrixPalette3 = u_matrixPalette[matrixIndex + 2] * blendWeight;
blendWeight = a_blendWeight[1]; blendWeight = a_blendWeight[1];
matrixIndex = int(a_blendIndex[1]) * 3; if (blendWeight > 0.0)
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight; {
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight; matrixIndex = int(a_blendIndex[1]) * 3;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight; matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
}
blendWeight = a_blendWeight[2]; blendWeight = a_blendWeight[2];
matrixIndex = int(a_blendIndex[2]) * 3; if (blendWeight > 0.0)
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight; {
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight; matrixIndex = int(a_blendIndex[2]) * 3;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight; matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
}
blendWeight = a_blendWeight[3]; blendWeight = a_blendWeight[3];
matrixIndex = int(a_blendIndex[3]) * 3; if (blendWeight > 0.0)
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight; {
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight; matrixIndex = int(a_blendIndex[3]) * 3;
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight; 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.x = dot(a_position, matrixPalette1);
_skinnedPosition.y = dot(a_position, matrixPalette2); _skinnedPosition.y = dot(a_position, matrixPalette2);
_skinnedPosition.z = dot(a_position, matrixPalette3); _skinnedPosition.z = dot(a_position, matrixPalette3);

View File

@ -194,7 +194,9 @@
"cocos/3d/CCAnimationCurve.h", "cocos/3d/CCAnimationCurve.h",
"cocos/3d/CCAnimationCurve.inl", "cocos/3d/CCAnimationCurve.inl",
"cocos/3d/CCBundle3D.cpp", "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/CCBundle3DData.h",
"cocos/3d/CCMesh.cpp", "cocos/3d/CCMesh.cpp",
"cocos/3d/CCMesh.h", "cocos/3d/CCMesh.h",

View File

@ -44,7 +44,8 @@ static std::function<Layer*()> createFunctions[] =
{ {
CL(Sprite3DBasicTest), CL(Sprite3DBasicTest),
CL(Sprite3DEffectTest), CL(Sprite3DEffectTest),
CL(Sprite3DWithSkinTest) CL(Sprite3DWithSkinTest),
CL(Animate3DTest)
}; };
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
@ -532,7 +533,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest()
} }
std::string Sprite3DWithSkinTest::title() const std::string Sprite3DWithSkinTest::title() const
{ {
return "Testing Sprite3D for animation from c3t"; return "Testing Sprite3D";
} }
std::string Sprite3DWithSkinTest::subtitle() const std::string Sprite3DWithSkinTest::subtitle() const
{ {
@ -541,12 +542,14 @@ std::string Sprite3DWithSkinTest::subtitle() const
void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p) 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); addChild(sprite);
sprite->setRotation3D(Vec3(-90.f, 0.f, 0.f));
sprite->setPosition( Vec2( p.x, p.y) ); sprite->setPosition( Vec2( p.x, p.y) );
auto animation = Animation3D::getOrCreate("Sprite3DTest/girl.c3t"); auto animation = Animation3D::getOrCreate(fileName);
if (animation) if (animation)
{ {
auto animate = Animate3D::create(animation); auto animate = Animate3D::create(animation);
@ -578,3 +581,141 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector<Touch*>& touches, Ev
addNewSpriteWithCoords( location ); 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;
}
}
}
}

View File

@ -29,6 +29,12 @@
#include "../BaseTest.h" #include "../BaseTest.h"
#include <string> #include <string>
namespace cocos2d {
class Animate3D;
class Sprite3D;
class Delay;
}
class Sprite3DTestDemo : public BaseTest class Sprite3DTestDemo : public BaseTest
{ {
public: public:
@ -151,6 +157,46 @@ public:
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event); 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 class Sprite3DTestScene : public TestScene
{ {
public: public:

View File

@ -34,6 +34,7 @@ Controller g_aTestNames[] = {
// TESTS MUST BE ORDERED ALPHABETICALLY // TESTS MUST BE ORDERED ALPHABETICALLY
// violators will be prosecuted // violators will be prosecuted
// //
{ "3D: Sprite3D", [](){ return new Sprite3DTestScene(); }},
{ "ActionManager", [](){return new ActionManagerTestScene(); } }, { "ActionManager", [](){return new ActionManagerTestScene(); } },
{ "Actions - Basic", [](){ return new ActionsTestScene(); } }, { "Actions - Basic", [](){ return new ActionsTestScene(); } },
{ "Actions - Ease", [](){return new ActionsEaseTestScene();} }, { "Actions - Ease", [](){return new ActionsEaseTestScene();} },
@ -83,7 +84,6 @@ Controller g_aTestNames[] = {
{ "Node: Scene", [](){return new SceneTestScene();} }, { "Node: Scene", [](){return new SceneTestScene();} },
{ "Node: Spine", []() { return new SpineTestScene(); } }, { "Node: Spine", []() { return new SpineTestScene(); } },
{ "Node: Sprite", [](){return new SpriteTestScene(); } }, { "Node: Sprite", [](){return new SpriteTestScene(); } },
{ "Node: Sprite3D", [](){ return new Sprite3DTestScene(); }},
{ "Node: TileMap", [](){return new TileMapTestScene(); } }, { "Node: TileMap", [](){return new TileMapTestScene(); } },
{ "Node: Text Input", [](){return new TextInputTestScene(); } }, { "Node: Text Input", [](){return new TextInputTestScene(); } },
{ "Node: UI", [](){ return new UITestScene(); }}, { "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