Awaria podczas uruchamiania OpenGL na iOS po ostrzeżeniu pamięci

Mam problem z aplikacją z zawieszonym komponentem OpenGL na iPadzie. Aplikacja generuje ostrzeżenie o pamięci i ulega awarii, ale wydaje się, że nie korzysta z tak dużej ilości pamięci. Czy czegoś mi brakuje?

Aplikacja jest oparta na systemie rzeczywistości rozszerzonej Vuforia (pożycza dużo z próbki ImageTargets). Mam około 40 różnych modeli, które muszę dołączyć do mojej aplikacji, więc w celu zachowania pamięci ładuję obiekty (i renderowanie tekstur itp.) Dynamicznie w aplikacji, tak jak ich potrzebuję. Próbowałem skopiować leniwy pomysł ładowania UIScrollView. Trzy alokacje 4 MB są teksturami, które załadowałem do pamięci, gdy użytkownik wybierze inny model do wyświetlenia.

Coś tu dziwnego?

Nie wiem zbyt wiele o OpenGL (częściowo z powodu wyboru silnika Vurforia). Cokolwiek z tego zrzutu ekranu poniżej powinno mnie dotyczyć? Zauważ, że przykładowa aplikacja Vurforia ImageTagets ma również niezainicjowane dane tekstury (około jednej na ramkę), więc nie sądzę, aby był to problem.

Każda pomoc byłaby mile widziana !!

Oto kod generujący obiekty 3D (w EAGLView):

// Load the textures for use by OpenGL
-(void)loadATexture:(int)texNumber {

if (texNumber >= 0 && texNumber < [tempTextureList count]) {
    currentlyChangingTextures = YES;

    [textureList removeAllObjects];
    [textureList addObject:[tempTextureList objectAtIndex:texNumber]];

    Texture *tex = [[Texture alloc] init];
    NSString *file = [textureList objectAtIndex:0];

    [tex loadImage:file];



    [textures replaceObjectAtIndex:texNumber withObject:tex];
    [tex release];

    // Remove all old textures outside of the one we're interested in and the two on either side of the picker.
    for (int i = 0; i < [textures count]; ++i) {

        if (i < targetIndex - 1 || i > targetIndex + 1) {
            [textures replaceObjectAtIndex:i withObject:@""];
        }
    }


    // Render - Generate the OpenGL texture objects
    GLuint nID;
    Texture *texture = [textures objectAtIndex:texNumber];
    glGenTextures(1, &nID);
    [texture setTextureID: nID];
    glBindTexture(GL_TEXTURE_2D, nID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, [texture width], [texture height], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)[texture pngData]);


    // Set up objects using the above textures.
    Object3D *obj3D = [[Object3D alloc] init];

    obj3D.numVertices = rugNumVerts;
    obj3D.vertices = rugVerts;
    obj3D.normals = rugNormals;
    obj3D.texCoords = rugTexCoords;

    obj3D.texture = [textures objectAtIndex:texNumber];

    [objects3D replaceObjectAtIndex:texNumber withObject:obj3D];
    [obj3D release];

    // Remove all objects except the one currently visible and the ones on either side of the picker.
    for (int i = 0; i < [tempTextureList count]; ++i) {

        if (i < targetIndex - 1 || i > targetIndex + 1) {
            Object3D *obj3D = [[Object3D alloc] init];
            [objects3D replaceObjectAtIndex:i withObject:obj3D];
            [obj3D release];
        }
    }


    if (QCAR::GL_20 & qUtils.QCARFlags) {
        [self initShaders];
    }


    currentlyChangingTextures = NO;
}

}

Oto kod w obiekcie tekstur.

- (id)init
{
self = [super init];
pngData = NULL;

return self;
}


- (BOOL)loadImage:(NSString*)filename
{
BOOL ret = NO;

// Build the full path of the image file
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
NSString* fullPath = [resourcePath stringByAppendingPathComponent:filename];

// Create a UIImage with the contents of the file
UIImage* uiImage = [UIImage imageWithContentsOfFile:fullPath];

if (uiImage) {
    // Get the inner CGImage from the UIImage wrapper
    CGImageRef cgImage = uiImage.CGImage;

    // Get the image size
    width = CGImageGetWidth(cgImage);
    height = CGImageGetHeight(cgImage);

    // Record the number of channels
    channels = CGImageGetBitsPerPixel(cgImage)/CGImageGetBitsPerComponent(cgImage);

    // Generate a CFData object from the CGImage object (a CFData object represents an area of memory)
    CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));

    // Copy the image data for use by Open GL
    ret = [self copyImageDataForOpenGL: imageData];
    CFRelease(imageData);
}

return ret;
}


- (void)dealloc
{
if (pngData) {
    delete[] pngData;
}

[super dealloc];
}

@end


@implementation Texture (TexturePrivateMethods)

- (BOOL)copyImageDataForOpenGL:(CFDataRef)imageData
{    
if (pngData) {
    delete[] pngData;
}

pngData = new unsigned char[width * height * channels];
const int rowSize = width * channels;
const unsigned char* pixels = (unsigned char*)CFDataGetBytePtr(imageData);

// Copy the row data from bottom to top
for (int i = 0; i < height; ++i) {
    memcpy(pngData + rowSize * i, pixels + rowSize * (height - 1 - i), width * channels);
}

return YES;
}

questionAnswers(2)

yourAnswerToTheQuestion