Search code examples
loadtexturesbackground-processcocos3d

Cocos3D - How to load a CC3Texture in background


I have an array of texture filenames that I want to load in background, and assign them to their corresponding CC3MeshNode when each texture is finished loading, like this:

NSArray *fileNames = @[@"MyTexture.png", @"OtherTexture.png"];

for (CC3MeshNode *meshNode in nodesWithTexture) {
    int index = *meshNode.userData;
    NSString *textureFileName = [fileNames objectAtIndex:index];

    [[CCTextureCache sharedTextureCache] addImageAsync: textureFileName withBlock:^(CCTexture2D *tex){
        CC3Texture *texture = [CC3Texture textureFromFile: textureFileName];    //<— SIGABRT with the error described bellow

        // this other alternative won't work because the inner CCTexture2D is a readonly property
        //   |
        //   V
        // CC3Texture *texture = [CC3Texture new];
        // teture.texture = tex;

        meshNode.texture = texture;
    }];
}    

The problem is that creating a CC3Texture in the bock effectively tries to load the texture again even when it is already in the texture cache:

[ERROR] CC3PVRTexture ‘MyTexture.pvr':3 cannot be added to the texture cache because the cache already contains a texture named MyTexture.pvr. Remove it first before adding another.

Also assigning the already loaded CCTexture2D *tex being passed to the block to a new CC3Texture *texture won't work because the property texture is readonly.


Solution

  • Are you trying to use the same textures with both Cocos3D and Cocos2D? If so, it's important that you load the texture as a Cocos3D CC3Texture. This is because Cocos3D has additional requirements for managing and configuring textures.

    You can then access the Cocos2D CCTexture texture via the ccTexture property of the CC3Texture. The CC3DemoMashUpScene addTelevision method contains some code at the end that you can uncomment to demonstrate the use of the CC3Texture ccTexture property.

    If you only need the texture for Cocos3D, then just load it using one of the CC3Texture class-side creation methods. It will be cached automatically.

    Regarding loading in the background, remember that you must do so via CC3Backgrounder in order to keep the GL context sane. You can do that via something like:

    [CC3Backgrounder.sharedBackgrounder runBlock: ^{ --load some stuff-- }];
    

    The CCDemoMashUpScene onOpen method demonstrates using CC3Backgrounder to perform a large amount of background loading. You can only perform background loading once the GL view has been established.