Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r873 - in trunk: Core/Util Interface Model/Groups fox/FManta scenes


Chronological Thread 
  • From: abe@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r873 - in trunk: Core/Util Interface Model/Groups fox/FManta scenes
  • Date: Sun, 29 Jan 2006 01:24:56 -0700 (MST)

Author: abe
Date: Sun Jan 29 01:24:55 2006
New Revision: 873

Added:
   trunk/Core/Util/Align.h
   trunk/Model/Groups/SSEKDTree.cc
   trunk/Model/Groups/SSEKDTree.h
Modified:
   trunk/Interface/RayPacket.h
   trunk/Model/Groups/CMakeLists.txt
   trunk/Model/Groups/KDTree.h
   trunk/Model/Groups/VerticalKDTree.cc
   trunk/Model/Groups/VerticalKDTree.h
   trunk/fox/FManta/FMantaWindow.cc
   trunk/fox/FManta/FMantaWindow.h
   trunk/scenes/boeing777.cc
Log:


Modified command line args for debugging
M    scenes/boeing777.cc

Added macro which may be redefined for different compilers to specify 
alignment.
A    Core/Util/Align.h

Added initial working version of SSE kdtree traversal.
A    Model/Groups/SSEKDTree.h
A    Model/Groups/SSEKDTree.cc
M    Model/Groups/VerticalKDTree.cc
M    Model/Groups/VerticalKDTree.h
M    Model/Groups/KDTree.h
M    Model/Groups/CMakeLists.txt
M    Interface/RayPacket.h

Added ability to enter pixel coordinates to shoot debugging ray
M    fox/FManta/FMantaWindow.cc
M    fox/FManta/FMantaWindow.h

