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/>.
27 static void display(void);
28 static void reshape(int x, int y);
29 static void keydown(unsigned char key, int x, int y);
30 static void keyup(unsigned char key, int x, int y);
31 static void skeydown(int key, int x, int y);
32 static void skeyup(int key, int x, int y);
33 static void mouse(int bn, int st, int x, int y);
34 static void motion(int x, int y);
35 static int translate_skey(int key);
37 #if defined(__unix__) || defined(unix)
42 static void (*glx_swap_interval_ext)();
43 static void (*glx_swap_interval_sgi)();
47 static PROC wgl_swap_interval_ext;
50 static rtk_rect rband;
53 int main(int argc, char **argv)
55 glutInit(&argc, argv);
57 load_options(CFGFILE);
59 glutInitWindowSize(opt.xres, opt.yres);
60 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
61 glutCreateWindow("RetroRay");
63 glutDisplayFunc(display);
64 glutReshapeFunc(reshape);
65 glutKeyboardFunc(keydown);
66 glutKeyboardUpFunc(keyup);
67 glutSpecialFunc(skeydown);
68 glutSpecialUpFunc(skeyup);
70 glutMotionFunc(motion);
71 glutPassiveMotionFunc(motion);
72 glutSpaceballMotionFunc(app_sball_motion);
73 glutSpaceballRotateFunc(app_sball_rotate);
74 glutSpaceballButtonFunc(app_sball_button);
76 #if defined(__unix__) || defined(unix)
77 xdpy = glXGetCurrentDisplay();
78 xwin = glXGetCurrentDrawable();
80 if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
81 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
85 wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
88 win_width = glutGet(GLUT_WINDOW_WIDTH);
89 win_height = glutGet(GLUT_WINDOW_HEIGHT);
90 win_aspect = (float)win_width / win_height;
93 add_log_stream(stdout);
95 if(app_init() == -1) {
103 unsigned long get_msec(void)
105 return (unsigned long)glutGet(GLUT_ELAPSED_TIME);
108 void app_redisplay(int x, int y, int w, int h)
110 /*dbgmsg("fakeupd: %d,%d (%dx%d)\n", x, y, w, h);*/
114 void app_swap_buffers(void)
116 glViewport(0, 0, win_width, win_height);
118 glMatrixMode(GL_MODELVIEW);
120 glMatrixMode(GL_PROJECTION);
123 glOrtho(0, win_width, win_height, 0, -1, 1);
127 glEnable(GL_ALPHA_TEST);
128 glAlphaFunc(GL_GREATER, 0.5f);
129 glDrawPixels(win_width, win_height, GL_BGRA, GL_UNSIGNED_BYTE, framebuf);
130 glDisable(GL_ALPHA_TEST);
132 glDisable(GL_DEPTH_TEST);
133 glDisable(GL_LIGHTING);
134 glBegin(GL_LINE_LOOP);
137 glVertex2f(win_width, 0);
138 glVertex2f(win_width, win_height);
139 glVertex2f(0, win_height);
142 if(rband.width | rband.height) {
144 glPushAttrib(GL_ENABLE_BIT);
145 glDisable(GL_DEPTH_TEST);
146 glDisable(GL_LIGHTING);
148 glEnable(GL_COLOR_LOGIC_OP);
151 glBegin(GL_LINE_LOOP);
153 glVertex2f(rband.x, rband.y);
154 glVertex2f(rband.x + rband.width, rband.y);
155 glVertex2f(rband.x + rband.width, rband.y + rband.height);
156 glVertex2f(rband.x, rband.y + rband.height);
163 glMatrixMode(GL_MODELVIEW);
166 assert(glGetError() == GL_NO_ERROR);
174 void app_resize(int x, int y)
176 if(x == win_width && y == win_height) return;
178 glutReshapeWindow(x, y);
181 void app_fullscreen(int fs)
183 static int prev_w, prev_h;
189 if(fs == fullscr) return;
192 prev_w = glutGet(GLUT_WINDOW_WIDTH);
193 prev_h = glutGet(GLUT_WINDOW_HEIGHT);
196 glutReshapeWindow(prev_w, prev_h);
201 #if defined(__unix__) || defined(unix)
202 void app_vsync(int vsync)
204 vsync = vsync ? 1 : 0;
205 if(glx_swap_interval_ext) {
206 glx_swap_interval_ext(xdpy, xwin, vsync);
207 } else if(glx_swap_interval_sgi) {
208 glx_swap_interval_sgi(vsync);
213 void app_vsync(int vsync)
215 if(wgl_swap_interval_ext) {
216 wgl_swap_interval_ext(vsync ? 1 : 0);
221 void app_rband(int x, int y, int w, int h)
232 static void display(void)
238 static void reshape(int x, int y)
243 static void keydown(unsigned char key, int x, int y)
245 modkeys = glutGetModifiers();
246 app_keyboard(key, 1);
249 static void keyup(unsigned char key, int x, int y)
251 app_keyboard(key, 0);
254 static void skeydown(int key, int x, int y)
257 modkeys = glutGetModifiers();
258 if((k = translate_skey(key)) >= 0) {
263 static void skeyup(int key, int x, int y)
265 int k = translate_skey(key);
271 static void mouse(int bn, int st, int x, int y)
273 modkeys = glutGetModifiers();
274 app_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
277 static void motion(int x, int y)
282 static int translate_skey(int key)
293 case GLUT_KEY_PAGE_UP:
295 case GLUT_KEY_PAGE_DOWN:
301 case GLUT_KEY_INSERT:
304 if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
305 return key - GLUT_KEY_F1 + KEY_F1;