4 * Copyright 2009 Parrot SA. All rights reserved.
5 * @author D HAEYER Frederic
8 #import "OpenGLSprite.h"
13 unsigned long RoundPower2(unsigned long x);
14 void BindTexture(Texture* texture);
19 static GLfloat const vertices[] =
27 static GLfloat const coordinates[] =
35 unsigned long RoundPower2(unsigned long x)
38 // rval<<=1 Is A Prettier Way Of Writing rval*=2;
44 void BindTexture(Texture* texture)
46 // Check whether the texture has already been generated
47 if(texture->state == INVALID)
49 // Generated the texture
50 // Note: this must NOT be done before the initialization of OpenGL (this is why it can NOT be done in "InitializeTexture")
51 glGenTextures(1, &texture->identifier);
52 printf("Video texture identifier : %d\n", texture->identifier);
53 texture->state = GENERATED;
57 glBindTexture(GL_TEXTURE_2D, texture->identifier);
59 // Check whether the texture data have already been sent to OpenGL
60 if(texture->state == GENERATED)
62 // Load the texture in the GPU
63 glTexImage2D(GL_TEXTURE_2D, 0, texture->format, texture->widthTexture, texture->heightTexture, 0, texture->format, texture->type, texture->data);
64 texture->state = SENT_TO_GPU;
68 void InitTexture(Texture *texture, CGSize imageSize, CGSize screenSize, eSCALING scaling)
70 int max_size = max(RoundPower2(imageSize.width), RoundPower2(imageSize.height));
71 // Define the texture format
72 texture->widthImage = imageSize.width;
73 texture->heightImage = imageSize.height;
74 texture->widthTexture = max_size;
75 texture->heightTexture = max_size;
76 NSLog(@"%s sizes %d, %d, %d, %d, %@\n", __FUNCTION__, texture->widthImage, texture->heightImage, texture->widthTexture, texture->heightTexture, NSStringFromCGSize(screenSize));
77 if(texture->bytesPerPixel == 2)
79 texture->format = GL_RGB;
80 texture->type = GL_UNSIGNED_SHORT_5_6_5;
84 texture->format = GL_RGBA;
85 texture->type = GL_UNSIGNED_BYTE;
91 texture->scaleModelX = texture->heightImage / screenSize.width;
92 texture->scaleModelY = texture->widthImage / screenSize.height;
95 texture->scaleModelX = (screenSize.height * texture->heightImage) / (screenSize.width * texture->widthImage);
96 texture->scaleModelY = 1.0f;
99 texture->scaleModelX = 1.0f;
100 texture->scaleModelY = (screenSize.width * texture->widthImage) / (screenSize.height * texture->heightImage);
103 texture->scaleModelX = 1.0f;
104 texture->scaleModelY = 1.0f;
107 texture->scaleTextureX = texture->widthImage / (float)texture->widthTexture;
108 texture->scaleTextureY = texture->heightImage / (float)texture->heightTexture;
111 @implementation OpenGLSprite
112 @synthesize position;
113 @synthesize rotation;
116 - (id)initWithPath:(NSString *)path withScaling:(eSCALING)_scaling withScreenSize:(CGSize)size
118 if ((self = [super init]))
121 image = [UIImage imageWithContentsOfFile:path];
127 // Init rotation, translation and scale
140 texture.bytesPerPixel = 4;
141 texture.format = GL_RGBA;
142 texture.type = GL_UNSIGNED_BYTE;
143 texture.state = INVALID;
144 InitTexture(&texture, image.size, screenSize, scaling);
146 NSLog(@"Default Image size : %@", NSStringFromCGSize(image.size));
147 oldSize = CGSizeMake(image.size.width, image.size.height);
148 oldBytesPerPixel = texture.bytesPerPixel;
150 // Allocate memory to store the texture data
151 default_image = vp_os_malloc(texture.widthTexture * texture.heightTexture * texture.bytesPerPixel);
152 texture.data = default_image;
154 CGContextRef context = CGBitmapContextCreate(texture.data, texture.widthTexture, texture.heightTexture, 8, texture.widthTexture * texture.bytesPerPixel, CGImageGetColorSpace(image.CGImage), kCGImageAlphaNoneSkipLast);
156 // Draw the image into the texture
157 CGContextDrawImage(context, CGRectMake(0.0f, texture.heightTexture - texture.heightImage, texture.widthImage, texture.heightImage), image.CGImage);
159 // Release the context (but keep the texture data buffer to make it possible modifying the texture in real-time)
160 CGContextRelease(context);
169 if ((oldSize.width != texture.widthImage) || (oldSize.height != texture.heightImage) || (oldBytesPerPixel != texture.bytesPerPixel))
171 NSLog(@"%s oldSize : %d, %d - texture : %d, %d, oldBytesPerPixel : %d", __FUNCTION__, (int)oldSize.width, (int)oldSize.height, (int)texture.widthImage, (int)texture.heightImage, oldBytesPerPixel);
172 CGSize current_size = CGSizeMake(texture.widthImage, texture.heightImage);
173 InitTexture(&texture, current_size, screenSize, scaling);
174 texture.state = GENERATED;
175 oldSize = current_size;
176 oldBytesPerPixel = texture.bytesPerPixel;
183 - (void)drawSelfIfNeeded:(BOOL)needed
185 glMatrixMode(GL_MODELVIEW);
187 glTranslatef(position.x, position.y, position.z);
192 glScalef(texture.scaleModelX * scale.x, texture.scaleModelY * scale.y, scale.z);
194 glRotatef(rotation.x, 1.0, 0.0, 0.0);
195 glRotatef(rotation.y, 0.0, 1.0, 0.0);
196 glRotatef(rotation.z, 0.0, 0.0, 1.0);
198 glMatrixMode(GL_TEXTURE);
200 glScalef(texture.scaleTextureX, texture.scaleTextureY, 1.0f);
202 glVertexPointer(2, GL_FLOAT, 0, vertices);
203 glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
205 // Bind the background texture if needed, resend to gpu
207 texture.state = GENERATED;
209 BindTexture(&texture);
211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
216 // Draw the background quad
217 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
222 // Remove the texture from the GPU
223 if(texture.state != INVALID)
225 glDeleteTextures(1, &texture.identifier);
228 // Free the memory allocated to store the texture data
229 vp_os_free(default_image);