rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@3
|
2 #include <stdlib.h>
|
nuclear@2
|
3 #include <string.h>
|
nuclear@2
|
4 #include <errno.h>
|
nuclear@3
|
5 #ifndef __APPLE__
|
nuclear@3
|
6 #include <GL/glut.h>
|
nuclear@3
|
7 #else
|
nuclear@3
|
8 #include <GLUT/glut.h>
|
nuclear@3
|
9 #endif
|
nuclear@3
|
10 #include "rt.h"
|
nuclear@12
|
11 #include "matrix.h"
|
nuclear@0
|
12
|
nuclear@3
|
13 void cleanup();
|
nuclear@3
|
14 void disp();
|
nuclear@3
|
15 void reshape(int x, int y);
|
nuclear@3
|
16 void keyb(unsigned char key, int x, int y);
|
nuclear@3
|
17 void mouse(int bn, int status, int x, int y);
|
nuclear@3
|
18 void motion(int x, int y);
|
nuclear@2
|
19 bool write_ppm(const char *fname, float *fb, int xsz, int ysz);
|
nuclear@2
|
20
|
nuclear@3
|
21 static int xsz, ysz;
|
nuclear@3
|
22 static bool need_update = true;
|
nuclear@3
|
23
|
nuclear@8
|
24 static float cam_theta, cam_phi = 25.0;
|
nuclear@8
|
25 static float cam_dist = 10.0;
|
nuclear@8
|
26
|
nuclear@12
|
27 static bool dbg_glrender;
|
nuclear@12
|
28
|
nuclear@3
|
29 int main(int argc, char **argv)
|
nuclear@0
|
30 {
|
nuclear@3
|
31 glutInitWindowSize(800, 600);
|
nuclear@3
|
32 glutInit(&argc, argv);
|
nuclear@3
|
33 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
nuclear@3
|
34 glutCreateWindow("OpenCL Raytracer");
|
nuclear@0
|
35
|
nuclear@3
|
36 xsz = glutGet(GLUT_WINDOW_WIDTH);
|
nuclear@3
|
37 ysz = glutGet(GLUT_WINDOW_HEIGHT);
|
nuclear@2
|
38
|
nuclear@3
|
39 glutDisplayFunc(disp);
|
nuclear@3
|
40 glutReshapeFunc(reshape);
|
nuclear@3
|
41 glutKeyboardFunc(keyb);
|
nuclear@3
|
42 glutMouseFunc(mouse);
|
nuclear@3
|
43 glutMotionFunc(motion);
|
nuclear@0
|
44
|
nuclear@12
|
45 if(!init_renderer(xsz, ysz)) {
|
nuclear@0
|
46 return 1;
|
nuclear@0
|
47 }
|
nuclear@3
|
48 atexit(cleanup);
|
nuclear@0
|
49
|
nuclear@3
|
50 /*glGenTextures(1, &tex);
|
nuclear@3
|
51 glBindTexture(GL_TEXTURE_2D, tex);*/
|
nuclear@3
|
52 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
nuclear@3
|
53 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
nuclear@3
|
54 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@3
|
55 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@3
|
56 glTexImage2D(GL_TEXTURE_2D, 0, 4, xsz, ysz, 0, GL_RGBA, GL_FLOAT, 0);
|
nuclear@2
|
57
|
nuclear@3
|
58 glutMainLoop();
|
nuclear@0
|
59 return 0;
|
nuclear@0
|
60 }
|
nuclear@2
|
61
|
nuclear@3
|
62 void cleanup()
|
nuclear@2
|
63 {
|
nuclear@3
|
64 destroy_renderer();
|
nuclear@3
|
65 }
|
nuclear@2
|
66
|
nuclear@12
|
67 static Matrix4x4 mat, inv_mat, inv_trans;
|
nuclear@12
|
68
|
nuclear@3
|
69 void disp()
|
nuclear@3
|
70 {
|
nuclear@8
|
71 glMatrixMode(GL_MODELVIEW);
|
nuclear@8
|
72 glLoadIdentity();
|
nuclear@8
|
73
|
nuclear@3
|
74 if(need_update) {
|
nuclear@12
|
75 glPushMatrix();
|
nuclear@12
|
76 glRotatef(-cam_theta, 0, 1, 0);
|
nuclear@12
|
77 glRotatef(-cam_phi, 1, 0, 0);
|
nuclear@12
|
78 glTranslatef(0, 0, cam_dist);
|
nuclear@8
|
79
|
nuclear@12
|
80 glGetFloatv(GL_MODELVIEW_MATRIX, mat.m);
|
nuclear@8
|
81
|
nuclear@12
|
82 inv_mat = mat;
|
nuclear@12
|
83 inv_mat.invert();
|
nuclear@12
|
84
|
nuclear@12
|
85 /*inv_trans = inv_mat;
|
nuclear@12
|
86 inv_trans.transpose();*/
|
nuclear@12
|
87 inv_trans = mat;
|
nuclear@12
|
88 inv_trans.m[3] = inv_trans.m[7] = inv_trans.m[11] = 0.0;
|
nuclear@12
|
89 inv_trans.m[12] = inv_trans.m[13] = inv_trans.m[14] = 0.0;
|
nuclear@12
|
90 inv_trans.m[15] = 1.0;
|
nuclear@12
|
91
|
nuclear@12
|
92 set_xform(mat.m, inv_trans.m);
|
nuclear@8
|
93 glPopMatrix();
|
nuclear@8
|
94
|
nuclear@12
|
95 if(!render()) {
|
nuclear@12
|
96 exit(1);
|
nuclear@12
|
97 }
|
nuclear@3
|
98 need_update = false;
|
nuclear@3
|
99 }
|
nuclear@2
|
100
|
nuclear@12
|
101 if(dbg_glrender) {
|
nuclear@12
|
102 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@12
|
103 glLoadMatrixf(inv_mat.m);
|
nuclear@12
|
104 dbg_render_gl();
|
nuclear@12
|
105 } else {
|
nuclear@12
|
106 glEnable(GL_TEXTURE_2D);
|
nuclear@2
|
107
|
nuclear@12
|
108 glBegin(GL_QUADS);
|
nuclear@12
|
109 glColor3f(1, 1, 1);
|
nuclear@12
|
110 glTexCoord2f(0, 1); glVertex2f(-1, -1);
|
nuclear@12
|
111 glTexCoord2f(1, 1); glVertex2f(1, -1);
|
nuclear@12
|
112 glTexCoord2f(1, 0); glVertex2f(1, 1);
|
nuclear@12
|
113 glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
nuclear@12
|
114 glEnd();
|
nuclear@2
|
115
|
nuclear@12
|
116 glDisable(GL_TEXTURE_2D);
|
nuclear@12
|
117 }
|
nuclear@3
|
118
|
nuclear@3
|
119 glutSwapBuffers();
|
nuclear@3
|
120 }
|
nuclear@3
|
121
|
nuclear@3
|
122 void reshape(int x, int y)
|
nuclear@3
|
123 {
|
nuclear@3
|
124 glViewport(0, 0, x, y);
|
nuclear@3
|
125
|
nuclear@3
|
126 /* reallocate the framebuffer */
|
nuclear@3
|
127 /*delete [] fb;
|
nuclear@3
|
128 fb = new float[x * y * 4];
|
nuclear@3
|
129 set_framebuffer(fb, x, y);*/
|
nuclear@3
|
130 }
|
nuclear@3
|
131
|
nuclear@3
|
132 void keyb(unsigned char key, int x, int y)
|
nuclear@3
|
133 {
|
nuclear@3
|
134 switch(key) {
|
nuclear@3
|
135 case 27:
|
nuclear@3
|
136 exit(0);
|
nuclear@3
|
137
|
nuclear@12
|
138 case 'r':
|
nuclear@12
|
139 need_update = true;
|
nuclear@12
|
140 glutPostRedisplay();
|
nuclear@3
|
141 break;
|
nuclear@3
|
142
|
nuclear@12
|
143 case 'd':
|
nuclear@12
|
144 dbg_glrender = !dbg_glrender;
|
nuclear@12
|
145 if(dbg_glrender) {
|
nuclear@12
|
146 printf("DEBUG GL RENDER\n");
|
nuclear@12
|
147 }
|
nuclear@3
|
148 glutPostRedisplay();
|
nuclear@3
|
149 break;
|
nuclear@3
|
150
|
nuclear@3
|
151 default:
|
nuclear@3
|
152 break;
|
nuclear@3
|
153 }
|
nuclear@3
|
154 }
|
nuclear@3
|
155
|
nuclear@8
|
156 static bool bnstate[32];
|
nuclear@8
|
157 static int prev_x, prev_y;
|
nuclear@8
|
158
|
nuclear@3
|
159 void mouse(int bn, int state, int x, int y)
|
nuclear@3
|
160 {
|
nuclear@8
|
161 if(state == GLUT_DOWN) {
|
nuclear@8
|
162 prev_x = x;
|
nuclear@8
|
163 prev_y = y;
|
nuclear@8
|
164 bnstate[bn] = true;
|
nuclear@8
|
165 } else {
|
nuclear@8
|
166 bnstate[bn] = false;
|
nuclear@8
|
167 }
|
nuclear@3
|
168 }
|
nuclear@3
|
169
|
nuclear@8
|
170 #define ROT_SCALE 0.5
|
nuclear@8
|
171 #define PAN_SCALE 0.1
|
nuclear@8
|
172
|
nuclear@3
|
173 void motion(int x, int y)
|
nuclear@3
|
174 {
|
nuclear@8
|
175 int dx = x - prev_x;
|
nuclear@8
|
176 int dy = y - prev_y;
|
nuclear@8
|
177 prev_x = x;
|
nuclear@8
|
178 prev_y = y;
|
nuclear@8
|
179
|
nuclear@8
|
180 if(bnstate[0]) {
|
nuclear@8
|
181 cam_theta += dx * ROT_SCALE;
|
nuclear@8
|
182 cam_phi += dy * ROT_SCALE;
|
nuclear@8
|
183
|
nuclear@12
|
184 if(cam_phi < -89) cam_phi = -89;
|
nuclear@8
|
185 if(cam_phi > 89) cam_phi = 89;
|
nuclear@8
|
186
|
nuclear@8
|
187 need_update = true;
|
nuclear@8
|
188 glutPostRedisplay();
|
nuclear@8
|
189 }
|
nuclear@8
|
190 if(bnstate[2]) {
|
nuclear@8
|
191 cam_dist += dy * PAN_SCALE;
|
nuclear@8
|
192 if(cam_dist < 0) cam_dist = 0;
|
nuclear@8
|
193
|
nuclear@8
|
194 need_update = true;
|
nuclear@8
|
195 glutPostRedisplay();
|
nuclear@8
|
196 }
|
nuclear@2
|
197 }
|
nuclear@2
|
198
|
nuclear@2
|
199 bool write_ppm(const char *fname, float *fb, int xsz, int ysz)
|
nuclear@2
|
200 {
|
nuclear@2
|
201 FILE *fp;
|
nuclear@2
|
202
|
nuclear@2
|
203 if(!(fp = fopen(fname, "wb"))) {
|
nuclear@2
|
204 fprintf(stderr, "write_ppm: failed to open file %s for writing: %s\n", fname, strerror(errno));
|
nuclear@2
|
205 return false;
|
nuclear@2
|
206 }
|
nuclear@2
|
207 fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
|
nuclear@2
|
208
|
nuclear@2
|
209 for(int i=0; i<xsz * ysz * 4; i++) {
|
nuclear@2
|
210 if(i % 4 == 3) continue;
|
nuclear@2
|
211
|
nuclear@2
|
212 unsigned char c = (unsigned char)(fb[i] * 255.0);
|
nuclear@2
|
213 fputc(c, fp);
|
nuclear@2
|
214 }
|
nuclear@2
|
215 fclose(fp);
|
nuclear@2
|
216 return true;
|
nuclear@2
|
217 }
|