132001f49Smrg/**
232001f49Smrg * AA lines with texture mapped quads
332001f49Smrg *
432001f49Smrg * Brian Paul
532001f49Smrg * 9 Feb 2008
632001f49Smrg */
732001f49Smrg
832001f49Smrg
932001f49Smrg#include <assert.h>
1032001f49Smrg#include <string.h>
1132001f49Smrg#include <stdio.h>
1232001f49Smrg#include <stdlib.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <GL/glew.h>
1532001f49Smrg#include "glut_wrap.h"
1632001f49Smrg
1732001f49Smrg#ifndef M_PI
1832001f49Smrg#define M_PI 3.1415926535
1932001f49Smrg#endif
2032001f49Smrg
2132001f49Smrgstatic GLint WinWidth = 300, WinHeight = 300;
2232001f49Smrgstatic GLint win = 0;
2332001f49Smrgstatic GLfloat Width = 8.;
2432001f49Smrg
2532001f49Smrg/*
2632001f49Smrg * Quad strip for line from v0 to v1:
2732001f49Smrg *
2832001f49Smrg 1   3                     5   7
2932001f49Smrg +---+---------------------+---+
3032001f49Smrg |                             |
3132001f49Smrg |   *v0                 v1*   |
3232001f49Smrg |                             |
3332001f49Smrg +---+---------------------+---+
3432001f49Smrg 0   2                     4   6
3532001f49Smrg */
3632001f49Smrgstatic void
3732001f49SmrgQuadLine(const GLfloat *v0, const GLfloat *v1, GLfloat width)
3832001f49Smrg{
3932001f49Smrg   GLfloat dx = v1[0] - v0[0];
4032001f49Smrg   GLfloat dy = v1[1] - v0[1];
4132001f49Smrg   GLfloat len = sqrt(dx*dx + dy*dy);
4232001f49Smrg   float dx0, dx1, dx2, dx3, dx4, dx5, dx6, dx7;
4332001f49Smrg   float dy0, dy1, dy2, dy3, dy4, dy5, dy6, dy7;
4432001f49Smrg
4532001f49Smrg   dx /= len;
4632001f49Smrg   dy /= len;
4732001f49Smrg
4832001f49Smrg   width *= 0.5;  /* half width */
4932001f49Smrg   dx = dx * (width + 0.0);
5032001f49Smrg   dy = dy * (width + 0.0);
5132001f49Smrg
5232001f49Smrg   dx0 = -dx+dy;  dy0 = -dy-dx;
5332001f49Smrg   dx1 = -dx-dy;  dy1 = -dy+dx;
5432001f49Smrg
5532001f49Smrg   dx2 =   0+dy;  dy2 = -dx+0;
5632001f49Smrg   dx3 =   0-dy;  dy3 = +dx+0;
5732001f49Smrg
5832001f49Smrg   dx4 =   0+dy;  dy4 = -dx+0;
5932001f49Smrg   dx5 =   0-dy;  dy5 = +dx+0;
6032001f49Smrg
6132001f49Smrg   dx6 =  dx+dy;  dy6 =  dy-dx;
6232001f49Smrg   dx7 =  dx-dy;  dy7 =  dy+dx;
6332001f49Smrg
6432001f49Smrg   /*
6532001f49Smrg   printf("dx, dy = %g, %g\n", dx, dy);
6632001f49Smrg   printf("  dx0, dy0: %g, %g\n", dx0, dy0);
6732001f49Smrg   printf("  dx1, dy1: %g, %g\n", dx1, dy1);
6832001f49Smrg   printf("  dx2, dy2: %g, %g\n", dx2, dy2);
6932001f49Smrg   printf("  dx3, dy3: %g, %g\n", dx3, dy3);
7032001f49Smrg   */
7132001f49Smrg
7232001f49Smrg   glBegin(GL_QUAD_STRIP);
7332001f49Smrg   glTexCoord2f(0, 0);
7432001f49Smrg   glVertex2f(v0[0] + dx0, v0[1] + dy0);
7532001f49Smrg   glTexCoord2f(0, 1);
7632001f49Smrg   glVertex2f(v0[0] + dx1, v0[1] + dy1);
7732001f49Smrg
7832001f49Smrg   glTexCoord2f(0.5, 0);
7932001f49Smrg   glVertex2f(v0[0] + dx2, v0[1] + dy2);
8032001f49Smrg   glTexCoord2f(0.5, 1);
8132001f49Smrg   glVertex2f(v0[0] + dx3, v0[1] + dy3);
8232001f49Smrg
8332001f49Smrg   glTexCoord2f(0.5, 0);
8432001f49Smrg   glVertex2f(v1[0] + dx2, v1[1] + dy2);
8532001f49Smrg   glTexCoord2f(0.5, 1);
8632001f49Smrg   glVertex2f(v1[0] + dx3, v1[1] + dy3);
8732001f49Smrg
8832001f49Smrg   glTexCoord2f(1, 0);
8932001f49Smrg   glVertex2f(v1[0] + dx6, v1[1] + dy6);
9032001f49Smrg   glTexCoord2f(1, 1);
9132001f49Smrg   glVertex2f(v1[0] + dx7, v1[1] + dy7);
9232001f49Smrg   glEnd();
9332001f49Smrg}
9432001f49Smrg
9532001f49Smrg
9632001f49Smrgstatic float Cos(float a)
9732001f49Smrg{
9832001f49Smrg   return cos(a * M_PI / 180.);
9932001f49Smrg}
10032001f49Smrg
10132001f49Smrgstatic float Sin(float a)
10232001f49Smrg{
10332001f49Smrg   return sin(a * M_PI / 180.);
10432001f49Smrg}
10532001f49Smrg
10632001f49Smrgstatic void
10732001f49SmrgRedisplay(void)
10832001f49Smrg{
10932001f49Smrg   float cx = 0.5 * WinWidth, cy = 0.5 * WinHeight;
11032001f49Smrg   float len = 0.5 * WinWidth - 20.0;
11132001f49Smrg   int i;
11232001f49Smrg
11332001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
11432001f49Smrg
11532001f49Smrg   glColor3f(1, 1, 1);
11632001f49Smrg
11732001f49Smrg   glEnable(GL_BLEND);
11832001f49Smrg   glEnable(GL_TEXTURE_2D);
11932001f49Smrg
12032001f49Smrg   for (i = 0; i < 360; i+=5) {
12132001f49Smrg      float v0[2], v1[2];
12232001f49Smrg      v0[0] = cx + 40 * Cos(i);
12332001f49Smrg      v0[1] = cy + 40 * Sin(i);
12432001f49Smrg      v1[0] = cx + len * Cos(i);
12532001f49Smrg      v1[1] = cy + len * Sin(i);
12632001f49Smrg      QuadLine(v0, v1, Width);
12732001f49Smrg   }
12832001f49Smrg
12932001f49Smrg   {
13032001f49Smrg      float v0[2], v1[2], x;
13132001f49Smrg      for (x = 0; x < 1.0; x += 0.2) {
13232001f49Smrg         v0[0] = cx + x;
13332001f49Smrg         v0[1] = cy + x * 40 - 20;
13432001f49Smrg         v1[0] = cx + x + 5.0;
13532001f49Smrg         v1[1] = cy + x * 40 - 20;
13632001f49Smrg         QuadLine(v0, v1, Width);
13732001f49Smrg      }
13832001f49Smrg   }
13932001f49Smrg
14032001f49Smrg   glDisable(GL_BLEND);
14132001f49Smrg   glDisable(GL_TEXTURE_2D);
14232001f49Smrg
14332001f49Smrg   glutSwapBuffers();
14432001f49Smrg}
14532001f49Smrg
14632001f49Smrg
14732001f49Smrgstatic void
14832001f49SmrgReshape(int width, int height)
14932001f49Smrg{
15032001f49Smrg   WinWidth = width;
15132001f49Smrg   WinHeight = height;
15232001f49Smrg   glViewport(0, 0, width, height);
15332001f49Smrg   glMatrixMode(GL_PROJECTION);
15432001f49Smrg   glLoadIdentity();
15532001f49Smrg   glOrtho(0, width, 0, height, -1, 1);
15632001f49Smrg   glMatrixMode(GL_MODELVIEW);
15732001f49Smrg   glLoadIdentity();
15832001f49Smrg}
15932001f49Smrg
16032001f49Smrg
16132001f49Smrgstatic void
16232001f49SmrgCleanUp(void)
16332001f49Smrg{
16432001f49Smrg   glutDestroyWindow(win);
16532001f49Smrg}
16632001f49Smrg
16732001f49Smrg
16832001f49Smrgstatic void
16932001f49SmrgKey(unsigned char key, int x, int y)
17032001f49Smrg{
17132001f49Smrg  (void) x;
17232001f49Smrg  (void) y;
17332001f49Smrg
17432001f49Smrg   switch(key) {
17532001f49Smrg   case 'w':
17632001f49Smrg      Width -= 0.5;
17732001f49Smrg      break;
17832001f49Smrg   case 'W':
17932001f49Smrg      Width += 0.5;
18032001f49Smrg      break;
18132001f49Smrg   case 27:
18232001f49Smrg      CleanUp();
18332001f49Smrg      exit(0);
18432001f49Smrg      break;
18532001f49Smrg   }
18632001f49Smrg#if 0
18732001f49Smrg   if (Width < 3)
18832001f49Smrg      Width = 3;
18932001f49Smrg#endif
19032001f49Smrg   printf("Width = %g\n", Width);
19132001f49Smrg   glutPostRedisplay();
19232001f49Smrg}
19332001f49Smrg
19432001f49Smrg
19532001f49Smrgstatic float
19632001f49Smrgramp4(GLint i, GLint size)
19732001f49Smrg{
19832001f49Smrg   float d;
19932001f49Smrg   if (i < 4 ) {
20032001f49Smrg      d = i / 4.0;
20132001f49Smrg   }
20232001f49Smrg   else if (i >= size - 5) {
20332001f49Smrg      d = 1.0 - (i - (size - 5)) / 4.0;
20432001f49Smrg   }
20532001f49Smrg   else {
20632001f49Smrg      d = 1.0;
20732001f49Smrg   }
20832001f49Smrg   return d;
20932001f49Smrg}
21032001f49Smrg
21132001f49Smrgstatic float
21232001f49Smrgramp2(GLint i, GLint size)
21332001f49Smrg{
21432001f49Smrg   float d;
21532001f49Smrg   if (i < 2 ) {
21632001f49Smrg      d = i / 2.0;
21732001f49Smrg   }
21832001f49Smrg   else if (i >= size - 3) {
21932001f49Smrg      d = 1.0 - (i - (size - 3)) / 2.0;
22032001f49Smrg   }
22132001f49Smrg   else {
22232001f49Smrg      d = 1.0;
22332001f49Smrg   }
22432001f49Smrg   return d;
22532001f49Smrg}
22632001f49Smrg
22732001f49Smrgstatic float
22832001f49Smrgramp1(GLint i, GLint size)
22932001f49Smrg{
23032001f49Smrg   float d;
23132001f49Smrg   if (i == 0 || i == size-1) {
23232001f49Smrg      d = 0.0;
23332001f49Smrg   }
23432001f49Smrg   else {
23532001f49Smrg      d = 1.0;
23632001f49Smrg   }
23732001f49Smrg   return d;
23832001f49Smrg}
23932001f49Smrg
24032001f49Smrg
24132001f49Smrg/**
24232001f49Smrg * Make an alpha texture for antialiasing lines.
24332001f49Smrg * Just a linear fall-off ramp for now.
24432001f49Smrg * Should have a number of different textures for different line widths.
24532001f49Smrg * Could try a bell-like-curve....
24632001f49Smrg */
24732001f49Smrgstatic void
24832001f49SmrgMakeTexture(void)
24932001f49Smrg{
25032001f49Smrg#define SZ 8
25132001f49Smrg   GLfloat tex[SZ][SZ];  /* alpha tex */
25232001f49Smrg   int i, j;
25332001f49Smrg   for (i = 0; i < SZ; i++) {
25432001f49Smrg      for (j = 0; j < SZ; j++) {
25532001f49Smrg#if 0
25632001f49Smrg         float k = (SZ-1) / 2.0;
25732001f49Smrg         float dx = fabs(i - k) / k;
25832001f49Smrg         float dy = fabs(j - k) / k;
25932001f49Smrg         float d;
26032001f49Smrg
26132001f49Smrg         dx = 1.0 - dx;
26232001f49Smrg         dy = 1.0 - dy;
26332001f49Smrg         d = dx * dy;
26432001f49Smrg
26532001f49Smrg#else
26632001f49Smrg         float d = ramp1(i, SZ) * ramp1(j, SZ);
26732001f49Smrg         printf("%d, %d: %g\n", i, j, d);
26832001f49Smrg#endif
26932001f49Smrg         tex[i][j] = d;
27032001f49Smrg      }
27132001f49Smrg   }
27232001f49Smrg
27332001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, SZ, SZ, 0, GL_ALPHA, GL_FLOAT, tex);
27432001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
27532001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
27632001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
27732001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
27832001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
27932001f49Smrg#undef SZ
28032001f49Smrg}
28132001f49Smrg
28232001f49Smrg
28332001f49Smrgstatic void
28432001f49SmrgMakeMipmap(void)
28532001f49Smrg{
28632001f49Smrg#define SZ 64
28732001f49Smrg   GLfloat tex[SZ][SZ];  /* alpha tex */
28832001f49Smrg   int level;
28932001f49Smrg
29032001f49Smrg   glPixelStorei(GL_UNPACK_ROW_LENGTH, SZ);
29132001f49Smrg   for (level = 0; level < 7; level++) {
29232001f49Smrg      int sz = 1 << (6 - level);
29332001f49Smrg      int i, j;
29432001f49Smrg      for (i = 0; i < sz; i++) {
29532001f49Smrg         for (j = 0; j < sz; j++) {
29632001f49Smrg            if (level == 6)
29732001f49Smrg               tex[i][j] = 1.0;
29832001f49Smrg            else if (level == 5)
29932001f49Smrg               tex[i][j] = 0.5;
30032001f49Smrg            else
30132001f49Smrg               tex[i][j] = ramp1(i, sz) * ramp1(j, sz);
30232001f49Smrg         }
30332001f49Smrg      }
30432001f49Smrg
30532001f49Smrg      glTexImage2D(GL_TEXTURE_2D, level, GL_ALPHA,
30632001f49Smrg                   sz, sz, 0, GL_ALPHA, GL_FLOAT, tex);
30732001f49Smrg   }
30832001f49Smrg
30932001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
31032001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
31132001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
31232001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
31332001f49Smrg   /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); */
31432001f49Smrg   /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); */
31532001f49Smrg
31632001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
31732001f49Smrg#undef SZ
31832001f49Smrg}
31932001f49Smrg
32032001f49Smrg
32132001f49Smrgstatic void
32232001f49SmrgInit(void)
32332001f49Smrg{
32432001f49Smrg   (void) MakeTexture;
32532001f49Smrg   (void) ramp4;
32632001f49Smrg   (void) ramp2;
32732001f49Smrg
32832001f49Smrg   if (!GLEW_VERSION_2_0) {
32932001f49Smrg      printf("This program requires OpenGL 2.x\n");
33032001f49Smrg      exit(1);
33132001f49Smrg   }
33232001f49Smrg
33332001f49Smrg   glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
33432001f49Smrg
33532001f49Smrg   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
33632001f49Smrg
33732001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
33832001f49Smrg#if 0
33932001f49Smrg   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
34032001f49Smrg#elif 0
34132001f49Smrg   MakeTexture();
34232001f49Smrg#else
34332001f49Smrg   MakeMipmap();
34432001f49Smrg#endif
34532001f49Smrg}
34632001f49Smrg
34732001f49Smrg
34832001f49Smrgstatic void
34932001f49SmrgParseOptions(int argc, char *argv[])
35032001f49Smrg{
35132001f49Smrg}
35232001f49Smrg
35332001f49Smrg
35432001f49Smrgint
35532001f49Smrgmain(int argc, char *argv[])
35632001f49Smrg{
35732001f49Smrg   glutInit(&argc, argv);
35832001f49Smrg   glutInitWindowSize(WinWidth, WinHeight);
35932001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
36032001f49Smrg   win = glutCreateWindow(argv[0]);
36132001f49Smrg   glewInit();
36232001f49Smrg   glutReshapeFunc(Reshape);
36332001f49Smrg   glutKeyboardFunc(Key);
36432001f49Smrg   glutDisplayFunc(Redisplay);
36532001f49Smrg   ParseOptions(argc, argv);
36632001f49Smrg   Init();
36732001f49Smrg   glutMainLoop();
36832001f49Smrg   return 0;
36932001f49Smrg}
370