SPine數據組織
spAtlas:這個是從.atlas文件中解出來的結構,其中包含了紋理
struct spAtlas { spAtlasPage* pages; spAtlasRegion* regions; void* rendererObject; int ref; };
先不要管,看它的數據組織,spAtlasPage,spAtlasRegion,rendererObject都是什么東西?往下看
struct spAtlasPage { const spAtlas* atlas; const char* name; spAtlasFormat format; spAtlasFilter minFilter, magFilter; spAtlasWrap uWrap, vWrap; void* rendererObject; int width, height; spAtlasPage* next; };
spAtalsPage看它的成員,可以很簡單看出,哇哦,這個就是紋理,給你看看真相,哈哈
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path) { CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage(path); texture->retain(); self->rendererObject = texture; self->width = texture->getPixelsWide(); self->height = texture->getPixelsHigh(); }
看見沒有,真相在這里,里面有了紋理的寬,高。奇葩的是他竟然還有(spAtlasPage* next),很明顯這是一個鏈表結構啊,如果你的一個動作文件,用到了多張紋理,那么這個指針就派上用場了。其他暫時忽略,看上面(_spAtlasPage_createTexture)發現沒有,這里把紋理給持有了。所以紋理不會釋放哦。
struct spAtlasRegion { const char* name; int x, y, width, height; float u, v, u2, v2; int offsetX, offsetY; int originalWidth, originalHeight; int index; int/*bool*/rotate; int/*bool*/flip; int* splits; int* pads; spAtlasPage* page; spAtlasRegion* next; };
這貨一看,就是紋理當中包含的元素,一塊,一塊的描述信息。
看見這張紋理了嗎,它的每一塊都應該對應一個(spAtlasRegion)它。
這就是.atlas文件包含的信息啊!就是這樣圖片怎么怎么分割的,分隔成多少部分。每個部分的坐標是什么。
那個 renderobject是什么東西?我也不清楚,繼續看。
spAtlas* spAtlas_create (const char* begin, int length, const char* dir, void* rendererObject) { spAtlas* self; int count; const char* end = begin + length; int dirLength = strlen(dir); int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; spAtlasPage *page = 0; spAtlasPage *lastPage = 0; spAtlasRegion *lastRegion = 0; Str str; Str tuple[4]; self = NEW(spAtlas); self->rendererObject = rendererObject; ................
看見沒有,亮點在最后一句。創建這個對象的時候,需要傳進來一個東西void* rendererObject,然后,這個東西又賦予給了自己
spAtlas* self;
.......
self = NEW(spAtlas);
self->rendererObject = rendererObject;
然后在外面我的調用是
atlas = spAtlas_createFromFile(atlasFile, 0); 我竟然傳了一個0,哈哈,沒有用,暫時到這里。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
.JSON文件放的就是上面這些spAtlasRegion的樹形結構的組織信息,也就是骨架信息,和每個動作信息,每個動作當中每個關鍵幀中各個Region的數據。哈哈。
先看看,創建的代碼
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale) { initialize(); if(1) { CTimeMgr::GetInst()->time_begin("spAtlas_createFromFile"); atlas = spAtlas_createFromFile(atlasFile, 0); CCAssert(atlas, "Error reading atlas file."); CTimeMgr::GetInst()->time_end(); CTimeMgr::GetInst()->time_begin("spSkeletonJson_create"); spSkeletonJson* json = spSkeletonJson_create(atlas); CTimeMgr::GetInst()->time_end(); json->scale = scale; CTimeMgr::GetInst()->time_begin("spSkeletonJson_readSkeletonDataFile"); spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile); CTimeMgr::GetInst()->time_end(); CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data file."); spSkeletonJson_dispose(json); setSkeletonData(skeletonData, true); } else { atlas = spAtlas_createFromFile(atlasFile, 0); CCAssert(atlas, "Error reading atlas file."); spSkeletonJson* json = spSkeletonJson_create(atlas); json->scale = scale; spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile); CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data file."); spSkeletonJson_dispose(json); setSkeletonData(skeletonData, true); } }
if(1)中的內容,是我改的,else里面的內容是原有的。我改的目的,是為了1次加載多次使用,當然別的地方響應的有引用計數的析構了。還是老實的看else中的內容吧。
atlas = spAtlas_createFromFile(atlasFile, 0); 這個不用說了吧,我們暫且叫創建紋理圖集吧
spSkeletonJson* json = spSkeletonJson_create(atlas); 根據紋理圖集,創建一個JSON對象,它就像一個漏斗一樣,紋理解析JSON文件准備的,用完就析構了。
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);解析骨架文件
spSkeletonJson_dispose(json); 漏斗析構了吧
setSkeletonData(skeletonData, true); (以上代碼在SkeletonRenderer類的構造函數中,所以,看清楚沒有,解析出來的spSkeletonData被SkeletonRenderer持有了吧)
spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const char* path) { int length; spSkeletonData* skeletonData; const char* json = _spUtil_readFile(path, &length); if (!json) { _spSkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); return 0; } skeletonData = spSkeletonJson_readSkeletonData(self, json); FREE(json); return skeletonData; }
這里干啥了,亮點在這句 skeletonData = spSkeletonJson_readSkeletonData(self, json);
反正大家知道這里面解析了JSON文件就可以了!
行了。我們只要知道JSON文件是要給包含骨架組織和動畫運動的數據就可以了。而ATLAS文件才是與紋理相關就OK了。我們要做的是讓它不持有紋理,想用的時候加載,不想用的時候,把紋理都卸掉就可以了!
假如加載紋理需要40ms,紋理占有內存512*512*4 = 1M,如果我們按照這個目標更改的話。其實是用了40ms換去了1M內存。
速度和內存是需要平衡的。哈哈,我們下面要開始做微創手術了。