I have created a view (derived from UIScrollView) where the cells are drawn and zoom occurs. Everything is drawn with OpenGL ES 1.1. Zoom is specified by adding of a calculated new distance which is passed by fingers (sliding apart or moving together), which is multiplied by a constant coefficient:
fNewZoom += fDistance * fCoef;
fDistance may have negative value at minimization
There are 4 arrays of cells, each array contains cells with definite size. At zooming the most optimal cells by size are chosen for drawing and are drawn with the OpenGL ES 1.1. The initialization of all four textures takes place at the start while initialization of the drawing view.
Initialization of the view:
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
- (id)initWithCoder:(NSCoder*)coder
{
if((self = [super initWithCoder:coder]))
{
CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer;
eaglLayer.opaque = NO;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if(!m_context || ![EAGLContext setCurrentContext:m_context] || ![self createFramebuffer])
{
[self release];
return nil;
}
[self InitGLTextures];
}
return self;
}
Drawing specifically in function "- (void)drawView":
- (void)layoutSubviews
{
[self InvalidateView];
}
- (void)InvalidateView
{
[EAGLContext setCurrentContext:m_context];
[self destroyFramebuffer];
[self createFramebuffer];
[self drawView]; //drawing view
}
- (BOOL)createFramebuffer
{
glGenFramebuffersOES(1, &m_viewFramebuffer);
glGenRenderbuffersOES(1, &m_viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_viewRenderbuffer);
[m_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, m_viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &m_nBackingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &m_nBackingHeight);
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
{
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
return YES;
}
- (void)destroyFramebuffer
{
glDeleteFramebuffersOES(1, &m_viewFramebuffer);
m_viewFramebuffer = nil;
glDeleteRenderbuffersOES(1, &m_viewRenderbuffer);
m_viewRenderbuffer = nil;
}
//TEST DRAWING VIEW !!!!
- (void)drawView
{
const int nClues = 3; // = 900
const ImgElDimensionsF cellDimensions = _skinMgr.GetCellInfo();
const CGPoint offset = [self contentOffset];
float fDrawX = 0;
float fDrawY = 0;
int nCount1 = 1;
[self BeginDrawing];
//
for (int nRow = 0; nRow < nClues; nRow++)
{
for (int nColl = 0; nColl < nClues; nColl++)
{
[self AddNewCellType:imgCellTypeSelectedEmpty PosX:fDrawX PosY:fDrawY];
fDrawX += cellDimensions.fWidth;
}
fDrawX = 0;
fDrawY += cellDimensions.fHeight;
}
//
[self EndDrawing];
}
functions used for drawing:
- (void)BeginDrawing
{
m_pCellTextureArr = _skinMgr.GL_GetProperlyCellTextInfo();
glViewport(0, 0, m_nBackingWidth, m_nBackingHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, (GLfloat)m_nBackingWidth, 0.0f, (GLfloat)m_nBackingHeight, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Clears the view with black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Make sure that you are drawing to the current context
[EAGLContext setCurrentContext:m_context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_viewFramebuffer);
glClear(GL_COLOR_BUFFER_BIT);
//correct matrix pos
glTranslatef(0, (CGFloat)m_nBackingHeight, 0);
}
- (void)EndDrawing
{
ImgSize curImgSize = _skinMgr.GetCurrentImgSize();
glBindTexture(GL_TEXTURE_2D, m_cellsTextureArr[curImgSize]);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//if back cells was added
if (m_nCurAddBackCell > 0)
{
glVertexPointer(2, GL_FLOAT, 0, m_spriteVerticesBack);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, m_spriteTexcoordsBack);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, POINTS_PER_CELL * m_nCurAddBackCell);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//
m_nCurAddBackCell = 0;
}
}
With the help of this function the coordinate array of texture vertices for drawing is formed where m_spriteVerticesBack and m_spriteTexcoordsBack are dynamic arrays, seleсted by means of "new" function (m_spriteVerticesBack = new float[MAX_COUNT_CELLS * 12] )
- (BOOL)AddNewCellType:(ImgCellType)cellType PosX:(float)posX PosY:(float)posY
{
ImgElDimensionsF cellDimensions = _skinMgr.GL_GetCurrerntCellDimensions(cellType);
ImgTextureInfoF imgCellInfo = m_pCellTextureArr[cellType];
if (m_nCurAddBackCell >= m_nMaxCountBackCell)
return FALSE;
const int idx = m_nCurAddBackCell * ELEMENTS_PER_CELL;
//////////
//*-------
//| 3--4
//| | |
//| 1--2
//*
// 1X
m_spriteVerticesBack[idx + 0] = posX;
// 1Y
m_spriteVerticesBack[idx + 1] = -posY - cellDimensions.fHeight;
// 2X
m_spriteVerticesBack[idx + 2] = posX + cellDimensions.fWidth;
// 3Y
m_spriteVerticesBack[idx + 3] = -posY - cellDimensions.fHeight;
// 3X
m_spriteVerticesBack[idx + 4] = posX;
// 3Y
m_spriteVerticesBack[idx + 5] = -posY;
// 2X
m_spriteVerticesBack[idx + 6] = posX + cellDimensions.fWidth;
// 3Y
m_spriteVerticesBack[idx + 7] = -posY - cellDimensions.fHeight;
// 3X
m_spriteVerticesBack[idx + 8] = posX;
// 3Y
m_spriteVerticesBack[idx + 9] = -posY;
// 4X
m_spriteVerticesBack[idx + 10] = posX + cellDimensions.fWidth;
// 4Y
m_spriteVerticesBack[idx + 11] = -posY;
//////////
//1--2
//| |
//3--4
//
// 1X
m_spriteTexcoordsBack[idx + 0] = imgCellInfo.fX;
// 1Y
m_spriteTexcoordsBack[idx + 1] = imgCellInfo.fY + imgCellInfo.fHeight;
// 2X
m_spriteTexcoordsBack[idx + 2] = imgCellInfo.fX + imgCellInfo.fWidth;
// 2Y
m_spriteTexcoordsBack[idx + 3] = imgCellInfo.fY + imgCellInfo.fHeight;
// 3X
m_spriteTexcoordsBack[idx + 4] = imgCellInfo.fX;
// 3Y
m_spriteTexcoordsBack[idx + 5] = imgCellInfo.fY;
// 2X
m_spriteTexcoordsBack[idx + 6] = imgCellInfo.fX + imgCellInfo.fWidth;
// 2Y
m_spriteTexcoordsBack[idx + 7] = imgCellInfo.fY + imgCellInfo.fHeight;
// 3X
m_spriteTexcoordsBack[idx + 8] = imgCellInfo.fX;
// 3Y
m_spriteTexcoordsBack[idx + 9] = imgCellInfo.fY;
// 4X
m_spriteTexcoordsBack[idx + 10] = imgCellInfo.fX + imgCellInfo.fWidth;
// 4Y
m_spriteTexcoordsBack[idx + 11] = imgCellInfo.fY;
//
m_nCurAddBackCell++;
return TRUE;
}
The problem is that indifferently how many cells I draw - 9 (field size 3 х 3) or 900 (field size 30 х 30), the speed of drawing at zoom on (iPhone 2G) is the same!!! What decelerates drawing? Drawing is performed like jerking. What was my mistake? What have I omited? I want the increment or minimization to become gradually, how can I achieve that?