Skip to content

Instantly share code, notes, and snippets.

@hiepnd
Created December 2, 2011 11:01
Show Gist options
  • Save hiepnd/1422805 to your computer and use it in GitHub Desktop.
Save hiepnd/1422805 to your computer and use it in GitHub Desktop.
GVLoopSprite - Infinite spheral looping sprite
//
// GVLoopSprite.h
// GVScroll
//
// Created by Ngo Duc Hiep on 10/19/11.
// Copyright 2011 Gameville Studios. All rights reserved.
//
#import "cocos2d.h"
#define GVLS_USE_VBO 1
#if GVLS_USE_VBO
#define GVLS_VERTICES_VBO 0
#define GVLS_TEXCOORD_VBO 1
#define GVLS_INDICES_VBO 2
#endif
@interface GVLoopSprite : CCNode {
ccGridSize gridSize;
CCTexture2D *texture;
GLfloat *vertices;
GLfloat *coordinates;
GLushort *indices;
CGPoint textCoorOrigin;
GLfloat cx, cy;
#if GVLS_USE_VBO
GLuint vboids[3];
#endif
}
@property(nonatomic, retain) CCTexture2D *texture;
- (id) initWithContentSize:(CGSize) size texture:(CCTexture2D *) texture gridSize:(ccGridSize) gridsize;
+ (id) loopSpriteWithContentSize:(CGSize) size texture:(CCTexture2D *) texture gridSize:(ccGridSize) gridsize;
- (void) setZ:(float) z;
- (void) setR:(float) r0 z:(float) z;
- (void) moveBy:(CGPoint) move;
@end
//
// GVLoopSprite.m
// GVScroll
//
// Created by Ngo Duc Hiep on 10/19/11.
// Copyright 2011 Gameville Studios. All rights reserved.
//
#define _LINDEX(i,j) ((i) + (gridSize.x + 1) * (j))
#define _LSET_VERTICE(index,x,y,z) \
vertices[3*(index)] = x; \
vertices[3*(index)+1] = y; \
vertices[3*(index)+2] = z;
#define _LGET_VERTICE(o,i,j) \
(o)->x = vertices[3*_LINDEX(i,j)]; \
(o)->y = vertices[3*_LINDEX(i,j)+1]; \
(o)->z = vertices[3*_LINDEX(i,j)+2];
#define _LSET_TEXCOOR(index,x,y) \
coordinates[2*(index)] = x; \
coordinates[2*(index)+1] = y;
#import "GVLoopSprite.h"
@interface GVLoopSprite(Private)
- (void) initVertices;
- (void) updateTexCoords;
- (void) initIndices;
@end
@implementation GVLoopSprite(Private)
- (void) initVertices{
float dx = contentSizeInPixels_.width / gridSize.x;
float dy = contentSizeInPixels_.height / gridSize.y;
for (int i = 0; i <= gridSize.x; i++) {
for (int j = 0; j <= gridSize.y; j++) {
_LSET_VERTICE(_LINDEX(i, j),i * dx - contentSizeInPixels_.width/2,j * dy - contentSizeInPixels_.height/2,0);
}
}
#if GVLS_USE_VBO
int n = (gridSize.x + 1) * (gridSize.y + 1);
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_VERTICES_VBO]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices[0])*n*3, vertices);
free(vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
#endif
}
- (void) updateTexCoords{
for (int i = 0; i <= gridSize.x; i++) {
for (int j = 0; j <= gridSize.y; j++) {
_LSET_TEXCOOR(_LINDEX(i, j),textCoorOrigin.x + i * cx, textCoorOrigin.y + j * cy);
}
}
#if GVLS_USE_VBO
int n = (gridSize.x + 1) * (gridSize.y + 1);
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_TEXCOORD_VBO]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(coordinates[0])*n*2, coordinates);
glBindBuffer(GL_ARRAY_BUFFER, 0);
#endif
}
- (void) initIndices{
int i = 0, j = 0, r = 0;
BOOL forward = YES;
int c = 0;
while (r < 2*gridSize.x*gridSize.y + gridSize.y + 1) {
indices[r++] = _LINDEX(i, j);
if ((forward && j == c + 1 && i == gridSize.x) || (!forward && j == c + 1 && i == 0)) {
c++;
j++;
forward = !forward;
}else{
if (j == c) {
j++;
}else{
j--;
if (forward) {
i++;
}else{
i--;
}
}
}
}
#if GVLS_USE_VBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboids[GVLS_INDICES_VBO]);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices[0])*(2*gridSize.x*gridSize.y + gridSize.y + 1), indices);
free(indices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif
}
@end
@implementation GVLoopSprite
@synthesize texture;
+ (id) loopSpriteWithContentSize:(CGSize) size texture:(CCTexture2D *) texture gridSize:(ccGridSize) gridsize{
return [[[self alloc] initWithContentSize:size texture:texture gridSize:gridsize] autorelease];
}
- (id) initWithContentSize:(CGSize) size texture:(CCTexture2D *) texture_ gridSize:(ccGridSize) gridsize{
self = [super init];
[self setContentSize:size];
gridSize = gridsize;
int n = (gridSize.x + 1) * (gridSize.y + 1);
vertices = (GLfloat *) malloc(sizeof(GLfloat)*n*3);
indices = (GLushort *) malloc(sizeof(GLushort)*(2*gridSize.x*gridSize.y + gridSize.y + 1));
coordinates = (GLfloat *) malloc(sizeof(GLfloat)*n*2);
#if GVLS_USE_VBO
glGenBuffers(3, vboids);
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_VERTICES_VBO]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0])*(n*3), NULL,GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_TEXCOORD_VBO]);
glBufferData(GL_ARRAY_BUFFER, sizeof(coordinates[0])*(n*2), NULL,GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboids[GVLS_INDICES_VBO]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0])*(2*gridSize.x*gridSize.y + gridSize.y + 1), NULL,GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif
self.texture = texture_;
[self initIndices];
return self;
}
- (void) setTexture:(CCTexture2D *) texture_{
[texture autorelease];
texture = [texture_ retain];
if (texture.maxS < 1 || texture.maxT < 1) {
NSLog(@"GVLoopSprite: maxS != 1 or maxT != 1 => Will not display correctly");
}
textCoorOrigin = ccp(0,0);
float d = contentSizeInPixels_.width / gridSize.x;
cx = d / texture.pixelsWide;
d = contentSizeInPixels_.height / gridSize.y;
cy = d / texture.pixelsHigh;
[self updateTexCoords];
[self initVertices];
}
- (void) setZ:(float) z{
float r;
for (int i = 0; i <= gridSize.x; i++) {
for (int j = 0; j <= gridSize.y; j++) {
r = (float)((i-gridSize.x/2)*(i-gridSize.x/2) + (j-gridSize.y/2)*(j-gridSize.y/2)) / (gridSize.x*gridSize.x + gridSize.y*gridSize.y)*4;
r = gridSize.x*gridSize.x/4 + gridSize.y*gridSize.y/4 - (i-gridSize.x/2)*(i-gridSize.x/2) - (j-gridSize.y/2)*(j-gridSize.y/2);
r = sqrtf(r);
vertices[3*_LINDEX(i, j) + 2] = (r*z - 600);// * CC_CONTENT_SCALE_FACTOR();
}
}
}
- (void) setR:(float) r0 z:(float) z{
float r;
for (int i = 0; i <= gridSize.x; i++) {
for (int j = 0; j <= gridSize.y; j++) {
r = gridSize.x*gridSize.x/4 + gridSize.y*gridSize.y/4 - (i-gridSize.x/2)*(i-gridSize.x/2) - (j-gridSize.y/2)*(j-gridSize.y/2);
vertices[3*_LINDEX(i, j) + 2] = (r*r0 - z);// * CC_CONTENT_SCALE_FACTOR();
}
}
}
- (void) moveBy:(CGPoint) move{
move = ccpMult(move, CC_CONTENT_SCALE_FACTOR());
move.x = move.x / texture.pixelsWide;
move.y = move.y / texture.pixelsHigh;
textCoorOrigin = ccpAdd(textCoorOrigin, move);
[self updateTexCoords];
}
- (void) draw{
glBindTexture(GL_TEXTURE_2D, [texture name]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glDisableClientState(GL_COLOR_ARRAY);
#if GVLS_USE_VBO
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_VERTICES_VBO]);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboids[GVLS_TEXCOORD_VBO]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboids[GVLS_INDICES_VBO]);
glDrawElements(GL_TRIANGLE_STRIP, 2*gridSize.x*gridSize.y + gridSize.y + 1, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawElements(GL_TRIANGLE_STRIP, 2*gridSize.x*gridSize.y + gridSize.y + 1, GL_UNSIGNED_SHORT, indices);
#endif
glEnableClientState(GL_COLOR_ARRAY);
}
- (void) dealloc{
#if GVLS_USE_VBO
glDeleteBuffers(3, vboids);
#else
free(vertices);
free(indices);
#endif
[texture release];
free(coordinates);
[super dealloc];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment