Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r1002 - in trunk: Model/Groups Model/Readers scenes


Chronological Thread 
  • From: bigler@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r1002 - in trunk: Model/Groups Model/Readers scenes
  • Date: Thu, 6 Apr 2006 16:49:47 -0600 (MDT)

Author: bigler
Date: Thu Apr  6 16:49:46 2006
New Revision: 1002

Modified:
   trunk/Model/Groups/CMakeLists.txt
   trunk/Model/Groups/KDTree2.cc
   trunk/Model/Groups/KDTree2.h
   trunk/Model/Groups/KDTreeLoaderIW.cc
   trunk/Model/Readers/IW.cc
   trunk/Model/Readers/IW.h
   trunk/scenes/iwviewer.cc
Log:

Model/Groups/CMakeLists.txt

  Added KDTree2.{cc,h}

Model/Groups/KDTree2.cc
Model/Groups/KDTree2.h

  Loads data from IWObject and IWNode.

  Intersection and shading seem to work properly, although there are
  some stippled triangles.  Those are present in the WaldTriangle
  version (which I stole the intersection code from), so I'm inclined
  to think it comes from that.

Model/Groups/KDTreeLoaderIW.cc

  Moved the bsp file parsing stuff to IW.{h,cc}.

Model/Readers/IW.cc
Model/Readers/IW.h

  Added file parsing stuff for IW's kd-trees.

scenes/iwviewer.cc

  You can now load in kd-trees by specifying a -bsp <filename> on the
  command line.


Modified: trunk/Model/Groups/CMakeLists.txt
==============================================================================
--- trunk/Model/Groups/CMakeLists.txt   (original)
+++ trunk/Model/Groups/CMakeLists.txt   Thu Apr  6 16:49:46 2006
@@ -22,6 +22,8 @@
      Groups/KDTreeLoader.h
      Groups/KDTreeLoaderIW.cc
      Groups/KDTreeLoaderIW.h
+     Groups/KDTree2.cc
+     Groups/KDTree2.h
      Groups/PsiGammaTable.cc
      Groups/PsiGammaTable.h
      Groups/RealisticBvh.cc

Modified: trunk/Model/Groups/KDTree2.cc
==============================================================================
--- trunk/Model/Groups/KDTree2.cc       (original)
+++ trunk/Model/Groups/KDTree2.cc       Thu Apr  6 16:49:46 2006
@@ -27,16 +27,121 @@
 */
 
 #include <Model/Groups/KDTree2.h>
+#include <Interface/RayPacket.h>
+#include <Model/Intersections/AxisAlignedBox.h>
+#include <Core/Color/ColorSpace.h>
+#include <Model/Readers/IW.h>
+#include <MantaTypes.h>
+
+#include <Core/Math/MiscMath.h>
+
+#include <stdlib.h>
+
+#include <stack>
+
+using namespace Manta;
+using namespace SCIRun;
+
+KDTree2::KDTree2(Material* material_in)
+  : PrimitiveCommon( material_in ),
+
+    triangles(NULL), num_tris(0),
+    tri_indices(NULL), num_tri_indices(0),
+    group_ids(NULL),
+    group_colors(NULL), num_groups(0)
+{
+}
+
+int
+KDTree2::loadIW(IWObject* iw, IWTree* tree) {
+  // Allocate memory
+  reserveTriangles(iw->triangles.size());
+  reserveTriangleIndices(tree->num_tri_indices);
+  reserveGroupIDs();
+  reserveGroupColors(iw->shaders.size());
+  unsigned int num_nodes = tree->num_nodes + tree->num_empty_nodes;
+  Node* nodes = static_cast<Node*>(malloc(num_nodes*sizeof(Node)));
+  rootNode = nodes;
+
+  bbox.reset();
+  
+  // Load in the triangles
+  for(size_t ti = 0; ti < iw->triangles.size(); ++ti) {
+    Vector va(iw->va(ti));
+    Vector vb(iw->vb(ti));
+    Vector vc(iw->vc(ti));
+
+    // Do bounding box extension
+    bbox.extendByPoint(va);
+    bbox.extendByPoint(vb);
+    bbox.extendByPoint(vc);
+
+    // Create the triangle and copy it over
+    Triangle tri(va, vc, vb);
+    triangles[ti] = tri;
+
+    // Copy of the color id
+    group_ids[ti] = iw->triangles[ti][3];
+  }
+
+  // Load in the colors
+  for(size_t ci = 0; ci < iw->shaders.size(); ++ci) {
+    group_colors[ci] = iw->shaders[ci];
+  }
+
+  // Load in the kd-tree data
+  Node* current_node = nodes;
+  unsigned int current_node_index = 0;
+  unsigned int current_tri_index = 0;
+
+  IWNode* top = tree->head;
+  top->index = current_node_index++;
+  std::stack<IWNode*> nodestack;
+  nodestack.push(top);
+  while(!nodestack.empty()) {
+    Node& node = nodes[top->index];
+    if (top->isNode()) {
+      // Node
+      node.type = top->flags;
+      node.split = top->split;
+
+      // Assign the left and right nodes
+      node.leftChild = nodes + current_node_index;
+      // For relative references you can do this:
+      // node.leftChild = current_node_index - top->index;
+
+      ASSERT(top->left);
+      ASSERT(top->right);
+      top->left->index  = current_node_index++;
+      top->right->index = current_node_index++;
+
+      // Push the children on the stack
+      nodestack.push(top->left);
+      nodestack.push(top->right);
+      
+    } else {
+      // Leaf
+      node.type = 3;
+      node.listLen = top->num_tris;
+      node.listBegin = current_tri_index;
+      unsigned int* tri_ids_p = tri_indices + current_tri_index;
+      for(unsigned int i = 0; i < node.listLen; ++i) {
+        *tri_ids_p = top->tri_ids[i];
+        ++tri_ids_p;
+      }
+      current_tri_index += node.listLen;
+    }
+    top = nodestack.top();
+    nodestack.pop();
+  }
+
+  return 0;
+}
 
 KDTree2::Triangle::Triangle(const Vector& _p1,
                             const Vector& _p2,
                             const Vector& _p3)
 {
-  box.reset();
-  box.extendByPoint(_p1);
-  box.extendByPoint(_p2);
-  box.extendByPoint(_p3);
-
   Vector normal = Cross(_p2-_p1, _p3-_p1);
   normal.normalize();
 
@@ -90,8 +195,6 @@
   rays.computeInverseDirections();
   rays.computeSigns();
 
-  RayTriIntersectUserData isectData;
-
   for(int i=rays.begin();i<rays.end();i++) {
 
     Real minDist, maxDist;
@@ -106,26 +209,158 @@
         // Determine the actual minimum distance.
         minDist = SCIRun::Max( minDist, T_EPSILON );
         maxDist = SCIRun::Min( maxDist, rays.getMinT(i) );
+        if (minDist > maxDist) continue;
 
-        // Send the ray to the _intersect function.
-        isectData.rayHitTriIndex = -1;
-        isectData.duplicate = 0;
-        intersect_node( rootNode, rays, i, isectData, context, 
(float)minDist, (float)maxDist);
+        intersect_node( rootNode,
+                        rays,
+                        i,
+                        (float)minDist,
+                        (float)maxDist );
 
       }
   }
 }
 
 void
