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

View File

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

View File

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

View File

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

View File

@ -39,15 +39,23 @@ NS_CC_BEGIN
class Animation3D;
class Bone;
/**
* Animate3D
* Animate3D, Animates a Sprite3D given with an Animation3D
*/
class Animate3D: public ActionInterval
{
public:
//create Animate3D using Animation.
/**create Animate3D using Animation.*/
static Animate3D* create(Animation3D* animation);
/**
* create Animate3D
* @param animation used to generate animate3D
* @param formTime
* @param duration Time the Animate3D lasts
* @return Animate3D created using animate
*/
static Animate3D* create(Animation3D* animation, float fromTime, float duration);
//
// Overrides
//
@ -58,9 +66,15 @@ public:
virtual void update(float t) override;
/**get & set speed */
float getSpeed() const { return _speed; }
void setSpeed(float speed) { _speed = speed; }
/**get & set blend weight*/
float getWeight() const { return _weight; }
void setWeight(float weight) { _weight = weight; }
/**get & set play back*/
bool getPlayBack() const { return _playBack; }
void setPlayBack(bool playBack) { _playBack = playBack; }
@ -69,11 +83,14 @@ CC_CONSTRUCTOR_ACCESS:
Animate3D();
virtual ~Animate3D();
Animation3D* _animation;
protected:
Animation3D* _animation; //animation data
float _speed;
float _weight;
bool _playBack;
float _speed; //playing speed
float _weight; //blend weight
float _start; //start time 0 - 1, used to generate sub Animate3D
float _last; //last time 0 - 1, used to generate sub Animate3D
bool _playBack; // is playing back
std::map<Bone*, Animation3D::Curve*> _boneCurves; //weak ref
};

View File

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

View File

@ -38,9 +38,12 @@
NS_CC_BEGIN
/**
* Evaluate Type
*/
enum class EvaluateType
{
INT_LINEAR,
INT_LINEAR,
INT_NEAR,
INT_QUAT_SLERP,
INT_USER_FUNCTION,
@ -54,15 +57,24 @@ class AnimationCurve: public Ref
{
public:
//create animation curve
/**create animation curve*/
static AnimationCurve* create(float* keytime, float* value, int count);
/**
* evalute value of time
* @param time Time to be estimated
* @param dst Estimated value of that time
* @param type EvaluateType
*/
void evaluate(float time, float* dst, EvaluateType type) const;
/**set evaluate function, allow the user use own function*/
void setEvaluateFun(std::function<void(float time, float* dst)> fun);
/**get start time*/
float getStartTime() const;
/**get end time*/
float getEndTime() const;
CC_CONSTRUCTOR_ACCESS:
@ -82,7 +94,7 @@ protected:
int _count;
int _componentSizeByte; //component size in byte, position and scale 3 * sizeof(float), rotation 4 * sizeof(float)
std::function<void(float time, float* dst)> _evaluateFun;
std::function<void(float time, float* dst)> _evaluateFun; //user defined function
};
NS_CC_END

View File

@ -27,55 +27,114 @@
#include "base/ccMacros.h"
#include "platform/CCFileUtils.h"
#include "renderer/CCGLProgram.h"
#include "CCBundleReader.h"
#include "base/CCData.h"
#include "json/document.h"
#define BUNDLE_TYPE_SCENE 1
#define BUNDLE_TYPE_NODE 2
#define BUNDLE_TYPE_ANIMATIONS 3
#define BUNDLE_TYPE_ANIMATION 4
#define BUNDLE_TYPE_ANIMATION_CHANNEL 5
#define BUNDLE_TYPE_MODEL 10
#define BUNDLE_TYPE_MATERIAL 16
#define BUNDLE_TYPE_EFFECT 18
#define BUNDLE_TYPE_CAMERA 32
#define BUNDLE_TYPE_LIGHT 33
#define BUNDLE_TYPE_MESH 34
#define BUNDLE_TYPE_MESHPART 35
#define BUNDLE_TYPE_MESHSKIN 36
static const char* ID = "id";
static const char* MESHDATA_MESH = "mesh";
static const char* MESHDATA_DEFAULTPART = "body";
static const char* MESHDATA_VERTEXSIZE = "vertexsize";
static const char* MESHDATA_VERTICES = "vertices";
static const char* MESHDATA_INDEXNUM = "indexnum";
static const char* MESHDATA_INDICES = "indices";
static const char* MESHDATA_ATTRIBUTES = "attributes";
static const char* MESHDATA_SIZE = "size";
static const char* MESHDATA_TYPE = "type";
static const char* MESHDATA_ATTRIBUTE = "attribute";
static const char* SKINDATA_SKIN = "skin";
static const char* SKINDATA_BONES = "bones";
static const char* SKINDATA_NODE = "node";
static const char* SKINDATA_BINDSHAPE = "bindshape";
static const char* SKINDATA_CHILDREN = "children";
static const char* SKINDATA_TRANSFORM = "tansform";
static const char* MATERIALDATA_MATERIAL = "material";
static const char* MATERIALDATA_BASE = "base";
static const char* MATERIALDATA_FILENAME = "filename";
static const char* ANIMATIONDATA_ANIMATION = "animation";
static const char* ANIMATIONDATA_LENGTH = "length";
static const char* ANIMATIONDATA_BONES = "bones";
static const char* ANIMATIONDATA_BONEID = "boneId";
static const char* ANIMATIONDATA_KEYFRAMES = "keyframes";
static const char* ANIMATIONDATA_TRANSLATION = "translation";
static const char* ANIMATIONDATA_ROTATION = "rotation";
static const char* ANIMATIONDATA_SCALE = "scale";
static const char* ANIMATIONDATA_KEYTIME = "keytime";
NS_CC_BEGIN
void getChildMap(std::map<int, std::vector<int> >& map, SkinData* skinData, const rapidjson::Value& val)
{
if (!skinData)
return;
if (!val.HasMember("children"))
return;
std::string parent_name = val["id"].GetString();
int parent_name_index = skinData->getBoneNameIndex(parent_name);
const rapidjson::Value& children = val["children"];
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
// get transform matrix
Mat4 transform;
const rapidjson::Value& parent_tranform = val[SKINDATA_TRANSFORM];
for (rapidjson::SizeType j = 0; j < parent_tranform.Size(); j++)
{
const rapidjson::Value& child = children[i];
std::string child_name = child["id"].GetString();
int child_name_index = skinData->getBoneNameIndex(child_name);
if (child_name_index >= 0)
{
map[parent_name_index].push_back(child_name_index);
getChildMap(map, skinData, child);
}
transform.m[j] = parent_tranform[j].GetDouble();
}
}
void getChildMapT(std::map<std::string, std::vector<std::string> >& map, const SkinData* skinData, const rapidjson::Value& val)
{
if (!skinData)
// set origin matrices
std::string parent_name = val[ID].GetString();
int parent_name_index = skinData->getSkinBoneNameIndex(parent_name);
if (parent_name_index < 0)
{
skinData->addNodeBoneNames(parent_name);
skinData->nodeBoneOriginMatrices.push_back(transform);
parent_name_index = skinData->getBoneNameIndex(parent_name);
}
else if (parent_name_index < skinData->skinBoneNames.size())
{
skinData->skinBoneOriginMatrices[parent_name_index] = (transform);
}
// set root bone index
if(skinData->rootBoneIndex < 0)
skinData->rootBoneIndex = parent_name_index;
if (!val.HasMember(SKINDATA_CHILDREN))
return;
if (!val.HasMember("children"))
return;
std::string parent_name = val["id"].GetString();
const rapidjson::Value& children = val["children"];
const rapidjson::Value& children = val[SKINDATA_CHILDREN];
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
{
// get child bone name
const rapidjson::Value& child = children[i];
std::string child_name = child["id"].GetString();
map[parent_name].push_back(child_name);
getChildMapT(map, skinData, child);
std::string child_name = child[ID].GetString();
int child_name_index = skinData->getSkinBoneNameIndex(child_name);
if (child_name_index < 0)
{
skinData->addNodeBoneNames(child_name);
child_name_index = skinData->getBoneNameIndex(child_name);
}
map[parent_name_index].push_back(child_name_index);
getChildMap(map, skinData, child);
}
}
@ -93,184 +152,276 @@ void Bundle3D::destroyInstance()
CC_SAFE_DELETE(_instance);
}
void Bundle3D::clear()
{
if (_isBinary)
{
CC_SAFE_DELETE(_binaryBuffer);
CC_SAFE_DELETE_ARRAY(_references);
}
else
{
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
}
}
bool Bundle3D::load(const std::string& path)
{
if (_path == path)
return true;
getModelPath(path);
std::string strFileString = FileUtils::getInstance()->getStringFromFile(path);
ssize_t size = strFileString.length();
CC_SAFE_DELETE_ARRAY(_documentBuffer);
_documentBuffer = new char[size + 1];
memcpy(_documentBuffer, strFileString.c_str(), size);
_documentBuffer[size] = '\0';
if (_document.ParseInsitu<0>(_documentBuffer).HasParseError())
getModelRelativePath(path);
bool ret = false;
std::string ext = path.substr(path.length() - 4, 4);
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
if (ext == ".c3t")
{
_isBinary = false;
ret = loadJson(path);
}
else if (ext == ".c3b")
{
_isBinary = true;
ret = loadBinary(path);
}
else
{
CCLOGINFO("%s is invalid file formate", path);
}
ret?(_path = path):(_path = "");
return ret;
}
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
{
if (_isBinary)
{
return loadMeshDataBinary(meshdata);
}
else
{
return loadMeshDataJson(meshdata);
}
}
bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
{
if (_isBinary)
{
return loadSkinDataBinary(skindata);
}
else
{
return loadSkinDataJson(skindata);
}
}
bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdata)
{
if (_isBinary)
{
return loadMaterialDataBinary(materialdata);
}
else
{
return loadMaterialDataJson(materialdata);
}
}
bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animationdata)
{
if (_isBinary)
{
return loadAnimationDataBinary(animationdata);
}
else
{
return loadAnimationDataJson(animationdata);
}
}
bool Bundle3D::loadJson(const std::string& path)
{
clear();
Data data = FileUtils::getInstance()->getDataFromFile(path);
ssize_t size = data.getSize();
// json need null-terminated string.
_jsonBuffer = new char[size + 1];
memcpy(_jsonBuffer, data.getBytes(), size);
_jsonBuffer[size] = '\0';
if (_jsonReader.ParseInsitu<0>(_jsonBuffer).HasParseError())
{
assert(0);
CC_SAFE_DELETE_ARRAY(_documentBuffer);
_path = "";
clear();
return false;
}
_path = path;
return true;
}
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
bool Bundle3D::loadMeshDataJson(MeshData* meshdata)
{
meshdata->resetData();
assert(_document.HasMember("mesh"));
const rapidjson::Value& mash_data_array = _document["mesh"];
assert(_jsonReader.HasMember(MESHDATA_MESH));
const rapidjson::Value& mash_data_array = _jsonReader[MESHDATA_MESH];
assert(mash_data_array.IsArray());
const rapidjson::Value& mash_data_val = mash_data_array[(rapidjson::SizeType)0];
assert(mash_data_val.HasMember("body"));
const rapidjson::Value& mesh_data_body_array = mash_data_val["body"];
assert(mash_data_val.HasMember(MESHDATA_DEFAULTPART));
const rapidjson::Value& mesh_data_body_array = mash_data_val[MESHDATA_DEFAULTPART];
assert(mesh_data_body_array.IsArray());
const rapidjson::Value& mesh_data_body_array_0 = mesh_data_body_array[(rapidjson::SizeType)0];
// vertex_size
assert(mesh_data_body_array_0.HasMember("vertexsize"));
meshdata->vertexSizeInFloat = mesh_data_body_array_0["vertexsize"].GetInt();
assert(mesh_data_body_array_0.HasMember(MESHDATA_VERTEXSIZE));
meshdata->vertexSizeInFloat = mesh_data_body_array_0[MESHDATA_VERTEXSIZE].GetInt();
// vertices
meshdata->vertex.resize(meshdata->vertexSizeInFloat);
const rapidjson::Value& mesh_data_body_vertices = mesh_data_body_array_0["vertices"];
const rapidjson::Value& mesh_data_body_vertices = mesh_data_body_array_0[MESHDATA_VERTICES];
for (rapidjson::SizeType i = 0; i < mesh_data_body_vertices.Size(); i++)
meshdata->vertex[i] = mesh_data_body_vertices[i].GetDouble();
// index_number
meshdata->numIndex = mesh_data_body_array_0["indexnum"].GetUint();
meshdata->numIndex = mesh_data_body_array_0[MESHDATA_INDEXNUM].GetUint();
// indices
meshdata->indices.resize(meshdata->numIndex);
const rapidjson::Value& mesh_data_body_indices_val = mesh_data_body_array_0["indices"];
const rapidjson::Value& mesh_data_body_indices_val = mesh_data_body_array_0[MESHDATA_INDICES];
for (rapidjson::SizeType i = 0; i < mesh_data_body_indices_val.Size(); i++)
meshdata->indices[i] = (unsigned short)mesh_data_body_indices_val[i].GetUint();
// mesh_vertex_attribute
const rapidjson::Value& mesh_vertex_attribute = mash_data_val["attributes"];
const rapidjson::Value& mesh_vertex_attribute = mash_data_val[MESHDATA_ATTRIBUTES];
meshdata->attribCount = mesh_vertex_attribute.Size();
meshdata->attribs.resize(meshdata->attribCount);
for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); i++)
{
const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[i];
meshdata->attribs[i].size = mesh_vertex_attribute_val["size"].GetUint();
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * parseGLTypeSize(mesh_vertex_attribute_val["type"].GetString());
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val["type"].GetString());
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val["attribute"].GetString());
meshdata->attribs[i].size = mesh_vertex_attribute_val[MESHDATA_SIZE].GetUint();
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * 4;
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val[MESHDATA_TYPE].GetString());
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[MESHDATA_ATTRIBUTE].GetString());
}
return true;
}
bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
bool Bundle3D::loadSkinDataJson(SkinData* skindata)
{
if (!_document.HasMember("skin")) return false;
if (!_jsonReader.HasMember(SKINDATA_SKIN )) return false;
skindata->resetData();
const rapidjson::Value& skin_data_array = _document["skin"];
const rapidjson::Value& skin_data_array = _jsonReader[SKINDATA_SKIN ];
assert(skin_data_array.IsArray());
const rapidjson::Value& skin_data_array_val_0 = skin_data_array[(rapidjson::SizeType)0];
if (!skin_data_array_val_0.HasMember("bones"))
if (!skin_data_array_val_0.HasMember(SKINDATA_BONES))
return false;
const rapidjson::Value& skin_data_bones = skin_data_array_val_0["bones"];
const rapidjson::Value& skin_data_bones = skin_data_array_val_0[SKINDATA_BONES];
for (rapidjson::SizeType i = 0; i < skin_data_bones.Size(); i++)
{
const rapidjson::Value& skin_data_bone = skin_data_bones[i];
std::string name = skin_data_bone["node"].GetString();
skindata->boneNames.push_back(name);
std::string name = skin_data_bone[SKINDATA_NODE].GetString();
skindata->addSkinBoneNames(name);
Mat4 mat_bind_pos;
const rapidjson::Value& bind_pos = skin_data_bone["bindshape"];
const rapidjson::Value& bind_pos = skin_data_bone[SKINDATA_BINDSHAPE];
for (rapidjson::SizeType j = 0; j < bind_pos.Size(); j++)
{
mat_bind_pos.m[j] = bind_pos[j].GetDouble();
}
skindata->inverseBindPoseMatrices.push_back(mat_bind_pos);
}
// set root bone infomation
const rapidjson::Value& skin_data_1 = skin_data_array[1];
const rapidjson::Value& bone_array_0 = skin_data_1["children"][(rapidjson::SizeType)0];
skindata->rootBoneIndex = skindata->getBoneNameIndex(bone_array_0["id"].GetString());
getChildMap(skindata->boneChild, skindata, bone_array_0);
// parent and child relationship map
skindata->skinBoneOriginMatrices.resize(skindata->skinBoneNames.size());
//skindata->nodeBoneOriginMatrices.resize(skindata->nodeBoneNames.size());
getChildMap(skindata->boneChild, skindata, skin_data_1);
return true;
}
bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdata)
bool Bundle3D::loadMaterialDataJson(MaterialData* materialdata)
{
if (!_document.HasMember("material"))
if (!_jsonReader.HasMember(MATERIALDATA_MATERIAL))
return false;
const rapidjson::Value& material_data_array = _document["material"];
const rapidjson::Value& material_data_array = _jsonReader[MATERIALDATA_MATERIAL];
const rapidjson::Value& material_data_array_0 = material_data_array[(rapidjson::SizeType)0];
const rapidjson::Value& material_data_base_array = material_data_array_0["base"];
const rapidjson::Value& material_data_base_array = material_data_array_0[MATERIALDATA_BASE];
const rapidjson::Value& material_data_base_array_0 = material_data_base_array[(rapidjson::SizeType)0];
materialdata->texturePath = _modelRelativePath + material_data_base_array_0["filename"].GetString();
materialdata->texturePath = _modelRelativePath + material_data_base_array_0[MATERIALDATA_FILENAME].GetString();
return true;
}
bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animationdata)
bool Bundle3D::loadAnimationDataJson(Animation3DData* animationdata)
{
if (!_document.HasMember("animation")) return false;
if (!_jsonReader.HasMember(ANIMATIONDATA_ANIMATION)) return false;
animationdata->_rotationKeys.clear();
animationdata->_scaleKeys.clear();
animationdata->_translationKeys.clear();
const rapidjson::Value& animation_data_array = _document["animation"];
const rapidjson::Value& animation_data_array = _jsonReader[ANIMATIONDATA_ANIMATION];
if (animation_data_array.Size()==0) return false;
const rapidjson::Value& animation_data_array_val_0 = animation_data_array[(rapidjson::SizeType)0];
animationdata->_totalTime = animation_data_array_val_0["length"].GetDouble();
animationdata->_totalTime = animation_data_array_val_0[ANIMATIONDATA_LENGTH].GetDouble();
const rapidjson::Value& bones = animation_data_array_val_0["bones"];
const rapidjson::Value& bones = animation_data_array_val_0[ANIMATIONDATA_BONES];
for (rapidjson::SizeType i = 0; i < bones.Size(); i++)
{
const rapidjson::Value& bone = bones[i];
std::string bone_name = bone["boneId"].GetString();
std::string bone_name = bone[ANIMATIONDATA_BONEID].GetString();
if ( bone.HasMember("keyframes"))
if ( bone.HasMember(ANIMATIONDATA_KEYFRAMES))
{
const rapidjson::Value& bone_keyframes = bone["keyframes"];
for (rapidjson::SizeType j = 0; j < bone_keyframes.Size(); j++)
const rapidjson::Value& bone_keyframes = bone[ANIMATIONDATA_KEYFRAMES];
rapidjson::SizeType keyframe_size = bone_keyframes.Size();
for (rapidjson::SizeType j = 0; j < keyframe_size; j++)
{
const rapidjson::Value& bone_keyframe = bone_keyframes[j];
if ( bone_keyframe.HasMember("translation"))
if ( bone_keyframe.HasMember(ANIMATIONDATA_TRANSLATION))
{
const rapidjson::Value& bone_keyframe_translation = bone_keyframe["translation"];
float keytime = bone_keyframe["keytime"].GetDouble();
const rapidjson::Value& bone_keyframe_translation = bone_keyframe[ANIMATIONDATA_TRANSLATION];
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
Vec3 val = Vec3(bone_keyframe_translation[(rapidjson::SizeType)0].GetDouble(), bone_keyframe_translation[1].GetDouble(), bone_keyframe_translation[2].GetDouble());
animationdata->_translationKeys[bone_name].push_back(Animation3DData::Vec3Key(keytime,val));
}
if ( bone_keyframe.HasMember("rotation"))
if ( bone_keyframe.HasMember(ANIMATIONDATA_ROTATION))
{
const rapidjson::Value& bone_keyframe_rotation = bone_keyframe["rotation"];
float keytime = bone_keyframe["keytime"].GetDouble();
const rapidjson::Value& bone_keyframe_rotation = bone_keyframe[ANIMATIONDATA_ROTATION];
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
Quaternion val = Quaternion(bone_keyframe_rotation[(rapidjson::SizeType)0].GetDouble(),bone_keyframe_rotation[1].GetDouble(),bone_keyframe_rotation[2].GetDouble(),bone_keyframe_rotation[3].GetDouble());
animationdata->_rotationKeys[bone_name].push_back(Animation3DData::QuatKey(keytime,val));
}
if ( bone_keyframe.HasMember("scale"))
if ( bone_keyframe.HasMember(ANIMATIONDATA_SCALE))
{
const rapidjson::Value& bone_keyframe_scale = bone_keyframe["scale"];
float keytime = bone_keyframe["keytime"].GetDouble();
const rapidjson::Value& bone_keyframe_scale = bone_keyframe[ANIMATIONDATA_SCALE];
float keytime = bone_keyframe[ANIMATIONDATA_KEYTIME].GetDouble();
Vec3 val = Vec3(bone_keyframe_scale[(rapidjson::SizeType)0].GetDouble(), bone_keyframe_scale[1].GetDouble(), bone_keyframe_scale[2].GetDouble());
animationdata->_scaleKeys[bone_name].push_back(Animation3DData::Vec3Key(keytime,val));
}
@ -281,6 +432,330 @@ bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animati
return true;
}
bool Bundle3D::loadBinary(const std::string& path)
{
clear();
// get file data
CC_SAFE_DELETE(_binaryBuffer);
_binaryBuffer = new Data();
*_binaryBuffer = FileUtils::getInstance()->getDataFromFile(path);
if (_binaryBuffer->isNull())
{
clear();
CCLOGINFO(false, "Failed to read file: %s", path.c_str());
return false;
}
// Create bundle reader
//CC_SAFE_DELETE(_bundleReader);
_binaryReader.init( (char*)_binaryBuffer->getBytes(), _binaryBuffer->getSize() );
// Read identifier info
char identifier[] = { 'C', '3', 'B', '\0'};
char sig[4];
if (_binaryReader.read(sig, 1, 4) != 4 || memcmp(sig, identifier, 4) != 0)
{
clear();
CCLOGINFO(false, "Invalid identifier: %s", path.c_str());
return false;
}
// Read version
unsigned char ver[2];
if (_binaryReader.read(ver, 1, 2) != 2 || ver[0] != 0 || ver[1] != 1)
{
clear();
CCLOGINFO(false, "Unsupported version: (%d, %d)", ver[0], ver[1]);
return false;
}
// Read ref table size
if (_binaryReader.read(&_referenceCount, 4, 1) != 1)
{
clear();
CCLOGINFO("Failed to read ref table size '%s'.", path.c_str());
return false;
}
// Read all refs
CC_SAFE_DELETE_ARRAY(_references);
_references = new Reference[_referenceCount];
for (ssize_t i = 0; i < _referenceCount; ++i)
{
if ((_references[i].id = _binaryReader.readString()).empty() ||
_binaryReader.read(&_references[i].type, 4, 1) != 1 ||
_binaryReader.read(&_references[i].offset, 4, 1) != 1)
{
clear();
CCLOGINFO("Failed to read ref number %d for bundle '%s'.", i, path.c_str());
CC_SAFE_DELETE_ARRAY(_references);
return false;
}
}
return true;
}
bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
{
if (!seekToFirstType(BUNDLE_TYPE_MESH))
return false;
meshdata->resetData();
// read mesh data
if (_binaryReader.read(&meshdata->attribCount, 4, 1) != 1 || meshdata->attribCount < 1)
{
CCLOGINFO("Failed to read meshdata: attribCount '%s'.", _path.c_str());
return false;
}
meshdata->attribs.resize(meshdata->attribCount);
for (ssize_t i = 0; i < meshdata->attribCount; i++)
{
unsigned int vUsage, vSize;
if (_binaryReader.read(&vUsage, 4, 1) != 1 || _binaryReader.read(&vSize, 4, 1) != 1)
{
CCLOGINFO("Failed to read meshdata: usage or size '%s'.", _path.c_str());
return false;
}
meshdata->attribs[i].size = vSize;
meshdata->attribs[i].attribSizeBytes = meshdata->attribs[i].size * 4;
meshdata->attribs[i].type = GL_FLOAT;
meshdata->attribs[i].vertexAttrib = vUsage;
}
// Read vertex data
if (_binaryReader.read(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0)
{
CCLOGINFO("Failed to read meshdata: vertexSizeInFloat '%s'.", _path.c_str());
return false;
}
meshdata->vertex.resize(meshdata->vertexSizeInFloat);
if (_binaryReader.read(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat)
{
CCLOGINFO("Failed to read meshdata: vertex element '%s'.", _path.c_str());
return false;
}
// Read index data
ssize_t meshPartCount = 1;
//_binaryReader.read(&meshPartCount, 4, 1);
for (ssize_t i = 0; i < meshPartCount; ++i)
{
ssize_t nIndexCount;
if (_binaryReader.read(&nIndexCount, 4, 1) != 1)
{
CCLOGINFO("Failed to read meshdata: nIndexCount '%s'.", _path.c_str());
return false;
}
meshdata->numIndex = nIndexCount;
meshdata->indices.resize(meshdata->numIndex);
if (_binaryReader.read(&meshdata->indices[0], 2, meshdata->numIndex) != nIndexCount)
{
CCLOGINFO("Failed to read meshdata: indices '%s'.", _path.c_str());
return false;
}
}
return true;
}
bool Bundle3D::loadSkinDataBinary(SkinData* skindata)
{
if (!seekToFirstType(BUNDLE_TYPE_MESHSKIN))
return false;
skindata->resetData();
std::string boneName = _binaryReader.readString();
// transform
float bindShape[16];
if (!_binaryReader.readMatrix(bindShape))
{
CCLOGINFO("Failed to read SkinData: bindShape matrix '%s'.", _path.c_str());
return false;
}
// bone count
unsigned int boneNum;
if (!_binaryReader.read(&boneNum))
{
CCLOGINFO("Failed to read SkinData: boneNum '%s'.", _path.c_str());
return false;
}
// bone names and bind pos
float bindpos[16];
for (unsigned int i = 0; i < boneNum; i++)
{
std::string skinBoneName = _binaryReader.readString();
skindata->skinBoneNames.push_back(skinBoneName);
if (!_binaryReader.readMatrix(bindpos))
{
CCLOGINFO("Failed to load SkinData: bindpos '%s'.", _path.c_str());
return nullptr;
}
skindata->inverseBindPoseMatrices.push_back(bindpos);
}
skindata->skinBoneOriginMatrices.resize(boneNum);
boneName = _binaryReader.readString();
// bind shape
_binaryReader.readMatrix(bindShape);
int rootIndex = skindata->getSkinBoneNameIndex(boneName);
if(rootIndex < 0)
{
skindata->addNodeBoneNames(boneName);
rootIndex = skindata->getBoneNameIndex(boneName);
skindata->nodeBoneOriginMatrices.push_back(bindShape);
}
else
{
skindata->skinBoneOriginMatrices[rootIndex] = bindShape;
}
// set root bone index
skindata->rootBoneIndex = rootIndex;
// read parent and child relationship map
float transform[16];
unsigned int linkNum;
_binaryReader.read(&linkNum);
for (unsigned int i = 0; i < linkNum; ++i)
{
std::string id = _binaryReader.readString();
int index = skindata->getSkinBoneNameIndex(id);
std::string parentid = _binaryReader.readString();
if (!_binaryReader.readMatrix(transform))
{
CCLOGINFO("Failed to load SkinData: transform '%s'.", _path.c_str());
return nullptr;
}
if(index < 0)
{
skindata->addNodeBoneNames(id);
index = skindata->getBoneNameIndex(id);
skindata->nodeBoneOriginMatrices.push_back(transform);
}
else
{
skindata->skinBoneOriginMatrices[index] = transform;
}
int parentIndex = skindata->getSkinBoneNameIndex(parentid);
if(parentIndex < 0)
{
skindata->addNodeBoneNames(parentid);
parentIndex = skindata->getBoneNameIndex(parentid);
}
skindata->boneChild[parentIndex].push_back(index);
}
return true;
}
bool Bundle3D::loadMaterialDataBinary(MaterialData* materialdata)
{
if (!seekToFirstType(BUNDLE_TYPE_MATERIAL))
return false;
std::string texturePath = _binaryReader.readString();
if (texturePath.empty())
{
CCLOGINFO("Failed to read Materialdata: texturePath is empty '%s'.", _path.c_str());
return false;
}
materialdata->texturePath = _modelRelativePath + texturePath;
return true;
}
bool Bundle3D::loadAnimationDataBinary(Animation3DData* animationdata)
{
if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS))
return false;
animationdata->_rotationKeys.clear();
animationdata->_scaleKeys.clear();
animationdata->_translationKeys.clear();
_binaryReader.readString();
if (!_binaryReader.read(&animationdata->_totalTime))
{
CCLOGINFO("Failed to read AnimationData: totalTime '%s'.", _path.c_str());
return false;
}
ssize_t animNum;
if (!_binaryReader.read(&animNum))
{
CCLOGINFO("Failed to read AnimationData: animNum '%s'.", _path.c_str());
return false;
}
for (ssize_t i = 0; i < animNum; ++i)
{
std::string boneName = _binaryReader.readString();
ssize_t keyframeNum;
if (!_binaryReader.read(&keyframeNum))
{
CCLOGINFO("Failed to read AnimationData: keyframeNum '%s'.", _path.c_str());
return false;
}
for (ssize_t j = 0; j < keyframeNum; ++j)
{
float keytime;
if (!_binaryReader.read(&keytime))
{
CCLOGINFO("Failed to read AnimationData: keytime '%s'.", _path.c_str());
return false;
}
Quaternion rotate;
if (_binaryReader.read(&rotate, 4, 4) != 4)
{
CCLOGINFO("Failed to read AnimationData: rotate '%s'.", _path.c_str());
return false;
}
animationdata->_rotationKeys[boneName].push_back(Animation3DData::QuatKey(keytime, rotate));
Vec3 scale;
if (_binaryReader.read(&scale, 4, 3) != 3)
{
CCLOGINFO("Failed to read AnimationData: scale '%s'.", _path.c_str());
return false;
}
animationdata->_scaleKeys[boneName].push_back(Animation3DData::Vec3Key(keytime, scale));
Vec3 position;
if (_binaryReader.read(&position, 4, 3) != 3)
{
CCLOGINFO("Failed to read AnimationData: position '%s'.", _path.c_str());
return false;
}
animationdata->_translationKeys[boneName].push_back(Animation3DData::Vec3Key(keytime, position));
}
}
return true;
}
GLenum Bundle3D::parseGLType(const std::string& str)
{
if (str == "GL_FLOAT")
@ -298,23 +773,6 @@ GLenum Bundle3D::parseGLType(const std::string& str)
}
}
unsigned int Bundle3D::parseGLTypeSize(const std::string& str)
{
if (str == "GL_FLOAT")
{
return sizeof(float);
}
else if (str == "GL_UNSIGNED_INT")
{
return sizeof(unsigned int);
}
else
{
assert(0);
return -1;
}
}
unsigned int Bundle3D::parseGLProgramAttribute(const std::string& str)
{
if (str == "VERTEX_ATTRIB_POSITION")
@ -348,7 +806,7 @@ unsigned int Bundle3D::parseGLProgramAttribute(const std::string& str)
}
}
void Bundle3D::getModelPath(const std::string& path)
void Bundle3D::getModelRelativePath(const std::string& path)
{
int index = path.find_last_of('/');
std::string fullModelPath;
@ -365,19 +823,41 @@ void Bundle3D::getModelPath(const std::string& path)
}
}
Reference* Bundle3D::seekToFirstType(unsigned int type)
{
// for each Reference
for (unsigned int i = 0; i < _referenceCount; ++i)
{
Reference* ref = &_references[i];
if (ref->type == type)
{
// Found a match
if (_binaryReader.seek(ref->offset, SEEK_SET) == false)
{
CCLOGINFO("Failed to seek to object '%s' in bundle '%s'.", ref->id.c_str(), _path.c_str());
return nullptr;
}
return ref;
}
}
return nullptr;
}
Bundle3D::Bundle3D()
:_isBinary(false)
,_modelRelativePath("")
,_documentBuffer(nullptr)
,_path("")
:_isBinary(false),
_modelRelativePath(""),
_path(""),
_jsonBuffer(nullptr),
_binaryBuffer(nullptr),
_referenceCount(0),
_references(nullptr)
{
}
Bundle3D::~Bundle3D()
{
CC_SAFE_DELETE_ARRAY(_documentBuffer);
clear();
}
NS_CC_END

