2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
25 static void display(void);
26 static void reshape(int x, int y);
27 static void keydown(unsigned char key, int x, int y);
28 static void keyup(unsigned char key, int x, int y);
29 static void skeydown(int key, int x, int y);
30 static void skeyup(int key, int x, int y);
31 static void mouse(int bn, int st, int x, int y);
32 static void motion(int x, int y);
33 static int translate_skey(int key);
34 static void draw_cursor(int x, int y);
36 #if defined(__unix__) || defined(unix)
41 static void (*glx_swap_interval_ext)();
42 static void (*glx_swap_interval_sgi)();
46 static PROC wgl_swap_interval_ext;
51 int main(int argc, char **argv)
53 glutInit(&argc, argv);
54 glutInitWindowSize(640, 480);
55 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
56 glutCreateWindow("RetroRay");
58 glutDisplayFunc(display);
59 glutReshapeFunc(reshape);
60 glutKeyboardFunc(keydown);
61 glutKeyboardUpFunc(keyup);
62 glutSpecialFunc(skeydown);
63 glutSpecialUpFunc(skeyup);
65 glutMotionFunc(motion);
66 glutPassiveMotionFunc(motion);
67 glutSpaceballMotionFunc(app_sball_motion);
68 glutSpaceballRotateFunc(app_sball_rotate);
69 glutSpaceballButtonFunc(app_sball_button);
71 #if defined(__unix__) || defined(unix)
72 xdpy = glXGetCurrentDisplay();
73 xwin = glXGetCurrentDrawable();
75 if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
76 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
80 wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
83 win_width = glutGet(GLUT_WINDOW_WIDTH);
84 win_height = glutGet(GLUT_WINDOW_HEIGHT);
85 win_aspect = (float)win_width / win_height;
89 if(app_init() == -1) {
97 long app_getmsec(void)
99 return glutGet(GLUT_ELAPSED_TIME);
102 void app_redisplay(void)
107 void app_swap_buffers(void)
109 glMatrixMode(GL_PROJECTION);
112 glMatrixMode(GL_MODELVIEW);
115 glRasterPos2i(-1, 1);
117 glEnable(GL_ALPHA_TEST);
118 glAlphaFunc(GL_GREATER, 0.5f);
119 glDrawPixels(win_width, win_height, GL_BGRA, GL_UNSIGNED_BYTE, framebuf);
120 glDisable(GL_ALPHA_TEST);
122 glMatrixMode(GL_PROJECTION);
124 glMatrixMode(GL_MODELVIEW);
127 assert(glGetError() == GL_NO_ERROR);
135 void app_resize(int x, int y)
137 if(x == win_width && y == win_height) return;
139 glutReshapeWindow(x, y);
142 void app_fullscreen(int fs)
144 static int prev_w, prev_h;
150 if(fs == fullscr) return;
153 prev_w = glutGet(GLUT_WINDOW_WIDTH);
154 prev_h = glutGet(GLUT_WINDOW_HEIGHT);
157 glutReshapeWindow(prev_w, prev_h);
162 #if defined(__unix__) || defined(unix)
163 void app_vsync(int vsync)
165 vsync = vsync ? 1 : 0;
166 if(glx_swap_interval_ext) {
167 glx_swap_interval_ext(xdpy, xwin, vsync);
168 } else if(glx_swap_interval_sgi) {
169 glx_swap_interval_sgi(vsync);
174 void app_vsync(int vsync)
176 if(wgl_swap_interval_ext) {
177 wgl_swap_interval_ext(vsync ? 1 : 0);
183 static void display(void)
187 draw_cursor(mouse_x, mouse_y);
192 static void reshape(int x, int y)
197 static void keydown(unsigned char key, int x, int y)
199 modkeys = glutGetModifiers();
200 app_keyboard(key, 1);
203 static void keyup(unsigned char key, int x, int y)
205 app_keyboard(key, 0);
208 static void skeydown(int key, int x, int y)
211 modkeys = glutGetModifiers();
212 if((k = translate_skey(key)) >= 0) {
217 static void skeyup(int key, int x, int y)
219 int k = translate_skey(key);
225 static void mouse(int bn, int st, int x, int y)
227 modkeys = glutGetModifiers();
228 app_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
231 static void motion(int x, int y)
236 static int translate_skey(int key)
247 case GLUT_KEY_PAGE_UP:
249 case GLUT_KEY_PAGE_DOWN:
255 case GLUT_KEY_INSERT:
258 if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
259 return key - GLUT_KEY_F1 + KEY_F1;
266 static void draw_cursor(int x, int y)
269 uint32_t *fbptr = framebuf + y * win_width + x;
273 if(y > offs) fbptr[-win_width * offs] ^= 0xffffff;
274 if(y < win_height - offs - 1) fbptr[win_width * offs] ^= 0xffffff;
275 if(x > offs) fbptr[-offs] ^= 0xffffff;
276 if(x < win_width - offs - 1) fbptr[offs] ^= 0xffffff;