-KDTree2::computeNormal(const RenderContext& context, RayPacket &rays) const {
+KDTree2::intersect_node( Node* start_node, RayPacket& rays, int which,
+                         float minDist, float maxDist ) const {
+  float near = minDist;
+  float far  = maxDist;
+  
+  Stack stack[MaxStackSize];
+  Stack *sptr = stack;
+
+  // mailBox.clear(); //...
+
+  RayPacketData* data = rays.data;
+  const int ray_signs[3] = { data->signs[0][which],
+                             data->signs[1][which],
+                             data->signs[2][which] };
+  const float origin[3] = { data->origin[0][which],
+                            data->origin[1][which],
+                            data->origin[2][which] };
+  const float direction[3] = { data->direction[0][which],
+                               data->direction[1][which],
+                               data->direction[2][which] };
+  const float invDir[3] = { data->inverseDirection[0][which],
+                            data->inverseDirection[1][which],
+                            data->inverseDirection[2][which] };
+  Node* node = start_node;
+
+  do {
+    while (node->type != 3 /* leaf */ ) {
+      int axis = node->type;
+      float dist = (node->split - origin[axis]) * invDir[axis];
+      
+      Node* nearChild = node->leftChild + ray_signs[axis];
+      Node* farChild  = node->leftChild + (1-ray_signs[axis]);
+      
+      if (dist > far) // if interval (far end) is infront of the plane
+        {
+          node = nearChild;
+          continue;
+        }
+      if (dist < near) // KEEP THE ORDER OF COMPARISONS (nan's etc)
+        {
+          node = farChild;
+          continue;
+        }
+      // else: have to traverse both children
+      node = nearChild;
+      
+      // push  farchild [dist..far]
+      sptr->node = farChild;
+      sptr->far = far;
+      sptr++;
+      // go to nearchild [near...dist]
+      far = dist;
+      node = nearChild;
+    }
+    
+    // now, have a leaf
+    if (node->listLen > 0) {
+      int hit_tri = -1;
+//       fprintf(stderr, "node(%u): listBegin = %u, listLen = %u\n",
+//               (rootNode-node)/sizeof(Node), node->listBegin, 
node->listLen);
+      for (int tri_index=node->listBegin;
+           tri_index<node->listBegin+node->listLen;
+           ++tri_index) {
+        //            intersectTriangle(....); // with mailboxing
+        const Triangle& tri = triangles[tri_indices[tri_index]];
+        const int axis = tri.k;
+        const int ku = (axis==2)?0:axis+1;
+        const int kv = (axis==0)?2:axis-1;
+          
+        const float n_u    = tri.n_u;
+        const float n_v    = tri.n_v;
+        const float n_d    = tri.n_d;
+            
+        const float org_k  = origin[axis];
+        const float org_ku = origin[ku];
+        const float org_kv = origin[kv];
+        const float f0     = n_d - (org_k + n_u * org_ku + n_v * org_kv);
+
+        const float dir_k  = direction[axis];
+        const float dir_ku = direction[ku];
+        const float dir_kv = direction[kv];
+
+        const float nd0 = n_u * dir_ku + n_v * dir_kv + dir_k;
+        const float nd  = 1.f/nd0;
+
+        const float f = f0 * nd;
+        // plane test
+        if ( f < T_EPSILON || f > data->minT[which] )
+          continue;
+
+        const float hu = org_ku + f*dir_ku;
+        const float hv = org_kv + f*dir_kv;
+        const float lambda = tri.b_d + hu*tri.b_nu + hv * tri.b_nv;
+
+        // barycentric test
+        if ( lambda < 0.f )
+          continue;
+
+        const float mue = tri.c_d + hu * tri.c_nu + hv * tri.c_nv;
+        if ( mue < 0.f || mue + lambda > 1.f )
+          continue;
+
+        if (rays.hit(which, f, getMaterial(), this, getTexCoordMapper())) {
+//           if (tri_index > 11)
+//             fprintf(stderr, "hit_tri = %d, tri_index = %d\n", hit_tri, 
tri_index);
+          hit_tri = tri_indices[tri_index];
+        }
+      }
+      if (hit_tri >= 0) {
+        ScratchData sd;
+        sd.tri_index = hit_tri;
+        rays.scratchpad<ScratchData>(which) = sd;
+      }
+      if (data->minT[which] < far) return;
+    }
+
+    // pop item from stack:
+    // if stack is empty, we're done
+    if (sptr <= stack) // stack is empty
+      { return; };
+    // do actual popping
+    near = far; // next subtree's entry (near) is current subtree's exit(far)
+    sptr--;
+    far = sptr->far;
+    node = sptr->node;
+  } while (1);
+}
+
+
+void
+KDTree2::computeNormal(const RenderContext& context, RayPacket& rays) const {
   RayPacketData* data = rays.data;
   for ( int ray = rays.begin(); ray < rays.end(); ray++ ) {
     const Triangle& tri = 
triangles[rays.scratchpad<ScratchData>(ray).tri_index];
     
     const int axis = tri.k;
-    const int ku   = (axis==2)?0:k+1;
-    const int kv   = (axis==0)?2:k-1;
-    const flaot mult = tri.n_k;
+    const int ku   = (axis==2)?0:axis+1;
+    const int kv   = (axis==0)?2:axis-1;
+    const float mult = tri.n_k;
     
     data->normal[axis][ray] = mult;
     data->normal[ku][ray]   = mult * tri.n_u;
@@ -133,6 +368,79 @@
   }
   rays.setFlag(RayPacket::HaveUnitNormals);
 }
+
+// Returns 0 on success
+int
+KDTree2::reserveTriangles(size_t num_tris_in) {
+  triangles = static_cast<Triangle*>(malloc(num_tris_in*sizeof(Triangle)));
+  if (triangles) {
+    num_tris = num_tris_in;
+    return 0;
+  } else {
+    return 1;
+  }
+}
+        
+// Returns 0 on success
+int
+KDTree2::reserveTriangleIndices(size_t num_tri_indices_in) {
+  tri_indices =
+    static_cast<unsigned int*>(malloc(num_tri_indices_in*sizeof(Triangle)));
+  if (tri_indices) {
+    num_tri_indices = num_tri_indices_in;
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+// Returns 0 on success
+int
+KDTree2::reserveGroupIDs() {
+  if (!num_tris)
+    // Haven't said how many triangles yet
+    return 1;
+  group_ids = static_cast<unsigned int*>(malloc(num_tris*sizeof(unsigned 
int)));
+  if (!group_ids)
+    return 1;
+  return 0;
+}
+
+// Returns 0 on success
+int
+KDTree2::reserveGroupColors(unsigned int num_groups_in) {
+  group_colors = static_cast<Color*>(malloc(num_groups_in*sizeof(Color)));
+  if (group_colors) {
+    num_groups = num_groups_in;
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+void
+KDTree2Texture::mapValues(const RenderContext& context, RayPacket& rays,
+                          Color results[]) const {
+  if (kdtree->group_ids && kdtree->group_colors) {
+    // Have group ids and colors
+    const unsigned int* group_ids = kdtree->group_ids;
+    const Color* group_colors     = kdtree->group_colors;
+    
+    for ( int ray = rays.begin(); ray < rays.end(); ++ray) {
+      unsigned int tri_index = 
rays.scratchpad<KDTree2::ScratchData>(ray).tri_index;
+      const int group_id = group_ids[tri_index];
+      results[ray] = group_colors[group_id];
+    }
+  } else {
+    // No colors, so just assign something
+    Color default_color(RGBColor(0.7, 0.7, 0.7 ));
+    for ( int ray = rays.begin(); ray < rays.end(); ++ray) {
+      results[ray] = default_color;
+    }
+  }
+    
+}
+
 
 
 

Modified: trunk/Model/Groups/KDTree2.h
==============================================================================
--- trunk/Model/Groups/KDTree2.h        (original)
+++ trunk/Model/Groups/KDTree2.h        Thu Apr  6 16:49:46 2006
@@ -32,22 +32,35 @@
 #include <Model/Primitives/PrimitiveCommon.h>
 #include <Core/Geometry/Vector.h>
 #include <Core/Geometry/Ray.h>
+#include <Core/Geometry/BBox.h>
+#include <Interface/Texture.h>
 
 namespace Manta {
 
+  class IWObject;
+  class IWTree;
+  
   class KDTree2 : public PrimitiveCommon {
   public:
+
+    KDTree2(Material* material);
+    // Return 0 on success
+    int loadIW(IWObject*, IWTree*);
     
+    enum {
+      MaxStackSize = 128
+    };
+
     struct Node {
       union {
-        Node *left_son; // rigth_son = left_son+1;
+        Node *leftChild; // rigth_son = left_son+1;
         int listBegin;
       };
       union {
         float split; // internal
         int listLen; // leaf
-      }
-      char type; // 0=x,1=y,z=2,leaf=3
+      };
+      unsigned char type; // 0=x,1=y,z=2,leaf=3
     };
 
     class Triangle {
@@ -87,43 +100,46 @@
                                RayPacket &rays) const;    
 
     // Returns 0 on success
-    int reserveTriangles(size_t num_tris_in) {
-      triangles = 
static_cast<Triangle*>(malloc(num_tris_in*sizeof(Triangle)));
-      if (triangles) {
-        num_tris = num_tris_in;
-        return 0;
-      } else {
-        return 1;
-      }
-    }
-        
-    // Returns 0 on success
-    int reserveTriangleIndices(size_t num_tri_indices_in) {
-      tri_indicies =
-        static_cast<Triangle*>(malloc(num_tri_indices_in*sizeof(Triangle)));
-      if (tri_indicies) {
-        num_tri_indices = num_tri_indices_in;
-        return 0;
-      } else {
-        return 1;
-      }
-    }
-
+    int reserveTriangles(unsigned int num_tris_in);
+    int reserveTriangleIndices(unsigned int num_tri_indices_in);
+    int reserveGroupIDs();
+    int reserveGroupColors(unsigned int num_groups_in);
+    
     // Triangle list stuff
-    Triangle* triangles;
-    size_t num_tris;
-    unsigned int* tri_indices;
-    size_t num_tri_indices;
-
+    Triangle*     triangles;    // size == num_tris
+    unsigned int  num_tris;
+    unsigned int* tri_indices;  // size == num_tri_indices
+    unsigned int  num_tri_indices;
+
+    // Group
+    unsigned int* group_ids;    // size == num_tris;
+                                // group_ids[i] = [0,num_groups-1]
+    Color*        group_colors; // size == num_groups;
+    unsigned int  num_groups;
 
     // Root node
-    Node* root_node;
+    Node* rootNode;
     
     BBox bbox;
 
   protected:
-    void intersect_node();
+    void intersect_node(Node* start_node, RayPacket& rays, int which,
+                        float minDist, float maxDist) const;
+
+    struct Stack {
+      Node* node;
+      float far;
+    };
+  };
+
+  class KDTree2Texture: public Texture<Color> {
+  public:
+    KDTree2Texture(): kdtree(0) {}
+    
+    virtual void mapValues(const RenderContext& context, RayPacket& rays,
+                           Color results[]) const;
 
+    KDTree2* kdtree;
   };
   
 } // end namespace Manta

Modified: trunk/Model/Groups/KDTreeLoaderIW.cc
==============================================================================
--- trunk/Model/Groups/KDTreeLoaderIW.cc        (original)
+++ trunk/Model/Groups/KDTreeLoaderIW.cc        Thu Apr  6 16:49:46 2006
@@ -101,66 +101,24 @@
 */
 
 
-struct IWNode {
-  IWNode()
-    : left(0), right(0), parent(0),
-      split(0), flags(0),
-      num_tris(0), tri_ids(0),
-      index(0)
-  {}
-  IWNode(IWNode* parent)
-    : left(0), right(0), parent(parent),
-      split(0), flags(0),
-      num_tris(0), tri_ids(0),
-      index(0)
-  {}
-  ~IWNode() {
-    if (left) delete left;
-    if (right) delete right;
-    if (tri_ids) delete[] tri_ids;
-  }
-
-  void setRight(IWNode* node) {
-    right = node;
-    flags |= KDNODE_RIGHT_CHILD_MASK;
-  }
-  void setLeft(IWNode* node) {
-    left = node;
-    flags |= KDNODE_LEFT_CHILD_MASK;
-  }
-  bool isNode() const {
-    return flags & KDNODE_INTERNAL_MASK;
-  }
-  bool isLeaf() const {
-    return (flags & KDNODE_INTERNAL_MASK) == 0;
-  }
-  
-  IWNode *left, *right, *parent;
-  float split;
-  int flags;
-  unsigned int num_tris;
-  int* tri_ids;
-  unsigned index;
-};
-
 // Load the specified file (and associated kdtree files) using the
 // given number of processors.  The geometry should be found in
 // geom_filename and the bsp data should be found in bsp_filename.
 int Manta::Kdtree::loadIW( KDTreeData* kdtree, const char* geom_filename,
                            const char* bsp_filename, int np )
 {
-  FILE* bspf = fopen(bsp_filename, "r");
-  if (!bspf) {
-               fprintf(stderr, "Error: cannot open %s for loading\n", 
bsp_filename);
-    return LoadingProblem;
-  }
   IWObject* iw = IWObjectRead(geom_filename);
   if (!iw) {
-    fclose(bspf);
     return LoadingProblem;
   }
 
-  // Allocate space for the triangles and read them in:
+  IWTree* tree = IWTreeRead(bsp_filename);
+  if (!tree) {
+    return LoadingProblem;
+  }
+
+
+  // Allocate space for the triangles
   unsigned int num_tris = static_cast<unsigned int>(iw->triangles.size());
        kdtree->tris = new VArray<Triangle>(num_tris);
        kdtree->tris->setLen(num_tris);
@@ -220,6 +178,8 @@
     }
   }
 
+  delete iw;
+  
   // Copy the bounding box over.
   kdtree->bbox = bbox;  
        cerr << "Model bounds: min: " << kdtree->bbox[0] << " max: " << 
kdtree->bbox[1] << "\n";
@@ -227,119 +187,28 @@
   ///////////////////////////////////////////////////////
   // Load in the BSP stuff
 
-  // First pass.
-  // 
   // Count the number of triangle indecies and nodes needed.
-  unsigned int num_tri_indicies = 0;
-  unsigned int num_nodes = 0;
-  // Buffer for line.  This will be allocated by getline and
-  // reallocated as needed.  We will need to free it later, though.
-  char* bline = NULL;
-  size_t bline_len = 0;
-
-  IWNode* head = 0;
-  IWNode* top = head;
-
-  while((getline(&bline, &bline_len, bspf)) != -1) {
-//     fprintf (stderr, "line(%u): %s\n", bline_len, bline);
-    // Check the first token
-    char token[2];
-    int num = sscanf(bline, "%1s", token);
-    //    fprintf(stderr, "num = %d, token = %s\n", num, token);
-    if (strcmp(token, "N") == 0) {
-      num_nodes ++;
-//       fprintf(stderr, "Node %u found\n", num_nodes);
-
-      IWNode* node = new IWNode(top);
-      // Is this the first node?
-      if (top) {
-        if (top->left) {
-          top->setRight(node);
-        } else {
-          top->setLeft(node);
-        }
-      } else {
-        // Set the head to the first node
-        head = node;
-      }
-      // Decend
-      top = node;
+  unsigned int num_tri_indices = tree->num_tri_indices;
+  unsigned int num_nodes = tree->num_nodes;
 
-      char axis_c;
-      sscanf(bline, "%*s %c=%f,d=%*d", &axis_c, &(node->split));
-//       fprintf(stderr, "axis = %c, split = %g\n", axis_c, node->split);
-      switch (axis_c) {
-      case 'x': node->flags |= 0; break;
-      case 'y': node->flags |= 1; break;
-      case 'z': node->flags |= 2; break;
-      }
-
-    } else if (strcmp(token, "L") == 0) {
-      IWNode* node = new IWNode(top);
-
-      if (top->left) {
-        top->setRight(node);
-        // Finish up this level
-        while (top && top->right) {
-          top = top->parent;
-        }
-      } else {
-        top->setLeft(node);
-      }
-
-      // Grab how many objects we have
-      sscanf(bline, "%*s %u", &(node->num_tris));
-//       fprintf(stderr, "L %u\n", node->num_tris);
-      num_tri_indicies += node->num_tris;
-      if (node->num_tris) {
-        num_nodes++;
-
-        // If you ever change what type triIndices is you will need to
-        // update this bit of code for the right type.
-        int* tri_ids_p = node->tri_ids = new int[node->num_tris];
-        int pos = 0; // Where to pick up parsing next.  This will give
-                     // us an offset to our token string, so that we
-                     // can grab the next integer one at a time.
-        sscanf(bline, "%*s %*u %n", &pos);
-        //        fprintf(stderr, "pos = %d\n", pos);
-        char* bline_p = bline+pos;
-        for(unsigned int i = 0; i < node->num_tris; ++i) {
-          sscanf(bline_p, "%d %n", tri_ids_p, &pos);
-          //          fprintf(stderr, "pos = %d, %d\n", pos, *tri_ids_p);
-//           fprintf(stderr, "tri (%d) = %d\n", i, *tri_ids_p);
-          bline_p += pos;
-          ++tri_ids_p;
-        }
-      }
-      // else empty leaf
-    } else {
-      fprintf(stderr, "Unrecongnized token (%c)\n", token);
-    }
-    
-  }
-
-  // Allocate space for the num_tri_indicies.  If this gets changed to
+  // Allocate space for the num_tri_indices.  If this gets changed to
   // unsigned int from int, you need up update the parser code below.
-  kdtree->triIndices = new VArray<int>(num_tri_indicies);
-  kdtree->triIndices->setLen(num_tri_indicies);
+  kdtree->triIndices = new VArray<int>(num_tri_indices);
+  kdtree->triIndices->setLen(num_tri_indices);
 
   // Allocate space for the nodes
   KDTreeNode* nodes =
     reinterpret_cast<KDTreeNode*>(malloc(num_nodes*sizeof(KDTreeNode)));
   KDTreeNode* current_node = nodes;
   unsigned int current_node_index = 0;
-  KDTreeNode* parent = NULL;
   
-  // Reset the file pointer
-  fseek(bspf, 0, SEEK_SET);
-
   unsigned int current_tri_index = 0;
   int* tri_ids_p = kdtree->triIndices->getArray();
 
   bool bsp_debug = false;
   
   // Now traverse the data structure and fill in the kd tree data.
-  top = head;
+  IWNode* top = tree->head;
   top->index = current_node_index++;
   stack<IWNode*> nodestack;
   nodestack.push(top);
@@ -389,7 +258,7 @@
         if (bsp_debug)
           fprintf(stderr, "Leaf(#%u): num_tris = %d (",
                   top->index, top->num_tris);
-        // Copy the indicies
+        // Copy the indices
         for(unsigned int i = 0; i < top->num_tris; ++i) {
           *tri_ids_p = top->tri_ids[i];
           if (bsp_debug) fprintf(stderr, "%d, ", *tri_ids_p);
@@ -409,19 +278,15 @@
     nodestack.pop();
   }
 
-  fprintf(stderr, "num_tri_indicies = %u\n", num_tri_indicies);
+  fprintf(stderr, "num_tri_indices = %u\n", num_tri_indices);
   fprintf(stderr, "current_tri_index = %u\n", current_tri_index);
   fprintf(stderr, "num_nodes = %u, current_node_index = %u\n",
           num_nodes, current_node_index);
 
-  delete head;
+  delete tree;
 
        // Specify the root node loaded from the file.
        kdtree->rootNode = nodes;
-  
-  if (bline) free(bline);
-  fclose(bspf);
-
   
   return 1;
 } // int loadIW()

Modified: trunk/Model/Readers/IW.cc
==============================================================================
--- trunk/Model/Readers/IW.cc   (original)
+++ trunk/Model/Readers/IW.cc   Thu Apr  6 16:49:46 2006
@@ -180,7 +180,7 @@
     return 0;
   }
   