View File

@ -34,10 +34,18 @@
#include "base/ccTypes.h"
#include "json/document.h"
#include "CCBundleReader.h"
NS_CC_BEGIN
class Animation3D;
class Data;
/**
* Defines a bundle file that contains a collection of assets. Mesh, Material, MeshSkin, Animation
* There are two types of bundle files, c3t and c3b.
* c3t text file
* c3b binary file
*/
class Bundle3D
{
public:
@ -46,6 +54,13 @@ public:
static void destroyInstance();
void clear();
/**
* load a file. You must load a file first, then call loadMeshData, loadSkinData, and so on
* @param path File to be loaded
* @return result of load
*/
bool load(const std::string& path);
/**
@ -71,17 +86,75 @@ public:
* @param id The ID of the animation, load the first animation in the bundle if it is empty
*/
bool loadAnimationData(const std::string& id, Animation3DData* animationdata);
protected:
bool loadJson(const std::string& path);
bool loadMeshDataJson(MeshData* meshdata);
bool loadSkinDataJson(SkinData* skindata);
bool loadMaterialDataJson(MaterialData* materialdata);
bool loadAnimationDataJson(Animation3DData* animationdata);
/**
* load data in binary
* @param path The c3b file path
*/
bool loadBinary(const std::string& path);
/**
* load mesh data in binary
* @param meshdata The mesh data pointer
*/
bool loadMeshDataBinary(MeshData* meshdata);
/**
* load skin data in binary
* @param skindata The skin data pointer
*/
bool loadSkinDataBinary(SkinData* skindata);
/**
* load material data in binary
* @param materialdata The material pointer
*/
bool loadMaterialDataBinary(MaterialData* materialdata);
/**
* load animation data in binary
* @param animationdata The animation data pointer
*/
bool loadAnimationDataBinary(Animation3DData* animationdata);
protected:
/**
* get define data type
* @param str The type in string
*/
GLenum parseGLType(const std::string& str);
unsigned int parseGLTypeSize(const std::string& str);
/**
* get vertex attribute type
* @param str The type in string
*/
unsigned int parseGLProgramAttribute(const std::string& str);
// get model path
void getModelPath(const std::string& path);
/*
* get model path
* @param str Full path of model file
*/
void getModelRelativePath(const std::string& path);
/*
* set the read position in buffer to the target type
* @param The data type
*/
Reference* seekToFirstType(unsigned int type);
protected:
CC_CONSTRUCTOR_ACCESS:
Bundle3D();
~Bundle3D();
@ -91,11 +164,17 @@ protected:
static Bundle3D* _instance;
std::string _modelRelativePath;
char* _documentBuffer;
std::string _path;
// for json reading
char* _jsonBuffer;
rapidjson::Document _jsonReader;
rapidjson::Document _document;
// for binary reading
Data* _binaryBuffer;
BundleReader _binaryReader;
size_t _referenceCount;
Reference* _references;
bool _isBinary;
};