Added: trunk/Core/Util/Align.h
==============================================================================
--- (empty file)
+++ trunk/Core/Util/Align.h     Sun Jan 29 01:24:55 2006
@@ -0,0 +1,41 @@
+/*
+  For more information, please see: http://software.sci.utah.edu
+
+  The MIT License
+
+  Copyright (c) 2005-2006
+  Scientific Computing and Imaging Institute, University of Utah
+
+  License for the specific language governing rights and limitations under
+  Permission is hereby granted, free of charge, to any person obtaining a
+  copy of this software and associated documentation files (the "Software"),
+  to deal in the Software without restriction, including without limitation
+  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+  and/or sell copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+  DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _CORE_UTIL_ALIGN__H
+#define _CORE_UTIL_ALIGN__H
+
+
+#define MANTA_ALIGN(size) \
+  __declspec( align( (size) ) )
+
+#define MANTA_IS_ALIGNED(addr,size) \
+  ((((size_t)(addr))%(size))==0)
+
+
+#endif
+

Modified: trunk/Interface/RayPacket.h
==============================================================================
--- trunk/Interface/RayPacket.h (original)
+++ trunk/Interface/RayPacket.h Sun Jan 29 01:24:55 2006
@@ -6,6 +6,7 @@
 #include <Core/Geometry/Ray.h>
 #include <Core/Math/Expon.h>
 #include <Core/Util/Assert.h>
+#include <Core/Util/Align.h>
 #include <Interface/Parameters.h>
 #include <Interface/Primitive.h>
 #include <Interface/TexCoordMapper.h>
@@ -14,6 +15,8 @@
 namespace Manta {
   class Material;
   class RenderContext;
+
+  MANTA_ALIGN(16)
   class RayPacketData {
   public:
     enum {
@@ -41,14 +44,16 @@
     TexCoordMapperCP hitTex[Size];
 
     // Real-based arrays
+    MANTA_ALIGN(16) Real origin[3][Size];
+    MANTA_ALIGN(16) Real direction[3][Size];
+    MANTA_ALIGN(16) Real inverseDirection[3][Size];
+    MANTA_ALIGN(16) Real minT[Size];
+
     Real image[2][Size];
-    Real origin[3][Size];
-    Real direction[3][Size];
     Real normal[3][Size];
     Real hitPosition[3][Size];
-    Real minT[Size];
     Real texCoords[3][Size];
-    Real inverseDirection[3][Size];
+
 
     // Color-based arrays
     Color::ComponentType color[Manta::Color::NumComponents][Size];

Modified: trunk/Model/Groups/CMakeLists.txt
==============================================================================
--- trunk/Model/Groups/CMakeLists.txt   (original)
+++ trunk/Model/Groups/CMakeLists.txt   Sun Jan 29 01:24:55 2006
@@ -35,6 +35,9 @@
     ${Manta_Groups_SRCS}
     Groups/VerticalKDTree.h
     Groups/VerticalKDTree.cc
+    
+    Groups/SSEKDTree.cc
+    Groups/SSEKDTree.h
     )
 
 # Otherwise include a stub implementation.

Modified: trunk/Model/Groups/KDTree.h
==============================================================================
--- trunk/Model/Groups/KDTree.h (original)
+++ trunk/Model/Groups/KDTree.h Sun Jan 29 01:24:55 2006
@@ -296,6 +296,7 @@
       // Transparent KDTree will use data owned by this kdtree.
       friend class TransparentKDTree;
       friend class VerticalKDTree;
+      friend class SSEKDTree;
 
       // The Kdtree::load(...) function is used to load data into the kdtree.
       friend int Manta::Kdtree::load( KDTree *kdtree, const char *filename,

Added: trunk/Model/Groups/SSEKDTree.cc
==============================================================================
--- (empty file)
+++ trunk/Model/Groups/SSEKDTree.cc     Sun Jan 29 01:24:55 2006
@@ -0,0 +1,758 @@
+
+
+/*
+  For more information, please see: http://software.sci.utah.edu

+  The MIT License

+  Copyright (c) 2005
+  Scientific Computing and Imaging Institute, University of Utah

+  License for the specific language governing rights and limitations under
+  Permission is hereby granted, free of charge, to any person obtaining a
+  copy of this software and associated documentation files (the "Software"),
+  to deal in the Software without restriction, including without limitation
+  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+  and/or sell copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following conditions:

+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.

+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+  DEALINGS IN THE SOFTWARE.
+*/
+
+#include <Model/Groups/SSEKDTree.h>
+#include <Model/Groups/varray.h>
+
+#include <Model/Intersections/AxisAlignedBox.h>
+#include <Interface/Context.h>
+
+#include <SCIRun/Core/Thread/Time.h>
+#include <SCIRun/Core/Thread/Thread.h>
+#include <SCIRun/Core/Thread/Runnable.h>
+#include <SCIRun/Core/Thread/Barrier.h>
+
+#include <sgi_stl_warnings_off.h>
+#include <iostream>
+#include <sgi_stl_warnings_off.h>
+
+#include <stdio.h>
+
+using namespace Manta;
+using namespace Manta::Kdtree;
+using namespace SCIRun;
+using std::cerr;
+using std::endl;
+
+#define SHOW_DUPLICATES 0
+
+//static unsigned long global_counter = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// Triangle Intersection routines.
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+inline void intersectTriangleEdgeSSE( IntersectPacket *result,               
                       
+                                      const RayPacket &rays,
+                                      const int which,
+                                      const int tri_index,
+                                      const Vector &edge1,
+                                      const Vector &edge2,
+                                      const Point &p0 );
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// INTERSECT TRIANGLES  INTERSECT TRIANGLES  INTERSECT TRIANGLES  INTERSECT 
TRI
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+namespace Manta {
+  namespace Kdtree {
+    MANTA_ALIGN(16)
+    struct IntersectPacket {
+      union { int active_mask[4]; __m128 active_mask4; };
+      union { int hit_mask[4];    __m128 hit_mask4; };
+      union { float t[4];         __m128 t4; };
+      union { float u[4];         __m128 u4; };
+      union { float v[4];         __m128 v4; };
+      
+      int   hit_index[TraversalPacketSize];
+    };
+  };
+};
+
+void SSEKDTree::intersectTriangles(IntersectPacket *intersect_packet,
+                                   const RayPacket &rays,
+                                   int which,
+                                   unsigned int listBegin,
+                                   unsigned int listSize ) const {
+
+
+  // Initialize nearset variables.
+  intersect_packet->hit_mask4 = _mm_set1_ps( 0.0 );
+  intersect_packet->t4        = _mm_load_ps( &rays.getMinT(which) );
+
+  // Iterate over all of the triangles.
+  unsigned int listEnd = listBegin+listSize;
+
+#pragma swp
+  for (unsigned int i = listBegin; i<listEnd; ++i) {
+
+    const int index     = triIndices->get( i );
+    const Triangle &tri = tris->get( index );
+
+    // Intersect the packet with one triangle.
+    intersectTriangleEdgeSSE( intersect_packet,
+                              rays,
+                              which,
+                              index,
+                              tri.edge1,
+                              tri.edge2,
+                              tri[0] );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// This is the Manta interface method.
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void SSEKDTree::intersect(const RenderContext& context, RayPacket& rays) 
const
+{
+  rays.normalizeDirections();
+  rays.computeInverseDirections();
+  rays.computeSigns();
+  
+  // Find runs of rays with the same direction signs.
+  for(int i = rays.begin();i<rays.end();){
+
+    int sign = rays.getSignMask( i );
+    int end = i+1;
+
+    // Find the end of the run.
+    while(end < rays.end() && (rays.getSignMask(end)==sign)) 
+      end++;
+
+    // Create a sub packet.
+    RayPacket subPacket(rays, i, end);
+
+    // Set the constant sign flag.
+    subPacket.resetFlag( RayPacket::HaveSigns );
+
+    subPacket.computeSigns();
+    assert( subPacket.getFlag( RayPacket::ConstantSigns ) );
+
+    
///////////////////////////////////////////////////////////////////////////
+    // Make sure that the traversal packet starts with an index that is
+    // TraversalPacketSize aligned.    
+    int which = subPacket.begin();
+    int p_start = (which % TraversalPacketSize);
+
+    // Set which to be TraversalPacketSize aligned.
+    // The un-used rays are already set to false.
+    which -= p_start;
+    
+    
////////////////////////////////////////////////////////////////////////////
+    // Iterate over sub groups of rays.
+    for(;which<subPacket.end();which+=TraversalPacketSize) {
+
+      Real minDist[TraversalPacketSize];
+      Real maxDist[TraversalPacketSize];
+
+      Mask valid_mask( Mask::False );
+      
+      // Compute min and max distance for the kdtree.
+      for (int 
p=p_start;(p<TraversalPacketSize)&&((which+p)<subPacket.end());++p) {
+
+        assert(getMaterial());
+        
+        // Intersect the ray with the bounding box for the group.
+        valid_mask[p] = Intersection::intersectAaBox( bbox,
+                                                      minDist[p],
+                                                      maxDist[p],
+                                                      
subPacket.getRay(which+p),
+                                                      
subPacket.getSigns(which+p),
+                                                      
subPacket.getInverseDirection(which+p));
+#if 0
+        if (p_start && valid_mask[p]) {
+          subPacket.scratchpad<ScratchPadInfo>(which+p).payload = 
Color(RGB(1,0,0));
+          
assert(rays.hit(which+p,T_EPSILON*8,getMaterial(),this,(TexCoordMapper *)1));
+        }
+#endif        
+        
+        // Determine the actual minimum distance.
+        minDist[p] = SCIRun::Max( minDist[p], T_EPSILON );
+        maxDist[p] = SCIRun::Min( maxDist[p], subPacket.getMinT(which+p) );
+      }
+
+      // Check to see if a traversal is necessary.
+      if (any(valid_mask)) {
+
+        // Make sure that the vector operations won't overflow the ray 
packet.
+        assert( (which+TraversalPacketSize) <= RayPacket::MaxSize );
+        
+        // Intersect the subpacket with the tree.
+        intersect_node( context, valid_mask, subPacket, which, p_start, 
minDist, maxDist );        
+      }
+
+      // Returned to alignment for additional rays in the packet.
+      p_start = 0;      
+
+    }    
+
+    
///////////////////////////////////////////////////////////////////////////
+    // Find the next run.
+    i=end;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// This function performs the KD-Tree Traversal.
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// Traversal Stack Entry.
+MANTA_ALIGN(16) struct Stack {
+  union {
+    float t_near[TraversalPacketSize];
+    __m128 t_near4;
+  };
+  union {
+    float t_far [TraversalPacketSize];
+    __m128 t_far4;
+  };
+  __m128 mask;
+  KDTreeNode* node;
+  char padding[8];
+};
+
+void SSEKDTree::intersect_node( const RenderContext &context,
+                                     const Mask &valid_mask,
+                                     RayPacket &rays,
+                                     int which,
+                                     int p_start,
+                                     float minDist[TraversalPacketSize],
+                                     float maxDist[TraversalPacketSize] ) 
const
+{
+
+  
/////////////////////////////////////////////////////////////////////////////
+  // Stack pointers.
+  KDTreeNode *nearNode = rootNode;
+  KDTreeNode *farNode;
+
+  
/////////////////////////////////////////////////////////////////////////////
+  // Keep a stack of entry and exit positions into the traversal nodes.
+  MANTA_ALIGN(16) Stack stack[128];
+  int stack_index = 1;
+
+  // Initialize the stack.
+  for (int p=0;p<TraversalPacketSize;++p) {
+    stack[1].t_near[p] = minDist[p];
+    stack[1].t_far [p] = maxDist[p];
+  }
+
+  // Start at the root.
+  stack[1].node = rootNode;
+
+  
/////////////////////////////////////////////////////////////////////////////
+  // Mask to keep track of rays that still need to find closest 
intersections.
+  __m128 live_mask;
+  for (int p=0;p<TraversalPacketSize;++p) {
+    ((int *)(&live_mask))[p] = (valid_mask[p]) ? 0xffffffff : 0x0;
+  }
+  stack[1].mask = live_mask;
+  
+  // if (rays.getFlag( RayPacket::DebugPacket )) std::cerr << "valid_mask: " 
<< valid_mask << "\n";
+    
+  
/////////////////////////////////////////////////////////////////////////////
+  // Load the ray origins and directions into registers.
+  const __m128 origin4[3] = {
+    _mm_load_ps( &rays.getOrigin(which,0) ),
+    _mm_load_ps( &rays.getOrigin(which,1) ),
+    _mm_load_ps( &rays.getOrigin(which,2) ) };
+
+  const __m128 inv_direction4[3] = {
+    _mm_load_ps( &rays.getInverseDirection(which,0) ),
+    _mm_load_ps( &rays.getInverseDirection(which,1) ),
+    _mm_load_ps( &rays.getInverseDirection(which,2) ) };
+    
+  // Process nodes on the stack.
+  while (stack_index) {
+
+    
///////////////////////////////////////////////////////////////////////////
+    // Pop off the node on top of the stack.
+    KDTreeNode *node = stack[stack_index].node;
+
+    // Copy t_near and t_far from the stack.
+    __m128 t_near = stack[stack_index].t_near4;
+    __m128 t_far  = stack[stack_index].t_far4;
+
+    // Obtain the active mask for this subtree.
+    __m128 active_mask = stack[stack_index].mask;
+
+#if 0
+    if (rays.getFlag( RayPacket::DebugPacket )) {
+      std::cerr << "P " << stack_index << " ";
+      std::cerr << "\t"; M128_DEBUG(rays,active_mask);
+      std::cerr << "\t"; M128_DEBUG(rays,t_near);
+      std::cerr << "\t"; M128_DEBUG(rays,t_far);
+    }
+#endif
+
+    // Pop stack.
+    stack_index--;
+    
+    /////////////////////////////////////////////////////////////////////
+    
///////////////////////////////////////////////////////////////////////////
+    // Traverse down to a leaf.
+    while (node && node->isInternal()) {
+
+      // Obtain axis and split point.
+      const int axis = node->axis();
+      const __m128 split = _mm_set1_ps( node->split() );
+
+      // Identify near_index and far_index.
+      assert( rays.getFlag( RayPacket::ConstantSigns ) );
+            
+      const int near_index = rays.getSign(which+p_start,axis);
+      const int far_index  = (1 - near_index);
+      
+      
/////////////////////////////////////////////////////////////////////////
+      // Compute t_split.
+      __m128 t_split = _mm_mul_ps( _mm_sub_ps( split,
+                                               origin4[axis] ),
+                                   inv_direction4[axis] );
+
+#define SSE_XOR( A, B ) \
+  _mm_or_ps( _mm_andnot_ps( (B), (A) ), \
+             _mm_andnot_ps( (A), (B) ) )
+      
+#define SSE_ALL( mask, cmp ) \
+  _mm_movemask_ps( SSE_XOR( _mm_and_ps( (mask), \
+                                        (cmp) ), \
+                            (mask) ) ) == 0
+      
+      
/////////////////////////////////////////////////////////////////////////
+      // Classify the case.
+      // Mask cmp_result;
+      // set_lte( cmp_result, t_split, t_near );
+// #if 0
+      __m128 cmp_result = _mm_cmple_ps( t_split, t_near );      
+      if (SSE_ALL( active_mask, cmp_result)) {
+
+        
///////////////////////////////////////////////////////////////////////
+        // Case I: "Near Only"
+
+        // if (rays.getFlag( RayPacket::DebugPacket )) { std::cerr << "A\n"; 
}
+        
+        // Update the current node.
+        node = node->getChild( far_index );
+        
+        // No stack operations.
+        continue;
+      }
+      
+      // set_gte( cmp_result, t_split, t_far );
+      cmp_result = _mm_cmpge_ps( t_split, t_far );
+      if (SSE_ALL( active_mask, cmp_result)) {
+
+        
///////////////////////////////////////////////////////////////////////
+        // Case II: "Far Only"
+
+        // if (rays.getFlag( RayPacket::DebugPacket )) { std::cerr << "B\n"; 
}
+        
+        // Update the current node.
+        node = node->getChild( near_index );
+
+        // No stack operations.
+        continue;
+      }
+// #endif
+      
/////////////////////////////////////////////////////////////////////////
+      // Otherwise:
+
+      // Case III "Both" -- Push far node on stack.
+#if 0
+      if (rays.getFlag( RayPacket::DebugPacket )) {
+        std::cerr << "C\n";
+      }      
+#endif 
+      // Check to make sure some rays hit the far child.
+      cmp_result = _mm_and_ps( active_mask,
+                               _mm_cmple_ps( t_split, t_far ) );
+      if (_mm_movemask_ps( cmp_result )) {
+        stack_index++;
+        stack[stack_index].node = node->getChild( far_index );
+        stack[stack_index].mask = cmp_result; 
+        
+        // Copy t_split and t_far to the stack.
+        stack[stack_index].t_near4 = t_split;
+        stack[stack_index].t_far4  = t_far;
+#if 0        
+        if (rays.getFlag( RayPacket::DebugPacket )) {
+          std::cerr << "\tPush node: " << stack_index << " ";
+          M128_DEBUG(rays,stack[stack_index].mask);
+        }
+#endif 
+      }
+#if 0
+      else {
+        if (rays.getFlag( RayPacket::DebugPacket )) {
+          std::cerr << "\tPush node: <skipped> ";
+          M128_DEBUG(rays,cmp_result);
+        }
+      }
+#endif      
+
+      // Check to make sure something hits the near node.
+      cmp_result = _mm_and_ps( active_mask,
+                               _mm_cmple_ps( t_near, t_far ) );            
+      if (_mm_movemask_ps( cmp_result )) {
+            
+        // Update the current node.
+        node = node->getChild( near_index );
+        active_mask = cmp_result;
+
+        // Copy t_split to t_far.
+        t_far = t_split;
+#if 0
+        if (rays.getFlag( RayPacket::DebugPacket )) {
+          std::cerr << "\tNear node: ";
+          M128_DEBUG(rays,active_mask);
+        }
+#endif
+      }
+      else {
+        node = 0;
+#if 0
+        if (rays.getFlag( RayPacket::DebugPacket )) {
+          std::cerr << "\tNear node: <skipped> ";
+          M128_DEBUG(rays,cmp_result);
+        }
+#endif
+      }
+
+
+    }
+
+    
///////////////////////////////////////////////////////////////////////////
+    
///////////////////////////////////////////////////////////////////////////
+    // Check to see if we found a non-empty leaf node.
+    if (node) {
+
+      
/////////////////////////////////////////////////////////////////////////
+      
/////////////////////////////////////////////////////////////////////////
+      // Intersect the rays with a list of triangles.
+
+# if 0
+      if (rays.getFlag( RayPacket::DebugPacket )) {
+        std::cerr << "Leaf Intersect: " << active << "\n";
+        std::cerr << "  leaf: "; M128_DEBUG(rays,active_mask);
+        std::cerr << "  leaf: "; M128_DEBUG(rays,live_mask);
+      }
+#endif
+      IntersectPacket intersect_packet;
+      intersect_packet.active_mask4 = active_mask;
+      
+      intersectTriangles(&intersect_packet,
+                         rays,
+                         which,
+                         node->listBegin(),
+                         node->listSize());
+
+      ///////////////////////////////////////////////////////////////////////
+      ///////////////////////////////////////////////////////////////////////
+      // Check against the hit record.        
+      for (int p=0;p<TraversalPacketSize;++p) {
+        if (intersect_packet.hit_mask[p]) {
+
+          // Check the hit t against the ray packet min t.
+          intersect_packet.hit_mask[p] = rays.hit( which+p,
+                                                   intersect_packet.t[p],
+                                                   getMaterial(), this, 0 );
+        }
+      }
+
+      
/////////////////////////////////////////////////////////////////////////
+      // Interpolate normals for successful hits.
+      // normal = (n1 * u) + (n2 * v) + (n0 * (1 - u - v));
+      for (int p=0;p<TraversalPacketSize;++p) {
+
+
+        // Note that hit_mask[p] is only set to true when a hit occurs and
+        // active_mask[p] is true.
+        if (intersect_packet.hit_mask[p]) {
+
+          assert( intersect_packet.hit_index[p] < tris->getLen() );
+          
+          // Interpolate between the three vertices.
+          Vectorf &n0 = normals[intersect_packet.hit_index[p]][0];
+          Vectorf &n1 = normals[intersect_packet.hit_index[p]][1];
+          Vectorf &n2 = normals[intersect_packet.hit_index[p]][2];
+          
+          float u = intersect_packet.u[p];
+          float v = intersect_packet.v[p];
+
+          // Copy values to the scratchpad.
+          ScratchPadInfo& scratch_pad = 
rays.scratchpad<ScratchPadInfo>(which+p);
+          scratch_pad.normal = (n1 * u) + (n2 * v) + (n0 * (1 - u - v));
+          scratch_pad.payload = 
tris->get(intersect_packet.hit_index[p]).payload;
+          scratch_pad.a = u;
+          scratch_pad.b = v;
+        }          
+      }
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+    // Check to see if the hit is inside the current cell.
+// # if 0
+
+    __m128 min_t      = _mm_load_ps( &rays.getMinT(which) );    
+
+    // Only turn off active rays which terminate in the current node.
+    static const __m128 nan = _mm_set1_ps( (float)0xffffffff );
+    live_mask =  _mm_and_ps( live_mask,
+                             _mm_or_ps ( _mm_cmpgt_ps( min_t, t_far ),
+                                         _mm_sub_ps  ( nan, active_mask  )));
+    
+    // Check to see if any rays are active any longer.
+    // if (none(active_mask)) {
+    if (_mm_movemask_ps( live_mask ) == 0) {
+
+      // Done with this packet.
+      break;
+    }
+// #endif
+  }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Simple kdtree functions.
+///////////////////////////////////////////////////////////////////////////////
+
+SSEKDTree::SSEKDTree( KDTree *kdtree_, Material *material_ )
+  : PrimitiveCommon( material_ ),
+    rootNode( kdtree_->rootNode ),
+    triIndices( kdtree_->triIndices ),
+    tris( kdtree_->tris ),
+    normals( kdtree_->normals )
+{
+  bbox.extendByBox( kdtree_->bbox );
+}
+SSEKDTree::~SSEKDTree() { };
+
+void SSEKDTree::computeNormal(const RenderContext& /*context*/,
+                           RayPacket& rays) const {
+
+  // Copy the normal out of the KDTree::ScratchPadInfo structure.
+  for (int i=rays.begin();i<rays.end();++i) {
+    rays.setNormal(i, rays.scratchpad<ScratchPadInfo>(i).normal);
+  }
+}
+
+void SSEKDTree::computeBounds(const PreprocessContext&, BBox &box_ ) const {
+
+  box_.extendByBox( bbox );
+}
+
+void SSEKDTree::computeBounds( BBox &box_ ) const {
+
+  box_.extendByBox( bbox );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#define MANTA_SSE_DOT(out, x1, y1, z1, x2, y2, z2) \
+{ \
+    out = _mm_add_ps(_mm_mul_ps(x1, x2), _mm_mul_ps(y1, y2)); \
+    out = _mm_add_ps(_mm_mul_ps(z1, z2), out); \
+}
+#define MANTA_SSE_CROSS(xout, yout, zout, x1, y1, z1, x2, y2, z2) \
+{ \
+    xout = _mm_sub_ps(_mm_mul_ps(y1, z2), _mm_mul_ps(z1, y2)); \
+    yout = _mm_sub_ps(_mm_mul_ps(z1, x2), _mm_mul_ps(x1, z2)); \
+    zout = _mm_sub_ps(_mm_mul_ps(x1, y2), _mm_mul_ps(y1, x2)); \
+}
+
+// Newton-Raphson Iteration for 1/x
+inline __m128 accurateReciprocal(const __m128& v) {
+
+  const __m128 rcp = _mm_rcp_ps(v);
+  return _mm_sub_ps(_mm_add_ps(rcp, rcp),_mm_mul_ps(_mm_mul_ps(rcp,rcp),v));
+}
+
+void intersectTriangleEdgeSSE( IntersectPacket *result,
+                                  
+                               const RayPacket &rays,
+                               const int which,
+                               const int tri_index,
+                               const Vector &edge0,
+                               const Vector &edge1,
+                               const Point &p0 )
+{
+  __m128 xdir, ydir, zdir;
+  __m128 xnorm, ynorm, znorm;
+  __m128 xorig, yorig, zorig;
+  __m128 xoffset, yoffset, zoffset;
+  __m128 xcorner, ycorner, zcorner;
+  __m128 xcross, ycross, zcross;
+  __m128 xedge, yedge, zedge;
+  __m128 reciprocal;
+  __m128 determinant;
+  __m128 udet, vdet;
+  __m128 absu, absdet, absuv;
+  __m128 odn, t, u, v;
+  __m128 umask, vmask, uvmask;
+  int res;
+
+  // Calculate the normal based on the triangle edges.
+  Vector normal = Cross( edge0, edge1 );
+
+  xnorm = _mm_set1_ps( normal[0] );
+  ynorm = _mm_set1_ps( normal[1] );
+  znorm = _mm_set1_ps( normal[2] );
+
+  // Load the ray direction.
+  xdir = _mm_load_ps( &rays.getDirection(which,0) );
+  ydir = _mm_load_ps( &rays.getDirection(which,1) );
+  zdir = _mm_load_ps( &rays.getDirection(which,2) );
+  
+  // Compute determinant = N . D
+  MANTA_SSE_DOT( determinant,
+                 xdir, ydir, zdir,
+                 xnorm, ynorm, znorm );
+  
+  // Load ray origin.
+  xorig = _mm_load_ps( &rays.getOrigin(which,0) );
+  yorig = _mm_load_ps( &rays.getOrigin(which,1) );
+  zorig = _mm_load_ps( &rays.getOrigin(which,2) );
+  
+  // Load vertex0
+  xcorner = _mm_set1_ps( p0[0] );
+  ycorner = _mm_set1_ps( p0[1] );
+  zcorner = _mm_set1_ps( p0[2] );
+  
+  // Compute origin - vertex0
+  xoffset = _mm_sub_ps( xorig, xcorner );
+  yoffset = _mm_sub_ps( yorig, ycorner );
+  zoffset = _mm_sub_ps( zorig, zcorner );
+  
+  // Cross direction w/ offset.
+  MANTA_SSE_CROSS( xcross, ycross, zcross,
+                   xdir, ydir, zdir, 
+                   xoffset, yoffset, zoffset );
+  
+  // Load edge1
+  xedge = _mm_set1_ps( edge1[0] );
+  yedge = _mm_set1_ps( edge1[1] );
+  zedge = _mm_set1_ps( edge1[2] );
+  
+  // Dot 
+  MANTA_SSE_DOT( u,
+                 xedge, yedge, zedge,
+                 xcross, ycross, zcross );
+
+  // Absolute value of u.
+  absu   = _mm_andnot_ps( _mm_set1_ps(-0.0f), u );
+
+  // Absolute value of det
+  absdet = _mm_andnot_ps( _mm_set1_ps(-0.0f), determinant );
+  
+  udet   = _mm_mul_ps   ( u, determinant );
+
+  // Compute () && (u*det >= 0)
+  umask  = _mm_and_ps   ( _mm_cmple_ps( absu, absdet ), 
+                          _mm_cmpge_ps( udet, _mm_setzero_ps() ) );
+  
+  // Load edge0
+  xedge = _mm_set1_ps( edge0[0] );
+  yedge = _mm_set1_ps( edge0[1] );
+  zedge = _mm_set1_ps( edge0[2] );
+  
+  MANTA_SSE_DOT( v,
+                 xedge, yedge, zedge,
+                 xcross, ycross, zcross );
+
+  // Absolute value u - v.
+  absuv = _mm_andnot_ps( _mm_set1_ps(-0.0f),
+                         _mm_sub_ps(u, v) );
+  vdet  = _mm_mul_ps   ( v, determinant );
+  vmask = _mm_and_ps( _mm_cmple_ps( absuv, absdet ), 
+                      _mm_cmple_ps( vdet, _mm_setzero_ps() ) );
+
+  // Determine which rays intersect the triangle.
+  uvmask = _mm_and_ps( umask, vmask );
+  
+  res = _mm_movemask_ps( uvmask );
+  if (res == 0)
+    return;
+
+  // Compute inverse det.
+  //reciprocal = _mm_rcp_ps(determinant);
+  reciprocal = accurateReciprocal(determinant);
+    
+  MANTA_SSE_DOT( odn,
+                 xoffset, yoffset, zoffset,
+                 xnorm, ynorm, znorm );
+
+  
/////////////////////////////////////////////////////////////////////////////
+  // Compute t, u, v
+
+  // odn * (-1/det)
+  t = _mm_mul_ps( odn, _mm_sub_ps( _mm_setzero_ps(), reciprocal));
+
+  // u * (1/det)
+  u = _mm_mul_ps( u, reciprocal );
+
+  // v * (-1/det)
+  v = _mm_mul_ps( v, _mm_sub_ps( _mm_setzero_ps(), reciprocal ) );
+
+  // Check the hit t against the current value in the result.
+  // (active_mask && uv_mask) && (t < result->t) && (t > T_EPSILON);
+  /*
+  static const __m128 epsilon = _mm_set1_ps( T_EPSILON );
+  result->hit_mask4 = _mm_and_ps( _mm_and_ps(result->active_mask, uvmask),
+                                 _mm_and_ps( _mm_cmplt_ps( t, result->t4 ),
+                                             _mm_cmpgt_ps( t, epsilon) ));
+  */
+  // Copy out individual results for rays which generated value hits.
+  for (int p=0; p<TraversalPacketSize; p++) {
+    int   hit    = ((const int   *)&uvmask)[p];
+    if (result->active_mask[p] && hit) {
+      float scalar = ((const float *)&t)[p];
+      if ( (hit) &&
+           (scalar < result->t[p]) &&
+           (scalar > T_EPSILON)) {
+           
+        // Copy the results for this ray.
+        result->t[p] = scalar;
+        result->u[p] = ((const float *)&u)[p];
+        result->v[p] = ((const float *)&v)[p];
+        result->hit_mask[p]  = 0xffffffff;
+        result->hit_index[p] = tri_index;
+      }
+    }
+  }
+}
+
+
+
+
+

Added: trunk/Model/Groups/SSEKDTree.h
==============================================================================
--- (empty file)
+++ trunk/Model/Groups/SSEKDTree.h      Sun Jan 29 01:24:55 2006
@@ -0,0 +1,126 @@
+/*
+  For more information, please see: http://software.sci.utah.edu
+
+  The MIT License
+
+  Copyright (c) 2006
+  Scientific Computing and Imaging Institute, Univeristy of Utah
+
+  License for the specific language governing rights and limitations under
+  Permission is hereby granted, free of charge, to any person obtaining a
+  copy of this software and associated documentation files (the "Software"),
+  to deal in the Software without restriction, including without limitation
+  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+  and/or sell copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+  DEALINGS IN THE SOFTWARE.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// NOTE: Manta::Real must be "float" in order for CMake to include this code.
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// Abe Stephens
+
+#ifndef __SSE_KD_TREE_H__
+#define __SSE_KD_TREE_H__
+
+
+#include <Core/Geometry/PointVector.h>
+#include <Core/Geometry/BBox.h>
+
+#include <Interface/RayPacket.h>
+#include <Interface/Texture.h>
+
+#include <Model/Groups/KDTree.h>
+#include <Model/Groups/varray.h>
+#include <Model/Groups/KdtreeParameters.h>
+#include <Model/Groups/VerticalKDTree.h>
+
+#include <iostream>
+
+#include <xmmintrin.h>
+#include <Core/Util/Align.h>
+
+namespace Manta {
+
+  // Note: Kdtree is the namespace: KDTree, VerticalKDTree are classes
+  // in the namespace.
+  namespace Kdtree {
+
+    
///////////////////////////////////////////////////////////////////////////
+    
///////////////////////////////////////////////////////////////////////////
+    // SSE KDTREE CLASS PROPER
+    
///////////////////////////////////////////////////////////////////////////
+    
///////////////////////////////////////////////////////////////////////////
+    class SSEKDTree : public PrimitiveCommon, public KDTreeDebug {
+    public:
+      typedef KDTree::ScratchPadInfo ScratchPadInfo;
+
+      
/////////////////////////////////////////////////////////////////////////
+      // Constructor.
+      SSEKDTree( KDTree *kdtree_, Material *material_ );      
+      virtual ~SSEKDTree();
+
+      
/////////////////////////////////////////////////////////////////////////
+      // Primitive Interface.
+      virtual void intersect(const RenderContext& context, RayPacket& rays) 
const;
+      void computeNormal (const RenderContext& context, RayPacket& rays) 
const;
+      void computeBounds (const PreprocessContext&, BBox &box_ ) const;
+      void computeBounds ( BBox &box_ ) const;
+
+      
/////////////////////////////////////////////////////////////////////////
+      // Accessors.
+      virtual void        setRootNode( KDTreeNode *node ) { rootNode = node; 
};
+      virtual KDTreeNode *getRootNode()                   { return rootNode; 
};      
+      
+    private:
+      BBox bbox;
+      KDTreeNode       *rootNode;
+
+      VArray<int>      *triIndices;
+      VArray<Triangle> *tris;
+      TriangleNormal   *normals;
+
+                       VArray<int> *triToGroupMap;
+                       VArray<int> *groupToNameMap;
+                       VArray<char> *groupNames;
+                       VArray<unsigned char> *triFlags;
+
+      // This method intersects a list of triangles with the rays.
+      void intersectTriangles(IntersectPacket *intersect_packet,
+                         const RayPacket &rays,
+                         int which,
+                         unsigned int listBegin,
+                         unsigned int listSize ) const;
+
+      // This method is called to intersect a single ray with the kdtree.
+      void intersect_node( const RenderContext &context,
+                           const Mask &valid_mask,
+                           RayPacket &rays,
+                           int which,
+                           int p_start,
+                           float minDist[TraversalPacketSize],
+                           float maxDist[TraversalPacketSize] ) const;
+      
+
+    };
+
+  } // end namespace Kdtree
+
+} // end namespace Manta
+
+
+#endif

Modified: trunk/Model/Groups/VerticalKDTree.cc
==============================================================================
--- trunk/Model/Groups/VerticalKDTree.cc        (original)
+++ trunk/Model/Groups/VerticalKDTree.cc        Sun Jan 29 01:24:55 2006
@@ -61,12 +61,6 @@
 
///////////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////////
 
-static int
-intersect_triangle3(const float orig[3], 
-                    const float dir[3],
-                    const float vert0[3], const float vert1[3], const float 
vert2[3],
-                    float *t, float *u, float *v );
-
 // Currently this routine is the fastest.
 // This is a C version of the ray triangle intersection edge form.
 static inline int
@@ -76,12 +70,6 @@
                          float *t, float *u, float *v,
                          const float *edge1, const float *edge2);
 
-// This is a C++ version of the above routine.
-static int
-intersectTriangle3Edge(const Vectorf &direction, const Pointf &origin, 
-                       const Vectorf &edge1, Vectorf &edge2, Pointf &p0,
-                       float &t, float &u, float &v );
-
 
 
///////////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////////
@@ -89,6 +77,26 @@
 
///////////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////////
 
+namespace Manta {
+  namespace Kdtree {
+    class IntersectPacket {
+    public:
+      const Mask active_mask;
+      Mask hit_mask;
+      
+      int   hit_index[TraversalPacketSize];
+      
+      float t[TraversalPacketSize];
+      float u[TraversalPacketSize];
+      float v[TraversalPacketSize];
+      
+      IntersectPacket( const Mask &active_mask_ )
+        : active_mask( active_mask_ ) { };
+    };
+  };
+};
+
+
 void VerticalKDTree::intersectTriangles(IntersectPacket &intersect_packet,
                                        const RayPacket &rays,
                                        int which,
@@ -334,8 +342,6 @@
       const float split = node->split();
 
       // Identify near_index and far_index.
-      assert( rays.getFlag( RayPacket::ConstantSigns ) );
-            
       const int near_index = rays.getSign(which+p_start,axis);
       const int far_index  = (1 - near_index);
       
@@ -386,31 +392,44 @@
       //      if (rays.getFlag( RayPacket::DebugPacket )) { std::cerr << 
"C\n"; }
       
       // Case III "Both" -- Push far node on stack.
-      stack_index++;
-      stack[stack_index].node = node->getChild( far_index );
-
-      // Copy t_split and t_far to the stack.
-      for (int p=0;p<TraversalPacketSize;++p) {
-        stack[stack_index].t_near[p] = t_split[p];
-        stack[stack_index].t_far [p] = t_far[p];
-      }
 
       // Determine the valid mask for the far subtree.
       set_lte( cmp_result, t_split, t_far );
-      set_and( stack[stack_index].mask, cmp_result, active_mask );
-      // stack[stack_index].mask = active_mask;
-      
-      // Update the current node.
-      node = node->getChild( near_index );
+      set_and( cmp_result, cmp_result, active_mask );
 
-      // Copy t_split to t_far.
-      for (int p=0;p<TraversalPacketSize;++p) {
-        t_far[p] = t_split[p];
+      // Check to see if any rays enter the far node.
+      if (any(cmp_result)) {
+
+        stack_index++;
+        stack[stack_index].node = node->getChild( far_index );
+        stack[stack_index].mask = cmp_result;
+        
+        // Copy t_split and t_far to the stack.
+        for (int p=0;p<TraversalPacketSize;++p) {
+          stack[stack_index].t_near[p] = t_split[p];
+          stack[stack_index].t_far [p] = t_far[p];
+        }
       }
 
       // Update the active mask.      
       set_lte( cmp_result, t_near, t_far );
-      set_and( active_mask, active_mask, cmp_result );
+      set_and( cmp_result, active_mask, cmp_result );
+
+      // Check to see if any rays hit the near node.
+      if (any( cmp_result )) {
+        // Update the current node.
+        node = node->getChild( near_index );
+        active_mask = cmp_result;
+
+        // Copy t_split to t_far.
+        for (int p=0;p<TraversalPacketSize;++p) {
+          t_far[p] = t_split[p];
+        }
+      }
+      else {
+        // Otherwise done with this subtree.
+        node = 0;
+      }
     }
 
     
///////////////////////////////////////////////////////////////////////////

Modified: trunk/Model/Groups/VerticalKDTree.h
==============================================================================
--- trunk/Model/Groups/VerticalKDTree.h (original)
+++ trunk/Model/Groups/VerticalKDTree.h Sun Jan 29 01:24:55 2006
@@ -170,20 +170,7 @@
     // INTERSECT PACKET  INTERSECT PACKET  INTERSECT PACKET  INTERSECT 
PACKET  
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
-    class IntersectPacket {
-    public:
-      const Mask active_mask;
-      Mask hit_mask;
-
-      int   hit_index[TraversalPacketSize];
-
-      float t[TraversalPacketSize];
-      float u[TraversalPacketSize];
-      float v[TraversalPacketSize];
-
-      IntersectPacket( const Mask &active_mask_ )
-        : active_mask( active_mask_ ) { };
-    };
+    class IntersectPacket;
 
     inline std::ostream &operator<< (std::ostream &out, const Mask &mask) {
 

Modified: trunk/fox/FManta/FMantaWindow.cc
==============================================================================
--- trunk/fox/FManta/FMantaWindow.cc    (original)
+++ trunk/fox/FManta/FMantaWindow.cc    Sun Jan 29 01:24:55 2006
@@ -84,8 +84,9 @@
   FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_UNHIDE_ALL,    
FMantaWindow::onUnHideAll ),
 
   FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_POSITIVEZ_UP, 
FMantaWindow::onCoordSystemUp ),
-  FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_POSITIVEY_UP, 
FMantaWindow::onCoordSystemUp )
-  
+  FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_POSITIVEY_UP, 
FMantaWindow::onCoordSystemUp ),
+
+  FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_DEBUG_RAY_DIALOG, 
FMantaWindow::onDebugRayDialog )
 };
 
 
FXIMPLEMENT(FMantaWindow,FXMainWindow,FMantaWindowMap,ARRAYNUMBER(FMantaWindowMap));
@@ -101,7 +102,9 @@
     fast_quit( false ) ,
     cutting_snap( 1 ),
     debug_packet( 1 ), 
-    extra_options_dialog( 0 )
+    extra_options_dialog( 0 ),
+    debug_ray_x( 0 ),
+    debug_ray_y( 0 )
 {
   
/////////////////////////////////////////////////////////////////////////////
   // Menu Bar.
@@ -174,10 +177,16 @@
   positivey_up = new FXMenuRadio( options_menu, "Positive Y up", this, 
ID_POSITIVEY_UP );
   new FXMenuSeparator( options_menu );
 
+  new FXMenuTitle( menu_bar, "Options", 0, options_menu );
+  
+  // Debug Menu.
+  debug_menu = new FXMenuPane( this );
+  
   // Debug shoot one ray.
-  new FXMenuCheck( options_menu, "Debug ray on click", new FXDataTarget( 
debug_packet ), FXDataTarget::ID_VALUE );
+  new FXMenuCheck  ( debug_menu, "Debug ray on click", new FXDataTarget( 
debug_packet ), FXDataTarget::ID_VALUE );
+  new FXMenuCommand( debug_menu, "Debug ray at coords", 0, this, 
ID_DEBUG_RAY_DIALOG );
   
-  new FXMenuTitle( menu_bar, "Options", 0, options_menu );
+  new FXMenuTitle( menu_bar, "Debug", 0, debug_menu );
 
   
/////////////////////////////////////////////////////////////////////////////
   // Create the content of the window.
@@ -414,11 +423,19 @@
 
 long FMantaWindow::onCameraText( FXObject *sender, FXSelector key, void 
*data ) {
 
+  // Get a pointer to the camera.
+  Camera *camera = manta_interface->getCamera( 
manta_frame->getMantaChannel() );
+  
+  // Get the camera in text form.
+  ostringstream str;
+  camera->output( str );
+
+  FXString camera_description = str.str().c_str();
+  
   // Collect a string from the user.
-  FXString description;
-  if (FXInputDialog::getString(description, getApp(), "Enter Text..", 
"Camera Spec:", 0 )) {
+  if (FXInputDialog::getString(camera_description, getApp(), "Enter Text..", 
"Camera Spec:", 0 )) {
     manta_interface->addTransaction("Camera",
-                                   
Callback::create(this,&FMantaWindow::mantaCamera2,string(description.text())));
+                                   
Callback::create(this,&FMantaWindow::mantaCamera2,string(camera_description.text())));
   }
 
   return 1;
@@ -453,10 +470,9 @@
 long FMantaWindow::onShadowAlgorithmText( FXObject *sender, FXSelector key, 
void *data ) {
        
   // Collect a string from the user.
-  FXString description;
-  if (FXInputDialog::getString(description, getApp(), "Enter Text..", 
"Shadow Algorithm Spec:", 0 )) {
+  if (FXInputDialog::getString(shadow_description, getApp(), "Enter Text..", 
"Shadow Algorithm Spec:", 0 )) {
     manta_interface->addTransaction("Shadow Algorithm.",
-                                   
Callback::create(this,&FMantaWindow::mantaShadowAlgorithm,string(description.text())));
+                                   
Callback::create(this,&FMantaWindow::mantaShadowAlgorithm,string(shadow_description.text())));
   }
        
   return 1;
@@ -492,10 +508,9 @@
 long FMantaWindow::onPixelSamplerText( FXObject *sender, FXSelector key, 
void *data ) {
 
   // Collect a string from the user.
-  FXString description;
-  if (FXInputDialog::getString(description, getApp(), "Enter Text", "Pixel 
Sampler Spec:", 0 )) {
+  if (FXInputDialog::getString(sampler_description, getApp(), "Enter Text", 
"Pixel Sampler Spec:", 0 )) {
     manta_interface->addTransaction("Pixel Sampler.",
-                                   
Callback::create(this,&FMantaWindow::mantaPixelSampler,string(description.text())));
+                                   
Callback::create(this,&FMantaWindow::mantaPixelSampler,string(sampler_description.text())));
   }
 
   return 1;
@@ -527,10 +542,9 @@
 long FMantaWindow::onTraverserText( FXObject *sender, FXSelector key, void 
*data ) {
        
   // Collect a string from the user.
-  FXString description;
-  if (FXInputDialog::getString(description, getApp(), "Enter Text", "Image 
Traverser Spec:", 0 )) {
+  if (FXInputDialog::getString(traverser_description, getApp(), "Enter 
Text", "Image Traverser Spec:", 0 )) {
     manta_interface->addTransaction("Image Traverser.",
-                                   
Callback::create(this,&FMantaWindow::mantaTraverser,string(description.text())));
+                                   
Callback::create(this,&FMantaWindow::mantaTraverser,string(traverser_description.text())));
   }
        
   return 1;
@@ -547,8 +561,12 @@
     
     Point point;
     Vector normal;
+
+    // Save the location.
+    debug_ray_x = event->win_x;
+    debug_ray_y = event->win_y;
     
-    if (manta_frame->shootOneRay( event->win_x, event->win_y, point, normal, 
true )) {
+    if (manta_frame->shootOneRay( debug_ray_x, debug_ray_y, point, normal, 
true )) {
       
       std::cerr << point << std::endl;
       std::cerr << normal << std::endl;
@@ -558,6 +576,33 @@
   return 1;
 }
 
+long FMantaWindow::onDebugRayDialog( FXObject* sender, FXSelector key,
+                                     void* /*data*/ ) {
+
+  FXString description;
+  description.format( "%d %d", debug_ray_x, debug_ray_y );
+  
+  if (FXInputDialog::getString(description, getApp(), "Enter Text", "Image 
coords:", 0 )) {
+    std::istringstream str( description.text() );
+
+    // Input the image coords.
+    str >> debug_ray_x >> debug_ray_y;
+
+    Point point;
+    Vector normal;
+    
+    // Send the debug ray.
+    if (manta_frame->shootOneRay( debug_ray_x, debug_ray_y, point, normal, 
true )) {
+      
+      std::cerr << point << std::endl;
+      std::cerr << normal << std::endl;
+    }    
+  }  
+  
+  return 1;
+}
+
+
 long FMantaWindow::onAddCuttingPlane( FXObject *sender, FXSelector key, void 
*data ) {
 
   FXEvent *event = (FXEvent *)data;
@@ -951,6 +996,7 @@
   
   return 1;
 }
+
 
 
///////////////////////////////////////////////////////////////////////////////
 

Modified: trunk/fox/FManta/FMantaWindow.h
==============================================================================
--- trunk/fox/FManta/FMantaWindow.h     (original)
+++ trunk/fox/FManta/FMantaWindow.h     Sun Jan 29 01:24:55 2006
@@ -45,6 +45,7 @@
     FXMenuPane *sampler_menu;
     FXMenuPane *traverser_menu;
     FXMenuPane *options_menu;
+    FXMenuPane *debug_menu;
                
     FXMenuCommand *cutting_flip;
     FXMenuCheck   *hide_selected_check;
@@ -75,7 +76,16 @@
     FMantaImageFrame *manta_frame;
                
     bool fast_quit;
-               
+
+    // String to save user entered specifications.
+    FXString shadow_description;
+    FXString sampler_description;
+    FXString traverser_description;
+
+    // Debug ray image locations.
+    int debug_ray_x;
+    int debug_ray_y;
+    
   public:
     // Commands for the main window.
     enum {
@@ -131,6 +141,9 @@
       // Coordinate system up
       ID_POSITIVEZ_UP,
       ID_POSITIVEY_UP,
+
+      // Debug ray dialog.
+      ID_DEBUG_RAY_DIALOG,
       
       ID_LAST
     };
@@ -187,6 +200,7 @@
     long onPOI( FXObject *sender, FXSelector key, void *data );
     long onExtraOptions   ( FXObject *sender, FXSelector key, void *data );
     long onCoordSystemUp  ( FXObject *sender, FXSelector key, void *data );
+    long onDebugRayDialog ( FXObject *sender, FXSelector key, void *data );
                
     // Accessors.
     void setMantaInterface( MantaInterface *manta_interface_, int 
manta_channel_ ) { 

Modified: trunk/scenes/boeing777.cc
==============================================================================
--- trunk/scenes/boeing777.cc   (original)
+++ trunk/scenes/boeing777.cc   Sun Jan 29 01:24:55 2006
@@ -47,6 +47,7 @@
 #include <Model/Groups/KDTree.h>
 #include <Model/Groups/TransparentKDTree.h>
 #include <Model/Groups/VerticalKDTree.h>
+#include <Model/Groups/SSEKDTree.h>
 #include <Model/Lights/PointLight.h>
 #include <Model/Lights/HeadLight.h>
 #include <Model/Materials/Lambertian.h>
@@ -83,7 +84,7 @@
                         MTL_SOLID_WIRE,
                         MTL_WIRE,
                         MTL_RAYDIRECTION };
-enum TraversalType    { TRAVERSAL_SINGLE, TRAVERSAL_VERTICAL };
+enum TraversalType    { TRAVERSAL_SINGLE, TRAVERSAL_VERTICAL, TRAVERSAL_SSE 
};
 
 ///////////////////////////////////////////////////////////////////////////
 // This function constructs the Boeing 777 Test Scene using a KdTree.
@@ -107,6 +108,7 @@
   int    ambient_rays = 16;
   int    phong_exp = 512;
   ColorComponent phong_reflect = 0;
+  float scene_ambient[] = { 0.2, 0.2, 0.2 };
   
   bool use_transparency = false;
 
@@ -175,12 +177,24 @@
     else if (args[i] == "-vertical") {
       traversal = TRAVERSAL_VERTICAL; 
     }
+    else if (args[i] == "-sse") {
+      traversal = TRAVERSAL_SSE;
+    }
+    else if (args[i] == "-scene_ambient") {
+      if (!(getArg(i,args,scene_ambient[0]) &&
+            getArg(i,args,scene_ambient[1]) &&
+            getArg(i,args,scene_ambient[2])))
+      {
+        cerr << "-ambient_light <r> <g> <b>\n";
+      }
+    }
                else {
                        cerr << "Valid options for boeing777:\n";
                        cerr << "-file <filename>"             << endl;
                        cerr << "-np   <num build workers>"    << endl;
                        cerr << "-cutting [<point> <normal>]"  << endl;
       cerr << "Materials:-------------------------------------\n";
+      cerr << "-scene_ambient <r> <g> <b>\n";
                        cerr << "-alpha <alpha>"               << endl;
       cerr << "-phong <exp> <reflection> **default**" << endl;
       cerr << "-ambient <max dist> <secondary rays>"  << endl;
@@ -192,6 +206,7 @@
       cerr << "-bg marble  Currently only marble is supported.\n";
       cerr << "Traversals:------------------------------------\n";
       cerr << "-vertical -- Use vertical traversal code.\n";
+      cerr << "-sse      -- Use SSE intrinsic code.\n";
       
                        throw IllegalArgument( "boeing777", i, args );
                }
@@ -201,6 +216,17 @@
        Scene *scene = new Scene();
        Object *root_object = 0;
 
+       
/////////////////////////////////////////////////////////////////////////////
+       // Add a head light.
+       LightSet *lights = new LightSet();
+       
+       lights->add( new HeadLight( 2.0, Color(RGB(1.0,1.0,1.0)) ));
+       lights->setAmbientLight( new 
ConstantAmbient(Color(RGB(scene_ambient[0],
+                                                         scene_ambient[1],
+                                                         
scene_ambient[2]))));
+       scene->setLights(lights);
+
+  
   // Choose a material.
   Material *kd_material = 0;
   switch (material_type) {
@@ -223,7 +249,7 @@
     kd_material = new Flat( new NormalTexture() );
     break;
   case MTL_RAYDIRECTION:
-    kd_material = new Lambertian( new 
WireframeTexture<KDTree::ScratchPadInfo>( new RaySignTexture(), Color(RGB(0, 
0, 0)) ) );
+    kd_material = new Lambertian( new RaySignTexture() );
     break;
   case MTL_SOLID_WIRE:
     kd_material = new Phong( new WireframeTexture<KDTree::ScratchPadInfo>( 
new KDTreeTexture(), Color(RGB(0, 0, 0)) ),
@@ -272,6 +298,10 @@
     // Create a vertical kdtree.
     kd_primitive = new VerticalKDTree( kdtree, kd_material );
   }
+  else if (traversal == TRAVERSAL_SSE) {
+    // Create a sse kdtree.
+    kd_primitive = new SSEKDTree( kdtree, kd_material );
+  }
        
        
////////////////////////////////////////////////////////////////////////////
        // Compute the middle of the model for a cutting plane.
@@ -292,13 +322,6 @@
                root_object = kd_primitive;
        }
        
-       
/////////////////////////////////////////////////////////////////////////////
-       // Add a head light.
-       LightSet *lights = new LightSet();
-       
-       lights->add( new HeadLight( 2.0, Color(RGB(1.0,1.0,1.0)) ));
-       lights->setAmbientLight( new ConstantAmbient( 
Color(RGBColor(0.2,0.2,0.2) ) ));
-       scene->setLights(lights);
        
        // Add the tree to the scene.
        scene->setObject( root_object );




  • [MANTA] r873 - in trunk: Core/Util Interface Model/Groups fox/FManta scenes, abe, 01/29/2006

Archive powered by MHonArc 2.6.16.

Top of page