Archiv der Kategorie ‘Glut‘

 
 

Krink

Over the weekend and on monday I created an bunch of visual and non-visual C experiments. Here is one of the programs that came out particularly nicely. I’ve only bothered compiling it on OSX but it would be easy to port over to windows since it uses glut. You have a few choices for viewing:

Look at stills on flickr:

krinkScreen shot 2011-04-11 at 10.03.13 PMScreen shot 2011-04-11 at 10.15.35 PMScreen shot 2011-04-11 at 10.13.06 PMScreen shot 2011-04-11 at 10.11.18 PMScreen shot 2011-04-11 at 10.09.01 PMScreen shot 2011-04-11 at 10.08.21 PMScreen shot 2011-04-11 at 10.06.39 PMScreen shot 2011-04-11 at 10.06.00 PMScreen shot 2011-04-11 at 10.04.07 PMScreen shot 2011-04-11 at 10.03.41 PMScreen shot 2011-04-11 at 10.17.00 PMScreen shot 2011-04-11 at 10.15.47 PMScreen shot 2011-04-11 at 10.15.28 PMScreen shot 2011-04-11 at 10.14.57 PMScreen shot 2011-04-11 at 10.13.43 PMScreen shot 2011-04-11 at 10.08.01 PMScreen shot 2011-04-11 at 10.04.52 PMScreen shot 2011-04-11 at 9.49.16 PMScreen shot 2011-04-11 at 9.48.50 PM

Watch the short video:

Download the Application:

KrinkApp

Download the Xcode Project:

Krink

I don’t want to post all the code here since there are a few files and it would be kind of confusing – if you’d like to see all the code, download the Xcode project. I will highlight a few parts though:

Some code snippets:

Circle.h

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct Circle{
	float x;
	float y;
	float vx;
	float vy;
	float dist;
	Color *col;
	int id;
	void (*update)(struct Circle *c);
} Circle;
 
Circle makeCircle();
static void update(Circle *c);

The interesting thing here is the function pointer member of the struct. Later on in Circle.c we point all new Circle structs update member to Circle.c’s static update function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "main.h"
#include "Circle.h"
 
Circle makeCircle(){
 
	Circle c;
	c.x = rand() % width;
	c.y = rand() % height;
	c.vx = rnd() * 8 - 4;
	c.vy = rnd() * 8 - 4;
	c.dist = 10 + rnd() * 100;
	c.col = makeColor();
	c.update = update; 
	c.id = 0;
 
	return c;
}
 
static void update(Circle *c){
 
	c->x += c->vx;
	c->y += c->vy;
 
	if (c->x > width) c->vx *= -1, c->x = width;
	if (c->y > height) c->vy *= -1, c->y = height;
 
	if (c->x < 0) c->vx *= -1, c->x = 0;
	if (c->y < 0) c->vy *= -1, c->y = 0;
 
	glVertex2f(c->x , c->y);
}

Here’s a snippet from main.h:

1
2
3
4
5
6
7
8
typedef struct {
	float r;
	float g;
	float b;
	float a;
} Color;
 
extern Color *makeColor();

and then later in main.c we define makeColor():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Color *makeColor(){
	static Color colors[COLOR_NUM] =
	{{0.765, 0.902, 0.875, 0.2},
		{0.039, 0.059, 0.075, 0.2},
		{0.247, 0.251, 0.259, 0.2},
		{0.345, 0.514, 0.549, 0.2},
		{0.929, 0.878, 0.671, 0.2},
		{0.851, 0.965, 1.000, 0.2},
		{0.498, 0.247, 0.149, 0.2},
		{0.090, 0.098, 0.078, 0.2},
		{0.545, 0.584, 0.486, 0.2},
		{0.157, 0.180, 0.133, 0.2}};
 
	return &colors[rand() % COLOR_NUM];
}

For some reason I decided to encapsulate all the colors into a function that would then spit out a pointer to a random value in the static colors array – so there are only every COLOR_NUM color struct instances no matter how many particles (Circle struct instances) there are. Lots of other ways to do this same thing I guess… I got the colors from my drawings, I speed coded a little AS3 to grab a few random values from a given MovieClip and write the struct initializations. The actionscript is funny because I coded it javascript style for some reason:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var panel = addChild(new Sprite());
 
var bit = new BitmapData(sample.width, sample.height, false, 0);
 
bit.draw(sample);
 
var cols;
 
stage.addEventListener(MouseEvent.CLICK, function(){
	cols = "{";
	for (var i = 0; i<10; i++){
		var c = bit.getPixel(int(Math.random() * sample.width), 
							 int(Math.random() * sample.height));
		cols += toArray(c);
		panel.graphics.beginFill(c);
		panel.graphics.drawRect(0, i * 20, 20, 20);
	}
	cols = cols.substr(0,cols.length-2) + "};";
	trace(cols);
});
 
var alph = 0.2;
function toArray(c){
	var r = (c >> 16) & 0xFF;
	r /= 0xFF;
	var g = (c >> 8) & 0xFF;
	g /= 0xFF;
	var b = c & 0xFF;
	b /= 0xFF;
	return "{"+r.toFixed(3)+", "+g.toFixed(3)+", "+b.toFixed(3)+", " + alph + "},\n";
}

C Glut OpenGL & Xcode Project

Two people asked me about OpenGL C and Xcode this last week. So I figured I’d make a quick video to show an easy way to get up and running.

Little Mistake
Note that you should change the Active Architecture of your project to i386. I forgot to do that in the video. It will still work if you don’t do this, but you’ll get some loading errors in the console… so, make this change after you’ve watched the video:

The first 3 minutes of this video show everything you need to know, the next 7 minutes is just me sort of rambling about a few things that you may or may not need to know, so feel free to just watch the first 3 minutes and then go and code some OpenGL.


Source for template is at bottom of post.

Links:
Red Book
stdlib.h
vbl sync

Here is the source for the 2D template, once you’ve got your project set up, just copy it into main.c and compile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
 
#include <GLUT/glut.h>
#include <OpenGL/OpenGL.h>
 
int mouseX = 0;
int mouseY = 0;
int width;
int height;
 
void init(){
	glPointSize(60.0);
}
 
void render() {
	//glClear(GL_COLOR_BUFFER_BIT);	
 
	glColor4f(1, 1, 1, 0.5);
	glBegin(GL_POINTS);
	glVertex2i(mouseX, mouseY);
	glEnd();
 
	// you need this (see double buffering)
	glutSwapBuffers();
}
 
void resize(int w, int h) {
	glClear(GL_COLOR_BUFFER_BIT);
	width = w;
	height = h;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);  
	glLoadIdentity();            
	glOrtho(0, w, 0, h, -1, 1);   
	glScalef(1, -1, 1);         
	glTranslatef(0, -h, 0);
}
 
void idle() {
	glutPostRedisplay();
}
 
void mouse(int x, int y){
	mouseX = x;
	mouseY = y;
}
 
int main(int argc, char** argv){
 
	glutInit(&argc, argv);
 
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 
	width = 640;
	height = 480;
	glutInitWindowSize(width, height);
	glutCreateWindow("Template");
	//glutFullScreen();
	//glutSetCursor(GLUT_CURSOR_NONE); 
 
	glutPassiveMotionFunc(mouse);
	glutDisplayFunc(render);
	glutReshapeFunc(resize);
	glutIdleFunc(idle);
 
	glEnable(GL_BLEND);	
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_DEPTH_TEST);
 
	glEnable(GL_POINT_SMOOTH);
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
 
	// VBL synching prevent tearing
	GLint sync = 1;
	CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &sync);
 
	init();
 
	glutMainLoop();
 
	return EXIT_SUCCESS;
}