-  // Make sure that the triangle indicies and shader indicies are cool
+  // Make sure that the triangle indices and shader indicies are cool
   for(size_t i = 0; i < iw->triangles.size(); ++i) {
     unsigned int a, b, c, group;
     a = iw->triangles[i][0];
@@ -220,3 +220,115 @@
 
   return iw;
 }
+
+IWTree* Manta::IWTreeRead(const char* filename)
+{
+  unsigned int num_tri_indices = 0;
+  unsigned int num_nodes = 0;
+  unsigned int num_empty_nodes = 0;
+  
+  FILE* bspf = fopen(filename, "r");
+  if (!bspf) {
+               fprintf(stderr, "Error: cannot open %s for loading\n", 
filename);
+    return 0;
+  }
+
+  // Buffer for line.  This will be allocated by getline and
+  // reallocated as needed.  We will need to free it later, though.
+  char* bline = NULL;
+  size_t bline_len = 0;
+
+  IWNode* head = 0;
+  IWNode* top = head;
+
+  while((getline(&bline, &bline_len, bspf)) != -1) {
+//     fprintf (stderr, "line(%u): %s\n", bline_len, bline);
+    // Check the first token
+    char token[2];
+    int num = sscanf(bline, "%1s", token);
+    //    fprintf(stderr, "num = %d, token = %s\n", num, token);
+    if (strcmp(token, "N") == 0) {
+      num_nodes ++;
+//       fprintf(stderr, "Node %u found\n", num_nodes);
+      
+      IWNode* node = new IWNode(top);
+      // Is this the first node?
+      if (top) {
+        if (top->left) {
+          top->setRight(node);
+        } else {
+          top->setLeft(node);
+        }
+      } else {
+        // Set the head to the first node
+        head = node;
+      }
+      // Decend
+      top = node;
+
+      char axis_c;
+      sscanf(bline, "%*s %c=%f,d=%*d", &axis_c, &(node->split));
+//       fprintf(stderr, "axis = %c, split = %g\n", axis_c, node->split);
+      switch (axis_c) {
+      case 'x': node->flags |= 0; break;
+      case 'y': node->flags |= 1; break;
+      case 'z': node->flags |= 2; break;
+      }
+
+    } else if (strcmp(token, "L") == 0) {
+      IWNode* node = new IWNode(top);
+
+      if (top->left) {
+        top->setRight(node);
+        // Finish up this level
+        while (top && top->right) {
+          top = top->parent;
+        }
+      } else {
+        top->setLeft(node);
+      }
+
+      // Grab how many objects we have
+      sscanf(bline, "%*s %u", &(node->num_tris));
+//       fprintf(stderr, "L %u\n", node->num_tris);
+      num_tri_indices += node->num_tris;
+      if (node->num_tris) {
+        num_nodes++;
+
+        // If you ever change what type triIndices is you will need to
+        // update this bit of code for the right type.
+        int* tri_ids_p = node->tri_ids = new int[node->num_tris];
+        int pos = 0; // Where to pick up parsing next.  This will give
+                     // us an offset to our token string, so that we
+                     // can grab the next integer one at a time.
+        sscanf(bline, "%*s %*u %n", &pos);
+        //        fprintf(stderr, "pos = %d\n", pos);
+        char* bline_p = bline+pos;
+        for(unsigned int i = 0; i < node->num_tris; ++i) {
+          sscanf(bline_p, "%d %n", tri_ids_p, &pos);
+          //          fprintf(stderr, "pos = %d, %d\n", pos, *tri_ids_p);
+//           fprintf(stderr, "tri (%d) = %d\n", i, *tri_ids_p);
+          bline_p += pos;
+          ++tri_ids_p;
+        }
+      } else {
+        // else empty leaf
+        num_empty_nodes++;
+      }
+    } else {
+      fprintf(stderr, "Unrecongnized token (%c)\n", token);
+    }
+    
+  }
+
+  if (bline) free(bline);
+  fclose(bspf);
+
+  IWTree* tree = new IWTree();
+  tree->head = head;
+  tree->num_nodes = num_nodes;
+  tree->num_tri_indices = num_tri_indices;
+
+  return tree;
+}
+

