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 if(rband.width | rband.height) {
133 glPushAttrib(GL_ENABLE_BIT);
134 glDisable(GL_DEPTH_TEST);
135 glDisable(GL_LIGHTING);
137 glEnable(GL_COLOR_LOGIC_OP);
140 glBegin(GL_LINE_LOOP);
142 glVertex2f(rband.x, rband.y);
143 glVertex2f(rband.x + rband.width, rband.y);
144 glVertex2f(rband.x + rband.width, rband.y + rband.height);
145 glVertex2f(rband.x, rband.y + rband.height);
152 glMatrixMode(GL_MODELVIEW);
155 assert(glGetError() == GL_NO_ERROR);
163 void app_resize(int x, int y)
165 if(x == win_width && y == win_height) return;
167 glutReshapeWindow(x, y);
170 void app_fullscreen(int fs)
172 static int prev_w, prev_h;
178 if(fs == fullscr) return;
181 prev_w = glutGet(GLUT_WINDOW_WIDTH);
182 prev_h = glutGet(GLUT_WINDOW_HEIGHT);
185 glutReshapeWindow(prev_w, prev_h);
190 #if defined(__unix__) || defined(unix)
191 void app_vsync(int vsync)
193 vsync = vsync ? 1 : 0;
194 if(glx_swap_interval_ext) {
195 glx_swap_interval_ext(xdpy, xwin, vsync);
196 } else if(glx_swap_interval_sgi) {
197 glx_swap_interval_sgi(vsync);
202 void app_vsync(int vsync)
204 if(wgl_swap_interval_ext) {
205 wgl_swap_interval_ext(vsync ? 1 : 0);
210 void app_rband(int x, int y, int w, int h)
221 static void display(void)
227 static void reshape(int x, int y)
232 static void keydown(unsigned char key, int x, int y)
234 modkeys = glutGetModifiers();
235 app_keyboard(key, 1);
238 static void keyup(unsigned char key, int x, int y)
240 app_keyboard(key, 0);
243 static void skeydown(int key, int x, int y)
246 modkeys = glutGetModifiers();
247 if((k = translate_skey(key)) >= 0) {
252 static void skeyup(int key, int x, int y)
254 int k = translate_skey(key);
260 static void mouse(int bn, int st, int x, int y)
262 modkeys = glutGetModifiers();
263 app_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
266 static void motion(int x, int y)
271 static int translate_skey(int key)
282 case GLUT_KEY_PAGE_UP:
284 case GLUT_KEY_PAGE_DOWN:
290 case GLUT_KEY_INSERT:
293 if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
294 return key - GLUT_KEY_F1 + KEY_F1;