NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
VisualizationBVH.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, FI MUNI CZ
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the <organization> nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Authors:
28  * Marek Vinkler
29  *
30  */
31 
33 #include "ray/PixelTable.hpp"
34 
35 using namespace FW;
36 
37 #define NO_NODE FW_S32_MIN
38 #define ROOT_ADDR 0
39 
40 // Colors for the obsolete visualization
41 /*#define COLOR_NODE 0x33FFFFFF
42 #define COLOR_SIBLING 0x33000000
43 #define COLOR_LEFT 0x7F0000FF
44 #define COLOR_RIGHT 0x7F00FF00
45 #define COLOR_RAY 0xFFFFFFFF
46 #define COLOR_TRI_INVIS 0xFF000000
47 #define COLOR_TRI_VIS 0xFFFFFFFF
48 
49 #define COLOR_LEFT_SAH 0x7F0000FF
50 #define COLOR_RIGHT_SAH 0x7F00FF00
51 #define COLOR_LEFT_SVBH 0x7FFF00FF
52 #define COLOR_RIGHT_SVBH 0x7FFFFF00
53 #define COLOR_LEFT_OSAH 0x7F00FFFF
54 #define COLOR_RIGHT_OSAH 0x7FFF0000*/
55 
56 #define COLOR_NODE 0x14FFFFFF
57 #define COLOR_SIBLING 0x14000000
58 #define COLOR_LEFT 0x330000FF
59 #define COLOR_RIGHT 0x3300FF00
60 #define COLOR_RAY 0xFFFFFFFF
61 #define COLOR_TRI_INVIS 0xFF000000
62 #define COLOR_TRI_VIS 0xFFFFFFFF
63 
64 #define COLOR_LEFT_SAH 0x330000FF
65 #define COLOR_RIGHT_SAH 0x3300FF00
66 #define COLOR_LEFT_SVBH 0x33FF00FF
67 #define COLOR_RIGHT_SVBH 0x33FFFF00
68 #define COLOR_LEFT_OSAH 0x3300FFFF
69 #define COLOR_RIGHT_OSAH 0x33FF0000
70 
71 //------------------------------------------------------------------------
72 
73 VisualizationBVH::VisualizationBVH(CudaBVH* bvh, Scene* scene, const Array<AABB> &emptyBoxes, const RayBuffer* rays, Buffer* visibility)
74 : Visualization(scene),
75  m_bvh(bvh)
76 {
77  // Initialize m_node, m_sibling, m_left and m_right
78  m_bvh->getNode(m_node.addr, &m_nodeSplit, m_left.box, m_right.box, m_left.addr, m_right.addr);
79  m_node.box = m_left.box + m_right.box; // Compute the root box
80  growParentBox();
81  m_sibling.addr = NO_NODE;
82 
83  // Inititalize stacks
84  m_nodeStack.add(0);
85  m_splitPath.add(m_nodeSplit.getTypeName() + " " + m_nodeSplit.getAxisName() + ": ");
86 
87  // Clear the osah split counts in current node
88  memset(m_osahSplits, 0, sizeof(m_osahSplits));
89 
90  // Initialize rays
91  if(rays != NULL)
92  {
93  Array<Vec4f> lines;
94  const int stride = 4096;
95 
96  //PixelTable pixelTable;
97  //pixelTable.setSize(Vec2i(1024, 768));
98 
99  //for(S32 i = 0; i < 1024*32; i++)
100  //{
101  // int index = pixelTable.getPixelToIndex().getMutablePtr()[i];
102  // Ray ray = rays->getRayForSlot(index);
103  // float t;
104  // if(rays->getResultForSlot(index).hit())
105  // //t = rays->getResultForSlot(i*stride).t;
106  // t = rays->getResultForSlot(index).padA;
107  // else
108  // t = ray.tmax;
109  // lines.add(Vec4f(ray.origin, 1.0f));
110  // lines.add(Vec4f(ray.origin + t*ray.direction, 1.0f));
111  //}
112 
113  for(S32 i = 0; i < rays->getSize()/stride; i++)
114  {
115  Ray ray = rays->getRayForSlot(i*stride);
116  float t;
117  if(rays->getResultForSlot(i*stride).hit())
118  //t = rays->getResultForSlot(i*stride).t;
119  t = rays->getResultForSlot(i*stride).padA;
120  else
121  t = ray.tmax;
122  lines.add(Vec4f(ray.origin, 1.0f));
123  lines.add(Vec4f(ray.origin + t*ray.direction, 1.0f));
124  }
125 
127  m_rays.set(lines.getPtr(), lines.getNumBytes());
128  }
129  else
130  {
131  m_showRays = false;
132  }
133 
134  // Initialize empty boxes
135  Array<Vec4f> boxes, colors, lineColors, colorPalette;
136  for(int i = 0; i < emptyBoxes.getSize(); i++)
137  addBoxQuads(emptyBoxes[i], boxes);
139  m_emptyBoxes.set(boxes.getPtr(), boxes.getNumBytes());
140  // Initialize colors for empty boxes
141  /*for(int r = 1; r > -1; r--)
142  for(int g = 1; g > -1; g--)
143  for(int b = 1; b > -1; b--)*/
144  for(int r = 0; r < 2; r++)
145  for(int g = 0; g < 2; g++)
146  for(int b = 0; b < 2; b++)
147  if(r+g+b < 3)
148  colorPalette.add(Vec4f((float)r, (float)g, (float)b, 0.33f));
149  for(int i = 0; i < emptyBoxes.getSize(); i++)
150  for(int j = 0; j < 6*4; j++) // Repeate for each vertex of the box 6 faces * 4 vertices per face
151  {
152  colors.add(colorPalette[i % colorPalette.getSize()]);
153  lineColors.add(colorPalette[i % colorPalette.getSize()]);
154  lineColors.getLast().w = 1.0f;
155  }
157  m_emptyColors.set(colors.getPtr(), colors.getNumBytes());
159  m_emptyLineColors.set(lineColors.getPtr(), lineColors.getNumBytes());
160 
161  // Initialize visibility
162  if(visibility != NULL)
163  {
164  m_visibility.set((S32*)visibility->getPtr(), m_scene->getNumTriangles());
165  }
166  else
167  {
170  }
171 
177 }
178 
179 //------------------------------------------------------------------------
180 
182 {
183 }
184 
185 //------------------------------------------------------------------------
186 
188 {
189  //FW_ASSERT(m_window == ev.window || ev.type == Window::EventType_AddListener);
190 
191  // Handle events.
192 
193  switch (ev.type)
194  {
195  /*case Window::EventType_AddListener:
196  FW_ASSERT(!m_window);
197  m_window = ev.window;
198  repaint();
199  return false;
200 
201  case Window::EventType_RemoveListener:
202  repaint();
203  m_window = NULL;
204  return false;*/
205 
207  //if (ev.key == FW_KEY_V) setVisible(!m_visible);
208  if(isVisible())
209  {
210  if (ev.key == FW_KEY_B) { m_splitColors = !m_splitColors; setColorMapping(); }
211  if (ev.key == FW_KEY_J) { m_showChildren = !m_showChildren; }
212  if (ev.key == FW_KEY_U && m_rays.getSize() > 0) { m_showRays = !m_showRays; }
213  if (ev.key == FW_KEY_P && m_emptyBoxes.getSize() > 0) { m_showEmpty = !m_showEmpty; }
214  if (ev.key == FW_KEY_O) { m_showCurrTris = !m_showCurrTris; prepareTreeData(m_node.addr); }
215  if (ev.key == FW_KEY_L) { m_showAllOSAH = !m_showAllOSAH; prepareTreeData(m_node.addr); }
216  if (ev.key == FW_KEY_T) { moveToParent(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
217  if (ev.key == FW_KEY_Y) { moveToSibling(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
218  if (ev.key == FW_KEY_G) { moveToLeft(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
219  if (ev.key == FW_KEY_H) { moveToRight(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
220  if (ev.key == FW_KEY_I) { moveUp(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
221  if (ev.key == FW_KEY_K) { moveDown(); if(m_showCurrTris || m_showAllOSAH) prepareTreeData(m_node.addr); }
222  }
223  break;
224 
225  default:
226  break;
227  }
228 
229  return false;
230 }
231 
232 //------------------------------------------------------------------------
233 
235 {
236  moveUp();
237 
238  // Update path
239  m_nodeStack[m_currentDepth] = m_node.addr;
240  m_splitPath.getPtr(m_currentDepth)[m_splitPath[m_currentDepth].indexOf(':')+1] = ' ';
241  m_nodeStack.resize(m_currentDepth+1);
242  m_splitPath.resize(m_currentDepth+1);
243 }
244 
245 //------------------------------------------------------------------------
246 
248 {
249  if(m_sibling.addr == NO_NODE)
250  return;
251 
252  NodeData temp;
253  temp = m_node;
254  m_node = m_sibling;
255  m_sibling = temp;
256 
257  if(!m_bvh->isLeaf(m_node.addr))
258  {
259  m_bvh->getNode(m_node.addr, &m_nodeSplit, m_left.box, m_right.box, m_left.addr, m_right.addr);
260  }
261  // Set color mapping for visible nodes
262  setColorMapping();
263 
264  // Update path
265  m_nodeStack[m_currentDepth] = m_node.addr;
266  m_splitPath[m_currentDepth] = m_nodeSplit.getTypeName() + " " + m_nodeSplit.getAxisName() + ": ";
267  m_nodeStack.resize(m_currentDepth+1);
268  m_splitPath.resize(m_currentDepth+1);
269  if( m_splitPath.getPtr(m_currentDepth - 1)[m_splitPath[m_currentDepth].indexOf(':')+1] == 'L' )
270  m_splitPath.getPtr(m_currentDepth - 1)[m_splitPath[m_currentDepth].indexOf(':')+1] = 'R';
271  else
272  m_splitPath.getPtr(m_currentDepth - 1)[m_splitPath[m_currentDepth].indexOf(':')+1] = 'L';
273 }
274 
275 //------------------------------------------------------------------------
276 
278 {
279  if(m_bvh->isLeaf(m_left.addr))
280  return;
281 
282  m_node = m_left;
283  m_sibling = m_right;
284 
285  if(!m_bvh->isLeaf(m_node.addr))
286  {
287  m_bvh->getNode(m_node.addr, &m_nodeSplit, m_left.box, m_right.box, m_left.addr, m_right.addr);
288  }
289  else
290  {
291  m_left.addr = NO_NODE;
292  m_right.addr = NO_NODE;
293  }
294 
295  growParentBox();
296  // Set color mapping for visible nodes
297  setColorMapping();
298 
299  // Update path
300  m_splitPath.getPtr(m_currentDepth)[m_splitPath[m_currentDepth].indexOf(':')+1] = 'L';
301  m_nodeStack.resize(m_currentDepth+1);
302  m_splitPath.resize(m_currentDepth+1);
303  // Add to the path
304  m_nodeStack.add(m_node.addr);
305  m_splitPath.add(m_nodeSplit.getTypeName() + " " + m_nodeSplit.getAxisName() + ": ");
306  m_currentDepth++;
307 }
308 
309 //------------------------------------------------------------------------
310 
312 {
313  if(m_bvh->isLeaf(m_right.addr))
314  return;
315 
316  m_node = m_right;
317  m_sibling = m_left;
318 
319  if(!m_bvh->isLeaf(m_node.addr))
320  {
321  m_bvh->getNode(m_node.addr, &m_nodeSplit, m_left.box, m_right.box, m_left.addr, m_right.addr);
322  }
323  else
324  {
325  m_left.addr = NO_NODE;
326  m_right.addr = NO_NODE;
327  }
328 
329  growParentBox();
330  // Set color mapping for visible nodes
331  setColorMapping();
332 
333  // Update path
334  m_splitPath.getPtr(m_currentDepth)[m_splitPath[m_currentDepth].indexOf(':')+1] = 'R';
335  m_nodeStack.resize(m_currentDepth+1);
336  m_splitPath.resize(m_currentDepth+1);
337  // Add to the path
338  m_nodeStack.add(m_node.addr);
339  m_splitPath.add(m_nodeSplit.getTypeName() + " " + m_nodeSplit.getAxisName() + ": ");
340  m_currentDepth++;
341 }
342 
343 //------------------------------------------------------------------------
344 
346 {
347  if(m_currentDepth > 0)
348  {
349  m_currentDepth--;
350  getFromIndex(m_currentDepth);
351  }
352 }
353 
354 //------------------------------------------------------------------------
355 
357 {
358  if(m_currentDepth < m_nodeStack.getSize()-1)
359  {
360  m_currentDepth++;
361  getFromIndex(m_currentDepth);
362  }
363 }
364 
365 //------------------------------------------------------------------------
366 
368 {
369  FW_ASSERT(gl);
370 
371  if(!isVisible())
372  return;
373 
374  Mat4f oldXform = gl->setVGXform(gl->xformFitToView(-1.0f, 2.0f) * camera.getWorldToClip());
375  glPushAttrib(GL_ENABLE_BIT);
376  glEnable(GL_DEPTH_TEST);
377  glDepthFunc(GL_LESS);
378  glEnable(GL_CULL_FACE);
379  glFrontFace(GL_CW);
380 
381  // Draw primary rays
382  drawRays(gl, m_rayColor);
383 
384  // Obsolete visualization, boxes hide each other
385  // Draw back faces of bounding boxes - for correct depth
386  /*glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
387  //glCullFace(GL_FRONT);
388  drawNodes(gl, true);
389  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
390 
391  // Draw front faces of bounding boxes - for blending
392  glDisable(GL_DEPTH_TEST);
393  glDepthFunc(GL_LEQUAL);
394  glCullFace(GL_BACK);
395  drawNodes(gl, false);*/
396 
397  // New Visualization, all rays are visible
398  // Render boxes and primitives without culling so everything is visible
399  glDisable(GL_DEPTH_TEST);
400  glDisable(GL_CULL_FACE);
401 
402  // Draw boxes
403  drawNodes(gl, false);
404 
405  // Draw primitives
406  drawPrimitives(gl);
407 
408  //glDisable(GL_DEPTH_TEST);
409  glPopAttrib();
410  gl->setVGXform(oldXform);
411 
412  // Draw path information
413  drawPathInfo(gl);
414 }
415 
416 //------------------------------------------------------------------------
417 
418 void VisualizationBVH::getFromIndex(S32 idx)
419 {
420  if(idx < 0 || idx > m_nodeStack.getSize()-1)
421  return;
422 
423  if(!m_bvh->isLeaf(m_nodeStack[idx]))
424  {
425  m_bvh->getNode(m_nodeStack[idx], &m_nodeSplit, m_left.box, m_right.box, m_left.addr, m_right.addr);
426  }
427  else
428  {
429  m_left.addr = NO_NODE;
430  m_right.addr = NO_NODE;
431  }
432 
433  if(idx > 0) // Node is not the root, we can find its sibling
434  {
435  S32 parent = m_nodeStack[idx-1];
436  NodeData left, right;
437 
438  m_bvh->getNode(parent, NULL, left.box, right.box, left.addr, right.addr);
439 
440  if(left.addr == m_nodeStack[idx]) // Left child is the current node
441  {
442  m_node = left;
443  m_sibling = right;
444  }
445  else // Right child is the current node
446  {
447  m_node = right;
448  m_sibling = left;
449  }
450  }
451  else // Node is the root, we need to compute the box and disable sibling
452  {
453  m_node.addr = m_nodeStack[idx];
454  m_node.box = m_left.box + m_right.box;
455  m_sibling.addr = NO_NODE;
456  }
457 
458  growParentBox();
459  // Set color mapping for visible nodes
460  setColorMapping();
461 }
462 
463 //------------------------------------------------------------------------
464 
465 void VisualizationBVH::growParentBox()
466 {
467  float incrTop = (m_node.box.max() - m_node.box.min()).length() / 50.0f;
468  //float incrBottom = incrTop / 2.0f;
469  m_node.box.grow(m_node.box.min()-incrTop/*-0.01f*/); // Grow the parent box to avoid z-fighting
470  m_node.box.grow(m_node.box.max()+incrTop/*+0.01f*/); // Grow the parent box to avoid z-fighting
471 
472  if(m_sibling.addr != NO_NODE) // Root node has no sibling
473  {
474  m_sibling.box.grow(m_sibling.box.min()-incrTop/*+0.01f*/); // Grow the sibling box to avoid z-fighting
475  m_sibling.box.grow(m_sibling.box.max()+incrTop/*-0.01f*/); // Grow the sibling box to avoid z-fighting
476  }
477 }
478 
479 //------------------------------------------------------------------------
480 
481 void VisualizationBVH::drawNodes(GLContext* gl, bool onlyChildren)
482 {
483  // Draw children of the current node
484  if(m_showChildren)
485  {
486  drawBox(gl, m_left, m_leftColor);
487  drawBox(gl, m_right, m_rightColor);
488  }
489 
490  // Draw current node and its sibling
491  if(!onlyChildren)
492  {
493  drawBox(gl, m_node, m_nodeColor);
494  drawBox(gl, m_sibling, m_siblingColor);
495  }
496 
497  // Draw visible child of the OSAH split
499  {
500  if(!onlyChildren)
501  {
502  // Draw filled faces
503  if(m_showEmpty)
504  gl->drawColorBuffer(m_emptyBoxes, m_emptyColors, GL_QUADS, 0);
505  //glDepthFunc(GL_ALWAYS);
506 
507  // Draw edges, use opaque ray color
508  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
509  if(m_showAllOSAH)
510  gl->drawBuffer(m_boxes, GL_QUADS, 0, COLOR_RAY);
511  if(m_showEmpty)
513  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
514  //glDepthFunc(GL_LEQUAL);
515  }
516  }
517 }
518 
519 //------------------------------------------------------------------------
520 
521 void VisualizationBVH::drawBox(GLContext* gl, const NodeData &node, U32 abgr)
522 {
523  if(node.addr != NO_NODE)
524  {
525  // Draw filled faces
526  gl->drawBox(node.box.min(), node.box.max(), abgr);
527  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
528  // Draw edges, use the same color but opaque
529  gl->drawBox(node.box.min(), node.box.max(), abgr | 0xFF000000);
530  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
531  }
532 }
533 
534 //------------------------------------------------------------------------
535 
536 void VisualizationBVH::drawRays(GLContext* gl, U32 abgr)
537 {
538  if(m_showRays)
539  {
540  glLineWidth(2.0f);
541  gl->drawBuffer(m_rays, GL_LINES, 0, abgr);
542  glLineWidth(1.0f);
543  }
544 }
545 
546 //------------------------------------------------------------------------
547 
548 void VisualizationBVH::drawPrimitives(GLContext* gl)
549 {
550  if(m_showCurrTris)
551  {
552  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
553  gl->drawBuffer(m_invisTris, GL_TRIANGLES, 0, COLOR_TRI_INVIS);
554  gl->drawBuffer(m_visTris, GL_TRIANGLES, 0, COLOR_TRI_VIS);
555  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
556  }
557 }
558 
559 //------------------------------------------------------------------------
560 
561 void VisualizationBVH::drawPathInfo(GLContext* gl)
562 {
563  S32 fontSize = 16;
564  Vec2f origin = Vec2f(8.0f, (F32)gl->getViewSize().y - 4.0f);
565  Vec2f pos = origin;
566 
567  Mat4f oldXform = gl->setVGXform(gl->xformMatchPixels());
568  gl->setFont("Arial", fontSize, GLContext::FontStyle_Bold);
569 
570  char leftBox[100], rightBox[100];
571  m_left.box.min().sprint(leftBox, 100);
572  strcat_s(leftBox, ", ");
573  m_left.box.max().sprint(leftBox + strlen(leftBox), 100-strlen(leftBox));
574  m_right.box.min().sprint(rightBox, 100);
575  strcat_s(rightBox, ", ");
576  m_right.box.max().sprint(rightBox + strlen(rightBox), 100-strlen(rightBox));
577 
578  if(m_showCurrTris)
579  {
580  gl->drawLabel(sprintf("Left count: %u Right count: %u",
581  m_leftPrims, m_rightPrims), pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
582  pos.y -= (F32)fontSize;
583  gl->drawLabel(sprintf("Left area: %.2f (%s) Right area: %.2f (%s)",
584  m_left.box.area(), leftBox, m_right.box.area(), rightBox), pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
585  }
586  else
587  {
588  gl->drawLabel(sprintf("Left area: %.2f (%s) Right area: %.2f (%s)",
589  m_left.box.area(), leftBox, m_right.box.area(), rightBox), pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
590  }
591  pos.y -= (F32)fontSize;
592  gl->drawLabel(sprintf("Current depth: %d Path depth: %d OSAH split counts: %d x- %d y- %d z-axis",
593  m_currentDepth, m_nodeStack.getSize()-1, m_osahSplits[0], m_osahSplits[1], m_osahSplits[2]), pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
594  pos.y -= (F32)fontSize;
595 
596  const float rightMargin = 100.0f;
597  String header("Split path: ");
598  gl->drawLabel(header, pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
599  pos.x += gl->getStringSize(header).x;
600 
601  // Write path before the current node
602  for(S32 i = 0; i < m_currentDepth; i++)
603  {
604  if(pos.x > (F32)gl->getViewSize().x - rightMargin)
605  {
606  pos.x = origin.x;
607  pos.y -= (F32)fontSize;
608  }
609 
610  String cur = m_splitPath[i] + "| ";
611  gl->drawLabel(cur, pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
612  pos.x += gl->getStringSize(cur).x;
613  }
614 
615  // Write the current node
616  if(pos.x > (F32)gl->getViewSize().x - rightMargin)
617  {
618  pos.x = origin.x;
619  pos.y -= (F32)fontSize;
620  }
621  gl->drawLabel(m_splitPath[m_currentDepth], pos, Vec2f(0.0f, 1.0f), 0xFF0000FF);
622  pos.x += gl->getStringSize(m_splitPath[m_currentDepth]).x;
623 
624  // Write path after the current node
625  for(S32 i = m_currentDepth+1; i < m_splitPath.getSize(); i++)
626  {
627  if(pos.x > (F32)gl->getViewSize().x - rightMargin)
628  {
629  pos.x = origin.x;
630  pos.y -= (F32)fontSize;
631  }
632 
633  String cur = String("| ") + m_splitPath[i];
634  gl->drawLabel(cur, pos, Vec2f(0.0f, 1.0f), 0xFFFFFFFF);
635  pos.x += gl->getStringSize(cur).x;
636  }
637 
638  gl->setVGXform(oldXform);
639  gl->setDefaultFont();
640 }
641 
642 //-----------------------------------------------------------------------
643 
644 void VisualizationBVH::setColorMapping()
645 {
646  if(!m_splitColors)
647  {
650  return;
651  }
652 
653  if(m_nodeSplit.getType() == SplitInfo::SAH)
654  {
657  }
658  else if(m_nodeSplit.getType() == SplitInfo::SBVH)
659  {
662  }
663  else
664  {
667  }
668 }
669 
670 //-----------------------------------------------------------------------
671 
672 void VisualizationBVH::prepareTreeData(S32 node)
673 {
674  S32 stack[100];
675  int stackIndex = 1;
676  Array<Vec4f> boxes;
677  Array<Vec4f> verticesInvis;
678  Array<Vec4f> verticesVis;
679  Array<S32> indices;
680  U32 prims = 0;
681  S32 rightChild = 0;
682 
683  // Clear the osah split counts in current node
684  memset(m_osahSplits, 0, sizeof(m_osahSplits));
685 
686  while(stackIndex > 0)
687  {
688  for(;;)
689  {
690  if(node < 0)
691  {
692  if(m_showCurrTris) // Process triangle
693  {
694  indices.clear();
695  m_bvh->getTriangleIndices(node, indices);
696  prims += indices.getSize();
697 
698  for(int i = 0; i < indices.getSize(); i++)
699  {
700  Array<Vec4f> *ptr = &verticesInvis;
701  if(m_visibility[indices[i]])
702  ptr = &verticesVis;
703 
704  //const Vec3i& ind = m_bvh->getScene()->getTriangle(indices[i]).vertices;
705  const Vec3i& ind = *(Vec3i*)m_scene->getTriVtxIndexBuffer().getPtr();
706  for(int j = 0; j < 3; j++)
707  {
708  //const Vec3f& v = m_bvh->getScene()->getVertex(ind[j]);
709  const Vec3f& v = (Vec3f)(m_scene->getVtxPosBuffer()[ind[j]]);
710  ptr->add(Vec4f(v, 1.0f));
711  }
712  }
713  }
714 
715  break;
716  }
717  else
718  {
719  AABB child0, child1;
720  S32 child0Addr, child1Addr;
721  SplitInfo splitInfo;
722 
723  m_bvh->getNode(node, &splitInfo, child0, child1, child0Addr, child1Addr);
724  if(m_showCurrTris && rightChild == 0)
725  rightChild = child1Addr;
726 
727  if(m_showAllOSAH && splitInfo.getOSAHChosen()) // Process split
728  {
729  m_osahSplits[splitInfo.getAxis()]++;
730  // Compute the box
731  //AABB bbox = child0 + child1;
732  //AABB bbox = child0; // child with more visible triangles in case of OSAH split
733  //addBoxQuads(bbox, boxes);
734  addBoxQuads(child0, boxes);
735  addBoxQuads(child1, boxes);
736  }
737 
738  node = child0Addr;
739  stack[stackIndex++] = child1Addr;
740  }
741  }
742  stackIndex--;
743  node = stack[stackIndex];
744  if(m_showCurrTris && node == rightChild)
745  {
746  m_leftPrims = prims;
747  prims = 0;
748  }
749  }
750 
751  if(m_showAllOSAH)
752  {
754  m_boxes.set(boxes.getPtr(), boxes.getNumBytes());
755  }
756 
757  if(m_showCurrTris)
758  {
759  m_rightPrims = prims;
760  m_invisTris.resizeDiscard(verticesInvis.getNumBytes());
761  m_invisTris.set(verticesInvis.getPtr(), verticesInvis.getNumBytes());
762  m_visTris.resizeDiscard(verticesVis.getNumBytes());
763  m_visTris.set(verticesVis.getPtr(), verticesVis.getNumBytes());
764  }
765 }
766 
767 //-----------------------------------------------------------------------
768 
769 void VisualizationBVH::addBoxQuads(const AABB &box, Array<Vec4f> &buffer)
770 {
771  Vec3f min = box.min();
772  Vec3f max = box.max();
773  // Add buffer as 4 quads
774  // Min x
775  buffer.add(Vec4f(min.x, min.y, min.z, 1.0f));
776  buffer.add(Vec4f(min.x, max.y, min.z, 1.0f));
777  buffer.add(Vec4f(min.x, max.y, max.z, 1.0f));
778  buffer.add(Vec4f(min.x, min.y, max.z, 1.0f));
779  // Max x
780  buffer.add(Vec4f(max.x, max.y, max.z, 1.0f));
781  buffer.add(Vec4f(max.x, max.y, min.z, 1.0f));
782  buffer.add(Vec4f(max.x, min.y, min.z, 1.0f));
783  buffer.add(Vec4f(max.x, min.y, max.z, 1.0f));
784  // Min y
785  buffer.add(Vec4f(min.x, min.y, min.z, 1.0f));
786  buffer.add(Vec4f(min.x, min.y, max.z, 1.0f));
787  buffer.add(Vec4f(max.x, min.y, max.z, 1.0f));
788  buffer.add(Vec4f(max.x, min.y, min.z, 1.0f));
789  // Max y
790  buffer.add(Vec4f(max.x, max.y, max.z, 1.0f));
791  buffer.add(Vec4f(min.x, max.y, max.z, 1.0f));
792  buffer.add(Vec4f(min.x, max.y, min.z, 1.0f));
793  buffer.add(Vec4f(max.x, max.y, min.z, 1.0f));
794  // Min z
795  buffer.add(Vec4f(min.x, min.y, min.z, 1.0f));
796  buffer.add(Vec4f(max.x, min.y, min.z, 1.0f));
797  buffer.add(Vec4f(max.x, max.y, min.z, 1.0f));
798  buffer.add(Vec4f(min.x, max.y, min.z, 1.0f));
799  // Max z
800  buffer.add(Vec4f(max.x, max.y, max.z, 1.0f));
801  buffer.add(Vec4f(max.x, min.y, max.z, 1.0f));
802  buffer.add(Vec4f(min.x, min.y, max.z, 1.0f));
803  buffer.add(Vec4f(min.x, max.y, max.z, 1.0f));
804 }
805 
806 //------------------------------------------------------------------------
#define FW_KEY_L
Definition: Keys.hpp:204
#define COLOR_LEFT_OSAH
Class for the visualization.
FW_CUDA_FUNC T length(const VectorBase< T, L, S > &v)
Definition: Math.hpp:459
S32 getSize() const
Gets size of the buffer (number of rays).
Definition: RayBuffer.hpp:52
#define NULL
Definition: Defs.hpp:39
Definitions for the BVH visualization framework.
#define COLOR_LEFT
void set(const void *ptr)
Definition: Buffer.hpp:92
#define COLOR_SIBLING
Cuda BVH class.
Definition: CudaBVH.hpp:93
Buffer & getTriVtxIndexBuffer(void)
Returns buffer of triangle's vertex indieces.
Definition: Scene.hpp:75
S32 m_currentDepth
Current node's depth information.
Buffer m_emptyLineColors
Buffer holding line colors of empty boxes as quad primitives.
Mat4f setVGXform(const Mat4f &m)
Definition: GLContext.hpp:171
void setDefaultFont(void)
Definition: GLContext.hpp:188
U32 m_nodeColor
Color of the current node.
FW_CUDA_FUNC const Vec3f & max(void) const
Definition: Util.hpp:49
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer
Definition: DLLImports.inl:315
String getTypeName() const
Definition: BVHNode.hpp:110
bool m_showEmpty
Flag whether to show empty nodes.
void draw(GLContext *gl, CameraControls &camera)
The method used to draw the current state of visualization to the OpenGL context. ...
S32 m_osahSplits[3]
Counters of the number of OSAH splits in the subtree under the set node in the x, y and z dimensions...
void ** ptr
Definition: DLLImports.cpp:74
Buffer m_rays
Buffer holding some rays as line segments.
void moveDown()
Sets the node to be visualized to be the succesor of the currently visualized node on the set path...
Buffer & getVtxPosBuffer(void)
Returns vertex position buffer.
Definition: Scene.hpp:103
Vec2i drawLabel(const String &str, const Vec4f &pos, const Vec2f &align, U32 fgABGR, U32 bgABGR)
Definition: GLContext.cpp:704
FW_CUDA_FUNC bool hit(void) const
Definition: Util.hpp:80
#define FW_KEY_J
Definition: Keys.hpp:202
#define COLOR_TRI_INVIS
U32 m_leftColor
Color of the left child of the current node.
Buffer m_emptyBoxes
Buffer holding empty boxes as quad primitives.
#define COLOR_RAY
void moveUp()
Sets the node to be visualized to be the predecesor of the currently visualized node on the set path...
bool getOSAHChosen() const
Definition: BVHNode.hpp:100
Definition: Util.hpp:62
S64 getSize(void) const
Definition: Buffer.hpp:69
void clear(void)
Definition: Array.hpp:359
void drawBuffer(Buffer &buffer, GLenum mode, int offset, U32 abgr)
Definition: GLContext.cpp:479
void moveToRight()
Sets the node to be visualized to be the right child of the currently visualized node.
Vec2i getStringSize(const String &str)
Definition: GLContext.cpp:674
Mat4f getWorldToClip(void) const
const Ray & getRayForSlot(S32 slot) const
Gets a ray assigned to a given slot.
Definition: RayBuffer.hpp:89
const U8 * getPtr(S64 ofs=0)
Definition: Buffer.hpp:106
#define COLOR_RIGHT
S32 getNumBytes(void) const
void drawColorBuffer(Buffer &buffer, Buffer &color, GLenum mode, int offset)
Definition: GLContext.cpp:558
bool m_splitColors
Flag whether to map left/right children colors based on the split type.
Mat4f xformFitToView(const Vec2f &pos, const Vec2f &size) const
Definition: GLContext.hpp:151
bool m_showAllOSAH
Flag whether to show all OSAH split nodes.
SplitAxis getAxis() const
Definition: BVHNode.hpp:115
Vec3f origin
Definition: Util.hpp:67
void reset(S size=0)
Definition: Array.hpp:317
float F32
Definition: Defs.hpp:89
const T & getLast(void) const
#define COLOR_NODE
#define COLOR_TRI_VIS
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v
Definition: DLLImports.inl:329
void moveToLeft()
Sets the node to be visualized to be the left child of the currently visualized node.
void moveToSibling()
Sets the node to be visualized to be the sibling of the currently visualized node.
Buffer m_visTris
Buffer holding invisible selected triangles.
#define FW_KEY_I
Definition: Keys.hpp:201
Ray buffer class. Stores rays.
Definition: RayBuffer.hpp:38
#define COLOR_RIGHT_OSAH
FW_CUDA_FUNC T min(const VectorBase< T, L, S > &v)
Definition: Math.hpp:461
Vec3f direction
Definition: Util.hpp:69
FW_CUDA_FUNC T max(const VectorBase< T, L, S > &v)
Definition: Math.hpp:462
void setFont(const String &name, int size, U32 style)
Definition: GLContext.cpp:645
int getNumTriangles(void) const
Definition: Scene.hpp:61
#define COLOR_LEFT_SAH
String getAxisName() const
Definition: BVHNode.hpp:120
float tmax
Definition: Util.hpp:70
#define FW_ASSERT(X)
Definition: Defs.hpp:67
#define FW_KEY_B
Definition: Keys.hpp:194
signed int S32
Definition: Defs.hpp:88
#define FW_KEY_H
Definition: Keys.hpp:200
#define COLOR_RIGHT_SVBH
S32 padA
Definition: Util.hpp:85
U32 m_rayColor
Color of the ray line indices.
#define NO_NODE
Array< String > m_splitPath
Text representation of the VisualizationBVH::m_nodeStack path.
Mat4f xformMatchPixels(void) const
Definition: GLContext.hpp:152
T & add(void)
Definition: Array.hpp:384
FW_CUDA_FUNC const Vec3f & min(void) const
Definition: Util.hpp:48
String sprintf(const char *fmt,...)
Definition: Defs.cpp:241
void moveToParent()
Sets the node to be visualized to be the parent of the currently visualized node. ...
bool isVisible() const
Return whether the visualization renders its output.
VisualizationBVH(CudaBVH *bvh, Scene *scene, const Array< AABB > &emptyBoxes, const RayBuffer *rays=NULL, Buffer *visibility=NULL)
Constructor.
unsigned int U32
Definition: Defs.hpp:85
#define FW_KEY_Y
Definition: Keys.hpp:217
#define FW_KEY_O
Definition: Keys.hpp:207
#define FW_KEY_U
Definition: Keys.hpp:213
Class holding information about a split of a BVH node.
Definition: BVHNode.hpp:58
Class holding 3d scene.
Definition: Scene.hpp:44
bool m_showRays
Flag whether to show the ray segments.
Buffer m_emptyColors
Buffer holding colors of empty boxes as quad primitives.
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid pixels GLint GLsizei const GLfloat value GLint GLfloat GLfloat v1 GLint GLfloat GLfloat GLfloat v2 GLint GLsizei const GLfloat value GLint GLsizei GLboolean const GLfloat value GLuint program GLuint GLfloat GLfloat GLfloat z GLuint GLint GLenum GLboolean GLsizei stride
Definition: DLLImports.inl:365
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction f
Definition: DLLImports.inl:88
#define FW_KEY_T
Definition: Keys.hpp:212
U32 m_rightPrims
Number of primitives in the right child of the current node.
const RayResult & getResultForSlot(S32 slot) const
Gets a ray result assigned to a given slot.
Definition: RayBuffer.hpp:103
bool isLeaf(S32 node)
Definition: CudaBVH.hpp:185
#define COLOR_RIGHT_SAH
virtual bool handleEvent(const Window::Event &ev)
Handles visualization events - key commands influencing the output.
#define COLOR_LEFT_SVBH
bool m_showChildren
Flag whether to show children of the current node.
void drawBox(const Vec3f &min, const Vec3f &max, U32 abgr)
Definition: GLContext.cpp:383
EventType type
Definition: Window.hpp:69
Buffer m_boxes
Buffer holding selected boxes as quad primitives.
T set(S idx, const T &item)
Definition: Array.hpp:248
U32 m_rightColor
Color of the right child of the current node.
void getTriangleIndices(S32 node, Array< S32 > &indices)
Definition: CudaBVH.cpp:341
const Vec2i & getViewSize(void) const
Definition: GLContext.hpp:148
#define FW_KEY_K
Definition: Keys.hpp:203
#define FW_KEY_G
Definition: Keys.hpp:199
bool m_showCurrTris
Flag whether to show triangles of the current node.};.
void getNode(S32 node, SplitInfo *splitInfo, AABB &child0, AABB &child1, S32 &child0Addr, S32 &child1Addr)
Definition: CudaBVH.cpp:323
const T * getPtr(S32idx=0) const
U32 m_siblingColor
Color of the sibling of the current node.
void resizeDiscard(S64 size)
Definition: Buffer.hpp:83
U32 m_leftPrims
Number of primitives in the left child of the current node.
void resize(S size)
Definition: Array.hpp:366
Array< S32 > m_visibility
Visibility of individual triangles.
S32 getSize(void) const
~VisualizationBVH(void)
Destructor.
Buffer m_invisTris
Buffer holding visible selected triangles.
SplitType getType() const
Definition: BVHNode.hpp:105
#define FW_KEY_P
Definition: Keys.hpp:208