1. binary loader is OK.

2. add some comment.
This commit is contained in:
lvlong 2014-06-20 15:30:08 +08:00
parent 8493c4579b
commit e4bbfad773
5 changed files with 354 additions and 200 deletions

View File

@ -72,27 +72,6 @@ void getChildMap(std::map<int, std::vector<int> >& map, SkinData* skinData, cons
}
}
void getChildMapT(std::map<std::string, std::vector<std::string> >& map, const SkinData* skinData, const rapidjson::Value& val)
{
if (!skinData)
return;
if (!val.HasMember("children"))
return;
std::string parent_name = val["id"].GetString();
const rapidjson::Value& children = val["children"];
for (rapidjson::SizeType i = 0; i < children.Size(); i++)
{
const rapidjson::Value& child = children[i];
std::string child_name = child["id"].GetString();
map[parent_name].push_back(child_name);
getChildMapT(map, skinData, child);
}
}
Bundle3D* Bundle3D::_instance = nullptr;
Bundle3D* Bundle3D::getInstance()
@ -107,39 +86,109 @@ void Bundle3D::purgeBundle3D()
CC_SAFE_DELETE(_instance);
}
void Bundle3D::clearBuffer()
{
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
CC_SAFE_DELETE(_binaryBuffer);
}
bool Bundle3D::load(const std::string& path)
{
return loadBinary(path);//
if (_path == path)
return true;
getModelPath(path);
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)
{
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())
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
_jsonBuffer = new char[size + 1];
memcpy(_jsonBuffer, strFileString.c_str(), size);
_jsonBuffer[size] = '\0';
if (_document.ParseInsitu<0>(_jsonBuffer).HasParseError())
{
assert(0);
CC_SAFE_DELETE_ARRAY(_documentBuffer);
_path = "";
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
return false;
}
_path = path;
return true;
}
/**
* load mesh data from bundle
* @param id The ID of the mesh, load the first Mesh in the bundle if it is empty
*/
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
bool Bundle3D::loadMeshDataJson(MeshData* meshdata)
{
return loadMeshDataBinary(meshdata);
meshdata->resetData();
assert(_document.HasMember("mesh"));
@ -182,7 +231,7 @@ bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
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].attribSizeBytes = meshdata->attribs[i].size * 4;
meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val["type"].GetString());
meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val["attribute"].GetString());
}
@ -195,7 +244,7 @@ bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
* load skin data from bundle
* @param id The ID of the skin, load the first Skin in the bundle if it is empty
*/
bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
bool Bundle3D::loadSkinDataJson(SkinData* skindata)
{
if (!_document.HasMember("skin")) return false;
@ -236,7 +285,7 @@ bool Bundle3D::loadSkinData(const std::string& id, SkinData* skindata)
* load material data from bundle
* @param id The ID of the material, load the first Material in the bundle if it is empty
*/
bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdata)
bool Bundle3D::loadMaterialDataJson(MaterialData* materialdata)
{
if (!_document.HasMember("material"))
return false;
@ -258,7 +307,7 @@ bool Bundle3D::loadMaterialData(const std::string& id, MaterialData* materialdat
* load material data from bundle
* @param id The ID of the animation, load the first animation in the bundle if it is empty
*/
bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animationdata)
bool Bundle3D::loadAnimationDataJson(Animation3DData* animationdata)
{
if (!_document.HasMember("animation")) return false;
@ -319,31 +368,26 @@ bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animati
bool Bundle3D::loadBinary(const std::string& path)
{
if (_path == path)
return true;
// get file data
CC_SAFE_DELETE(_data);
_data = new Data();
*_data = FileUtils::getInstance()->getDataFromFile(path);
if (_data->isNull())
CC_SAFE_DELETE(_binaryBuffer);
_binaryBuffer = new Data();
*_binaryBuffer = FileUtils::getInstance()->getDataFromFile(path);
if (_binaryBuffer->isNull())
{
_path = "";
CCLOGINFO(false, "Failed to read file: %s", path.c_str());
return false;
}
// Create bundle reader
CC_SAFE_DELETE(_bundleReader);
_bundleReader = BundleReader::create((char*)_data->getBytes(), _data->getSize());
_bundleReader = BundleReader::create((char*)_binaryBuffer->getBytes(), _binaryBuffer->getSize());
// Read identifier info
char identifier[] = { 'C', '3', 'B', '\0'};
// Read header info
char sig[4];
if (_bundleReader->read(sig, 1, 4) != 4 || memcmp(sig, identifier, 4) != 0)
{
_path = "";
CCLOGINFO(false, "Invalid header: %s", path.c_str());
CCLOGINFO(false, "Invalid identifier: %s", path.c_str());
return false;
}
@ -351,99 +395,48 @@ bool Bundle3D::loadBinary(const std::string& path)
unsigned char ver[2];
if (_bundleReader->read(ver, 1, 2) != 2 || ver[0] != 0 || ver[1] != 1)
{
_path = "";
CCLOGINFO(false, "Unsupported version: (%d, %d)", ver[0], ver[1]);
return false;
}
// Read has skin
unsigned char isSkin;
if (!_bundleReader->read(&isSkin))
{
_path = "";
CCLOGINFO(false, "Invalid bundle header");
return false;
}
//// Read ref table
// Read ref table size
unsigned int refCount;
if (_bundleReader->read(&refCount, 4, 1) != 1)
if (_bundleReader->read(&_referenceCount, 4, 1) != 1)
{
_path = "";
CCLOGINFO("Failed to read ref table size '%s'.", path.c_str());
return false;
}
_referenceCount = refCount;
// Read all refs
CC_SAFE_DELETE_ARRAY(_references);
_references = new Reference[refCount];
for (unsigned int i = 0; i < refCount; ++i)
_references = new Reference[_referenceCount];
for (unsigned int i = 0; i < _referenceCount; ++i)
{
if ((_references[i].id = _bundleReader->readString()).empty() ||
_bundleReader->read(&_references[i].type, 4, 1) != 1 ||
_bundleReader->read(&_references[i].offset, 4, 1) != 1)
{
_path = "";
CCLOGINFO("Failed to read ref number %d for bundle '%s'.", i,path.c_str());
CCLOGINFO("Failed to read ref number %d for bundle '%s'.", i, path.c_str());
CC_SAFE_DELETE_ARRAY(_references);
return false;
}
}
seekToFirstType(BUNDLE_TYPE_MESH);
/*unsigned int childrenCount;
if (!_bundleReader->read(&childrenCount))
{
_path = "";
CCLOGINFO("Failed to read childrenCount '%s'.", path.c_str());
return false;
}
unsigned int nodeType;
_bundleReader->read(&nodeType);
float transform[16];
if(_bundleReader->read(transform, sizeof(float), 16) != 16)
{
_path = "";
return false;
}
std::string parentName = _bundleReader->readString();
if (!_bundleReader->read(&childrenCount))
{
_path = "";
CCLOGINFO("Failed to read childrenCount '%s'.", path.c_str());
return false;
}
unsigned char hasMesh;
_bundleReader->read(&hasMesh);
unsigned char hasMorph;
_bundleReader->read(&hasMorph);
unsigned char hasSkin;
_bundleReader->read(&hasSkin);
unsigned char hasMaterial;
_bundleReader->read(&hasMaterial);*/
_path = path;
return true;
}
bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
{
if (!seekToFirstType(BUNDLE_TYPE_MESH))
return false;
meshdata->resetData();
// read mesh data
if (_bundleReader->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++)
@ -451,6 +444,7 @@ bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
unsigned int vUsage, vSize;
if (_bundleReader->read(&vUsage, 4, 1) != 1 || _bundleReader->read(&vSize, 4, 1) != 1)
{
CCLOGINFO("Failed to read meshdata: usage or size '%s'.", _path.c_str());
return false;
}
@ -463,37 +457,35 @@ bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
// Read vertex data
if (_bundleReader->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 (_bundleReader->read(&meshdata->vertex, 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat)
if (_bundleReader->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
unsigned int meshPartCount;
if (_bundleReader->read(&meshPartCount, 4, 1) != 1)
{
return false;
}
unsigned int meshPartCount = 1;
//_bundleReader->read(&meshPartCount, 4, 1);
for (unsigned int i = 0; i < meshPartCount; ++i)
{
// Read primitive type, index format and index count
unsigned int pType, iFormat, iByteCount;
if (_bundleReader->read(&pType, 4, 1) != 1 ||
_bundleReader->read(&iFormat, 4, 1) != 1 ||
_bundleReader->read(&iByteCount, 4, 1) != 1)
unsigned int nIndexCount;
if (_bundleReader->read(&nIndexCount, 4, 1) != 1)
{
CCLOGINFO("Failed to read meshdata: nIndexCount '%s'.", _path.c_str());
return false;
}
meshdata->numIndex = iByteCount / 4;
if (_bundleReader->read(&meshdata->indices, 2, iByteCount) != iByteCount)
meshdata->numIndex = nIndexCount;
meshdata->indices.resize(meshdata->numIndex);
if (_bundleReader->read(&meshdata->indices[0], 2, meshdata->numIndex) != nIndexCount)
{
CCLOGINFO("Failed to read meshdata: indices '%s'.", _path.c_str());
return false;
}
}
@ -501,42 +493,160 @@ bool Bundle3D::loadMeshDataBinary(MeshData* meshdata)
return true;
}
bool Bundle3D::loadMeshSkin(SkinData* skindata)
bool Bundle3D::loadSkinDataBinary(SkinData* skindata)
{
if (!seekToFirstType(BUNDLE_TYPE_MESHSKIN))
return false;
skindata->resetData();
// bind shape
// transform
float bindShape[16];
_bundleReader->readMatrix(bindShape);
if (!_bundleReader->readMatrix(bindShape))
{
CCLOGINFO("Failed to read SkinData: bindShape matrix '%s'.", _path.c_str());
return false;
}
unsigned int jointCount;
_bundleReader->read(&jointCount);
// bone count
unsigned int boneNum;
if (!_bundleReader->read(&boneNum))
{
CCLOGINFO("Failed to read SkinData: boneNum '%s'.", _path.c_str());
return false;
}
for (unsigned int i = 0; i < jointCount; i++)
// bone names and bind pos
float bindpos[16];
for (unsigned int i = 0; i < boneNum; i++)
{
skindata->boneNames.push_back(_bundleReader->readString());
if (!_bundleReader->readMatrix(bindpos))
{
CCLOGINFO("Failed to load SkinData: bindpos '%s'.", _path.c_str());
return NULL;
}
skindata->inverseBindPoseMatrices.push_back(bindpos);
}
unsigned int jointsBindPosesCount;
_bundleReader->read(&jointsBindPosesCount);
// bind shape
bindShape[16];
_bundleReader->readMatrix(bindShape);
if (jointsBindPosesCount > 0)
// read parent and child relationship map
float transform[16];
unsigned int linkNum;
_bundleReader->read(&linkNum);
for (unsigned int i = 0; i < linkNum; ++i)
{
assert(jointCount * 16 == jointsBindPosesCount);
float m[16];
for (unsigned int i = 0; i < jointCount; i++)
std::string id = _bundleReader->readString();
int index = skindata->getBoneNameIndex(id);
if (index >= 0 && skindata->rootBoneIndex < 0)
skindata->rootBoneIndex = index;
std::string parentid = _bundleReader->readString();
int parentIndex = skindata->getBoneNameIndex(parentid);
if (!_bundleReader->readMatrix(transform))
{
if (!_bundleReader->readMatrix(m))
CCLOGINFO("Failed to load SkinData: transform '%s'.", _path.c_str());
return NULL;
}
if (parentIndex < 0 || index < 0)
continue;
skindata->boneChild[parentIndex].push_back(index);
}
return true;
}
bool Bundle3D::loadMaterialDataBinary(MaterialData* materialdata)
{
if (!seekToFirstType(BUNDLE_TYPE_MATERIAL))
return false;
std::string texturePath = _bundleReader->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();
std::string id = _bundleReader->readString();
if (!_bundleReader->read(&animationdata->_totalTime))
{
CCLOGINFO("Failed to read AnimationData: totalTime '%s'.", _path.c_str());
return false;
}
unsigned int animNum;
if (!_bundleReader->read(&animNum))
{
CCLOGINFO("Failed to read AnimationData: animNum '%s'.", _path.c_str());
return false;
}
for (unsigned int i = 0; i < animNum; ++i)
{
std::string boneName = _bundleReader->readString();
unsigned int keyframeNum;
if (!_bundleReader->read(&keyframeNum))
{
CCLOGINFO("Failed to read AnimationData: keyframeNum '%s'.", _path.c_str());
return false;
}
for (unsigned int j = 0; j < keyframeNum; ++j)
{
float keytime;
if (!_bundleReader->read(&keytime))
{
CCLOGINFO("Failed to load C3DMeshSkin in bundle '%s'.", _path.c_str());
return NULL;
CCLOGINFO("Failed to read AnimationData: keytime '%s'.", _path.c_str());
return false;
}
skindata->inverseBindPoseMatrices.push_back(m);
Quaternion rotate;
if (_bundleReader->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 (_bundleReader->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 (_bundleReader->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));
}
}
skindata->rootBoneIndex = 0;//?????
return true;
}
@ -557,23 +667,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")
@ -607,7 +700,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;
@ -647,21 +740,21 @@ Reference* Bundle3D::seekToFirstType(unsigned int type)
Bundle3D::Bundle3D()
:_isBinary(false),
_modelRelativePath(""),
_documentBuffer(NULL),
_jsonBuffer(NULL),
_path(""),
_referenceCount(0),
_bundleReader(NULL),
_references(NULL),
_data(NULL)
_binaryBuffer(NULL)
{
}
Bundle3D::~Bundle3D()
{
CC_SAFE_DELETE_ARRAY(_documentBuffer);
CC_SAFE_DELETE_ARRAY(_jsonBuffer);
CC_SAFE_DELETE_ARRAY(_bundleReader);
CC_SAFE_DELETE_ARRAY(_references);
CC_SAFE_DELETE(_data);
CC_SAFE_DELETE(_binaryBuffer);
}
NS_CC_END

View File

@ -51,6 +51,12 @@ public:
static void purgeBundle3D();
void clearBuffer();
/**
* load file data include .c3t and .c3b
* @param path Model path
*/
bool load(const std::string& path);
//
@ -80,22 +86,71 @@ public:
*/
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);
bool loadMeshSkin(SkinData* skindata);
/**
* 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:
@ -106,17 +161,14 @@ protected:
std::string _modelRelativePath;
char* _documentBuffer;
char* _jsonBuffer;
std::string _path;
rapidjson::Document _document;
BundleReader* _bundleReader;
unsigned int _referenceCount;
Reference* _references;
Data* _data;
Data* _binaryBuffer;
bool _isBinary;
};

View File

@ -115,17 +115,16 @@ struct SkinData
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( const auto &item : boneNames )
{
if ((*iter) == name)
{
if (item == name)
return i;
}
else
++i;
}
return -1;
}
};
struct MaterialData

View File

@ -35,15 +35,25 @@
NS_CC_BEGIN
/**
* Stream is an interface for reading and writing a sequence of bytes.
* BundleReader is an interface for reading sequence of bytes.
*/
class BundleReader: public cocos2d::Ref
{
public:
/**
* Destructor
*/
~BundleReader();
/** creates an BundleReader with lpbuffer and length
* @param lpbuffer The pointer to the file data
* @param length The size for lpbuffer in bytes
*/
static BundleReader* create(char* lpbuffer, unsigned int length);
/**
* Close and delete buffer
*/
void close();
/**
@ -59,9 +69,9 @@ public:
size_t read(void* ptr, size_t size, size_t count);
/**
* Reads a line from the stream.
* Reads a line from the buffer.
*/
char* readLine(int num,char* line);
char* readLine(int num, char* line);
/**
* Writes an array of elements.
@ -75,12 +85,12 @@ public:
size_t write(const void* ptr, size_t size, size_t count);
/**
* Returns true if the end of the stream has been reached.
* Returns true if the end of the buffer has been reached.
*/
bool eof();
/**
* Returns the length of the stream in bytes.
* Returns the length of the buffer in bytes.
*/
size_t length();

View File

@ -541,7 +541,7 @@ std::string Sprite3DWithSkinTest::subtitle() const
void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p)
{
std::string fileName = "Sprite3DTest/girl.c3b";/*"Sprite3DTest/tianguang.c3b"*/
std::string fileName = "Sprite3DTest/scene.c3b";
auto sprite = Sprite3D::create(fileName);
addChild(sprite);
sprite->setRotation3D(Vec3(-90.f, 0.f, 0.f));