246 lines
4.3 KiB
C
246 lines
4.3 KiB
C
/**
|
|
* Test rubber-band selection box w/ logicops and blend.
|
|
*/
|
|
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <GL/glut.h>
|
|
#include "readtex.c"
|
|
|
|
#define IMAGE_FILE "../images/arch.rgb"
|
|
|
|
static int ImgWidth, ImgHeight;
|
|
static GLenum ImgFormat;
|
|
static GLubyte *Image = NULL;
|
|
|
|
static int Win;
|
|
static int Width = 512, Height = 512;
|
|
|
|
struct rect
|
|
{
|
|
int x0, y0, x1, y1;
|
|
};
|
|
|
|
static struct rect OldRect, NewRect;
|
|
|
|
static GLboolean ButtonDown = GL_FALSE;
|
|
static GLboolean LogicOp = 0*GL_TRUE;
|
|
|
|
static GLboolean RedrawBackground = GL_TRUE;
|
|
|
|
static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0};
|
|
static const GLfloat green[4] = {0.2, 1.0, 0.2, 1.0};
|
|
static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
|
|
|
|
|
|
/*
|
|
* Draw rubberband box in front buffer
|
|
*/
|
|
static void
|
|
DrawRect(const struct rect *r)
|
|
{
|
|
glDrawBuffer(GL_FRONT);
|
|
|
|
if (LogicOp) {
|
|
glLogicOp(GL_XOR);
|
|
glEnable(GL_COLOR_LOGIC_OP);
|
|
}
|
|
else {
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_ONE, GL_ONE);
|
|
glBlendEquation(GL_FUNC_SUBTRACT);
|
|
}
|
|
|
|
glColor3f(1, 1, 1);
|
|
|
|
glLineWidth(3.0);
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
glVertex2i(r->x0, r->y0);
|
|
glVertex2i(r->x1, r->y0);
|
|
glVertex2i(r->x1, r->y1);
|
|
glVertex2i(r->x0, r->y1);
|
|
glEnd();
|
|
|
|
glDisable(GL_COLOR_LOGIC_OP);
|
|
glDisable(GL_BLEND);
|
|
|
|
glDrawBuffer(GL_BACK);
|
|
}
|
|
|
|
|
|
static void
|
|
PrintString(const char *s)
|
|
{
|
|
while (*s) {
|
|
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
|
|
s++;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
DrawBackground(void)
|
|
{
|
|
char s[100];
|
|
|
|
sprintf(s, "[L/B] %s mode. Use mouse to make selection box.",
|
|
LogicOp ? "LogicOp" : "Blend");
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2);
|
|
glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
|
|
|
|
glWindowPos2i(10, 10);
|
|
PrintString(s);
|
|
|
|
glutSwapBuffers();
|
|
}
|
|
|
|
|
|
static void
|
|
Draw(void)
|
|
{
|
|
if (RedrawBackground) {
|
|
DrawBackground();
|
|
}
|
|
|
|
if (ButtonDown) {
|
|
if (!RedrawBackground)
|
|
DrawRect(&OldRect); /* erase old */
|
|
|
|
DrawRect(&NewRect); /* draw new */
|
|
|
|
OldRect = NewRect;
|
|
}
|
|
|
|
RedrawBackground = GL_FALSE;
|
|
}
|
|
|
|
|
|
static void
|
|
Reshape(int width, int height)
|
|
{
|
|
Width = width;
|
|
Height = height;
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glOrtho(0, Width, Height, 0, -1, 1); /* Inverted Y! */
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
RedrawBackground = GL_TRUE;
|
|
}
|
|
|
|
|
|
static void
|
|
Key(unsigned char key, int x, int y)
|
|
{
|
|
(void) x;
|
|
(void) y;
|
|
switch (key) {
|
|
case 'b':
|
|
case 'B':
|
|
LogicOp = GL_FALSE;
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
LogicOp = GL_TRUE;
|
|
break;
|
|
case 27:
|
|
glutDestroyWindow(Win);
|
|
exit(0);
|
|
break;
|
|
}
|
|
RedrawBackground = GL_TRUE;
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
|
|
static void
|
|
SpecialKey(int key, int x, int y)
|
|
{
|
|
(void) x;
|
|
(void) y;
|
|
switch (key) {
|
|
case GLUT_KEY_UP:
|
|
break;
|
|
case GLUT_KEY_DOWN:
|
|
break;
|
|
case GLUT_KEY_LEFT:
|
|
break;
|
|
case GLUT_KEY_RIGHT:
|
|
break;
|
|
}
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
|
|
static void
|
|
MouseMotion(int x, int y)
|
|
{
|
|
if (ButtonDown) {
|
|
NewRect.x1 = x;
|
|
NewRect.y1 = y;
|
|
glutPostRedisplay();
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
MouseButton(int button, int state, int x, int y)
|
|
{
|
|
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
|
|
ButtonDown = GL_TRUE;
|
|
RedrawBackground = GL_TRUE;
|
|
NewRect.x0 = NewRect.x1 = x;
|
|
NewRect.y0 = NewRect.y1 = y;
|
|
OldRect = NewRect;
|
|
}
|
|
else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
|
|
ButtonDown = GL_FALSE;
|
|
}
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
|
|
static void
|
|
Init(void)
|
|
{
|
|
Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat);
|
|
if (!Image) {
|
|
printf("Couldn't read %s\n", IMAGE_FILE);
|
|
exit(0);
|
|
}
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
glutInit(&argc, argv);
|
|
glutInitWindowSize(Width, Height);
|
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
|
Win = glutCreateWindow(argv[0]);
|
|
glutReshapeFunc(Reshape);
|
|
glutKeyboardFunc(Key);
|
|
glutSpecialFunc(SpecialKey);
|
|
glutMotionFunc(MouseMotion);
|
|
glutMouseFunc(MouseButton);
|
|
glutDisplayFunc(Draw);
|
|
Init();
|
|
glutPostRedisplay();
|
|
glutMainLoop();
|
|
return 0;
|
|
}
|