Modified: trunk/Model/Readers/IW.h
==============================================================================
--- trunk/Model/Readers/IW.h    (original)
+++ trunk/Model/Readers/IW.h    Thu Apr  6 16:49:46 2006
@@ -69,6 +69,14 @@
 
 namespace Manta {
 
+  class IWObject;
+  class IWNode;
+  class IWTree;
+  
+  // Return null if there was a problem
+  IWObject* IWObjectRead(const char* filename);
+  IWTree*   IWTreeRead(const char* filename);
+
   class IWObject {
   public:
     IWObject() {}
@@ -93,8 +101,58 @@
     IWObject( const Vector& copy ) {}
   };
 
-  // Return null if there was a problem
-  IWObject* IWObjectRead(const char* filename);
+  struct IWNode {
+    IWNode()
+      : left(0), right(0), parent(0),
+        split(0), flags(0),
+        num_tris(0), tri_ids(0),
+        index(0)
+    {}
+    IWNode(IWNode* parent)
+      : left(0), right(0), parent(parent),
+        split(0), flags(0),
+        num_tris(0), tri_ids(0),
+        index(0)
+    {}
+    ~IWNode() {
+      if (left) delete left;
+      if (right) delete right;
+      if (tri_ids) delete[] tri_ids;
+    }
+
+    void setRight(IWNode* node) {
+      right = node;
+    }
+    void setLeft(IWNode* node) {
+      left = node;
+    }
+    bool isNode() const {
+      return (left || right);
+    }
+    bool isLeaf() const {
+      return !(left || right);
+    }
+  
+    IWNode *left, *right, *parent;
+    float split;
+    int flags;
+    unsigned int num_tris;
+    int* tri_ids;
+    unsigned int index;
+  };
+
+  struct IWTree {
+    IWTree(): head(NULL) {}
+    
+    ~IWTree() {
+      if (head) delete head;
+    }
+    
+    IWNode* head;
+    unsigned int num_nodes;
+    unsigned int num_empty_nodes; // These are leaves with no triangles
+    unsigned int num_tri_indices;
+  };
   
 } // end namespace Manta
 

