diff --git a/cocos/2d/cocos2d.vcxproj b/cocos/2d/cocos2d.vcxproj index fa3b106289..fa5cc46754 100644 --- a/cocos/2d/cocos2d.vcxproj +++ b/cocos/2d/cocos2d.vcxproj @@ -178,6 +178,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + @@ -356,6 +357,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + diff --git a/cocos/2d/cocos2d.vcxproj.filters b/cocos/2d/cocos2d.vcxproj.filters index 9007db529c..ede51800c6 100644 --- a/cocos/2d/cocos2d.vcxproj.filters +++ b/cocos/2d/cocos2d.vcxproj.filters @@ -580,6 +580,9 @@ 3d + + 3d + @@ -1180,6 +1183,9 @@ 3d + + 3d + diff --git a/cocos/3d/CCBundle3D.cpp b/cocos/3d/CCBundle3D.cpp index 66edc74c1f..36fb76597e 100644 --- a/cocos/3d/CCBundle3D.cpp +++ b/cocos/3d/CCBundle3D.cpp @@ -26,8 +26,22 @@ #include "base/ccMacros.h" #include "platform/CCFileUtils.h" +#include "CCBundleReader.h" +#include "base/CCData.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 NS_CC_BEGIN @@ -95,6 +109,8 @@ void Bundle3D::purgeBundle3D() bool Bundle3D::load(const std::string& path) { + return loadBinary(path);// + if (_path == path) return true; @@ -122,6 +138,8 @@ bool Bundle3D::load(const std::string& path) */ bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata) { + return loadMeshDataBinary(meshdata); + meshdata->resetData(); assert(_document.HasMember("mesh")); @@ -168,7 +186,7 @@ bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata) meshdata->attribs[i].type = parseGLType(mesh_vertex_attribute_val["type"].GetString()); meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val["attribute"].GetString()); } - + return true; } @@ -299,6 +317,229 @@ bool Bundle3D::loadAnimationData(const std::string& id, Animation3DData* animati return true; } +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()) + { + _path = ""; + return false; + } + + CC_SAFE_DELETE(_bundleReader); + _bundleReader = BundleReader::create((char*)_data->getBytes(), _data->getSize()); + + 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()); + return false; + } + + // Read version + 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) + { + _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) + { + 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()); + 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) +{ + meshdata->resetData(); + + // read mesh data + if (_bundleReader->read(&meshdata->attribCount, 4, 1) != 1 || meshdata->attribCount < 1) + return false; + + meshdata->attribs.resize(meshdata->attribCount); + for (ssize_t i = 0; i < meshdata->attribCount; i++) + { + unsigned int vUsage, vSize; + if (_bundleReader->read(&vUsage, 4, 1) != 1 || _bundleReader->read(&vSize, 4, 1) != 1) + { + 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 (_bundleReader->read(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0) + { + return false; + } + + meshdata->vertex.resize(meshdata->vertexSizeInFloat); + if (_bundleReader->read(&meshdata->vertex, 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat) + { + return false; + } + + // Read index data + unsigned int meshPartCount; + if (_bundleReader->read(&meshPartCount, 4, 1) != 1) + { + return false; + } + + 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) + { + return false; + } + + meshdata->numIndex = iByteCount / 4; + + if (_bundleReader->read(&meshdata->indices, 2, iByteCount) != iByteCount) + { + return false; + } + } + + return true; +} + +bool Bundle3D::loadMeshSkin(SkinData* skindata) +{ + skindata->resetData(); + + // bind shape + float bindShape[16]; + _bundleReader->readMatrix(bindShape); + + unsigned int jointCount; + _bundleReader->read(&jointCount); + + for (unsigned int i = 0; i < jointCount; i++) + { + skindata->boneNames.push_back(_bundleReader->readString()); + } + + unsigned int jointsBindPosesCount; + _bundleReader->read(&jointsBindPosesCount); + + if (jointsBindPosesCount > 0) + { + assert(jointCount * 16 == jointsBindPosesCount); + float m[16]; + for (unsigned int i = 0; i < jointCount; i++) + { + if (!_bundleReader->readMatrix(m)) + { + CCLOGINFO("Failed to load C3DMeshSkin in bundle '%s'.", _path.c_str()); + return NULL; + } + skindata->inverseBindPoseMatrices.push_back(m); + } + } + + skindata->rootBoneIndex = 0;//????? + + return true; +} + GLenum Bundle3D::parseGLType(const std::string& str) { if (str == "GL_FLOAT") @@ -383,16 +624,44 @@ 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 (_bundleReader->seek(ref->offset, SEEK_SET) == false) + { + CCLOGINFO("Failed to seek to object '%s' in bundle '%s'.", ref->id.c_str(), _path.c_str()); + return NULL; + } + return ref; + } + } + return NULL; +} + Bundle3D::Bundle3D() -:_isBinary(false),_modelRelativePath(""),_documentBuffer(NULL),_path("") +:_isBinary(false), +_modelRelativePath(""), +_documentBuffer(NULL), +_path(""), +_referenceCount(0), +_bundleReader(NULL), +_references(NULL), +_data(NULL) { } Bundle3D::~Bundle3D() { CC_SAFE_DELETE_ARRAY(_documentBuffer); + CC_SAFE_DELETE_ARRAY(_bundleReader); + CC_SAFE_DELETE_ARRAY(_references); + CC_SAFE_DELETE(_data); } - - NS_CC_END diff --git a/cocos/3d/CCBundle3D.h b/cocos/3d/CCBundle3D.h index dbaefa1cc6..2a610a6dfa 100644 --- a/cocos/3d/CCBundle3D.h +++ b/cocos/3d/CCBundle3D.h @@ -39,8 +39,10 @@ #include "json/document.h" NS_CC_BEGIN - +class BundleReader; class Animation3D; +class Data; + class Bundle3D { public: @@ -78,6 +80,12 @@ public: */ bool loadAnimationData(const std::string& id, Animation3DData* animationdata); + bool loadBinary(const std::string& path); + + bool loadMeshDataBinary(MeshData* meshdata); + + bool loadMeshSkin(SkinData* skindata); + protected: GLenum parseGLType(const std::string& str); @@ -88,6 +96,8 @@ protected: // get model path void getModelPath(const std::string& path); + Reference* seekToFirstType(unsigned int type); + protected: Bundle3D(); ~Bundle3D(); @@ -101,6 +111,13 @@ protected: rapidjson::Document _document; + BundleReader* _bundleReader; + + unsigned int _referenceCount; + Reference* _references; + + Data* _data; + bool _isBinary; }; diff --git a/cocos/3d/CCBundle3DData.h b/cocos/3d/CCBundle3DData.h index 178a91d4ec..0e163f09cf 100644 --- a/cocos/3d/CCBundle3DData.h +++ b/cocos/3d/CCBundle3DData.h @@ -34,6 +34,26 @@ NS_CC_BEGIN +// vertex usage elements. +enum Vertex_Usage +{ + Vertex_Usage_POSITION = 1, + Vertex_Usage_NORMAL = 2, + Vertex_Usage_COLOR = 3, + Vertex_Usage_TANGENT = 4, + Vertex_Usage_BINORMAL = 5, + Vertex_Usage_BLENDWEIGHTS = 6, + Vertex_Usage_BLENDINDICES = 7, + Vertex_Usage_TEXCOORD0 = 8, + Vertex_Usage_TEXCOORD1 = 9, + Vertex_Usage_TEXCOORD2 = 10, + Vertex_Usage_TEXCOORD3 = 11, + Vertex_Usage_TEXCOORD4 = 12, + Vertex_Usage_TEXCOORD5 = 13, + Vertex_Usage_TEXCOORD6 = 14, + Vertex_Usage_TEXCOORD7 = 15 +}; + //mesh vertex attribute struct MeshVertexAttrib { @@ -182,6 +202,17 @@ public: } }; +class Reference +{ +public: + std::string id; + unsigned int type; + unsigned int offset; + + Reference(){}; + + ~Reference(){}; +}; NS_CC_END #endif //__CC_BUNDLE_3D_DATA_H__ diff --git a/cocos/3d/CCBundleReader.cpp b/cocos/3d/CCBundleReader.cpp new file mode 100644 index 0000000000..a84671f96d --- /dev/null +++ b/cocos/3d/CCBundleReader.cpp @@ -0,0 +1,211 @@ +#include "CCBundleReader.h" +#include "platform/CCFileUtils.h" + +NS_CC_BEGIN + +BundleReader::~BundleReader() +{ + close(); +}; + +BundleReader* BundleReader::create(char* lpbuffer, unsigned int length) +{ + if (lpbuffer) + { + BundleReader* stream = new BundleReader(); + stream->init(lpbuffer, length); + return stream; + } + return NULL; +} + +void BundleReader::close() +{ + CC_SAFE_DELETE(m_buffer); +} + +size_t BundleReader::read(void* ptr, size_t size, size_t count) +{ + if (!m_buffer || eof()) + return 0; + + size_t validCount; + size_t validLength = m_length - m_position; + size_t needLength = size*count; + char* ptr1 = (char*)ptr; + if(validLength <= needLength) + { + validCount = validLength/size; + size_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; + } + //*ptr1 = 0; + + return validCount; +} + +char* BundleReader::readLine(int num,char* line) +{ + if (!m_buffer) + return 0; + + //char* str = new char[num]; + char* buffer = (char*)m_buffer+m_position; + + char* p = line; + char c; + size_t readNum = 0; + while((c=*buffer) != 10 && readNum < (size_t)num && m_position<(long int)m_length) + { + *p = c; + p++; + buffer++; + m_position++; + readNum++; + } + *p = '\0'; + + return line; +} + +size_t BundleReader::write(const void* ptr, size_t size, size_t count) +{ + if (!m_buffer) + return 0; + + size_t validCount; + size_t validLength = m_length - m_position; + size_t needLength = size*count; + const char* ptr1 = (const char*)ptr; + if (validLength <= needLength) + { + validCount = validLength / size; + size_t readLength = size * validCount; + memcpy((char*)m_buffer + m_position, ptr1, readLength); + ptr1 += readLength; + m_position += readLength; + readLength = validLength - readLength; + if(readLength > 0) + { + memcpy((char*)m_buffer+m_position, ptr1, readLength); + m_position += readLength; + validCount += 1; + } + } + else + { + memcpy((char*)m_buffer + m_position, ptr1, needLength); + m_position += needLength; + validCount = count; + } + + return validCount; +} + +bool BundleReader::eof() +{ + if (!m_buffer) + return true; + return ((size_t)tell()) >= length(); +} + +size_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); +} + +BundleReader::BundleReader() +{ + m_buffer = NULL; + m_position = 0; + m_length = 0; +}; + +void BundleReader::init(char* lpbuffer, unsigned int length) +{ + m_position = 0; + m_buffer = lpbuffer; + m_length = length; +} + +} \ No newline at end of file diff --git a/cocos/3d/CCBundleReader.h b/cocos/3d/CCBundleReader.h new file mode 100644 index 0000000000..5bb6fb8a10 --- /dev/null +++ b/cocos/3d/CCBundleReader.h @@ -0,0 +1,203 @@ +/**************************************************************************** + 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 +#include + +#include "base/CCRef.h" +#include "base/CCPlatformMacros.h" +#include "base/CCConsole.h" + +NS_CC_BEGIN + +/** + * Stream is an interface for reading and writing a sequence of bytes. + */ +class BundleReader: public cocos2d::Ref +{ +public: + ~BundleReader(); + + static BundleReader* create(char* lpbuffer, unsigned int length); + + void close(); + + /** + * 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. + */ + size_t read(void* ptr, size_t size, size_t count); + + /** + * Reads a line from the stream. + */ + char* readLine(int num,char* line); + + /** + * Writes an array of elements. + * + * @param ptr The pointer to the array of elements to be written. + * @param size The size of each element to be written, in bytes. + * @param count The number of elements to write. + * + * @return The number of elements written. + */ + size_t write(const void* ptr, size_t size, size_t count); + + /** + * Returns true if the end of the stream has been reached. + */ + bool eof(); + + /** + * Returns the length of the stream in bytes. + */ + size_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 bool read(T* ptr); + template bool readArray(unsigned int* length, std::vector* values); + + /** + * first read length, then read string text + */ + std::string readString(); + bool readMatrix(float* m); + +private: + BundleReader(); + void init(char* lpbuffer, unsigned int length); + +private: + long int m_position; + size_t m_length; + char* m_buffer; +}; + +// template read routines +template +inline bool BundleReader::read(T *ptr) +{ + return (read(ptr, sizeof(T), 1) == 1); +} + +/** +* template function to read array of value. +*/ +template +inline bool BundleReader::readArray(unsigned int *length, std::vector *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 *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 *ptr) +{ + CCLOG("can not read std::string, use readString() instead"); + return false; +} + +/** +* template function to read array of value. +*/ +template<> +inline bool BundleReader::readArray(unsigned int *length, std::vector *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 diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 5ff2b3b186..a2d97dd5ea 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -541,12 +541,13 @@ std::string Sprite3DWithSkinTest::subtitle() const void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p) { - auto sprite = Sprite3D::create("Sprite3DTest/girl.c3t"); + std::string fileName = "Sprite3DTest/girl.c3b";/*"Sprite3DTest/tianguang.c3b"*/ + auto sprite = Sprite3D::create(fileName); 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);