132001f49Smrg/*
232001f49Smrg * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
332001f49Smrg *
432001f49Smrg * Permission to use, copy, modify, distribute, and sell this software and
532001f49Smrg * its documentation for any purpose is hereby granted without fee, provided
632001f49Smrg * that (i) the above copyright notices and this permission notice appear in
732001f49Smrg * all copies of the software and related documentation, and (ii) the name of
832001f49Smrg * Silicon Graphics may not be used in any advertising or
932001f49Smrg * publicity relating to the software without the specific, prior written
1032001f49Smrg * permission of Silicon Graphics.
1132001f49Smrg *
1232001f49Smrg * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
1332001f49Smrg * ANY KIND,
1432001f49Smrg * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1532001f49Smrg * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1632001f49Smrg *
1732001f49Smrg * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
1832001f49Smrg * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
1932001f49Smrg * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2032001f49Smrg * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
2132001f49Smrg * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2232001f49Smrg * OF THIS SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg#include <stdio.h>
2632001f49Smrg#include <stdlib.h>
2732001f49Smrg#include <string.h>
2832001f49Smrg#include <math.h>
2932001f49Smrg#include "glut_wrap.h"
3032001f49Smrg
3132001f49Smrg
3232001f49Smrg#define STEPCOUNT 40
3332001f49Smrg#define FALSE 0
3432001f49Smrg#define TRUE 1
3532001f49Smrg#define MAX(a, b) (((a) > (b)) ? (a) : (b))
3632001f49Smrg#define MIN(a, b) (((a) < (b)) ? (a) : (b))
3732001f49Smrg
3832001f49Smrg
3932001f49Smrgenum {
4032001f49Smrg    OP_NOOP = 0,
4132001f49Smrg    OP_STRETCH,
4232001f49Smrg    OP_DRAWPOINT,
4332001f49Smrg    OP_DRAWIMAGE
4432001f49Smrg};
4532001f49Smrg
4632001f49Smrg
4732001f49Smrgtypedef struct _cRec {
4832001f49Smrg    float x, y;
4932001f49Smrg} cRec;
5032001f49Smrg
5132001f49Smrgtypedef struct _vertexRec {
5232001f49Smrg    float x, y;
5332001f49Smrg    float dX, dY;
5432001f49Smrg    float tX, tY;
5532001f49Smrg} vertexRec;
5632001f49Smrg
5732001f49Smrg
5832001f49Smrg#include "loadppm.c"
5932001f49Smrg
6032001f49SmrgGLenum doubleBuffer;
6132001f49Smrgint imageSizeX, imageSizeY;
6232001f49Smrgchar *fileName = 0;
6332001f49SmrgPPMImage *image;
6432001f49SmrgcRec cList[50];
6532001f49SmrgvertexRec vList[5];
6632001f49Smrgint cCount, cIndex[2], cStep;
6732001f49SmrgGLenum op = OP_NOOP;
6832001f49Smrg
6932001f49Smrg
7032001f49Smrgstatic void DrawImage(void)
7132001f49Smrg{
7232001f49Smrg
7332001f49Smrg    glRasterPos2i(0, 0);
7432001f49Smrg    glDrawPixels(image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
7532001f49Smrg		 image->data);
7632001f49Smrg
7732001f49Smrg    glFlush();
7832001f49Smrg    if (doubleBuffer) {
7932001f49Smrg	glutSwapBuffers();
8032001f49Smrg    }
8132001f49Smrg
8232001f49Smrg    glRasterPos2i(0, 0);
8332001f49Smrg    glDrawPixels(image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
8432001f49Smrg		 image->data);
8532001f49Smrg}
8632001f49Smrg
8732001f49Smrgstatic void DrawPoint(void)
8832001f49Smrg{
8932001f49Smrg    int i;
9032001f49Smrg
9132001f49Smrg    glColor3f(1.0, 0.0, 1.0);
9232001f49Smrg    glPointSize(3.0);
9332001f49Smrg    glBegin(GL_POINTS);
9432001f49Smrg	for (i = 0; i < cCount; i++) {
9532001f49Smrg	    glVertex2f(cList[i].x, cList[i].y);
9632001f49Smrg	}
9732001f49Smrg    glEnd();
9832001f49Smrg
9932001f49Smrg    glFlush();
10032001f49Smrg    if (doubleBuffer) {
10132001f49Smrg	glutSwapBuffers();
10232001f49Smrg    }
10332001f49Smrg}
10432001f49Smrg
10532001f49Smrgstatic void InitVList(void)
10632001f49Smrg{
10732001f49Smrg
10832001f49Smrg    vList[0].x = 0.0;
10932001f49Smrg    vList[0].y = 0.0;
11032001f49Smrg    vList[0].dX = 0.0;
11132001f49Smrg    vList[0].dY = 0.0;
11232001f49Smrg    vList[0].tX = 0.0;
11332001f49Smrg    vList[0].tY = 0.0;
11432001f49Smrg
11532001f49Smrg    vList[1].x = (float)imageSizeX;
11632001f49Smrg    vList[1].y = 0.0;
11732001f49Smrg    vList[1].dX = 0.0;
11832001f49Smrg    vList[1].dY = 0.0;
11932001f49Smrg    vList[1].tX = 1.0;
12032001f49Smrg    vList[1].tY = 0.0;
12132001f49Smrg
12232001f49Smrg    vList[2].x = (float)imageSizeX;
12332001f49Smrg    vList[2].y = (float)imageSizeY;
12432001f49Smrg    vList[2].dX = 0.0;
12532001f49Smrg    vList[2].dY = 0.0;
12632001f49Smrg    vList[2].tX = 1.0;
12732001f49Smrg    vList[2].tY = 1.0;
12832001f49Smrg
12932001f49Smrg    vList[3].x = 0.0;
13032001f49Smrg    vList[3].y = (float)imageSizeY;
13132001f49Smrg    vList[3].dX = 0.0;
13232001f49Smrg    vList[3].dY = 0.0;
13332001f49Smrg    vList[3].tX = 0.0;
13432001f49Smrg    vList[3].tY = 1.0;
13532001f49Smrg
13632001f49Smrg    vList[4].x = cList[0].x;
13732001f49Smrg    vList[4].y = cList[0].y;
13832001f49Smrg    vList[4].dX = (cList[1].x - cList[0].x) / STEPCOUNT;
13932001f49Smrg    vList[4].dY = (cList[1].y - cList[0].y) / STEPCOUNT;
14032001f49Smrg    vList[4].tX = cList[0].x / (float)imageSizeX;
14132001f49Smrg    vList[4].tY = cList[0].y / (float)imageSizeY;
14232001f49Smrg}
14332001f49Smrg
14432001f49Smrgstatic void ScaleImage(int sizeX, int sizeY)
14532001f49Smrg{
14632001f49Smrg    GLubyte *buf;
14732001f49Smrg
14832001f49Smrg    buf = (GLubyte *)malloc(3*sizeX*sizeY);
14932001f49Smrg    gluScaleImage(GL_RGB, image->sizeX, image->sizeY, GL_UNSIGNED_BYTE,
15032001f49Smrg                  image->data, sizeX, sizeY, GL_UNSIGNED_BYTE, buf);
15132001f49Smrg    free(image->data);
15232001f49Smrg    image->data = buf;
15332001f49Smrg    image->sizeX = sizeX;
15432001f49Smrg    image->sizeY = sizeY;
15532001f49Smrg}
15632001f49Smrg
15732001f49Smrgstatic void SetPoint(int x, int y)
15832001f49Smrg{
15932001f49Smrg
16032001f49Smrg    cList[cCount].x = (float)x;
16132001f49Smrg    cList[cCount].y = (float)y;
16232001f49Smrg    cCount++;
16332001f49Smrg}
16432001f49Smrg
16532001f49Smrgstatic void Stretch(void)
16632001f49Smrg{
16732001f49Smrg
16832001f49Smrg    glBegin(GL_TRIANGLES);
16932001f49Smrg	glTexCoord2f(vList[0].tX, vList[0].tY);
17032001f49Smrg	glVertex2f(vList[0].x, vList[0].y);
17132001f49Smrg	glTexCoord2f(vList[1].tX, vList[1].tY);
17232001f49Smrg	glVertex2f(vList[1].x, vList[1].y);
17332001f49Smrg	glTexCoord2f(vList[4].tX, vList[4].tY);
17432001f49Smrg	glVertex2f(vList[4].x, vList[4].y);
17532001f49Smrg    glEnd();
17632001f49Smrg
17732001f49Smrg    glBegin(GL_TRIANGLES);
17832001f49Smrg	glTexCoord2f(vList[1].tX, vList[1].tY);
17932001f49Smrg	glVertex2f(vList[1].x, vList[1].y);
18032001f49Smrg	glTexCoord2f(vList[2].tX, vList[2].tY);
18132001f49Smrg	glVertex2f(vList[2].x, vList[2].y);
18232001f49Smrg	glTexCoord2f(vList[4].tX, vList[4].tY);
18332001f49Smrg	glVertex2f(vList[4].x, vList[4].y);
18432001f49Smrg    glEnd();
18532001f49Smrg
18632001f49Smrg    glBegin(GL_TRIANGLES);
18732001f49Smrg	glTexCoord2f(vList[2].tX, vList[2].tY);
18832001f49Smrg	glVertex2f(vList[2].x, vList[2].y);
18932001f49Smrg	glTexCoord2f(vList[3].tX, vList[3].tY);
19032001f49Smrg	glVertex2f(vList[3].x, vList[3].y);
19132001f49Smrg	glTexCoord2f(vList[4].tX, vList[4].tY);
19232001f49Smrg	glVertex2f(vList[4].x, vList[4].y);
19332001f49Smrg    glEnd();
19432001f49Smrg
19532001f49Smrg    glBegin(GL_TRIANGLES);
19632001f49Smrg	glTexCoord2f(vList[3].tX, vList[3].tY);
19732001f49Smrg	glVertex2f(vList[3].x, vList[3].y);
19832001f49Smrg	glTexCoord2f(vList[0].tX, vList[0].tY);
19932001f49Smrg	glVertex2f(vList[0].x, vList[0].y);
20032001f49Smrg	glTexCoord2f(vList[4].tX, vList[4].tY);
20132001f49Smrg	glVertex2f(vList[4].x, vList[4].y);
20232001f49Smrg    glEnd();
20332001f49Smrg
20432001f49Smrg    glFlush();
20532001f49Smrg    if (doubleBuffer) {
20632001f49Smrg	glutSwapBuffers();
20732001f49Smrg    }
20832001f49Smrg
20932001f49Smrg    if (++cStep < STEPCOUNT) {
21032001f49Smrg	vList[4].x += vList[4].dX;
21132001f49Smrg	vList[4].y += vList[4].dY;
21232001f49Smrg    } else {
21332001f49Smrg	cIndex[0] = cIndex[1];
21432001f49Smrg	cIndex[1] = cIndex[1] + 1;
21532001f49Smrg	if (cIndex[1] == cCount) {
21632001f49Smrg	    cIndex[1] = 0;
21732001f49Smrg	}
21832001f49Smrg	vList[4].dX = (cList[cIndex[1]].x - cList[cIndex[0]].x) / STEPCOUNT;
21932001f49Smrg	vList[4].dY = (cList[cIndex[1]].y - cList[cIndex[0]].y) / STEPCOUNT;
22032001f49Smrg	cStep = 0;
22132001f49Smrg    }
22232001f49Smrg}
22332001f49Smrg
22432001f49Smrgstatic void Key(unsigned char key, int x, int y)
22532001f49Smrg{
22632001f49Smrg
22732001f49Smrg    switch (key) {
22832001f49Smrg      case 27:
22932001f49Smrg	free(image->data);
23032001f49Smrg        exit(1);
23132001f49Smrg      case 32:
23232001f49Smrg	if (cCount > 1) {
23332001f49Smrg	    InitVList();
23432001f49Smrg	    cIndex[0] = 0;
23532001f49Smrg	    cIndex[1] = 1;
23632001f49Smrg	    cStep = 0;
23732001f49Smrg	    glEnable(GL_TEXTURE_2D);
23832001f49Smrg	    op = OP_STRETCH;
23932001f49Smrg	}
24032001f49Smrg	break;
24132001f49Smrg      default:
24232001f49Smrg	return;
24332001f49Smrg    }
24432001f49Smrg
24532001f49Smrg    glutPostRedisplay();
24632001f49Smrg}
24732001f49Smrg
24832001f49Smrgstatic void Mouse(int button, int state, int mouseX, int mouseY)
24932001f49Smrg{
25032001f49Smrg
25132001f49Smrg    if (state != GLUT_DOWN)
25232001f49Smrg	return;
25332001f49Smrg
25432001f49Smrg    if (op == OP_STRETCH) {
25532001f49Smrg	glDisable(GL_TEXTURE_2D);
25632001f49Smrg	cCount = 0;
25732001f49Smrg	op = OP_DRAWIMAGE;
25832001f49Smrg    } else {
25932001f49Smrg	SetPoint(mouseX, imageSizeY-mouseY);
26032001f49Smrg	op = OP_DRAWPOINT;
26132001f49Smrg    }
26232001f49Smrg
26332001f49Smrg    glutPostRedisplay();
26432001f49Smrg}
26532001f49Smrg
26632001f49Smrgstatic void Animate(void)
26732001f49Smrg{
26832001f49Smrg    static double t0 = -1.;
26932001f49Smrg    double t, dt;
27032001f49Smrg    t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
27132001f49Smrg    if (t0 < 0.)
27232001f49Smrg       t0 = t;
27332001f49Smrg    dt = t - t0;
27432001f49Smrg
27532001f49Smrg    if (dt < 1./60.)
27632001f49Smrg        return;
27732001f49Smrg
27832001f49Smrg    t0 = t;
27932001f49Smrg
28032001f49Smrg    switch (op) {
28132001f49Smrg      case OP_STRETCH:
28232001f49Smrg	Stretch();
28332001f49Smrg	break;
28432001f49Smrg      case OP_DRAWPOINT:
28532001f49Smrg	DrawPoint();
28632001f49Smrg	break;
28732001f49Smrg      case OP_DRAWIMAGE:
28832001f49Smrg	DrawImage();
28932001f49Smrg	break;
29032001f49Smrg      default:
29132001f49Smrg        break;
29232001f49Smrg    }
29332001f49Smrg}
29432001f49Smrg
29532001f49Smrgstatic GLenum Args(int argc, char **argv)
29632001f49Smrg{
29732001f49Smrg    GLint i;
29832001f49Smrg
29932001f49Smrg    doubleBuffer = GL_TRUE;
30032001f49Smrg
30132001f49Smrg    for (i = 1; i < argc; i++) {
30232001f49Smrg	if (strcmp(argv[i], "-sb") == 0) {
30332001f49Smrg	    doubleBuffer = GL_FALSE;
30432001f49Smrg	} else if (strcmp(argv[i], "-db") == 0) {
30532001f49Smrg	    doubleBuffer = GL_TRUE;
30632001f49Smrg	} else if (strcmp(argv[i], "-f") == 0) {
30732001f49Smrg	    if (i+1 >= argc || argv[i+1][0] == '-') {
30832001f49Smrg		printf("-f (No file name).\n");
30932001f49Smrg		return GL_FALSE;
31032001f49Smrg	    } else {
31132001f49Smrg		fileName = argv[++i];
31232001f49Smrg	    }
31332001f49Smrg	} else {
31432001f49Smrg	    printf("%s (Bad option).\n", argv[i]);
31532001f49Smrg	    return GL_FALSE;
31632001f49Smrg	}
31732001f49Smrg    }
31832001f49Smrg    return GL_TRUE;
31932001f49Smrg}
32032001f49Smrg
32132001f49Smrg#if !defined(GLUTCALLBACK)
32232001f49Smrg#define GLUTCALLBACK
32332001f49Smrg#endif
32432001f49Smrg
32532001f49Smrgstatic void GLUTCALLBACK glut_post_redisplay_p(void)
32632001f49Smrg{
32732001f49Smrg      glutPostRedisplay();
32832001f49Smrg}
32932001f49Smrg
33032001f49Smrgint main(int argc, char **argv)
33132001f49Smrg{
33232001f49Smrg    GLenum type;
33332001f49Smrg
33432001f49Smrg    glutInit(&argc, argv);
33532001f49Smrg
33632001f49Smrg    if (Args(argc, argv) == GL_FALSE) {
33732001f49Smrg	exit(1);
33832001f49Smrg    }
33932001f49Smrg
34032001f49Smrg    if (fileName == 0) {
34132001f49Smrg	printf("No image file.\n");
34232001f49Smrg	exit(1);
34332001f49Smrg    }
34432001f49Smrg
34532001f49Smrg    image = LoadPPM(fileName);
34632001f49Smrg
34732001f49Smrg    /* changed powf and logf to pow and log -Brian */
34832001f49Smrg    imageSizeX = (int)pow(2.0, (float)((int)(log(image->sizeX)/log(2.0))));
34932001f49Smrg    imageSizeY = (int)pow(2.0, (float)((int)(log(image->sizeY)/log(2.0))));
35032001f49Smrg
35132001f49Smrg    glutInitWindowPosition(0, 0); glutInitWindowSize( imageSizeX, imageSizeY);
35232001f49Smrg
35332001f49Smrg    type = GLUT_RGB;
35432001f49Smrg    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
35532001f49Smrg    glutInitDisplayMode(type);
35632001f49Smrg
35732001f49Smrg    if (glutCreateWindow("Stretch") == GL_FALSE) {
35832001f49Smrg        exit(1);
35932001f49Smrg    }
36032001f49Smrg
36132001f49Smrg    glViewport(0, 0, imageSizeX, imageSizeY);
36232001f49Smrg    gluOrtho2D(0, imageSizeX, 0, imageSizeY);
36332001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
36432001f49Smrg
36532001f49Smrg    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
36632001f49Smrg    glPixelStorei(GL_PACK_ALIGNMENT, 1);
36732001f49Smrg
36832001f49Smrg    ScaleImage(imageSizeX, imageSizeY);
36932001f49Smrg
37032001f49Smrg    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
37132001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
37232001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
37332001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
37432001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
37532001f49Smrg    glTexImage2D(GL_TEXTURE_2D, 0, 3, image->sizeX, image->sizeY, 0,
37632001f49Smrg                 GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)image->data);
37732001f49Smrg
37832001f49Smrg    cCount = 0;
37932001f49Smrg    cIndex[0] = 0;
38032001f49Smrg    cIndex[1] = 0;
38132001f49Smrg    cStep = 0;
38232001f49Smrg    op = OP_DRAWIMAGE;
38332001f49Smrg
38432001f49Smrg    glutKeyboardFunc(Key);
38532001f49Smrg    glutMouseFunc(Mouse);
38632001f49Smrg    glutDisplayFunc(Animate);
38732001f49Smrg    glutIdleFunc(glut_post_redisplay_p);
38832001f49Smrg    glutMainLoop();
38932001f49Smrg	return 0;
39032001f49Smrg}
391