Modified: trunk/scenes/iwviewer.cc
==============================================================================
--- trunk/scenes/iwviewer.cc    (original)
+++ trunk/scenes/iwviewer.cc    Thu Apr  6 16:49:46 2006
@@ -42,6 +42,7 @@
 #include <Model/Materials/Flat.h>
 #include <Model/Textures/NormalTexture.h>
 #include <Model/Groups/DynBVH.h>
+#include <Model/Groups/KDTree2.h>
 
 #include <iostream>
 #include <vector>
@@ -57,14 +58,24 @@
 enum {
   Lambertian_Material,
   Flat_Material,
-  Normal_Material,
+  Normal_Material
 };
 
-static string file_name;
+enum {
+  DynBVH_Build,
+  KDTree2_Build
+};
+
+static string iw_file_name;
+static string bsp_file_name;
 static int tri_type = WaldTri;
 static bool use_default_color = false;
 static int material_type = Lambertian_Material;
 static BBox bounds;
+static int build_type = DynBVH_Build;
+
+static Object* buildDynBVH(IWObject* iw);
+static Object* buildKDTree2(IWObject* iw);
 
 extern "C"
 Scene* make_scene(const ReadContext& context, const vector<string>& args) {
@@ -74,8 +85,13 @@
 
     if (args[i] == "-file" || args[i] == "-iwfile") {
       // Read in the file name.
-      if (!getStringArg(i, args, file_name))
+      if (!getStringArg(i, args, iw_file_name))
         throw IllegalArgument("iwviewer -file <filename>", i, args);
+    } else if (args[i] == "-bsp" || args[i] == "-bspfile") {
+      // Read in the file name.
+      if (!getStringArg(i, args, bsp_file_name))
+        throw IllegalArgument("iwviewer -bsp <filename>", i, args);
+      build_type = KDTree2_Build;
     } else if (args[i] == "-tri" ) {
       tri_type = Tri;
     } else if (args[i] == "-flat" ) {
@@ -85,12 +101,49 @@
     }
   }
 
-  IWObject* iw = IWObjectRead(file_name.c_str());
+  IWObject* iw = IWObjectRead(iw_file_name.c_str());
   if (!iw) {
-    cerr << "Error reading file : "<<file_name<<".\n";
+    cerr << "Error reading file : "<<iw_file_name<<".\n";
     return 0;
   }
 
+  ///////////////////////////////////////////////////////////////////////////
+  // Create the scene.
+  Scene *scene = new Scene();
+
+  // Add a head light.
+  LightSet *lights = new LightSet();
+  lights->add( new HeadLight( 0.0, Color(RGB(1.0,1.0,1.0)) ));
+  lights->setAmbientLight( new ConstantAmbient( Color(RGB(0.4,0.4,0.4) ) ));
+  scene->setLights( lights );
+
+  // Add the bvh to the scene.
+  switch(build_type) {
+  case DynBVH_Build: scene->setObject( buildDynBVH(iw) ); break;
+  case KDTree2_Build:
+    {
+      Object* kdtree = buildKDTree2(iw);
+      if (!kdtree) {
+        cerr << "Error building KDTree2\n";
+        delete iw;
+        return 0;
+      } else {
+        scene->setObject( kdtree );
+      }
+    }
+    break;
+  }
+
+  delete iw;
+
+  // Background.
+  scene->setBackground( new ConstantBackground( Color(RGB(0.8, 0.8, 1) ) ) );
+
+  return scene;
+  
+}
+
+Object* buildDynBVH(IWObject* iw) {
   // Make the materials
   vector<Material*> materials;
   for(size_t i = 0; i < iw->shaders.size(); ++i) {
@@ -136,22 +189,43 @@
     break;
   }
 
-  ///////////////////////////////////////////////////////////////////////////
-  // Create the scene.
-  Scene *scene = new Scene();
+  return bvh_group;
+}
 
-  // Add a head light.
-  LightSet *lights = new LightSet();
-  lights->add( new HeadLight( 0.0, Color(RGB(1.0,1.0,1.0)) ));
-  lights->setAmbientLight( new ConstantAmbient( Color(RGB(0.4,0.4,0.4) ) ));
-  scene->setLights( lights );
+Object* buildKDTree2(IWObject* iw) {
+  // attempt to open the bsp file
+  IWTree* tree = IWTreeRead(bsp_file_name.c_str());
+  if (!tree) {
+    cerr << "Error reading file : "<<bsp_file_name<<".\n";
+    return 0;
+  }
 
-  // Add the bvh to the scene.
-  scene->setObject( bvh_group );
+  Material* matl = 0;
+  KDTree2Texture* tex = new KDTree2Texture();
+  switch (material_type) {
+  case Lambertian_Material:
+    matl = new Lambertian( tex );
+    break;
+  case Flat_Material:
+    matl = new Flat( tex );
+    break;
+  case Normal_Material:
+    matl = new Flat( new NormalTexture() );
+    break;
+  }
 
-  // Background.
-  scene->setBackground( new ConstantBackground( Color(RGB(0.8, 0.8, 1) ) ) );
+  KDTree2* kdtree = new KDTree2(matl);
+  if (kdtree->loadIW(iw, tree)) {
+    delete tree;
+    cerr << "Error creating KDTree2\n";
+    return 0;
+  }
 
-  return scene;
+  // Put a reference back to the kdree
+  tex->kdtree = kdtree;
+
+  // Clean up
+  delete tree;
   
+  return kdtree;
 }




  • [MANTA] r1002 - in trunk: Model/Groups Model/Readers scenes, bigler, 04/06/2006

Archive powered by MHonArc 2.6.16.

Top of page