View File

@ -34,7 +34,7 @@
NS_CC_BEGIN
//mesh vertex attribute
/**mesh vertex attribute*/
struct MeshVertexAttrib
{
//attribute size
@ -47,6 +47,7 @@ struct MeshVertexAttrib
int attribSizeBytes;
};
/**mesh data*/
struct MeshData
{
std::vector<float> vertex;
@ -78,41 +79,90 @@ public:
}
};
/**skin data*/
struct SkinData
{
std::vector<std::string> boneNames;
std::vector<Mat4> inverseBindPoseMatrices; //bind pose of bone
std::vector<std::string> skinBoneNames; //skin bones affect skin
std::vector<std::string> nodeBoneNames; //node bones don't affect skin, all bones [skinBone, nodeBone]
std::vector<Mat4> inverseBindPoseMatrices; //bind pose of skin bone, only for skin bone
std::vector<Mat4> skinBoneOriginMatrices; // original bone transform, for skin bone
std::vector<Mat4> nodeBoneOriginMatrices; // original bone transform, for node bone
//bone child info, both skinbone and node bone
std::map<int, std::vector<int> > boneChild;//key parent, value child
int rootBoneIndex;
void resetData()
{
boneNames.clear();
skinBoneNames.clear();
nodeBoneNames.clear();
inverseBindPoseMatrices.clear();
skinBoneOriginMatrices.clear();
nodeBoneOriginMatrices.clear();
boneChild.clear();
rootBoneIndex = -1;
}
void addSkinBoneNames(const std::string& name)
{
for (auto iter : skinBoneNames)
{
if ((iter) == name)
return;
}
skinBoneNames.push_back(name);
}
void addNodeBoneNames(const std::string& name)
{
for (auto iter : nodeBoneNames)
{
if ((iter) == name)
return;
}
nodeBoneNames.push_back(name);
}
int getSkinBoneNameIndex(const std::string& name)const
{
int i = 0;
for (auto iter : skinBoneNames)
{
if ((iter) == name)
return i;
i++;
}
return -1;
}
int getBoneNameIndex(const std::string& name)const
{
std::vector<std::string>::const_iterator iter = boneNames.begin();
for (int i = 0; iter != boneNames.end(); ++iter, ++i)
int i = 0;
for (auto iter : skinBoneNames)
{
if ((*iter) == name)
{
if ((iter) == name)
return i;
}
i++;
}
for(auto iter : nodeBoneNames)
{
if (iter == name)
return i;
i++;
}
return -1;
}
};
/**material data*/
struct MaterialData
{
std::string texturePath;
};
/**animation data*/
struct Animation3DData
{
public:
@ -182,6 +232,19 @@ public:
}
};
/**reference data*/
struct Reference
{
public:
std::string id;
unsigned int type;
unsigned int offset;
Reference(){}
~Reference(){}
};
NS_CC_END
#endif //__CC_BUNDLE_3D_DATA_H__

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;
};
/** Mesh: TODO, add description of Mesh */
/**
* Mesh: Geometry with a collection of vertex.
* Supporting various vertex formats.
*/
class Mesh : public Ref
{
public:
@ -83,41 +86,49 @@ public:
POINTS = GL_POINTS
};
//create
/**create mesh from positions, normals, and so on*/
static Mesh* create(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const std::vector<unsigned short>& indices);
/**create mesh with vertex attributes*/
static Mesh* create(const std::vector<float>& vertices, int vertexSizeInFloat, const std::vector<unsigned short>& indices, int numIndex, const std::vector<MeshVertexAttrib>& attribs, int attribCount);
//get vertex buffer
/**get vertex buffer*/
inline GLuint getVertexBuffer() const { return _vertexBuffer; }
//get mesh vertex attribute count
/**get mesh vertex attribute count*/
ssize_t getMeshVertexAttribCount() const { return _renderdata._vertexAttribs.size(); }
//get MeshVertexAttribute by index
/**get MeshVertexAttribute by index*/
const MeshVertexAttrib& getMeshVertexAttribute(int idx) const { return _renderdata._vertexAttribs[idx]; }
//has vertex attribute?
/**has vertex attribute?*/
bool hasVertexAttrib(int attrib) { return _renderdata.hasVertexAttrib(attrib); }
//get per vertex size in bytes
/**get per vertex size in bytes*/
int getVertexSizeInBytes() const { return _renderdata._vertexsizeBytes; }
/** get primitive type*/
PrimitiveType getPrimitiveType() const { return _primitiveType; }
/**get index count*/
ssize_t getIndexCount() const { return _indexCount; }
/**get index format*/
IndexFormat getIndexFormat() const { return _indexFormat; }
/**get index buffer*/
GLuint getIndexBuffer() const {return _indexBuffer; }
//build vertex buffer from renderdata
/**build vertex buffer from renderdata*/
void restore();
CC_CONSTRUCTOR_ACCESS:
Mesh();
virtual ~Mesh();
/**init mesh*/
bool init(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const std::vector<unsigned short>& indices);
/**init mesh*/
bool init(const std::vector<float>& vertices, int vertexSizeInFloat, const std::vector<unsigned short>& indices, int numIndex, const std::vector<MeshVertexAttrib>& attribs, int attribCount);
//build buffer
/**build buffer*/
void buildBuffer();
/**free buffer*/
void cleanAndFreeBuffers();
protected:
@ -131,20 +142,25 @@ protected:
};
/**
* MeshCache
* Mesh Cache
*/
class MeshCache
{
public:
/**get & destroy*/
static MeshCache* getInstance();
static void destroyInstance();
/**get mesh from cache*/
Mesh* getMesh(const std::string& key) const;
/**add mesh to cache*/
bool addMesh(const std::string& key, Mesh* mesh);
/**remove all meshes*/
void removeAllMeshes();
/**remove unused meshes*/
void removeUnusedMesh();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
@ -158,9 +174,9 @@ CC_CONSTRUCTOR_ACCESS:
protected:
static MeshCache* _cacheInstance;
static MeshCache* _cacheInstance;//instance
std::unordered_map<std::string, Mesh*> _meshes;
std::unordered_map<std::string, Mesh*> _meshes; //cached meshes
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
EventListenerCustom* _backToForegroundlistener;

View File

@ -46,6 +46,20 @@ const Mat4& Bone::getInverseBindPose()
return _invBindPose;
}
void Bone::setOriPose(const Mat4& m)
{
_oriPose = m;
}
void Bone::resetPose()
{
_local =_oriPose;
for (auto it : _children) {
it->resetPose();
}
}
void Bone::setWorldMatDirty(bool dirty)
{
_worldDirty = dirty;
@ -81,8 +95,21 @@ const Mat4& Bone::getWorldMat()
return _world;
}
void Bone::setAnimationValue(float* trans, float* rot, float* scale, float weight)
void Bone::setAnimationValue(float* trans, float* rot, float* scale, void* tag, float weight)
{
for (auto& it : _blendStates) {
if (it.tag == tag)
{
if (trans)
it.localTranslate.set(trans);
if (rot)
it.localRot.set(rot);
if (scale)
it.localScale.set(scale);
it.weight = weight;
return;
}
}
BoneBlendState state;
if (trans)
state.localTranslate.set(trans);
@ -92,9 +119,9 @@ void Bone::setAnimationValue(float* trans, float* rot, float* scale, float weigh
state.localScale.set(scale);
state.weight = weight;
state.tag = tag;
_blendStates.push_back(state);
_localDirty = true;
}
void Bone::clearBoneBlendState()
@ -115,13 +142,6 @@ Bone* Bone::create(const std::string& id)
return bone;
}
/**
* Updates the joint matrix.
*
* @param matrixPalette The matrix palette to update.
*/
void Bone::updateJointMatrix(Vec4* matrixPalette)
{
{
@ -134,12 +154,11 @@ void Bone::updateJointMatrix(Vec4* matrixPalette)
}
}
//bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.
Bone* Bone::getParentBone()
{
return _parent;
}
int Bone::getChildBoneCount() const
ssize_t Bone::getChildBoneCount() const
{
return _children.size();
}
@ -168,15 +187,11 @@ void Bone::removeAllChildBone()
Bone::Bone(const std::string& id)
: _name(id)
, _parent(nullptr)
, _localDirty(true)
, _worldDirty(true)
{
}
/**
* Destructor.
*/
Bone::~Bone()
{
removeAllChildBone();
@ -186,8 +201,8 @@ void Bone::updateLocalMat()
{
if (_blendStates.size())
{
Vec3 translate(Vec3::ZERO), scale(Vec3::ONE);
Quaternion quat(Quaternion::identity());
Vec3 translate(Vec3::ZERO), scale(Vec3::ZERO);
Quaternion quat(Quaternion::zero());
float total = 0.f;
for (auto it: _blendStates) {
@ -195,13 +210,12 @@ void Bone::updateLocalMat()
}
if (total)
{
//if (_blendStates.size() == 1)
if (true)
if (_blendStates.size() == 1)
{
int cnt = _blendStates.size();
translate = _blendStates[cnt - 1].localTranslate;
scale = _blendStates[cnt - 1].localScale;
quat = _blendStates[cnt - 1].localRot;
auto& state = _blendStates[0];
translate = state.localTranslate;
scale = state.localScale;
quat = state.localRot;
}
else
{
@ -209,24 +223,18 @@ void Bone::updateLocalMat()
for (auto it : _blendStates) {
float weight = (it.weight * invTotal);
translate += it.localTranslate * weight;
if (!it.localScale.isZero())
scale.x += it.localScale.x * weight;
scale.y += it.localScale.y * weight;
scale.z += it.localScale.z * weight;
if (!quat.isZero())
{
scale.x *= it.localScale.x * weight;
scale.y *= it.localScale.y * weight;
scale.z *= it.localScale.z * weight;
}
if (!it.localRot.isZero())
{
if (!quat.isZero())
{
Quaternion& q = _blendStates[0].localRot;
if (q.x * quat.x + q.y * quat.y + q.z * quat.z + q.w * quat.w < 0)
Quaternion& q = _blendStates[0].localRot;
if (q.x * quat.x + q.y * quat.y + q.z * quat.z + q.w * quat.w < 0)
weight = -weight;
}
quat = Quaternion(it.localRot.x * weight + quat.x, it.localRot.y * weight + quat.y, it.localRot.z * weight + quat.z, it.localRot.w * weight + quat.w);
}
quat = Quaternion(it.localRot.x * weight + quat.x, it.localRot.y * weight + quat.y, it.localRot.z * weight + quat.z, it.localRot.w * weight + quat.w);
}
}
}
}
Mat4::createTranslation(translate, &_local);
@ -234,13 +242,7 @@ void Bone::updateLocalMat()
_local.scale(scale);
_blendStates.clear();
_localDirty = false;
}
else
{
CCLOG("use cached local");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -295,11 +297,17 @@ MeshSkin* MeshSkin::create(const std::string& filename, const std::string& name)
bool MeshSkin::initFromSkinData(const SkinData& skindata)
{
setBoneCount((int)skindata.boneNames.size());
for (size_t i = 0; i < skindata.boneNames.size(); i++) {
auto bone = Bone::create(skindata.boneNames[i]);
ssize_t i = 0;
for (; i < skindata.skinBoneNames.size(); i++) {
auto bone = Bone::create(skindata.skinBoneNames[i]);
bone->_invBindPose = skindata.inverseBindPoseMatrices[i];
addBone(bone);
bone->setOriPose(skindata.skinBoneOriginMatrices[i]);
addSkinBone(bone);
}
for (i = 0; i < skindata.nodeBoneNames.size(); i++) {
auto bone = Bone::create(skindata.nodeBoneNames[i]);
bone->setOriPose(skindata.nodeBoneOriginMatrices[i]);
addNodeBone(bone);
}
for (auto it : skindata.boneChild) {
auto parent = getBoneByIndex(it.first);
@ -311,29 +319,42 @@ bool MeshSkin::initFromSkinData(const SkinData& skindata)
}
setRootBone(getBoneByIndex(skindata.rootBoneIndex));
_rootBone->resetPose();
return true;
}
unsigned int MeshSkin::getBoneCount() const
ssize_t MeshSkin::getBoneCount() const
{
return _bones.size();
return _skinBones.size() + _nodeBones.size();
}
//get bone
Bone* MeshSkin::getBoneByIndex(unsigned int index) const
{
return _bones.at(index);
if (index < _skinBones.size())
return _skinBones.at(index);
index -= _skinBones.size();
if (index < _nodeBones.size())
return _nodeBones.at(index);
return nullptr;
}
Bone* MeshSkin::getBoneByName(const std::string& id) const
{
for (auto it : _bones) {
//search from skin bones
for (auto it : _skinBones) {
if (it->getName() == id)
return it;
}
//search from node bones
for (auto it : _nodeBones) {
if (it->getName() == id )
return it;
}
return nullptr;
}
//get & set root bone
Bone* MeshSkin::getRootBone() const
{
return _rootBone;
@ -345,36 +366,16 @@ void MeshSkin::setRootBone(Bone* joint)
_rootBone = joint;
}
void MeshSkin::setBoneCount(int boneCount)
int MeshSkin::getBoneIndex(Bone* bone) const
{
removeAllBones();
// Resize the joints vector and initialize to NULL
_bones.reserve(boneCount);
// for (auto i = 0; i < boneCount; i++)
// {
// _bones.pushBack(nullptr);
// }
// Rebuild the matrix palette. Each matrix is 3 rows of Vec4.
CC_SAFE_DELETE_ARRAY(_matrixPalette);
if (boneCount > 0)
{
_matrixPalette = new Vec4[boneCount * PALETTE_ROWS];
for (unsigned int i = 0; i < boneCount * PALETTE_ROWS; i+=PALETTE_ROWS)
{
_matrixPalette[i+0].set(1.0f, 0.0f, 0.0f, 0.0f);
_matrixPalette[i+1].set(0.0f, 1.0f, 0.0f, 0.0f);
_matrixPalette[i+2].set(0.0f, 0.0f, 1.0f, 0.0f);
}
int i = 0;
for (; i < _skinBones.size(); i++) {
if (_skinBones.at(i) == bone)
return i;
}
}
int MeshSkin::getBoneIndex(Bone* joint) const
{
for (auto i = 0; i < _bones.size(); i++) {
if (_bones.at(i) == joint)
int index = 0;
for (; index < _nodeBones.size(); index++, i++) {
if (_nodeBones.at(index) == bone)
return i;
}
return -1;
@ -385,8 +386,12 @@ Vec4* MeshSkin::getMatrixPalette()
{
updateBoneMatrix();
if (_matrixPalette == nullptr)
{
_matrixPalette = new Vec4[_skinBones.size() * PALETTE_ROWS];
}
int i = 0;
for (auto it : _bones )
for (auto it : _skinBones )
{
it->updateJointMatrix(&_matrixPalette[i++ * PALETTE_ROWS]);
}
@ -394,10 +399,9 @@ Vec4* MeshSkin::getMatrixPalette()
return _matrixPalette;
}
//getBoneCount() * 3
unsigned int MeshSkin::getMatrixPaletteSize() const
ssize_t MeshSkin::getMatrixPaletteSize() const
{
return _bones.size() * PALETTE_ROWS;
return _skinBones.size() * PALETTE_ROWS;
}
//refresh bone world matrix
@ -409,14 +413,20 @@ void MeshSkin::updateBoneMatrix()
void MeshSkin::removeAllBones()
{
_bones.clear();
_skinBones.clear();
_nodeBones.clear();
CC_SAFE_DELETE_ARRAY(_matrixPalette);
CC_SAFE_RELEASE(_rootBone);
}
void MeshSkin::addBone(Bone* bone)
void MeshSkin::addSkinBone(Bone* bone)
{
_bones.pushBack(bone);
_skinBones.pushBack(bone);
}
void MeshSkin::addNodeBone(Bone* bone)
{
_nodeBones.pushBack(bone);
}
////////////////////////////////////////////////////////////////////////

View File

@ -52,17 +52,26 @@ public:
*/
const Mat4& getInverseBindPose();
//update own world matrix and children's
/**update own world matrix and children's*/
void updateWorldMat();
void setWorldMatDirty(bool dirty = true);
/**get wrod matrix*/
const Mat4& getWorldMat();
/**get bone name*/
const std::string& getName() const { return _name; }
void setAnimationValue(float* trans, float* rot, float* scale, float weight = 1.0f);
/**
* set animation value
* @param trans translate vec3
* @param rot rotation quaternion
* @param scale scale vec3
* @param tag, unique tag, only blend animation between different tags
* @param weight, blend weight
*/
void setAnimationValue(float* trans, float* rot, float* scale, void* tag = nullptr, float weight = 1.0f);
/**clear bone blend states*/
void clearBoneBlendState();
/**
* Creates C3DBone.
@ -72,10 +81,22 @@ public:
/**
* Sets the inverse bind pose matrix.
*
* @param m C3DMatrix representing the inverse bind pose for this Bone.
* @param m Mat4 representing the inverse bind pose for this Bone.
*/
void setInverseBindPose(const Mat4& m);
/**
* Sets the bone's original pose.
*
* @param m Mat4 representing the original pose for this Bone.
*/
void setOriPose(const Mat4& m);
/**
* reset pose to origin
*/
void resetPose();
/**
* Updates the joint matrix.
*
@ -83,13 +104,19 @@ public:
*/
void updateJointMatrix(Vec4* matrixPalette);
//bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.
/**bone tree, we do not inherit from Node, Node has too many properties that we do not need. A clean Node is needed.*/
Bone* getParentBone();
int getChildBoneCount() const;
/**get child bone count*/
ssize_t getChildBoneCount() const;
/**get child bone by index*/
Bone* getChildBoneByIndex(int index);
/**add child bone*/
void addChildBone(Bone* bone);
/**remove child bone by index*/
void removeChildBoneByIndex(int index);
/**remove child bone*/
void removeChildBone(Bone* bone);
/**remove all child bone*/
void removeAllChildBone();
@ -102,11 +129,13 @@ protected:
Quaternion localRot;
Vec3 localScale;
float weight;
void* tag; //
BoneBlendState()
: localTranslate(Vec3::ZERO)
, localRot(Quaternion::identity())
, localScale(Vec3::ONE)
, weight(1.f)
, tag(nullptr)
{
}
@ -126,17 +155,21 @@ protected:
*/
void updateLocalMat();
std::string _name;
/**set world matrix dirty flag*/
void setWorldMatDirty(bool dirty = true);
std::string _name; // bone name
/**
* The Mat4 representation of the Joint's bind pose.
*/
Mat4 _invBindPose;
Bone* _parent;
Mat4 _oriPose; //original bone pose
Bone* _parent; //parent bone
Vector<Bone*> _children;
bool _localDirty;
bool _worldDirty;
Mat4 _world;
Mat4 _local;
@ -145,35 +178,38 @@ protected:
};
/////////////////////////////////////////////////////////////////////////////
/**
* MeshSkin, A class maintain a collection of bones that affect Mesh vertex.
* And it is responsible for computing matrix palletes that used by skin mesh rendering.
*/
class MeshSkin: public Ref
{
public:
//create a new meshskin if do not want to share meshskin
/**create a new meshskin if do not want to share meshskin*/
static MeshSkin* create(const std::string& filename, const std::string& name);
unsigned int getBoneCount() const;
/**get total bone count, skin bone + node bone*/
ssize_t getBoneCount() const;
void setBoneCount(int boneCount);
//get bone
/**get bone*/
Bone* getBoneByIndex(unsigned int index) const;
Bone* getBoneByName(const std::string& id) const;
//get & set root bone
/**get & set root bone*/
Bone* getRootBone() const;
void setRootBone(Bone* joint);
void setRootBone(Bone* bone);
int getBoneIndex(Bone* joint) const;
/**get bone index*/
int getBoneIndex(Bone* bone) const;
//compute matrix palette used by gpu skin
/**compute matrix palette used by gpu skin*/
Vec4* getMatrixPalette();
//getBoneCount() * 3
unsigned int getMatrixPaletteSize() const;
/**getSkinBoneCount() * 3*/
ssize_t getMatrixPaletteSize() const;
//refresh bone world matrix
/**refresh bone world matrix*/
void updateBoneMatrix();
CC_CONSTRUCTOR_ACCESS:
@ -182,43 +218,58 @@ CC_CONSTRUCTOR_ACCESS:
~MeshSkin();
/**init from skin data*/
bool initFromSkinData(const SkinData& skindata);
/**remove all bones*/
void removeAllBones();
void addBone(Bone* bone);
/**add skin bone*/
void addSkinBone(Bone* bone);
/**add Node bone*/
void addNodeBone(Bone* bone);
protected:
Vector<Bone*> _bones;
Vector<Bone*> _skinBones; // bones with skin
Vector<Bone*> _nodeBones; //bones without skin, only used to compute transform of children
Bone* _rootBone;
// Pointer to the array of palette matrices.
// This array is passed to the vertex shader as a uniform.
// Each 4x3 row-wise matrix is represented as 3 Vec4's.
// The number of Vec4's is (_joints.size() * 3).
// The number of Vec4's is (_skinBones.size() * 3).
Vec4* _matrixPalette;
};
/**
* MeshSkinData Cache
*/
class MeshSkinDataCache
{
public:
/**get & destroy*/
static MeshSkinDataCache* getInstance();
static void destroyInstance();
/**get mesh skin data from cache*/
const SkinData* getMeshSkinData(const std::string& key) const;
/**add mesh skin data to cache*/
bool addMeshSkinData(const std::string& key, const SkinData& skinData);
/**remove all mesh skin data*/
void removeAllMeshSkinData();
protected:
MeshSkinDataCache();
~MeshSkinDataCache();
static MeshSkinDataCache* _cacheInstance;
static MeshSkinDataCache* _cacheInstance; // instance
std::unordered_map<std::string, SkinData> _skinDatas;
std::unordered_map<std::string, SkinData> _skinDatas; //cached skindatas
};
NS_CC_END

View File

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

View File

@ -40,22 +40,24 @@ class Mesh;
class Texture2D;
class MeshSkin;
/** Sprite3D: TODO add description */
/** Sprite3D: A sprite can be loaded from 3D model files, .obj, .c3t, .c3b, then can be drawed as sprite */
class Sprite3D : public Node, public BlendProtocol
{
public:
/// creates a Sprite3D
/** creates a Sprite3D*/
static Sprite3D* create(const std::string &modelPath);
// creates a Sprite3D. It only supports one texture, and overrides the internal texture with 'texturePath'
static Sprite3D* create(const std::string &modelPath, const std::string &texturePath);
//set texture
/**set texture*/
void setTexture(const std::string& texFile);
void setTexture(Texture2D* texture);
/**get mesh*/
Mesh* getMesh() const { return _mesh; }
/**get skin*/
MeshSkin* getSkin() const { return _skin; }
// overrides
@ -68,28 +70,31 @@ CC_CONSTRUCTOR_ACCESS:
virtual ~Sprite3D();
bool initWithFile(const std::string &path);
//.mtl file should at the same directory with the same name if exist
/**.mtl file should at the same directory with the same name if exist*/
bool loadFromObj(const std::string& path);
//load from .c3b or .c3t
/**load from .c3b or .c3t*/
bool loadFromC3x(const std::string& path);
/**draw*/
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
/**get default shader*/
virtual GLProgram* getDefaultGLProgram(bool textured = true);
/**generate default GLProgramState*/
void genGLProgramState();
protected:
Mesh *_mesh;
MeshSkin *_skin;
Mesh* _mesh;//mesh
MeshSkin* _skin;//skin
MeshCommand _meshCommand;
MeshCommand _meshCommand; //render command
Texture2D* _texture;
BlendFunc _blend;
BlendFunc _blend;
};
extern std::string s_attributeNames[];
extern std::string s_attributeNames[];//attribute names array
NS_CC_END
#endif // __SPRITE3D_H_

View File

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

View File

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

View File

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

View File

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

View File

@ -157,7 +157,16 @@ public:
/** gets-or-creates an instance of GLProgramState for a given GLProgramName */
static GLProgramState* getOrCreateWithGLProgramName(const std::string &glProgramName );
// apply GLProgram, attributes and uniforms
void apply(const Mat4& modelView);
void applyGLProgram(const Mat4& modelView);
/**
* apply vertex attributes
* @param applyAttribFlags Call GL::enableVertexAttribs(_vertexAttribsFlags) or not
*/
void applyAttributes(bool applyAttribFlags = true);
void applyUniforms();
void setGLProgram(GLProgram* glprogram);
GLProgram* getGLProgram() const { return _glprogram; }

View File

@ -23,7 +23,12 @@
****************************************************************************/
#include "base/ccMacros.h"
#include "base/CCConfiguration.h"
#include "base/CCDirector.h"
#include "base/CCEventCustom.h"
#include "base/CCEventListenerCustom.h"
#include "base/CCEventDispatcher.h"
#include "base/CCEventType.h"
#include "renderer/CCMeshCommand.h"
#include "renderer/ccGLStateCache.h"
#include "renderer/CCGLProgram.h"
@ -32,6 +37,7 @@
#include "renderer/CCTextureAtlas.h"
#include "renderer/CCTexture2D.h"
#include "renderer/ccGLStateCache.h"
#include "xxhash.h"
NS_CC_BEGIN
@ -46,8 +52,15 @@ MeshCommand::MeshCommand()
, _displayColor(1.0f, 1.0f, 1.0f, 1.0f)
, _matrixPalette(nullptr)
, _matrixPaletteSize(0)
, _materialID(0)
, _vao(0)
{
_type = RenderCommand::Type::MESH_COMMAND;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// listen the event when app go to foreground
_backToForegroundlistener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(MeshCommand::listenBackToForeground, this));
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundlistener, -1);
#endif
}
void MeshCommand::init(float globalOrder,
@ -103,6 +116,10 @@ void MeshCommand::setDisplayColor(const Vec4& color)
MeshCommand::~MeshCommand()
{
releaseVAO();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundlistener);
#endif
}
void MeshCommand::applyRenderState()
@ -138,16 +155,85 @@ void MeshCommand::restoreRenderState()
}
}
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, void* mesh, const BlendFunc& blend)
{
int* intstate = static_cast<int*>(glProgramState);
int* intmesh = static_cast<int*>(mesh);
int statekey[] = {intstate[0], 0}, meshkey[] = {intmesh[0], 0};
if (sizeof(void*) > sizeof(int))
{
statekey[1] = intstate[1];
meshkey[1] = intmesh[1];
}
int intArray[] = {(int)texID, statekey[0], statekey[1], meshkey[0], meshkey[1], (int)blend.src, (int)blend.dst};
_materialID = XXH32((const void*)intArray, sizeof(intArray), 0);
}
void MeshCommand::MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform)
{
glProgram->setUniformLocationWith4fv(uniform->location, (const float*)_matrixPalette, _matrixPaletteSize);
}
void MeshCommand::preBatchDraw()
{
// set render state
applyRenderState();
// Set material
GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst);
if (_vao == 0)
buildVAO();
if (_vao)
{
GL::bindVAO(_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
_glProgramState->applyAttributes();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
}
}
void MeshCommand::batchDraw()
{
_glProgramState->setUniformVec4("u_color", _displayColor);
if (_matrixPaletteSize && _matrixPalette)
{
_glProgramState->setUniformCallback("u_matrixPalette", CC_CALLBACK_2(MeshCommand::MatrixPalleteCallBack, this));
}
_glProgramState->applyGLProgram(_mv);
_glProgramState->applyUniforms();
// Draw
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
}
void MeshCommand::postBatchDraw()
{
//restore render state
restoreRenderState();
if (_vao)
{
GL::bindVAO(0);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void MeshCommand::execute()
{
// set render state
applyRenderState();
// Set material
GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst);
@ -172,9 +258,49 @@ void MeshCommand::execute()
//restore render state
restoreRenderState();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MeshCommand::buildVAO()
{
releaseVAO();
if (Configuration::getInstance()->supportsShareableVAO())
{
glGenVertexArrays(1, &_vao);
GL::bindVAO(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
auto flags = _glProgramState->getVertexAttribsFlags();
for (int i = 0; flags > 0; i++) {
int flag = 1 << i;
if (flag & flags)
glEnableVertexAttribArray(i);
flags &= ~flag;
}
_glProgramState->applyAttributes(false);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
GL::bindVAO(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
void MeshCommand::releaseVAO()
{
if (Configuration::getInstance()->supportsShareableVAO() && _vao)
{
glDeleteVertexArrays(1, &_vao);
_vao = 0;
GL::bindVAO(0);
}
}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
void MeshCommand::listenBackToForeground(EventCustom* event)
{
releaseVAO();
}
#endif
NS_CC_END

View File

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

View File

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

View File

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

View File

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

View File

@ -194,7 +194,9 @@
"cocos/3d/CCAnimationCurve.h",
"cocos/3d/CCAnimationCurve.inl",
"cocos/3d/CCBundle3D.cpp",
"cocos/3d/CCBundle3D.h",
"cocos/3d/CCBundle3D.h",
"cocos/3d/CCBundleReader.cpp",
"cocos/3d/CCBundleReader.h",
"cocos/3d/CCBundle3DData.h",
"cocos/3d/CCMesh.cpp",
"cocos/3d/CCMesh.h",

View File

@ -44,7 +44,8 @@ static std::function<Layer*()> createFunctions[] =
{
CL(Sprite3DBasicTest),
CL(Sprite3DEffectTest),
CL(Sprite3DWithSkinTest)
CL(Sprite3DWithSkinTest),
CL(Animate3DTest)
};
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
@ -532,7 +533,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest()
}
std::string Sprite3DWithSkinTest::title() const
{
return "Testing Sprite3D for animation from c3t";
return "Testing Sprite3D";
}
std::string Sprite3DWithSkinTest::subtitle() const
{
@ -541,12 +542,14 @@ std::string Sprite3DWithSkinTest::subtitle() const
void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p)
{
auto sprite = Sprite3D::create("Sprite3DTest/girl.c3t");
std::string fileName = "Sprite3DTest/orc.c3b";
auto sprite = Sprite3D::create(fileName);
sprite->setScale(3);
sprite->setRotation3D(Vec3(0,180,0));
addChild(sprite);
sprite->setRotation3D(Vec3(-90.f, 0.f, 0.f));
sprite->setPosition( Vec2( p.x, p.y) );
auto animation = Animation3D::getOrCreate("Sprite3DTest/girl.c3t");
auto animation = Animation3D::getOrCreate(fileName);
if (animation)
{
auto animate = Animate3D::create(animation);
@ -578,3 +581,141 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector<Touch*>& touches, Ev
addNewSpriteWithCoords( location );
}
}
Animate3DTest::Animate3DTest()
: _hurt(nullptr)
, _swim(nullptr)
, _sprite(nullptr)
, _moveAction(nullptr)
, _transTime(0.1f)
, _elapseTransTime(0.f)
{
addSprite3D();
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
scheduleUpdate();
}
Animate3DTest::~Animate3DTest()
{
CC_SAFE_RELEASE(_moveAction);
CC_SAFE_RELEASE(_hurt);
CC_SAFE_RELEASE(_swim);
}
std::string Animate3DTest::title() const
{
return "Testing Animate3D";
}
std::string Animate3DTest::subtitle() const
{
return "Touch to beat the tortoise";
}
void Animate3DTest::update(float dt)
{
if (_state == State::HURT_TO_SWIMMING)
{
_elapseTransTime += dt;
float t = _elapseTransTime / _transTime;
if (t >= 1.f)
{
t = 1.f;
_sprite->stopAction(_hurt);
_state = State::SWIMMING;
}
_swim->setWeight(t);
_hurt->setWeight(1.f - t);
}
else if (_state == State::SWIMMING_TO_HURT)
{
_elapseTransTime += dt;
float t = _elapseTransTime / _transTime;
if (t >= 1.f)
{
t = 1.f;
_state = State::HURT;
}
_swim->setWeight(1.f - t);
_hurt->setWeight(t);
}
}
void Animate3DTest::addSprite3D()
{
std::string fileName = "Sprite3DTest/tortoise.c3b";
auto sprite = Sprite3D::create(fileName);
sprite->setScale(0.1f);
auto s = Director::getInstance()->getWinSize();
sprite->setPosition(Vec2(s.width * 4.f / 5.f, s.height / 2.f));
addChild(sprite);
_sprite = sprite;
auto animation = Animation3D::getOrCreate(fileName);
if (animation)
{
auto animate = Animate3D::create(animation, 0.f, 1.933f);
sprite->runAction(RepeatForever::create(animate));
_swim = animate;
_swim->retain();
_hurt = Animate3D::create(animation, 1.933f, 2.8f);
_hurt->retain();
_state = State::SWIMMING;
}
_moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f));
_moveAction->retain();
auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr);
seq->setTag(100);
sprite->runAction(seq);
}
void Animate3DTest::reachEndCallBack()
{
_sprite->stopActionByTag(100);
auto inverse = (MoveTo*)_moveAction->reverse();
inverse->retain();
_moveAction->release();
_moveAction = inverse;
auto rot = RotateBy::create(1.f, Vec3(0.f, 180.f, 0.f));
auto seq = Sequence::create(rot, _moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr);
seq->setTag(100);
_sprite->runAction(seq);
}
void Animate3DTest::renewCallBack()
{
_sprite->stopActionByTag(101);
_state = State::HURT_TO_SWIMMING;
}
void Animate3DTest::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
{
for (auto touch: touches)
{
auto location = touch->getLocation();
if (_sprite)
{
float len = (_sprite->getPosition() - location).length();
if (len < 40)
{
//hurt the tortoise
if (_state == State::SWIMMING)
{
_sprite->runAction(_hurt);
auto delay = DelayTime::create(_hurt->getDuration() - 0.1f);
auto seq = Sequence::create(delay, CallFunc::create(CC_CALLBACK_0(Animate3DTest::renewCallBack, this)), NULL);
seq->setTag(101);
_sprite->runAction(seq);
_state = State::SWIMMING_TO_HURT;
}
return;
}
}
}
}

View File

@ -29,6 +29,12 @@
#include "../BaseTest.h"
#include <string>
namespace cocos2d {
class Animate3D;
class Sprite3D;
class Delay;
}
class Sprite3DTestDemo : public BaseTest
{
public:
@ -151,6 +157,46 @@ public:
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
};
class Animate3DTest : public Sprite3DTestDemo
{
public:
CREATE_FUNC(Animate3DTest);
Animate3DTest();
~Animate3DTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
virtual void update(float dt) override;
protected:
void addSprite3D();
enum class State
{
SWIMMING,
SWIMMING_TO_HURT,
HURT,
HURT_TO_SWIMMING,
};
void reachEndCallBack();
void renewCallBack();
cocos2d::Sprite3D* _sprite;
cocos2d::Animate3D* _swim;
cocos2d::Animate3D* _hurt;
float _transTime;
float _elapseTransTime;
State _state;
MoveTo* _moveAction;
};
class Sprite3DTestScene : public TestScene
{
public:

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB