glpuzzle.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,489 行 · 第 1/3 页
CXX
1,489 行
/*
** Ok, no problem. ** Now we solve for x and y. We know
that w = c + d z, so we compute it. */
w = c + d * z;
/*
** Now for x and y: */
*selx = (in[0] * finalMatrix[0 * 4 + 0] +
in[1] * finalMatrix[1 * 4 + 0] +
z * finalMatrix[2 * 4 + 0] +
finalMatrix[3 * 4 + 0]) / w - OFFSETX;
*sely = (in[0] * finalMatrix[0 * 4 + 1] +
in[1] * finalMatrix[1 * 4 + 1] +
z * finalMatrix[2 * 4 + 1] +
finalMatrix[3 * 4 + 1]) / w - OFFSETY;
return 1;
}
static int selected;
static int selectx, selecty;
static float selstartx, selstarty;
void
grabPiece(int piece, float selx, float sely)
{
int hit;
selectx = int(selx);
selecty = int(sely);
if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) {
return;
}
hit = thePuzzle[selecty][selectx];
if (hit != piece)
return;
if (hit) {
movingPiece = hit;
while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) {
selectx--;
}
while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) {
selecty--;
}
move_x = selectx;
move_y = selecty;
selected = 1;
selstartx = selx;
selstarty = sely;
} else {
selected = 0;
}
changeState();
}
void
moveSelection(float selx, float sely)
{
float deltax, deltay;
int dir;
Config newpieces;
if (!selected)
return;
deltax = selx - selstartx;
deltay = sely - selstarty;
if (fabs(deltax) > fabs(deltay)) {
deltay = 0;
if (deltax > 0) {
if (deltax > 1)
deltax = 1;
dir = 2;
} else {
if (deltax < -1)
deltax = -1;
dir = 0;
}
} else {
deltax = 0;
if (deltay > 0) {
if (deltay > 1)
deltay = 1;
dir = 3;
} else {
if (deltay < -1)
deltay = -1;
dir = 1;
}
}
if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) {
move_x = deltax + selectx;
move_y = deltay + selecty;
if (deltax > 0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selectx++;
selstartx++;
} else if (deltax < -0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selectx--;
selstartx--;
} else if (deltay > 0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selecty++;
selstarty++;
} else if (deltay < -0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selecty--;
selstarty--;
}
} else {
if (deltay > 0 && thePuzzle[selecty][selectx] == 10 &&
selectx == 1 && selecty == 3) {
/* Allow visual movement of solution piece outside of the
box */
move_x = selectx;
move_y = sely - selstarty + selecty;
} else {
move_x = selectx;
move_y = selecty;
}
}
}
void
dropSelection(void)
{
if (!selected)
return;
movingPiece = 0;
selected = 0;
changeState();
}
static int left_mouse, middle_mouse;
static int mousex, mousey;
static int solving;
static int spinning;
static float lastquat[4];
static int sel_piece;
static void
Reshape(int width, int height)
{
W = width;
H = height;
glViewport(0, 0, W, H);
glGetIntegerv(GL_VIEWPORT, viewport);
}
void
toggleSolve(void)
{
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
} else {
glutChangeToMenuEntry(1, "Stop solving", 1);
glutSetWindowTitle("Solving...");
if (solvePuzzle()) {
solving = 1;
}
}
changeState();
glutPostRedisplay();
}
void reset(void)
{
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
changeState();
}
memcpy(thePuzzle, startConfig, HEIGHT * WIDTH);
glutPostRedisplay();
}
void
keyboard(unsigned char c, int x, int y)
{
int piece;
switch (c) {
case 27:
exit(0);
break;
case 'D':
case 'd':
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
changeState();
}
piece = selectPiece(x, y);
if (piece) {
nukePiece(piece);
}
glutPostRedisplay();
break;
case 'R':
case 'r':
reset();
break;
case 'S':
case 's':
toggleSolve();
break;
case 'b':
case 'B':
depth = 1 - depth;
if (depth) {
glEnable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
glutPostRedisplay();
break;
default:
break;
}
}
void
motion(int x, int y)
{
float selx, sely;
if (middle_mouse && !left_mouse) {
if (mousex != x || mousey != y) {
trackball(lastquat,
(2.0*mousex - W) / W,
(H - 2.0*mousey) / H,
(2.0*x - W) / W,
(H - 2.0*y) / H);
spinning = 1;
} else {
spinning = 0;
}
changeState();
} else {
computeCoords(sel_piece, x, y, &selx, &sely);
moveSelection(selx, sely);
}
mousex = x;
mousey = y;
glutPostRedisplay();
}
void
mouse(int b, int s, int x, int y)
{
float selx, sely;
mousex = x;
mousey = y;
curX = x;
curY = y;
if (s == GLUT_DOWN) {
switch (b) {
case GLUT_LEFT_BUTTON:
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
}
left_mouse = GL_TRUE;
sel_piece = selectPiece(mousex, mousey);
if (!sel_piece) {
left_mouse = GL_FALSE;
middle_mouse = GL_TRUE; // let it rotate object
} else if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) {
grabPiece(sel_piece, selx, sely);
}
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
middle_mouse = GL_TRUE;
glutPostRedisplay();
break;
}
} else {
if (left_mouse) {
left_mouse = GL_FALSE;
dropSelection();
glutPostRedisplay();
} else if (middle_mouse) {
middle_mouse = GL_FALSE;
glutPostRedisplay();
}
}
motion(x, y);
}
void
animate(void)
{
if (spinning) {
add_quats(lastquat, curquat, curquat);
}
glutPostRedisplay();
if (solving) {
if (!continueSolving()) {
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
}
}
if (!solving && !spinning && !visible) {
glutIdleFunc(NULL);
}
}
void
changeState(void)
{
if (visible) {
if (!solving && !spinning) {
glutIdleFunc(NULL);
} else {
glutIdleFunc(animate);
}
} else {
glutIdleFunc(NULL);
}
}
void
init(void)
{
static float lmodel_ambient[] =
{0.0, 0.0, 0.0, 0.0};
static float lmodel_twoside[] =
{GL_FALSE};
static float lmodel_local[] =
{GL_FALSE};
static float light0_ambient[] =
{0.1, 0.1, 0.1, 1.0};
static float light0_diffuse[] =
{1.0, 1.0, 1.0, 0.0};
static float light0_position[] =
{0.8660254, 0.5, 1, 0};
static float light0_specular[] =
{0.0, 0.0, 0.0, 0.0};
static float bevel_mat_ambient[] =
{0.0, 0.0, 0.0, 1.0};
static float bevel_mat_shininess[] =
{40.0};
static float bevel_mat_specular[] =
{0.0, 0.0, 0.0, 0.0};
static float bevel_mat_diffuse[] =
{1.0, 0.0, 0.0, 0.0};
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glClearColor(0.5, 0.5, 0.5, 0.0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
trackball(curquat, 0.0, 0.0, 0.0, 0.0);
srandom(time(NULL));
}
static void
Usage(void)
{
printf("Usage: puzzle [-s]\n");
printf(" -s: Run in single buffered mode\n");
exit(-1);
}
void
visibility(int v)
{
if (v == GLUT_VISIBLE) {
visible = 1;
} else {
visible = 0;
}
changeState();
}
void
menu(int choice)
{
switch(choice) {
case 1:
toggleSolve();
break;
case 2:
reset();
break;
case 3:
exit(0);
break;
}
}
int
main(int argc, char **argv)
{
long i;
glutInit(&argc, argv);
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 's':
doubleBuffer = 0;
break;
default:
Usage();
}
} else {
Usage();
}
}
glutInitWindowSize(W, H);
if (doubleBuffer) {
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
} else {
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE);
}
glutCreateWindow("glpuzzle");
visible = 1; // added for fltk, bug in original program?
init();
glGetIntegerv(GL_VIEWPORT, viewport);
printf("\n");
printf("r Reset puzzle\n");
printf("s Solve puzzle (may take a few seconds to compute)\n");
printf("d Destroy a piece - makes the puzzle easier\n");
printf("b Toggles the depth buffer on and off\n");
printf("\n");
printf("Left mouse moves pieces\n");
printf("Middle mouse spins the puzzle\n");
printf("Right mouse has menu\n");
glutReshapeFunc(Reshape);
glutDisplayFunc(redraw);
glutKeyboardFunc(keyboard);
glutMotionFunc(motion);
glutMouseFunc(mouse);
glutVisibilityFunc(visibility);
glutCreateMenu(menu);
glutAddMenuEntry("Solve", 1);
glutAddMenuEntry("Reset", 2);
glutAddMenuEntry("Quit", 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
#endif // added for fltk's distribution
//
// End of "$Id: glpuzzle.cxx,v 1.1.1.1 2003/06/03 22:25:48 agno Exp $".
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?