1 | /*--------------------------------------------------------------------------*/ |
---|
2 | /* Volume Rendering Application */ |
---|
3 | /* Copyright (C) 2006-2007 Nicholas Schwarz */ |
---|
4 | /* */ |
---|
5 | /* This software is free software; you can redistribute it and/or modify it */ |
---|
6 | /* under the terms of the GNU Lesser General Public License as published by */ |
---|
7 | /* the Free Software Foundation; either Version 2.1 of the License, or */ |
---|
8 | /* (at your option) any later version. */ |
---|
9 | /* */ |
---|
10 | /* This software is distributed in the hope that it will be useful, but */ |
---|
11 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ |
---|
12 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser */ |
---|
13 | /* General Public License for more details. */ |
---|
14 | /* */ |
---|
15 | /* You should have received a copy of the GNU Lesser Public License along */ |
---|
16 | /* with this library; if not, write to the Free Software Foundation, Inc., */ |
---|
17 | /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
---|
18 | /*--------------------------------------------------------------------------*/ |
---|
19 | |
---|
20 | #include "VolumeRendererShell.h" |
---|
21 | |
---|
22 | #include "SynchronizerClient.h" |
---|
23 | |
---|
24 | /*--------------------------------------------------------------------------*/ |
---|
25 | |
---|
26 | #ifdef SAGE |
---|
27 | |
---|
28 | // Define static variable for glXPBuffer |
---|
29 | GLXPbufferSGIX VolumeRendererShell::_glXPBuffer = 0; |
---|
30 | |
---|
31 | // Define static variable for X display |
---|
32 | Display* VolumeRendererShell::_xDisplay = NULL; |
---|
33 | |
---|
34 | // Define static variable for X error flag |
---|
35 | int VolumeRendererShell::_xErrorFlag = 0; |
---|
36 | |
---|
37 | // Define static variable for X visual info |
---|
38 | XVisualInfo* VolumeRendererShell::_xVisualInfo = NULL; |
---|
39 | |
---|
40 | #endif |
---|
41 | |
---|
42 | /*--------------------------------------------------------------------------*/ |
---|
43 | |
---|
44 | VolumeRendererShell::VolumeRendererShell() { |
---|
45 | |
---|
46 | // Initialize condition variable |
---|
47 | pthread_cond_init(&_conditionCond, NULL); |
---|
48 | |
---|
49 | // Initialize mutex |
---|
50 | pthread_mutex_init(&_conditionMutex, NULL); |
---|
51 | |
---|
52 | } |
---|
53 | |
---|
54 | /*--------------------------------------------------------------------------*/ |
---|
55 | |
---|
56 | VolumeRendererShell::~VolumeRendererShell() { |
---|
57 | |
---|
58 | // Clean up condition variable |
---|
59 | pthread_cond_destroy(&_conditionCond); |
---|
60 | |
---|
61 | // Clean up mutex |
---|
62 | pthread_mutex_destroy(&_conditionMutex); |
---|
63 | |
---|
64 | } |
---|
65 | |
---|
66 | /*--------------------------------------------------------------------------*/ |
---|
67 | |
---|
68 | void VolumeRendererShell::AbortRender(bool flag) { |
---|
69 | |
---|
70 | // Set abort flag |
---|
71 | _info._abortFlag = flag; |
---|
72 | |
---|
73 | } |
---|
74 | |
---|
75 | /*--------------------------------------------------------------------------*/ |
---|
76 | |
---|
77 | void VolumeRendererShell::DestroyDisplay() { |
---|
78 | |
---|
79 | #ifdef SAGE |
---|
80 | |
---|
81 | // Clean up pbuffer |
---|
82 | glXDestroyGLXPbufferSGIX(_xDisplay, _glXPBuffer); |
---|
83 | |
---|
84 | // Clean up visual info |
---|
85 | XFree(_xVisualInfo); |
---|
86 | |
---|
87 | // Close X connection |
---|
88 | XCloseDisplay(_xDisplay); |
---|
89 | |
---|
90 | #else |
---|
91 | |
---|
92 | // Quit SDL |
---|
93 | SDL_Quit(); |
---|
94 | |
---|
95 | #endif |
---|
96 | |
---|
97 | } |
---|
98 | |
---|
99 | /*--------------------------------------------------------------------------*/ |
---|
100 | |
---|
101 | #ifdef SAGE |
---|
102 | |
---|
103 | int VolumeRendererShell::HandleXError(Display* display, XErrorEvent *event) { |
---|
104 | |
---|
105 | // Set error flag |
---|
106 | _xErrorFlag = 1; |
---|
107 | |
---|
108 | // Return 0 |
---|
109 | return 0; |
---|
110 | |
---|
111 | } |
---|
112 | |
---|
113 | #endif |
---|
114 | |
---|
115 | /*--------------------------------------------------------------------------*/ |
---|
116 | |
---|
117 | void VolumeRendererShell::Init(int width, int height, bool fullScreen, |
---|
118 | char* hostname, int port, |
---|
119 | float left, float right, |
---|
120 | float bottom, float top, |
---|
121 | int rank, int numberOfNodes) { |
---|
122 | |
---|
123 | // Set mutex and condition variable in thread state |
---|
124 | _info._conditionCond = &_conditionCond; |
---|
125 | _info._conditionMutex = &_conditionMutex; |
---|
126 | |
---|
127 | // Set display information in thread state |
---|
128 | _info._displaySize[0] = width; |
---|
129 | _info._displaySize[1] = height; |
---|
130 | _info._fullScreenFlag = fullScreen; |
---|
131 | _info._normalCoordinates[0] = left; |
---|
132 | _info._normalCoordinates[1] = right; |
---|
133 | _info._normalCoordinates[2] = bottom; |
---|
134 | _info._normalCoordinates[3] = top; |
---|
135 | |
---|
136 | // Set synchronization hostname and port |
---|
137 | strcpy(_info._synchronizationHostname, hostname); |
---|
138 | _info._synchronizationPort = port; |
---|
139 | |
---|
140 | // Set rank and number of nodes |
---|
141 | _info._rank = rank; |
---|
142 | _info._numberOfNodes = numberOfNodes; |
---|
143 | |
---|
144 | // Create thread |
---|
145 | pthread_create(&_thread, NULL, VolumeRendererShell::ThreadFunction, &_info); |
---|
146 | |
---|
147 | } |
---|
148 | |
---|
149 | /*--------------------------------------------------------------------------*/ |
---|
150 | |
---|
151 | void VolumeRendererShell::InitDisplay(int width, int height, bool fullScreen, |
---|
152 | float left, float right, |
---|
153 | float bottom, float top) { |
---|
154 | |
---|
155 | #ifdef SAGE |
---|
156 | |
---|
157 | // GLX context |
---|
158 | GLXContext glXContext; |
---|
159 | |
---|
160 | // GLX pbuffer |
---|
161 | GLXFBConfigSGIX glXFBConfig = 0; |
---|
162 | |
---|
163 | // X screen |
---|
164 | int xScreen = 0; |
---|
165 | |
---|
166 | // Open display |
---|
167 | _xDisplay = XOpenDisplay(NULL); |
---|
168 | if (!_xDisplay) { |
---|
169 | fprintf(stderr, "VolumeRendererShell: Could not open X display.\n"); |
---|
170 | return; |
---|
171 | } |
---|
172 | |
---|
173 | // Get default screen |
---|
174 | xScreen = DefaultScreen(_xDisplay); |
---|
175 | |
---|
176 | // Double buffered, with depth buffer |
---|
177 | int fbAttribs[] = { |
---|
178 | GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX, |
---|
179 | GLX_DRAWABLE_TYPE_SGIX, GLX_PIXMAP_BIT_SGIX, |
---|
180 | GLX_RED_SIZE, 1, |
---|
181 | GLX_GREEN_SIZE, 1, |
---|
182 | GLX_BLUE_SIZE, 1, |
---|
183 | GLX_DEPTH_SIZE, 1, |
---|
184 | GLX_DOUBLEBUFFER, 1, |
---|
185 | GLX_STENCIL_SIZE, 0, |
---|
186 | None |
---|
187 | }; |
---|
188 | |
---|
189 | // Attributes |
---|
190 | int pbAttribs[] = { |
---|
191 | GLX_LARGEST_PBUFFER_SGIX, True, |
---|
192 | GLX_PRESERVED_CONTENTS_SGIX, False, |
---|
193 | None |
---|
194 | }; |
---|
195 | |
---|
196 | // Possible configurations |
---|
197 | GLXFBConfigSGIX* glXFBConfigs = NULL; |
---|
198 | int numberOfGLXFBConfigs; |
---|
199 | |
---|
200 | // Get list of possible frame buffer configurations |
---|
201 | glXFBConfigs = glXChooseFBConfigSGIX(_xDisplay, xScreen, |
---|
202 | fbAttribs, &numberOfGLXFBConfigs); |
---|
203 | if (numberOfGLXFBConfigs == 0 || !glXFBConfigs) { |
---|
204 | fprintf(stderr, "VolumeRendererShell: Choosing FBConfig failed.\n"); |
---|
205 | XCloseDisplay(_xDisplay); |
---|
206 | return; |
---|
207 | } |
---|
208 | |
---|
209 | // Create pbuffer using first config in the list that works |
---|
210 | for (int i = 0 ; i < numberOfGLXFBConfigs ; i++) { |
---|
211 | |
---|
212 | // Catch X errors with error handler |
---|
213 | int (*oldHandler)(Display*, XErrorEvent*); |
---|
214 | oldHandler = XSetErrorHandler(HandleXError); |
---|
215 | _xErrorFlag = 0; |
---|
216 | |
---|
217 | // Create pbuffer |
---|
218 | _glXPBuffer = glXCreateGLXPbufferSGIX(_xDisplay, glXFBConfigs[i], |
---|
219 | width, height, pbAttribs); |
---|
220 | |
---|
221 | // Restore original X error handler |
---|
222 | (void) XSetErrorHandler(oldHandler); |
---|
223 | |
---|
224 | // Found a working configuration |
---|
225 | if (!_xErrorFlag && _glXPBuffer != None) { |
---|
226 | glXFBConfig = glXFBConfigs[i]; |
---|
227 | break; |
---|
228 | } |
---|
229 | } |
---|
230 | |
---|
231 | // Clean up |
---|
232 | XFree(glXFBConfigs); |
---|
233 | |
---|
234 | // If a pbuffer couldn't be created |
---|
235 | if (_glXPBuffer == None) { |
---|
236 | fprintf(stderr, "VolumeRendererShell: Couldn't create pbuffer.\n"); |
---|
237 | XCloseDisplay(_xDisplay); |
---|
238 | return; |
---|
239 | } |
---|
240 | |
---|
241 | // Get corresponding XVisualInfo |
---|
242 | _xVisualInfo = glXGetVisualFromFBConfigSGIX(_xDisplay, glXFBConfig); |
---|
243 | if (!_xVisualInfo) { |
---|
244 | fprintf(stderr, "VolumeRendererShell: Can't get XVisualInfo.\n"); |
---|
245 | XCloseDisplay(_xDisplay); |
---|
246 | return; |
---|
247 | } |
---|
248 | |
---|
249 | // Create GLX context |
---|
250 | glXContext = glXCreateContext(_xDisplay, _xVisualInfo, NULL, True); |
---|
251 | if (!glXContext) { |
---|
252 | glXContext = glXCreateContext(_xDisplay, _xVisualInfo, NULL, False); |
---|
253 | if (!glXContext) { |
---|
254 | fprintf(stderr, "VolumeRendererShell: Couldn't create GLXContext.\n"); |
---|
255 | XFree(_xVisualInfo); |
---|
256 | XCloseDisplay(_xDisplay); |
---|
257 | return; |
---|
258 | } |
---|
259 | } |
---|
260 | |
---|
261 | // Bind context to pbuffer |
---|
262 | if (!glXMakeCurrent(_xDisplay, _glXPBuffer, glXContext)) { |
---|
263 | fprintf(stderr, "VolumeRendererShell: glXMakeCurrent failed.\n"); |
---|
264 | XFree(_xVisualInfo); |
---|
265 | XCloseDisplay(_xDisplay); |
---|
266 | return; |
---|
267 | } |
---|
268 | |
---|
269 | #else |
---|
270 | |
---|
271 | // Initialize SDL |
---|
272 | SDL_Init(SDL_INIT_VIDEO); |
---|
273 | |
---|
274 | // Set video mode |
---|
275 | if (fullScreen == false) { |
---|
276 | SDL_SetVideoMode(width, |
---|
277 | height, |
---|
278 | 0, |
---|
279 | SDL_DOUBLEBUF | SDL_OPENGL); |
---|
280 | } |
---|
281 | else { |
---|
282 | SDL_SetVideoMode(width, |
---|
283 | height, |
---|
284 | 0, |
---|
285 | SDL_DOUBLEBUF | SDL_OPENGL | SDL_FULLSCREEN); |
---|
286 | SDL_ShowCursor(SDL_DISABLE); |
---|
287 | } |
---|
288 | SDL_WM_SetCaption("Volume Renderer", NULL); |
---|
289 | |
---|
290 | #endif |
---|
291 | |
---|
292 | } |
---|
293 | |
---|
294 | /*--------------------------------------------------------------------------*/ |
---|
295 | |
---|
296 | bool VolumeRendererShell::InRender() { |
---|
297 | |
---|
298 | // Return in render flag |
---|
299 | return _info._inRenderFlag; |
---|
300 | |
---|
301 | } |
---|
302 | |
---|
303 | /*--------------------------------------------------------------------------*/ |
---|
304 | |
---|
305 | bool VolumeRendererShell::IsInitialized() { |
---|
306 | |
---|
307 | // To be implemented |
---|
308 | return true; |
---|
309 | |
---|
310 | } |
---|
311 | |
---|
312 | /*--------------------------------------------------------------------------*/ |
---|
313 | |
---|
314 | void VolumeRendererShell::Render() { |
---|
315 | |
---|
316 | // Signal thread to update volume renderer and render |
---|
317 | pthread_mutex_lock(&_conditionMutex); |
---|
318 | _info._renderFlag = true; |
---|
319 | pthread_cond_signal(&_conditionCond); |
---|
320 | pthread_mutex_unlock(&_conditionMutex); |
---|
321 | |
---|
322 | } |
---|
323 | |
---|
324 | /*--------------------------------------------------------------------------*/ |
---|
325 | |
---|
326 | void VolumeRendererShell::SetAxisOff() { |
---|
327 | |
---|
328 | // Set flag |
---|
329 | _info._axisOnFlag = false; |
---|
330 | |
---|
331 | // Set update flag |
---|
332 | _info._updateAxis = true; |
---|
333 | |
---|
334 | } |
---|
335 | |
---|
336 | /*--------------------------------------------------------------------------*/ |
---|
337 | |
---|
338 | void VolumeRendererShell::SetAxisOn() { |
---|
339 | |
---|
340 | // Set flag |
---|
341 | _info._axisOnFlag = true; |
---|
342 | |
---|
343 | // Set update flag |
---|
344 | _info._updateAxis = true; |
---|
345 | |
---|
346 | } |
---|
347 | |
---|
348 | /*--------------------------------------------------------------------------*/ |
---|
349 | |
---|
350 | void VolumeRendererShell::SetAxisPosition(float x, float y, float z) { |
---|
351 | |
---|
352 | // Set data |
---|
353 | _info._axisPosition[0] = x; |
---|
354 | _info._axisPosition[1] = y; |
---|
355 | _info._axisPosition[2] = z; |
---|
356 | |
---|
357 | // Set update flag |
---|
358 | _info._updateAxis = true; |
---|
359 | |
---|
360 | } |
---|
361 | |
---|
362 | /*--------------------------------------------------------------------------*/ |
---|
363 | |
---|
364 | void VolumeRendererShell::SetBrickBoxOff() { |
---|
365 | |
---|
366 | // Set flag |
---|
367 | _info._brickBoxOnFlag = false; |
---|
368 | |
---|
369 | // Set update flag |
---|
370 | _info._updateBrickBox = true; |
---|
371 | |
---|
372 | } |
---|
373 | |
---|
374 | /*--------------------------------------------------------------------------*/ |
---|
375 | |
---|
376 | void VolumeRendererShell::SetBrickBoxOn() { |
---|
377 | |
---|
378 | // Set flag |
---|
379 | _info._brickBoxOnFlag = true; |
---|
380 | |
---|
381 | // Set update flag |
---|
382 | _info._updateBrickBox = true; |
---|
383 | |
---|
384 | } |
---|
385 | |
---|
386 | /*--------------------------------------------------------------------------*/ |
---|
387 | |
---|
388 | void VolumeRendererShell::SetBoundingBoxOff() { |
---|
389 | |
---|
390 | // Set flag |
---|
391 | _info._boundingBoxOnFlag = false; |
---|
392 | |
---|
393 | // Set update flag |
---|
394 | _info._updateBoundingBox = true; |
---|
395 | |
---|
396 | } |
---|
397 | |
---|
398 | /*--------------------------------------------------------------------------*/ |
---|
399 | |
---|
400 | void VolumeRendererShell::SetBoundingBoxOn() { |
---|
401 | |
---|
402 | // Set flag |
---|
403 | _info._boundingBoxOnFlag = true; |
---|
404 | |
---|
405 | // Set update flag |
---|
406 | _info._updateBoundingBox = true; |
---|
407 | |
---|
408 | } |
---|
409 | |
---|
410 | /*--------------------------------------------------------------------------*/ |
---|
411 | |
---|
412 | void VolumeRendererShell::SetData(Octree* data) { |
---|
413 | |
---|
414 | // Set data |
---|
415 | _info._data = data; |
---|
416 | |
---|
417 | // Set default cache sizes |
---|
418 | _info._ramSize = 50; |
---|
419 | _info._vramSize = 10; |
---|
420 | |
---|
421 | // Set update flag |
---|
422 | _info._updateData = true; |
---|
423 | |
---|
424 | } |
---|
425 | |
---|
426 | /*--------------------------------------------------------------------------*/ |
---|
427 | |
---|
428 | void VolumeRendererShell::SetData(Octree* data, int ramSize, int vramSize) { |
---|
429 | |
---|
430 | // Set data |
---|
431 | _info._data = data; |
---|
432 | |
---|
433 | // Set cache sizes |
---|
434 | _info._ramSize = ramSize; |
---|
435 | _info._vramSize = vramSize; |
---|
436 | |
---|
437 | // Set update flag |
---|
438 | _info._updateData = true; |
---|
439 | |
---|
440 | } |
---|
441 | |
---|
442 | /*--------------------------------------------------------------------------*/ |
---|
443 | |
---|
444 | void VolumeRendererShell::SetExitFlag() { |
---|
445 | |
---|
446 | // Set exit flag |
---|
447 | _info._exitFlag = true; |
---|
448 | |
---|
449 | // Signal thread to update volume renderer and render |
---|
450 | pthread_mutex_lock(&_conditionMutex); |
---|
451 | _info._renderFlag = true; |
---|
452 | pthread_cond_signal(&_conditionCond); |
---|
453 | pthread_mutex_unlock(&_conditionMutex); |
---|
454 | |
---|
455 | // Wait for thread to finish |
---|
456 | pthread_join(_thread, NULL); |
---|
457 | |
---|
458 | } |
---|
459 | |
---|
460 | /*--------------------------------------------------------------------------*/ |
---|
461 | |
---|
462 | void VolumeRendererShell::SetFrustum(float left, float right, float bottom, |
---|
463 | float top, float near, float far) { |
---|
464 | |
---|
465 | // Set frustum |
---|
466 | _info._frustum[0] = left; |
---|
467 | _info._frustum[1] = right; |
---|
468 | _info._frustum[2] = bottom; |
---|
469 | _info._frustum[3] = top; |
---|
470 | _info._frustum[4] = near; |
---|
471 | _info._frustum[5] = far; |
---|
472 | |
---|
473 | // Set update flag |
---|
474 | _info._updateFrustum = true; |
---|
475 | |
---|
476 | } |
---|
477 | |
---|
478 | /*--------------------------------------------------------------------------*/ |
---|
479 | |
---|
480 | void VolumeRendererShell::SetMap(unsigned char* map) { |
---|
481 | |
---|
482 | // Set map |
---|
483 | _info._map = map; |
---|
484 | _info._mapType = VOLUME_RENDERER_THREAD_INFO_MAP_8; |
---|
485 | |
---|
486 | // Set update flag |
---|
487 | _info._updateMap = true; |
---|
488 | |
---|
489 | } |
---|
490 | |
---|
491 | /*--------------------------------------------------------------------------*/ |
---|
492 | |
---|
493 | void VolumeRendererShell::SetMap8(unsigned char* map) { |
---|
494 | |
---|
495 | // Set map |
---|
496 | _info._map = map; |
---|
497 | _info._mapType = VOLUME_RENDERER_THREAD_INFO_MAP_8; |
---|
498 | |
---|
499 | // Set update flag |
---|
500 | _info._updateMap = true; |
---|
501 | |
---|
502 | } |
---|
503 | |
---|
504 | /*--------------------------------------------------------------------------*/ |
---|
505 | |
---|
506 | void VolumeRendererShell::SetMap16(unsigned char* map) { |
---|
507 | |
---|
508 | // Set map |
---|
509 | _info._map = map; |
---|
510 | _info._mapType = VOLUME_RENDERER_THREAD_INFO_MAP_16; |
---|
511 | |
---|
512 | // Set update flag |
---|
513 | _info._updateMap = true; |
---|
514 | |
---|
515 | } |
---|
516 | |
---|
517 | /*--------------------------------------------------------------------------*/ |
---|
518 | |
---|
519 | void VolumeRendererShell::SetR(float m[16]) { |
---|
520 | |
---|
521 | // Set rotation matrix |
---|
522 | _info._R[0] = m[0]; |
---|
523 | _info._R[1] = m[1]; |
---|
524 | _info._R[2] = m[2]; |
---|
525 | _info._R[3] = m[3]; |
---|
526 | |
---|
527 | _info._R[4] = m[4]; |
---|
528 | _info._R[5] = m[5]; |
---|
529 | _info._R[6] = m[6]; |
---|
530 | _info._R[7] = m[7]; |
---|
531 | |
---|
532 | _info._R[8] = m[8]; |
---|
533 | _info._R[9] = m[9]; |
---|
534 | _info._R[10] = m[10]; |
---|
535 | _info._R[11] = m[11]; |
---|
536 | |
---|
537 | _info._R[12] = m[12]; |
---|
538 | _info._R[13] = m[13]; |
---|
539 | _info._R[14] = m[14]; |
---|
540 | _info._R[15] = m[15]; |
---|
541 | |
---|
542 | // Set update flag |
---|
543 | _info._updateR = true; |
---|
544 | |
---|
545 | } |
---|
546 | |
---|
547 | /*--------------------------------------------------------------------------*/ |
---|
548 | |
---|
549 | void VolumeRendererShell::SetS(float m[16]) { |
---|
550 | |
---|
551 | // Set scale matrix |
---|
552 | _info._S[0] = m[0]; |
---|
553 | _info._S[1] = m[1]; |
---|
554 | _info._S[2] = m[2]; |
---|
555 | _info._S[3] = m[3]; |
---|
556 | |
---|
557 | _info._S[4] = m[4]; |
---|
558 | _info._S[5] = m[5]; |
---|
559 | _info._S[6] = m[6]; |
---|
560 | _info._S[7] = m[7]; |
---|
561 | |
---|
562 | _info._S[8] = m[8]; |
---|
563 | _info._S[9] = m[9]; |
---|
564 | _info._S[10] = m[10]; |
---|
565 | _info._S[11] = m[11]; |
---|
566 | |
---|
567 | _info._S[12] = m[12]; |
---|
568 | _info._S[13] = m[13]; |
---|
569 | _info._S[14] = m[14]; |
---|
570 | _info._S[15] = m[15]; |
---|
571 | |
---|
572 | // Set update flag |
---|
573 | _info._updateS = true; |
---|
574 | |
---|
575 | } |
---|
576 | |
---|
577 | /*--------------------------------------------------------------------------*/ |
---|
578 | |
---|
579 | void VolumeRendererShell::SetSliceFrequency(double frequency) { |
---|
580 | |
---|
581 | // Set slice frequency |
---|
582 | _info._sliceFrequency = frequency; |
---|
583 | |
---|
584 | // Set update flag |
---|
585 | _info._updateSliceFrequency = true; |
---|
586 | |
---|
587 | } |
---|
588 | |
---|
589 | /*--------------------------------------------------------------------------*/ |
---|
590 | |
---|
591 | void VolumeRendererShell::SetT(float m[16]) { |
---|
592 | |
---|
593 | // Set translation matrix |
---|
594 | _info._T[0] = m[0]; |
---|
595 | _info._T[1] = m[1]; |
---|
596 | _info._T[2] = m[2]; |
---|
597 | _info._T[3] = m[3]; |
---|
598 | |
---|
599 | _info._T[4] = m[4]; |
---|
600 | _info._T[5] = m[5]; |
---|
601 | _info._T[6] = m[6]; |
---|
602 | _info._T[7] = m[7]; |
---|
603 | |
---|
604 | _info._T[8] = m[8]; |
---|
605 | _info._T[9] = m[9]; |
---|
606 | _info._T[10] = m[10]; |
---|
607 | _info._T[11] = m[11]; |
---|
608 | |
---|
609 | _info._T[12] = m[12]; |
---|
610 | _info._T[13] = m[13]; |
---|
611 | _info._T[14] = m[14]; |
---|
612 | _info._T[15] = m[15]; |
---|
613 | |
---|
614 | // Set update flag |
---|
615 | _info._updateT = true; |
---|
616 | |
---|
617 | } |
---|
618 | |
---|
619 | /*--------------------------------------------------------------------------*/ |
---|
620 | |
---|
621 | void VolumeRendererShell::SetViewport(int x, int y, int w, int h) { |
---|
622 | |
---|
623 | // Set viewport |
---|
624 | _info._viewport[0] = x; |
---|
625 | _info._viewport[1] = y; |
---|
626 | _info._viewport[2] = w; |
---|
627 | _info._viewport[3] = h; |
---|
628 | |
---|
629 | // Set update flag |
---|
630 | _info._updateViewport = true; |
---|
631 | |
---|
632 | } |
---|
633 | |
---|
634 | /*--------------------------------------------------------------------------*/ |
---|
635 | |
---|
636 | void *VolumeRendererShell::ThreadFunction(void* ptr) { |
---|
637 | |
---|
638 | #ifdef SAGE |
---|
639 | |
---|
640 | // Swap buffer observer class for SAGE |
---|
641 | class SwapBuffers : public VolumeRendererCommand { |
---|
642 | |
---|
643 | public: |
---|
644 | |
---|
645 | // Constructor |
---|
646 | SwapBuffers(int width, int height, |
---|
647 | Display* display, GLXPbufferSGIX pbuffer, |
---|
648 | char* hostname, int port, |
---|
649 | float left, float right, float bottom, float top, |
---|
650 | int rank, int numberOfNodes, int* level) { |
---|
651 | |
---|
652 | // Current level |
---|
653 | _level = level; |
---|
654 | |
---|
655 | // Display variables |
---|
656 | _xDisplay = display; |
---|
657 | _glXPBuffer = pbuffer; |
---|
658 | _height = height; |
---|
659 | _width = width; |
---|
660 | |
---|
661 | // Initialize synchronizer |
---|
662 | _synchronizerClient.Init(hostname, port); |
---|
663 | |
---|
664 | // Setup SAGE viewport |
---|
665 | _sageImageMap.left = left; |
---|
666 | _sageImageMap.right = right; |
---|
667 | _sageImageMap.bottom = bottom; |
---|
668 | _sageImageMap.top = top; |
---|
669 | |
---|
670 | // SAGE parameters |
---|
671 | _sageConfig.init("VRA.conf"); |
---|
672 | _sageConfig.setAppName("VRA"); |
---|
673 | _sageConfig.rank = rank; |
---|
674 | _sageConfig.nodeNum = numberOfNodes - 1; |
---|
675 | _sageConfig.resX = _width; |
---|
676 | _sageConfig.resY = _height; |
---|
677 | _sageConfig.imageMap = _sageImageMap; |
---|
678 | _sageConfig.pixFmt = PIXFMT_888; |
---|
679 | _sageConfig.rowOrd = BOTTOM_TO_TOP; |
---|
680 | _sageConfig.master = false; |
---|
681 | _sageConfig.rendering = true; |
---|
682 | |
---|
683 | // Initialize SAGE |
---|
684 | _sageInf.init(_sageConfig); |
---|
685 | |
---|
686 | // Check buffer |
---|
687 | _image = NULL; |
---|
688 | if (_image != NULL) |
---|
689 | delete [] _image; |
---|
690 | |
---|
691 | // Get buffer from SAGE |
---|
692 | _image = (GLubyte*) _sageInf.getBuffer(); |
---|
693 | |
---|
694 | } |
---|
695 | |
---|
696 | // Destructor |
---|
697 | ~SwapBuffers() { |
---|
698 | |
---|
699 | // Finalize synchronizer |
---|
700 | _synchronizerClient.Finalize(); |
---|
701 | |
---|
702 | } |
---|
703 | |
---|
704 | // Execute callback |
---|
705 | bool Execute(int value) { |
---|
706 | |
---|
707 | // Setup readback |
---|
708 | glReadBuffer(GL_FRONT); |
---|
709 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
---|
710 | |
---|
711 | // Synchronize with other nodes |
---|
712 | _synchronizerClient.Barrier(*_level); |
---|
713 | |
---|
714 | // Swap buffer |
---|
715 | if (value == 0) { |
---|
716 | glXSwapBuffers(_xDisplay, _glXPBuffer); |
---|
717 | glReadPixels(0, 0, _width, _height, |
---|
718 | GL_RGB, GL_UNSIGNED_BYTE, _image); |
---|
719 | _sageInf.swapBuffer(); |
---|
720 | _image = (GLubyte*) _sageInf.getBuffer(); |
---|
721 | return true; |
---|
722 | } |
---|
723 | |
---|
724 | // Send current buffer |
---|
725 | else { |
---|
726 | glReadPixels(0, 0, _width, _height, |
---|
727 | GL_RGB, GL_UNSIGNED_BYTE, _image); |
---|
728 | _sageInf.swapBuffer(); |
---|
729 | _image = (GLubyte*) _sageInf.getBuffer(); |
---|
730 | return false; |
---|
731 | } |
---|
732 | |
---|
733 | } |
---|
734 | |
---|
735 | private: |
---|
736 | |
---|
737 | // Current level |
---|
738 | int* _level; |
---|
739 | |
---|
740 | // Display variables |
---|
741 | Display* _xDisplay; |
---|
742 | GLXPbufferSGIX _glXPBuffer; |
---|
743 | GLubyte* _image; |
---|
744 | int _height; |
---|
745 | int _width; |
---|
746 | |
---|
747 | // SAGE variables |
---|
748 | sageRect _sageImageMap; |
---|
749 | sail _sageInf; |
---|
750 | sailConfig _sageConfig; |
---|
751 | |
---|
752 | // Synchronizer |
---|
753 | SynchronizerClient _synchronizerClient; |
---|
754 | |
---|
755 | }; |
---|
756 | |
---|
757 | #else |
---|
758 | |
---|
759 | // Swap buffer observer class for SDL |
---|
760 | class SwapBuffers : public VolumeRendererCommand { |
---|
761 | |
---|
762 | public: |
---|
763 | |
---|
764 | // Constructor |
---|
765 | SwapBuffers(char* hostname, int port, int* level) { |
---|
766 | |
---|
767 | // Current level |
---|
768 | _level = level; |
---|
769 | |
---|
770 | // Initialize synchronizer |
---|
771 | _synchronizerClient.Init(hostname, port); |
---|
772 | |
---|
773 | } |
---|
774 | |
---|
775 | // Destructor |
---|
776 | ~SwapBuffers() { |
---|
777 | |
---|
778 | // Finalize synchronizer |
---|
779 | _synchronizerClient.Finalize(); |
---|
780 | |
---|
781 | } |
---|
782 | |
---|
783 | // Execute callback |
---|
784 | virtual bool Execute(int value) { |
---|
785 | |
---|
786 | // Synchronizer with other nodes |
---|
787 | _synchronizerClient.Barrier(*_level); |
---|
788 | |
---|
789 | // Swap buffer |
---|
790 | if (value == 0) { |
---|
791 | SDL_GL_SwapBuffers(); |
---|
792 | return true; |
---|
793 | } |
---|
794 | |
---|
795 | return false; |
---|
796 | |
---|
797 | } |
---|
798 | |
---|
799 | private: |
---|
800 | |
---|
801 | // Current level |
---|
802 | int* _level; |
---|
803 | |
---|
804 | // Synchronizer |
---|
805 | SynchronizerClient _synchronizerClient; |
---|
806 | |
---|
807 | }; |
---|
808 | |
---|
809 | #endif |
---|
810 | |
---|
811 | // Progress observer class |
---|
812 | class ProgressUpdate : public VolumeRendererCommand { |
---|
813 | public: |
---|
814 | ProgressUpdate(int* level) { |
---|
815 | _level = level; |
---|
816 | } |
---|
817 | virtual bool Execute(int value) { |
---|
818 | *_level = value; |
---|
819 | return true; |
---|
820 | } |
---|
821 | private: |
---|
822 | int* _level; |
---|
823 | }; |
---|
824 | |
---|
825 | // Abort check observer class |
---|
826 | class AbortCheck : public VolumeRendererCommand { |
---|
827 | public: |
---|
828 | AbortCheck(VolumeRendererThreadInfo* info) { |
---|
829 | _info = info; |
---|
830 | } |
---|
831 | virtual bool Execute(int value) { |
---|
832 | if (_info -> _abortFlag == true) { |
---|
833 | _info -> _abortFlag = false; |
---|
834 | return true; |
---|
835 | } |
---|
836 | return false; |
---|
837 | } |
---|
838 | private: |
---|
839 | VolumeRendererThreadInfo* _info; |
---|
840 | }; |
---|
841 | |
---|
842 | // Current level |
---|
843 | int level = 0; |
---|
844 | |
---|
845 | // Cast thread info class |
---|
846 | VolumeRendererThreadInfo* info = (VolumeRendererThreadInfo*) ptr; |
---|
847 | |
---|
848 | // Initialize display |
---|
849 | InitDisplay(info -> _displaySize[0], |
---|
850 | info -> _displaySize[1], |
---|
851 | info -> _fullScreenFlag, |
---|
852 | info -> _normalCoordinates[0], |
---|
853 | info -> _normalCoordinates[1], |
---|
854 | info -> _normalCoordinates[2], |
---|
855 | info -> _normalCoordinates[3]); |
---|
856 | |
---|
857 | // Initialize volume renderer |
---|
858 | VolumeRenderer* renderer = new VolumeRenderer; |
---|
859 | renderer -> Init(); |
---|
860 | |
---|
861 | // Abort render observer |
---|
862 | VolumeRendererCommand* ac = new AbortCheck(info); |
---|
863 | renderer -> SetAbortRenderObserver(ac); |
---|
864 | |
---|
865 | // Progress observer |
---|
866 | VolumeRendererCommand* pu = new ProgressUpdate(&level); |
---|
867 | renderer -> SetProgressObserver(pu); |
---|
868 | |
---|
869 | #ifdef SAGE |
---|
870 | |
---|
871 | // Swap buffer observer |
---|
872 | VolumeRendererCommand* sb = |
---|
873 | new SwapBuffers(info -> _displaySize[0], |
---|
874 | info -> _displaySize[1], |
---|
875 | _xDisplay, _glXPBuffer, |
---|
876 | info -> _synchronizationHostname, |
---|
877 | info -> _synchronizationPort, |
---|
878 | info -> _normalCoordinates[0], |
---|
879 | info -> _normalCoordinates[1], |
---|
880 | info -> _normalCoordinates[2], |
---|
881 | info -> _normalCoordinates[3], |
---|
882 | info -> _rank, |
---|
883 | info -> _numberOfNodes, |
---|
884 | &level); |
---|
885 | renderer -> SetSwapBuffersObserver(sb); |
---|
886 | |
---|
887 | #else |
---|
888 | |
---|
889 | // Swap buffer observer |
---|
890 | VolumeRendererCommand* sb = |
---|
891 | new SwapBuffers(info -> _synchronizationHostname, |
---|
892 | info -> _synchronizationPort, |
---|
893 | &level); |
---|
894 | renderer -> SetSwapBuffersObserver(sb); |
---|
895 | |
---|
896 | #endif |
---|
897 | |
---|
898 | // Get mutex and condition variables |
---|
899 | pthread_mutex_t* conditionMutex = info -> _conditionMutex; |
---|
900 | pthread_cond_t* conditionCond = info -> _conditionCond; |
---|
901 | |
---|
902 | // Thread loop |
---|
903 | while(info -> _exitFlag == false) { |
---|
904 | |
---|
905 | // Wait on condition variable |
---|
906 | pthread_mutex_lock(conditionMutex); |
---|
907 | while(info -> _renderFlag == false) { |
---|
908 | pthread_cond_wait(conditionCond, conditionMutex); |
---|
909 | } |
---|
910 | pthread_mutex_unlock(conditionMutex); |
---|
911 | |
---|
912 | // Check exit flag |
---|
913 | if (info -> _exitFlag == true) { |
---|
914 | continue; |
---|
915 | } |
---|
916 | |
---|
917 | // Check for update axis flag |
---|
918 | if (info -> _updateAxis == true) { |
---|
919 | if (info -> _axisOnFlag == true) { |
---|
920 | renderer -> SetAxisOn(); |
---|
921 | } |
---|
922 | else { |
---|
923 | renderer -> SetAxisOff(); |
---|
924 | } |
---|
925 | renderer -> SetAxisPosition(info -> _axisPosition[0], |
---|
926 | info -> _axisPosition[1], |
---|
927 | info -> _axisPosition[2]); |
---|
928 | info -> _updateAxis = false; |
---|
929 | } |
---|
930 | |
---|
931 | // Check for update brick box flag |
---|
932 | if (info -> _updateBrickBox == true) { |
---|
933 | if (info -> _brickBoxOnFlag == true) { |
---|
934 | renderer -> SetBrickBoxOn(); |
---|
935 | } |
---|
936 | else { |
---|
937 | renderer -> SetBrickBoxOff(); |
---|
938 | } |
---|
939 | } |
---|
940 | |
---|
941 | // Check for update bounding box flag |
---|
942 | if (info -> _updateBoundingBox == true) { |
---|
943 | if (info -> _boundingBoxOnFlag == true) { |
---|
944 | renderer -> SetBoundingBoxOn(); |
---|
945 | } |
---|
946 | else { |
---|
947 | renderer -> SetBoundingBoxOff(); |
---|
948 | } |
---|
949 | } |
---|
950 | |
---|
951 | // Check for update data flag |
---|
952 | if (info -> _updateData == true) { |
---|
953 | renderer -> SetData(info -> _data, info -> _ramSize, info -> _vramSize); |
---|
954 | info -> _updateData = false; |
---|
955 | } |
---|
956 | |
---|
957 | // Check for update frustum flag |
---|
958 | if (info -> _updateFrustum == true) { |
---|
959 | renderer -> SetFrustum(info -> _frustum[0], info -> _frustum[1], |
---|
960 | info -> _frustum[2], info -> _frustum[3], |
---|
961 | info -> _frustum[4], info -> _frustum[5]); |
---|
962 | info -> _updateFrustum = false; |
---|
963 | } |
---|
964 | |
---|
965 | // Check for update map flag |
---|
966 | if (info -> _updateMap == true) { |
---|
967 | if (info -> _mapType == VOLUME_RENDERER_THREAD_INFO_MAP_8) { |
---|
968 | renderer -> SetMapUnsigned8Int(info -> _map); |
---|
969 | } |
---|
970 | else if (info -> _mapType == VOLUME_RENDERER_THREAD_INFO_MAP_16) { |
---|
971 | renderer -> SetMapUnsigned16Int(info -> _map); |
---|
972 | } |
---|
973 | info -> _updateMap = false; |
---|
974 | } |
---|
975 | |
---|
976 | // Check for update R flag |
---|
977 | if (info -> _updateR == true) { |
---|
978 | renderer -> SetR(info -> _R); |
---|
979 | info -> _updateR = false; |
---|
980 | } |
---|
981 | |
---|
982 | // Check for update S flag |
---|
983 | if (info -> _updateS == true) { |
---|
984 | renderer -> SetS(info -> _S); |
---|
985 | info -> _updateS = false; |
---|
986 | } |
---|
987 | |
---|
988 | // Check for update slice frequency flag |
---|
989 | if (info -> _updateSliceFrequency == true) { |
---|
990 | renderer -> SetSliceFrequency(info -> _sliceFrequency); |
---|
991 | info -> _updateSliceFrequency = false; |
---|
992 | } |
---|
993 | |
---|
994 | // Check for update T flag |
---|
995 | if (info -> _updateT == true) { |
---|
996 | renderer -> SetT(info -> _T); |
---|
997 | info -> _updateT = false; |
---|
998 | } |
---|
999 | |
---|
1000 | // Check for update viewport flag |
---|
1001 | if (info -> _updateViewport == true) { |
---|
1002 | renderer -> SetViewport(info -> _viewport[0], info -> _viewport[1], |
---|
1003 | info -> _viewport[2], info -> _viewport[3]); |
---|
1004 | info -> _updateViewport = false; |
---|
1005 | } |
---|
1006 | |
---|
1007 | // Render |
---|
1008 | info -> _inRenderFlag = true; |
---|
1009 | renderer -> Render(); |
---|
1010 | info -> _abortFlag = false; |
---|
1011 | info -> _inRenderFlag = false; |
---|
1012 | |
---|
1013 | // Reset render flag |
---|
1014 | info -> _renderFlag = false; |
---|
1015 | |
---|
1016 | } |
---|
1017 | |
---|
1018 | // Clean up renderer |
---|
1019 | delete renderer; |
---|
1020 | |
---|
1021 | // Clean up abort render observer |
---|
1022 | delete ac; |
---|
1023 | |
---|
1024 | // Clean up progress observer |
---|
1025 | delete pu; |
---|
1026 | |
---|
1027 | // Clean up swap buffer observer |
---|
1028 | delete sb; |
---|
1029 | |
---|
1030 | // Clean up display |
---|
1031 | DestroyDisplay(); |
---|
1032 | |
---|
1033 | } |
---|
1034 | |
---|
1035 | /*--------------------------------------------------------------------------*/ |
---|