Skip to content

Instantly share code, notes, and snippets.

@SecondReality
Created May 26, 2012 21:17
Show Gist options
  • Save SecondReality/2795343 to your computer and use it in GitHub Desktop.
Save SecondReality/2795343 to your computer and use it in GitHub Desktop.
Flexer
//
// Flexer.h
// OpenGLESTest
//
// Created by Steven Mark Rose on 26/09/2010.
// Copyright 2010 Second Reality. All rights reserved.
//
// The Flexer class is used to modify a vertex buffer so it can bend and trail and follow a moving point.
// Example uses are: Mouse Tails and Fish Bodies.
// After it has been initialised its length cannot be changed.
#import <Foundation/Foundation.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import "Vector2D.h"
@interface Flexer : NSObject
{
@private
int controlPointCount;
NSMutableArray* controlPoints;
GLfloat* vertexBuffer;
GLfloat* textureBuffer;
int vertexCount;
float controlPointDistance;
}
-(id)initWithLength:(int)length pointDistance:(float)pointDistance;
-(void)updateHeadPosition:(Vector2D)newHeadPosition direction:(Vector2D)direction width:(float)width;
@property GLfloat* vertexBuffer;
@property GLfloat* textureBuffer;
@property (readonly)int vertexCount;
@end
//
// Flexer.m
// OpenGLESTest
//
// Created by Steven Mark Rose on 26/09/2010.
// Copyright 2010 Second Reality. All rights reserved.
//
#import "Flexer.h"
#import "Vector2D.h"
@implementation Flexer
@synthesize vertexBuffer;
@synthesize textureBuffer;
@synthesize vertexCount;
-(id)initWithLength:(int)length pointDistance:(float)pointDistance
{
if(self=[super init])
{
controlPointCount=length;
controlPointDistance = pointDistance;
controlPoints=[[NSMutableArray alloc] init];
for(int i=0; i<controlPointCount; i++)
{
Vector2DWrapper * vectorWrapper = [[Vector2DWrapper alloc] init];
[controlPoints addObject:vectorWrapper];
[vectorWrapper release];
}
vertexCount=controlPointCount*2;
vertexBuffer = malloc(vertexCount*3*sizeof(float));
textureBuffer = malloc(vertexCount*2*sizeof(float));
// Initialise texture buffer:
float increase = 1.0f/(controlPointCount-1);
float textureOffset=0.0f;
for(int i=0; i<vertexCount*2; i+=4)
{
textureBuffer[i]=textureOffset;
textureBuffer[i+1]=1.0f;
textureBuffer[i+2]=textureOffset;
textureBuffer[i+3]=0.0f;
textureOffset+=increase;
}
}
return self;
}
-(void)dealloc
{
free(vertexBuffer);
vertexBuffer=NULL;
free(textureBuffer);
textureBuffer=NULL;
[controlPoints release];
[super dealloc];
}
-(void)updateHeadPosition:(Vector2D)newHeadPosition direction:(Vector2D)directionIn width:(float)width
{
Vector2DWrapper * headControlPointWrapper=[controlPoints objectAtIndex: 0];
headControlPointWrapper->v=newHeadPosition;
// Calculate the position of the first two vertices:
{
Vector2D perp = multiply(rotateBy90DegreesClockwise(directionIn), 0.10f);
Vector2D point1 = add(newHeadPosition, perp);
Vector2D point2 = subtract(newHeadPosition, perp);
vertexBuffer[0]=point1.x;
vertexBuffer[1]=point1.y;
vertexBuffer[2]=-1.8f;
vertexBuffer[3]=point2.x;
vertexBuffer[4]=point2.y;
vertexBuffer[5]=-1.8f;
}
// Update the remaining control points:
for(int i=1; i<controlPointCount; i++)
{
Vector2DWrapper* controlPointWrapper = [controlPoints objectAtIndex: i];
Vector2DWrapper* previousControlPointWrapper = [controlPoints objectAtIndex: i-1];
// Calculate the directional vector from the previous control point to this control point:
Vector2D direction = normalize(subtract(controlPointWrapper->v, previousControlPointWrapper->v));
controlPointWrapper->v=add(previousControlPointWrapper->v, multiply(direction, controlPointDistance));
}
// Update the vertices:
// Update the remaining control points:
for(int i=1; i<controlPointCount; i++)
{
Vector2DWrapper* previousControlPointWrapper = [controlPoints objectAtIndex: i-1];
Vector2DWrapper* controlPointWrapper = [controlPoints objectAtIndex: i];
Vector2D previousControlPoint = previousControlPointWrapper->v;
Vector2D controlPoint = controlPointWrapper->v;
// Calculate the directional vector from the previous control point to this control point:
Vector2D direction = normalize(subtract(controlPoint, previousControlPoint));
Vector2D perp;
if(i<controlPointCount-1)
{
Vector2DWrapper * nextControlPointWrapper = [controlPoints objectAtIndex: i+1];
Vector2D directionToNextControlPoint = normalize( subtract(nextControlPointWrapper->v, controlPoint));
// Adding two normalised vectors together like this is dangerous because they could point
// in opposite directions and nullify to give (0,0)
perp = normalize(rotateBy90DegreesClockwise(add(direction, directionToNextControlPoint)));
// Test if perp is NAN:
if(perp.x!=perp.x)
{
perp = rotateBy90DegreesClockwise(direction);
}
}
else
{
perp = rotateBy90DegreesClockwise(direction);
}
perp=multiply(perp, width);
Vector2D point2 = add(controlPoint, perp);
Vector2D point1 = subtract(controlPoint, perp);
int n=i;
vertexBuffer[n*2*3]=point1.x;
vertexBuffer[n*2*3+1]=point1.y;
vertexBuffer[n*2*3+2]=-1.8f;
vertexBuffer[n*2*3+3]=point2.x;
vertexBuffer[n*2*3+4]=point2.y;
vertexBuffer[n*2*3+5]=-1.8f;
}
/*
for(int i=0; i<controlPointCount*2; i++)
{
NSLog(@"Vertex %d: %f,%f,%f", i, vertexBuffer[i*3+0], vertexBuffer[i*3+1], vertexBuffer[i*3+2]);
}
*/
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment