📄 glpuzzle.c
字号:
closest = 0;
dist = 4294967295;
while (hits) {
if (selectBuf[(hits - 1) * 4 + 1] < dist) {
dist = selectBuf[(hits - 1) * 4 + 1];
closest = selectBuf[(hits - 1) * 4 + 3];
}
hits--;
}
return closest;
}
void nukePiece(int piece)
{
int i, j;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
if (thePuzzle[i][j] == piece) {
thePuzzle[i][j] = 0;
}
}
}
}
void multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16])
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
r[i * 4 + j] =
a[i * 4 + 0] * b[0 * 4 + j] +
a[i * 4 + 1] * b[1 * 4 + j] +
a[i * 4 + 2] * b[2 * 4 + j] +
a[i * 4 + 3] * b[3 * 4 + j];
}
}
}
void makeIdentity(GLfloat m[16])
{
m[0 + 4 * 0] = 1;
m[0 + 4 * 1] = 0;
m[0 + 4 * 2] = 0;
m[0 + 4 * 3] = 0;
m[1 + 4 * 0] = 0;
m[1 + 4 * 1] = 1;
m[1 + 4 * 2] = 0;
m[1 + 4 * 3] = 0;
m[2 + 4 * 0] = 0;
m[2 + 4 * 1] = 0;
m[2 + 4 * 2] = 1;
m[2 + 4 * 3] = 0;
m[3 + 4 * 0] = 0;
m[3 + 4 * 1] = 0;
m[3 + 4 * 2] = 0;
m[3 + 4 * 3] = 1;
}
/*
** inverse = invert(src)
*/
int invertMatrix(const GLfloat src[16], GLfloat inverse[16])
{
int i, j, k, swap;
double t;
GLfloat temp[4][4];
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
temp[i][j] = src[i * 4 + j];
}
}
makeIdentity(inverse);
for (i = 0; i < 4; i++) {
/*
** Look for largest element in column */
swap = i;
for (j = i + 1; j < 4; j++) {
if (fabs(temp[j][i]) > fabs(temp[i][i])) {
swap = j;
}
}
if (swap != i) {
/*
** Swap rows. */
for (k = 0; k < 4; k++) {
t = temp[i][k];
temp[i][k] = temp[swap][k];
temp[swap][k] = t;
t = inverse[i * 4 + k];
inverse[i * 4 + k] = inverse[swap * 4 + k];
inverse[swap * 4 + k] = t;
}
}
if (temp[i][i] == 0) {
/*
** No non-zero pivot. The matrix is singular, which
shouldn't ** happen. This means the user gave us a
bad matrix. */
return 0;
}
t = temp[i][i];
for (k = 0; k < 4; k++) {
temp[i][k] /= t;
inverse[i * 4 + k] /= t;
}
for (j = 0; j < 4; j++) {
if (j != i) {
t = temp[j][i];
for (k = 0; k < 4; k++) {
temp[j][k] -= temp[i][k] * t;
inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
}
}
}
}
return 1;
}
/*
** This is a screwball function. What it does is the following:
** Given screen x and y coordinates, compute the corresponding object space
** x and y coordinates given that the object space z is 0.9 + OFFSETZ.
** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that
** number.
*/
int computeCoords(int piece, int mousex, int mousey,
GLfloat * selx, GLfloat * sely)
{
GLfloat modelMatrix[16];
GLfloat projMatrix[16];
GLfloat finalMatrix[16];
GLfloat in[4];
GLfloat a, b, c, d;
GLfloat top, bot;
GLfloat z;
GLfloat w;
GLfloat height;
if (piece == 0)
return 0;
height = zsize[piece] - 0.1 + OFFSETZ;
glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
multMatrices(modelMatrix, projMatrix, finalMatrix);
if (!invertMatrix(finalMatrix, finalMatrix))
return 0;
in[0] = (2.0 * (mousex - viewport[0]) / viewport[2]) - 1;
in[1] = (2.0 * ((H - mousey) - viewport[1]) / viewport[3]) - 1;
a = in[0] * finalMatrix[0 * 4 + 2] +
in[1] * finalMatrix[1 * 4 + 2] +
finalMatrix[3 * 4 + 2];
b = finalMatrix[2 * 4 + 2];
c = in[0] * finalMatrix[0 * 4 + 3] +
in[1] * finalMatrix[1 * 4 + 3] +
finalMatrix[3 * 4 + 3];
d = finalMatrix[2 * 4 + 3];
top = height * c - a;
bot = b - height * d;
if (bot == 0.0)
return 0;
z = top / bot;
w = c + d * z;
*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 = selx;
selecty = 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;
}
}
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;
}
static int solving;
static float lastquat[4];
static int sel_piece;
static void CALLBACK Reshape(int width, int height)
{
W = width;
H = height;
glViewport(0, 0, W, H);
glGetIntegerv(GL_VIEWPORT, viewport);
}
void CALLBACK mousedown(AUX_EVENTREC *event)
{
float selx, sely;
int x, y;
x = event->data[AUX_MOUSEX];
y = event->data[AUX_MOUSEY];
curX = x;
curY = y;
if (solving) {
solving = 0;
movingPiece = 0;
}
sel_piece = selectPiece(x, y);
if (computeCoords(sel_piece, x, y, &selx, &sely)) {
grabPiece(sel_piece, selx, sely);
}
}
void CALLBACK mouseup(AUX_EVENTREC *event)
{
int x, y;
float selx, sely;
x = event->data[AUX_MOUSEX];
y = event->data[AUX_MOUSEY];
computeCoords(sel_piece, x, y, &selx, &sely);
moveSelection(selx, sely);
dropSelection();
redraw();
}
void init(void)
{
static float lmodel_ambient[] = {0.0f, 0.0f, 0.0f, 0.0f};
static float lmodel_twoside[] = {GL_FALSE};
static float lmodel_local[] = {GL_FALSE};
static float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
static float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f};
static float light0_position[] = {0.8660254f, 0.5f, 1.0f, 0.0f};
static float light0_specular[] = {0.0f, 0.0f, 0.0f, 0.0f};
static float bevel_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
static float bevel_mat_shininess[] = {40.0f};
static float bevel_mat_specular[] = {0.0f, 0.0f, 0.0f, 0.0f};
static float bevel_mat_diffuse[] = {1.0f, 0.0f, 0.0f, 0.0f};
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0f);
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
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);
}
void main(int argc, char **argv)
{
long i;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 's':
doubleBuffer = 0;
break;
default:
break;
}
} else {
break;
}
}
auxInitPosition(0, 0, W, H);
if (doubleBuffer) {
auxInitDisplayMode(AUX_DEPTH | AUX_RGB | AUX_DOUBLE);
} else {
auxInitDisplayMode(AUX_DEPTH | AUX_RGB | AUX_SINGLE);
}
auxInitWindow("glpuzzle");
init();
glGetIntegerv(GL_VIEWPORT, viewport);
auxReshapeFunc(Reshape);
auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,mousedown);
auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEUP,mouseup);
auxMainLoop(redraw);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -