Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r862 - in trunk: . Interface Model/Groups Model/Materials fox/FManta fox/dm_demo scenes


Chronological Thread 
  • From: abe@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r862 - in trunk: . Interface Model/Groups Model/Materials fox/FManta fox/dm_demo scenes
  • Date: Tue, 24 Jan 2006 04:02:50 -0700 (MST)

Author: abe
Date: Tue Jan 24 04:02:49 2006
New Revision: 862

Modified:
   trunk/CMakeLists.txt
   trunk/Interface/RayPacket.h
   trunk/Model/Groups/KDTree.cc
   trunk/Model/Groups/KDTree.h
   trunk/Model/Groups/TransparentKDTree.h
   trunk/Model/Groups/VerticalKDTree.cc
   trunk/Model/Groups/VerticalKDTree.h
   trunk/Model/Materials/NormalMaterial.cc
   trunk/Model/Materials/NormalMaterial.h
   trunk/fox/FManta/FMantaImageFrame.cc
   trunk/fox/FManta/FMantaImageFrame.h
   trunk/fox/FManta/FMantaKdExplorer.cc
   trunk/fox/FManta/FMantaKdExplorer.h
   trunk/fox/FManta/FMantaTrackballNav.cc
   trunk/fox/FManta/FMantaWindow.cc
   trunk/fox/FManta/FMantaWindow.h
   trunk/fox/dm_demo/dm_demo.cc
   trunk/scenes/boeing777.cc
Log:

Still debugging the Vertical KDTree Traversal.

Added WireFrame material and RayDirection (visualizes sign mask)
M    Model/Materials/NormalMaterial.cc
M    Model/Materials/NormalMaterial.h

Added new debug material options.
M    scenes/boeing777.cc

Added a debug packet mode. When set double middle click sends a ray packet 
with the DebugPacket flag set.
M    fox/dm_demo/dm_demo.cc
M    fox/FManta/FMantaTrackballNav.cc
M    fox/FManta/FMantaWindow.cc
M    fox/FManta/FMantaWindow.h
M    fox/FManta/FMantaImageFrame.cc
M    fox/FManta/FMantaImageFrame.h

Added DebugPacket flag, may be tested in breakpoint conditions.
M    Interface/RayPacket.h

Produces images, still a few bugs with the traversal.
M    Model/Groups/VerticalKDTree.cc
M    Model/Groups/VerticalKDTree.h

Modified optimization compiler options for x86_64
M    CMakeLists.txt

Added KDTreeDebug parent class to all KDTree related classes. This allows any 
kdtree to be explored.
M    fox/FManta/FMantaKdExplorer.cc
M    fox/FManta/FMantaKdExplorer.h
M    Model/Groups/TransparentKDTree.h
M    Model/Groups/KDTree.cc
M    Model/Groups/KDTree.h


Modified: trunk/CMakeLists.txt
==============================================================================
--- trunk/CMakeLists.txt        (original)
+++ trunk/CMakeLists.txt        Tue Jan 24 04:02:49 2006
@@ -85,16 +85,14 @@
 
 # Assume that if we are running on an Itanium (ia64), then it is an
 # SGI linux system
-
 IF   (CMAKE_SYSTEM_PROCESSOR MATCHES "ia64")
 
   SET(SGI_LINUX TRUE)
 
   # Warn if the compiler is not icc
   IF   (CMAKE_C_COMPILER MATCHES "icc$")
-    FIRST_TIME_SET(CMAKE_C_FLAGS_RELEASE "-O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release  Flags" FORCE)
+    FIRST_TIME_SET(CMAKE_C_FLAGS_RELEASE "-tpp2 -O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release  Flags" FORCE)
     FIRST_TIME_SET(CMAKE_C_FLAGS_DEBUG   "-O0 -g" CACHE STRING "Debug Flags" 
FORCE)
-
   ELSE (CMAKE_C_COMPILER MATCHES "icc$")
          FIRST_TIME_MESSAGE("Intel Compilers recommended on ia64. setenv CC 
icc before running cmake.")
          FIRST_TIME_SET(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math 
-funroll-loops -g" CACHE STRING "Release Flags" FORCE)
@@ -102,7 +100,7 @@
   ENDIF(CMAKE_C_COMPILER MATCHES "icc$")
 
   IF   (CMAKE_CXX_COMPILER MATCHES "icpc$")
-         FIRST_TIME_SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release Flags" FORCE)
+         FIRST_TIME_SET(CMAKE_CXX_FLAGS_RELEASE "-tpp2 -O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release Flags" FORCE)
          FIRST_TIME_SET(CMAKE_CXX_FLAGS_DEBUG   "-O0 -g" CACHE STRING "Debug 
Flags" FORCE)
   ELSE (CMAKE_CXX_COMPILER MATCHES "icpc$")
          FIRST_TIME_MESSAGE("Intel Compilers recommended on ia64.  setenv 
CXX icpc before running cmake.")
@@ -111,6 +109,26 @@
   ENDIF(CMAKE_CXX_COMPILER MATCHES "icpc$")
 
 ENDIF (CMAKE_SYSTEM_PROCESSOR MATCHES "ia64")
+
+######################################################################
+# Check for EMT64
+IF (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+
+  ####################################################################
+  # Check for Intel Compilers.
+  IF   (CMAKE_C_COMPILER MATCHES "icc$")
+    FIRST_TIME_SET(CMAKE_C_FLAGS_RELEASE "-tpp7 -O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release  Flags" FORCE)
+    FIRST_TIME_SET(CMAKE_C_FLAGS_DEBUG   "-O0 -g" CACHE STRING "Debug Flags" 
FORCE)
+  ENDIF(CMAKE_C_COMPILER MATCHES "icc$")
+
+  IF   (CMAKE_CXX_COMPILER MATCHES "icpc$")
+         FIRST_TIME_SET(CMAKE_CXX_FLAGS_RELEASE "-tpp7 -O3 -IPO -g 
-DSCI_ASSERTION_LEVEL=0" CACHE STRING "Release Flags" FORCE)
+         FIRST_TIME_SET(CMAKE_CXX_FLAGS_DEBUG   "-O0 -g" CACHE STRING "Debug 
Flags" FORCE)
+  ENDIF(CMAKE_CXX_COMPILER MATCHES "icpc$")
+
+ENDIF (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+
+
 
 
 ######################################################################

Modified: trunk/Interface/RayPacket.h
==============================================================================
--- trunk/Interface/RayPacket.h (original)
+++ trunk/Interface/RayPacket.h Tue Jan 24 04:02:49 2006
@@ -82,7 +82,9 @@
       HaveNormals           = 0x0200,
       HaveInverseDirections = 0x0400,
       HaveSigns             = 0x0800,
-      ConstantSigns         = 0x1000
+      ConstantSigns         = 0x1000,
+
+      DebugPacket           = 0x8000
     };
 
     // Create a "toplevel" raypacket.  You need to call resetHits or

Modified: trunk/Model/Groups/KDTree.cc
==============================================================================
--- trunk/Model/Groups/KDTree.cc        (original)
+++ trunk/Model/Groups/KDTree.cc        Tue Jan 24 04:02:49 2006
@@ -336,6 +336,8 @@
 
           ScratchPadInfo& scratch_pad = 
rays.scratchpad<ScratchPadInfo>(which);
           scratch_pad.normal = (n1 * u) + (n2 * v) + (n0 * (1 - u - v));
+          scratch_pad.a = u;
+          scratch_pad.b = v;
 
 #if SHOW_DUPLICATES
           if (isectData.duplicate == 0)

Modified: trunk/Model/Groups/KDTree.h
==============================================================================
--- trunk/Model/Groups/KDTree.h (original)
+++ trunk/Model/Groups/KDTree.h Tue Jan 24 04:02:49 2006
@@ -278,11 +278,20 @@
     };
 
     
///////////////////////////////////////////////////////////////////////////
+    // KDTREE DEBUG INTERFACE
+    
///////////////////////////////////////////////////////////////////////////
+    class KDTreeDebug {
+    public:
+      virtual void        setRootNode( KDTreeNode *node ) = 0;
+      virtual KDTreeNode *getRootNode()                   = 0;
+    };
+    
+    
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
     // KDTREE CLASS PROPER
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
-    class KDTree : public PrimitiveCommon {
+    class KDTree : public PrimitiveCommon, public KDTreeDebug {
 
       // Transparent KDTree will use data owned by this kdtree.
       friend class TransparentKDTree;
@@ -369,7 +378,7 @@
       struct ScratchPadInfo {
         Vector normal; // Normal of the intersected face.
         Color payload; // Payload of the intersected face.
-        Real a, b, c;
+        Real a, b;
       };
 
       virtual ~KDTree() {}
@@ -389,8 +398,8 @@
       int load( const char *fn, int np );
 
       // Accessors (used by gui to examine kdtree).
-      void        setRootNode( KDTreeNode *node ) { rootNode = node; };
-      KDTreeNode *getRootNode()                   { return rootNode; };
+      virtual void        setRootNode( KDTreeNode *node ) { rootNode = node; 
};
+      virtual KDTreeNode *getRootNode()                   { return rootNode; 
};
       
     };
 

Modified: trunk/Model/Groups/TransparentKDTree.h
==============================================================================
--- trunk/Model/Groups/TransparentKDTree.h      (original)
+++ trunk/Model/Groups/TransparentKDTree.h      Tue Jan 24 04:02:49 2006
@@ -48,10 +48,10 @@
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
     // TRANSPARENT KDTREE CLASS
-    // Note: Uses data structures defined in normal TransparentKDTree.
+    // Note: Uses data structures defined in normal KDTree.h
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
-    class TransparentKDTree : public PrimitiveCommon {
+    class TransparentKDTree : public PrimitiveCommon, public KDTreeDebug {
     private:
       BBox bbox;
 
@@ -156,6 +156,9 @@
       void computeNormal(const RenderContext& context, RayPacket& rays) 
const;
       void computeBounds(const PreprocessContext &context, BBox &box_ ) 
const { box_.extendByBox( bbox ); }
       void computeBounds( BBox &box_ ) const { box_.extendByBox( bbox ); }
+
+      virtual void        setRootNode( KDTreeNode *node ) { rootNode = node; 
};
+      virtual KDTreeNode *getRootNode()                   { return rootNode; 
};
     };
   }
 

Modified: trunk/Model/Groups/VerticalKDTree.cc
==============================================================================
--- trunk/Model/Groups/VerticalKDTree.cc        (original)
+++ trunk/Model/Groups/VerticalKDTree.cc        Tue Jan 24 04:02:49 2006
@@ -100,7 +100,12 @@
   
   // Initialize nearset variables.
   for (int p=0;p<TraversalPacketSize;++p) {
+
+    // Set the maxium hit distance.
     maxDist[p] = rays.getMinT(which+p);
+
+    // Clear the hit mask bit.
+    intersect_packet.hit_mask[p] = Mask::False;
   }
 
   // Iterate over all of the triangles.
@@ -114,14 +119,10 @@
     // Use horizontal intersection for now...
     for (int p=0;p<TraversalPacketSize;++p) {
 
-      // Convert origin and direction to float
-      Pointf origin     = rays.getOrigin(which+p);
-      Vectorf direction = rays.getDirection(which+p);
-      
       float t, u, v;      
       if(intersect_packet.active_mask[p] &&
-         intersect_triangle3_edge( origin.getDataPtr(),
-                                   direction.getDataPtr(),
+         intersect_triangle3_edge( rays.getOrigin(which+p).getDataPtr(),
+                                   rays.getDirection(which+p).getDataPtr(),
                                    &tri[0][0],
                                    &t, &u, &v,
                                    tri.edge1.getDataPtr(),
@@ -129,14 +130,22 @@
         
         // Check to see if the t value is closer.
         if (t < maxDist[p]) {
+
+          // Update the maxDist for a valid hit.
+          maxDist[p] = t;
+
+          // Set the new hit values in the intersection packet.
           intersect_packet.t[p] = t;
           intersect_packet.u[p] = u;
           intersect_packet.v[p] = v;
           intersect_packet.hit_index[p] = triIdx;
 
+          assert( triIdx < tris->getLen() );
+
           // Specify that a valid hit was found.
           intersect_packet.hit_mask[p] = Mask::True;
         }
+
       }
     }
   }
@@ -160,8 +169,8 @@
   // Iterate over sub groups of rays.
   for(int which=rays.begin();which<rays.end();which+=TraversalPacketSize) {
 
-    float minDist[TraversalPacketSize];
-    float maxDist[TraversalPacketSize];
+    Real minDist[TraversalPacketSize];
+    Real maxDist[TraversalPacketSize];
 
     // Compute min and max distance for the kdtree.
     for (int p=0;(p<TraversalPacketSize)&&((which+p)<rays.end());++p) {
@@ -187,6 +196,7 @@
       // Intersect the subpacket with the tree.
       intersect_node( context, valid_mask, rays, which, minDist, maxDist );
     }
+
   }
 }
 
@@ -280,7 +290,7 @@
       // if (entryPos_coord_on_axis <= split) {
       Mask cmp_result;
       set_lte( cmp_result, entry_axis, split );
-      if (all( active_mask, cmp_result )) {
+      if (any( cmp_result )) {
 
         
///////////////////////////////////////////////////////////////////////
         // Check to see if entry and exit are on the
@@ -314,7 +324,7 @@
 
           
/////////////////////////////////////////////////////////////////////
           // Case "C"
-          
+
           nearNode = nearNode->right();
           continue;
         }
@@ -383,8 +393,13 @@
       // 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];
@@ -392,10 +407,13 @@
           
           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;
         }          
       }
     }
@@ -437,7 +455,7 @@
     tris( kdtree_->tris ),
     normals( kdtree_->normals )
 {
-  bbox.extendByBox( bbox );
+  bbox.extendByBox( kdtree_->bbox );
 }
 VerticalKDTree::~VerticalKDTree() { };
 

Modified: trunk/Model/Groups/VerticalKDTree.h
==============================================================================
--- trunk/Model/Groups/VerticalKDTree.h (original)
+++ trunk/Model/Groups/VerticalKDTree.h Tue Jan 24 04:02:49 2006
@@ -48,6 +48,8 @@
 #include <Model/Groups/varray.h>
 #include <Model/Groups/KdtreeParameters.h>
 
+#include <iostream>
+
 namespace Manta {
 
   // Note: Kdtree is the namespace: KDTree, VerticalKDTree are classes
@@ -113,24 +115,48 @@
       }
     }
 
-    static inline bool all( const Mask &active, const Mask &mask ) {
-      bool result = mask[0];
-      for (int p=1;p<TraversalPacketSize;++p) {
-        result = result && (mask[p] || (!active[p]));
-      }
-      return result;
-    }
-
     static inline bool any( const Mask &mask ) {
       bool result = mask[0];
-      for (int p=1;p<TraversalPacketSize;++p) {
+      for (int p=1;(!result) && (p<TraversalPacketSize);++p) {
         result = (result || mask[p]);
       }
+      return result;
     }
 
     static inline bool none( const Mask &mask ) {
       return !any( mask );
     }
+    
+    // Returns true if all the masks that are active are true.
+    static inline bool all( const Mask &active, const Mask &mask ) {
+
+      bool result = any(active);
+
+      for (int p=0;p<TraversalPacketSize;++p) {
+        if (active[p]) {
+          if (!mask[p]) {
+            result = false;
+          }
+        }
+      }
+
+      return result;
+      
+#if 0
+      bool result = mask[0] || (!active[0]);
+      bool any_active  = active[0];
+
+      for (int p=1;(p<TraversalPacketSize);++p) {
+        result = result && (mask[p] || (!active[p]));
+        any_active = any_active || active[p];
+      }
+
+      // Make sure atleast one bit is active.
+      return result && any_active;
+#endif
+    }
+
+
 
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
@@ -139,8 +165,8 @@
     
///////////////////////////////////////////////////////////////////////////
     class IntersectPacket {
     public:
-      Mask  active_mask;
-      Mask  hit_mask;
+      const Mask active_mask;
+      Mask hit_mask;
 
       int   hit_index[TraversalPacketSize];
 
@@ -152,12 +178,23 @@
         : active_mask( active_mask_ ) { };
     };
 
+    std::ostream &operator<< (std::ostream &out, const Mask &mask) {
+
+      out << "{ ";
+      for (int p=0;p<TraversalPacketSize;++p) {
+        out << " " << mask[p];
+      }
+      out << "} ";
+
+      return out;
+    }
+    
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
     // VERTICAL KDTREE CLASS PROPER
     
///////////////////////////////////////////////////////////////////////////
     
///////////////////////////////////////////////////////////////////////////
-    class VerticalKDTree : public PrimitiveCommon {
+    class VerticalKDTree : public PrimitiveCommon, public KDTreeDebug {
     public:
       typedef KDTree::ScratchPadInfo ScratchPadInfo;
 
@@ -175,8 +212,8 @@
 
       
/////////////////////////////////////////////////////////////////////////
       // Accessors.
-      void        setRootNode( KDTreeNode *node ) { rootNode = node; };
-      KDTreeNode *getRootNode()                   { return rootNode; };      
+      virtual void        setRootNode( KDTreeNode *node ) { rootNode = node; 
};
+      virtual KDTreeNode *getRootNode()                   { return rootNode; 
};      
       
     private:
       BBox bbox;

Modified: trunk/Model/Materials/NormalMaterial.cc
==============================================================================
--- trunk/Model/Materials/NormalMaterial.cc     (original)
+++ trunk/Model/Materials/NormalMaterial.cc     Tue Jan 24 04:02:49 2006
@@ -1,11 +1,46 @@
 
+/*
+  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.
+*/
+
 #include <Model/Materials/NormalMaterial.h>
 #include <Interface/RayPacket.h>
 
 #include <Model/Primitives/HeavyTriangle.h>
+#include <Model/Groups/KDTree.h>
 
 using namespace Manta;
 
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// NORMAL  NORMAL  NORMAL  NORMAL  NORMAL  NORMAL  NORMAL  NORMAL  NORMAL  
NORM
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
 void NormalMaterial::shade( const RenderContext &context, RayPacket &rays) 
const {
        
   // Compute the normal for each ray.
@@ -16,46 +51,114 @@
 
     // Copy the normal out.
     Vector normal = rays.getNormal(i);
+
+    normal = (normal *(Real)0.5) + Vector( 0.5, 0.5, 0.5 );
+
     rays.setColor( i, Color( RGB( normal[0],normal[1], normal[2] )) );
                
-#if 0
-    // Add a wireframe.
-    HeavyTriangle::TriangleHit &th =
-      rays.get(i).hitInfo.scratchpad<HeavyTriangle::TriangleHit>();
+       }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// RAY DIRECTION  RAY DIRECTION  RAY DIRECTION  RAY DIRECTION  RAY DIRECTION 
 R
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void RayDirectionMaterial::shade( const RenderContext &context, RayPacket 
&rays) const {
+       
+  // Compute the normal for each ray.
+  rays.computeNormals( context );
+       
+  // Iterate over the packet and set the colors.
+  for (int i=rays.begin();i<rays.end();++i) {
 
-    Real a = th.a;
-    Real b = th.b;
-    Real c = (1.0 - th.a - th.b);
+    // Copy the normal out.
+    VectorT<int,3> sign = rays.getSigns( i );
+
+    ColorComponent scale = 0.5;
+    if (rays.getFlag( RayPacket::ConstantSigns )) {
+      scale = 1.0;
+    }
     
-    if ((a > 0.9) && (b < 0.1) && (c < 0.1)) {
-      // rays.setResult( i, Color(RGB(1.0,0.0,0.0)) );
+    rays.setColor( i, Color( RGB( scale*sign[0],scale*sign[1], scale*sign[2] 
)) );
+               
+       }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// WIREFRAME  WIREFRAME  WIREFRAME  WIREFRAME  WIREFRAME  WIREFRAME  
WIREFRAME
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+template<>
+void WireFrameMaterial<HeavyTriangle::TriangleHit>::
+getBarycentricCoords( RayPacket &rays, int which, Real &a, Real &b, Real &c 
) const {
+
+  HeavyTriangle::TriangleHit &th =
+    rays.scratchpad<HeavyTriangle::TriangleHit>(which);
+  
+  a = th.a;
+  b = th.b;
+  c = ((Real)1.0 - th.a - th.b);
+}
+
+template<>
+void WireFrameMaterial<Kdtree::KDTree::ScratchPadInfo>::
+getBarycentricCoords( RayPacket &rays, int which, Real &a, Real &b, Real &c 
) const {
+
+  Kdtree::KDTree::ScratchPadInfo &info =
+    rays.scratchpad<Kdtree::KDTree::ScratchPadInfo>(which);
+
+  a = info.a;
+  b = info.b;
+  c = ((Real)1.0 - info.a - info.b);
+}
+
+template<class ScratchPadInfo>
+void WireFrameMaterial<ScratchPadInfo>::shade( const RenderContext &context, 
RayPacket &rays) const {
+       
+  // Compute the normal for each ray.
+  rays.computeNormals( context );
+       
+  // Iterate over the packet and set the colors.
+  for (int i=rays.begin();i<rays.end();++i) {
 
-      Vector normal = th.n1;
+    // Copy the normal out.
+    Vector normal = rays.getNormal(i);
+
+    normal = (normal *(Real)0.5) + Vector( 0.5, 0.5, 0.5 );
+
+    rays.setColor( i, Color( RGB( normal[0],normal[1], normal[2] )) );
+
+    // Lookup barycentric coordinates.
+    Real a, b, c;
+    getBarycentricCoords( rays, i, a, b, c );
+
+    // Add a wireframe.
+    if ((a > 0.9) && (b < 0.1) && (c < 0.1)) {
       Color rgb( RGB( normal[0],normal[1], normal[2] ));
-      rays.setResult( i, rgb );
+      rays.setColor( i, rgb );
     }
     else if ((b > 0.9) && (c < 0.1) && (a < 0.1)) {
-      // rays.setResult( i, Color(RGB(0.0,1.0,0.0)) );
-
-      Vector normal = th.n2;
       Color rgb( RGB( normal[0],normal[1], normal[2] ));
-      rays.setResult( i, rgb );
+      rays.setColor( i, rgb );
     }
     else if ((c > 0.9) && (a < 0.1) && (b < 0.1)) {
-      // rays.setResult( i, Color(RGB(0.0,0.0,1.0)) );
-      Vector normal = th.n0;
       Color rgb( RGB( normal[0],normal[1], normal[2] ));
-      rays.setResult( i, rgb );
+      rays.setColor( i, rgb );
     }
     else if ((a < 0.05) || (b < 0.05) || (c < 0.05)) {
-      rays.setResult( i, Color(RGB(0.0,0.0,0.0)) );
+      rays.setColor( i, Color(RGB(0.0,0.0,0.0)) );
     }
     else {
-      rays.setResult( i, Color(RGB(1.0,1.0,1.0)) );
+      rays.setColor( i, Color(RGB(1.0,1.0,1.0)) );
     }
-#endif
-
 
        }
 }
 
+template class WireFrameMaterial<HeavyTriangle::TriangleHit>;
+template class WireFrameMaterial<Kdtree::KDTree::ScratchPadInfo>;

Modified: trunk/Model/Materials/NormalMaterial.h
==============================================================================
--- trunk/Model/Materials/NormalMaterial.h      (original)
+++ trunk/Model/Materials/NormalMaterial.h      Tue Jan 24 04:02:49 2006
@@ -1,4 +1,32 @@
 
+/*
+  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 Manta_Model_NormalMaterial_h
 #define Manta_Model_NormalMaterial_h
 
@@ -6,12 +34,43 @@
 #include <Core/Color/Color.h>
 #include <Interface/Texture.h>
 
+// These are debugging materials. They should probably be implemented as 
procedural
+// textures so that they can be incorporated into more sophisticated shading 
models
+// (i.e. Phong shaded wireframe, etc)
+
+// Abe Stephens.
+
 namespace Manta {
+
+  
   class NormalMaterial : public LitMaterial {
-public:
+  public:
                NormalMaterial() {  };
     ~NormalMaterial() {  };
     void shade( const RenderContext &context, RayPacket &rays) const;
+  };
+
+  class RayDirectionMaterial : public LitMaterial {
+  public:
+               RayDirectionMaterial() {  };
+    ~RayDirectionMaterial() {  };
+    void shade( const RenderContext &context, RayPacket &rays) const;
+  };  
+  
+  template< class ScratchPadInfo >
+  class WireFrameMaterial : public LitMaterial {
+  public:
+               WireFrameMaterial() {  };
+    ~WireFrameMaterial() {  };
+    void shade( const RenderContext &context, RayPacket &rays) const;
+  private:
+
+    
///////////////////////////////////////////////////////////////////////////
+    // Note: This method must be implemented for each possible template 
parameter
+    // type explicitly. It is responsible for copying the coordinates out of 
the
+    // ray packet scratch pad.
+    void getBarycentricCoords( RayPacket &rays, int which,
+                               Real &a, Real &b, Real &c ) const;
   };
 };
 

Modified: trunk/fox/FManta/FMantaImageFrame.cc
==============================================================================
--- trunk/fox/FManta/FMantaImageFrame.cc        (original)
+++ trunk/fox/FManta/FMantaImageFrame.cc        Tue Jan 24 04:02:49 2006
@@ -118,7 +118,7 @@
     return navigator->onKeyPress( sender, sel, data );
 }
 
-bool FMantaImageFrame::shootOneRay( int pixel_x, int pixel_y, Point 
&result_position, Vector &result_normal ) {
+bool FMantaImageFrame::shootOneRay( int pixel_x, int pixel_y, Point 
&result_position, Vector &result_normal, bool debug_packet ) {
 
        // Make sure we have an instance of RTRT.
        RTRT *rtrt = dynamic_cast< RTRT * >( manta_interface );
@@ -153,11 +153,23 @@
        // Create a ray packet.
        RayPacketData data;
        RayPacket rays( data, 0, 1, 0, 0 );
-       
+
+  // Set the debug packet flag if necessary.
+  if (debug_packet) {
+    std::cerr << "Debug packet.\n";
+    rays.setFlag( RayPacket::DebugPacket );
+  }
+  
        // Shoot the ray.
        Color color;
        rtrt->shootOneRay( color, rays, image_x, image_y, manta_channel );
-       
+
+  // Check to see if additional output is necessary.
+  if (debug_packet) {
+    std::cerr << "hit: " << rays.wasHit(0)  << "\n";
+    std::cerr << "t:   " << rays.getMinT(0) << "\n";
+  }
+  
        // Check for a result.
        if (rays.wasHit(0)) {
        
@@ -165,10 +177,11 @@
                // these for us.
                result_position = rays.getHitPosition(0);
                result_normal   = rays.getNormal(0);
-       
+    
                return true;
        }
-       
+
+  
        return false;
 
 }

Modified: trunk/fox/FManta/FMantaImageFrame.h
==============================================================================
--- trunk/fox/FManta/FMantaImageFrame.h (original)
+++ trunk/fox/FManta/FMantaImageFrame.h Tue Jan 24 04:02:49 2006
@@ -63,7 +63,7 @@
                int            getMantaChannel  () { return manta_channel;   
};
                
                // Debugging.
-               bool shootOneRay( int pixel_x, int pixel_y, Point 
&result_position, Vector &result_normal );            
+               bool shootOneRay( int pixel_x, int pixel_y, Point 
&result_position, Vector &result_normal, bool debug_packet );         
        };
   
 };

Modified: trunk/fox/FManta/FMantaKdExplorer.cc
==============================================================================
--- trunk/fox/FManta/FMantaKdExplorer.cc        (original)
+++ trunk/fox/FManta/FMantaKdExplorer.cc        Tue Jan 24 04:02:49 2006
@@ -21,7 +21,7 @@
 
 
 FMantaKdExplorerDialog::FMantaKdExplorerDialog( FMantaWindow *manta_window_,
-                                                                             
                                  KDTree *kdtree_,
+                                                                             
                                  KDTreeDebug *kdtree_,
                                                                              
                                  const FXString &name, FXuint opts,
                                                                              
                                  FXint x,FXint y,FXint w,FXint h,FXint pl,
                                                                              
                                  FXint pr,FXint pt,FXint pb,FXint hs,FXint 
vs ) : 
@@ -64,7 +64,7 @@
   // Restore the root node.
   if (node_stack.size() > 0) {
     KDTreeNode *root = node_stack.front();
-    manta_interface->addTransaction( "Reset Root", Callback::create( kdtree, 
&KDTree::setRootNode, root ) );
+    manta_interface->addTransaction( "Reset Root", Callback::create( kdtree, 
&KDTreeDebug::setRootNode, root ) );
   }
 }
 
@@ -126,7 +126,7 @@
   node_stack.push_back( root );
   
   // Update manta.
-  manta_interface->addTransaction( "Reset Root", Callback::create( kdtree, 
&KDTree::setRootNode, root ) );
+  manta_interface->addTransaction( "Reset Root", Callback::create( kdtree, 
&KDTreeDebug::setRootNode, root ) );
 
   // Update buttons.
   update_buttons();
@@ -143,7 +143,7 @@
     KDTreeNode *root = node_stack.back();
   
     // Update manta.
-    manta_interface->addTransaction( "Set Parent", Callback::create( kdtree, 
&KDTree::setRootNode, root ) );
+    manta_interface->addTransaction( "Set Parent", Callback::create( kdtree, 
&KDTreeDebug::setRootNode, root ) );
 
     // Update buttons.
     update_buttons();
@@ -167,7 +167,7 @@
     node_stack.push_back( child );
 
     // Update manta.
-    manta_interface->addTransaction( "Set Left", Callback::create( kdtree, 
&KDTree::setRootNode, child ) );
+    manta_interface->addTransaction( "Set Left", Callback::create( kdtree, 
&KDTreeDebug::setRootNode, child ) );
 
     // Update buttons.
     update_buttons();
@@ -190,7 +190,7 @@
     node_stack.push_back( child );
 
     // Update manta.
-    manta_interface->addTransaction( "Set Right", Callback::create( kdtree, 
&KDTree::setRootNode, child ) );
+    manta_interface->addTransaction( "Set Right", Callback::create( kdtree, 
&KDTreeDebug::setRootNode, child ) );
 
     // Update buttons.
     update_buttons();

Modified: trunk/fox/FManta/FMantaKdExplorer.h
==============================================================================
--- trunk/fox/FManta/FMantaKdExplorer.h (original)
+++ trunk/fox/FManta/FMantaKdExplorer.h Tue Jan 24 04:02:49 2006
@@ -9,7 +9,7 @@
 using namespace Manta;
 
 #include <Model/Groups/KDTree.h>
-#include <Model/Groups/TransparentKDTree.h>
+
 using namespace Manta::Kdtree;
 
 #include <list>
@@ -36,7 +36,7 @@
     MantaInterface *manta_interface;
     
     // Target kdtree.
-    KDTree *kdtree;
+    KDTreeDebug *kdtree;
 
     // Information labels.
     FXLabel *depth_label;
@@ -65,7 +65,7 @@
     
     FMantaKdExplorerDialog() {  };
     FMantaKdExplorerDialog( FMantaWindow *manta_window_,
-                            KDTree *kdtree_,
+                            KDTreeDebug *kdtree_,
                   const FXString &name, FXuint opts=DECOR_ALL,
                   FXint x=50,FXint y=50,FXint w=0,FXint h=0,FXint pl=10,
                   FXint pr=10,FXint pt=10,FXint pb=10,FXint hs=4,FXint vs=4 
);

Modified: trunk/fox/FManta/FMantaTrackballNav.cc
==============================================================================
--- trunk/fox/FManta/FMantaTrackballNav.cc      (original)
+++ trunk/fox/FManta/FMantaTrackballNav.cc      Tue Jan 24 04:02:49 2006
@@ -69,8 +69,8 @@
 
       // std::cerr << "Setting center of rotation. " << event->win_x << " " 
<< event->win_y << std::endl;
                        
-      if (manta_frame->shootOneRay( event->win_x, event->win_y, lookat, 
normal )) {
-       manta_interface->addTransaction("camera lookat",
+      if (manta_frame->shootOneRay( event->win_x, event->win_y, lookat, 
normal, false )) {
+        manta_interface->addTransaction("camera lookat",
                                        Callback::create( this, 
&FMantaTrackballNav::mantaLookat, lookat ) );
       }
                        

Modified: trunk/fox/FManta/FMantaWindow.cc
==============================================================================
--- trunk/fox/FManta/FMantaWindow.cc    (original)
+++ trunk/fox/FManta/FMantaWindow.cc    Tue Jan 24 04:02:49 2006
@@ -76,6 +76,9 @@
   FXMAPFUNC(SEL_COMMAND,          FMantaWindow::ID_HIDE_SELECTED,    
FMantaWindow::onHideSelected ),
   FXMAPFUNC(SEL_RIGHTBUTTONPRESS, FMantaImageFrame::ID_PIXEL_SELECT, 
FMantaWindow::onPick ),
 
+  // Debug ray packet mode.
+  FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, FMantaImageFrame::ID_PIXEL_SELECT, 
FMantaWindow::onDebugPacketMode ),
+  
   // Other options.
   FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_EXTRA_OPTIONS, 
FMantaWindow::onExtraOptions ),
   FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_UNHIDE_ALL,    
FMantaWindow::onUnHideAll ),
@@ -97,6 +100,7 @@
     manta_interface( 0 ),
     fast_quit( false ) ,
     cutting_snap( 1 ),
+    debug_packet( 0 ), 
     extra_options_dialog( 0 )
 {
   
/////////////////////////////////////////////////////////////////////////////
@@ -169,7 +173,10 @@
   positivez_up->setCheck( true );
   positivey_up = new FXMenuRadio( options_menu, "Positive Y up", this, 
ID_POSITIVEY_UP );
   new FXMenuSeparator( options_menu );
-       
+
+  // Debug shoot one ray.
+  new FXMenuCheck( options_menu, "Debug ray on click", new FXDataTarget( 
debug_packet ), FXDataTarget::ID_VALUE );
+  
   new FXMenuTitle( menu_bar, "Options", 0, options_menu );
 
   
/////////////////////////////////////////////////////////////////////////////
@@ -524,12 +531,33 @@
   return 1;
 }
 
-long FMantaWindow::onAddCuttingPlane( FXObject *sender, FXSelector key, void 
*data ) {
+long FMantaWindow::onDebugPacketMode( FXObject *sender, FXSelector key, void 
*data ) {
 
   FXEvent *event = (FXEvent *)data;
 
-  std::cout << "Image location: " << event->win_x << " " << event->win_y << 
std::endl;
+  // Check to see if debug mode check box is checked.
+  if (debug_packet) {
+  
+    std::cerr << "Image location: " << event->win_x << " " << event->win_y 
<< std::endl;
+    
+    Point point;
+    Vector normal;
+    
+    if (manta_frame->shootOneRay( event->win_x, event->win_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;
+
+  
   if ((event->state & CONTROLMASK) == CONTROLMASK) {
     onPOI(sender, key, data);
     return 1;
@@ -539,7 +567,7 @@
   Vector normal;
        
   // Shoot a ray into the scene.
-  if (manta_frame->shootOneRay( event->win_x, event->win_y, point, normal )) 
{
+  if (manta_frame->shootOneRay( event->win_x, event->win_y, point, normal, 
false )) {
                
     // Check to see if the cutting plane should be snapped to an axis.
     if (cutting_snap) {
@@ -565,10 +593,6 @@
       normal = snap_axis[ max_axis ];
     }
                
-    std::cout << "Adding cutting plane" << std::endl;
-    std::cout << point << std::endl;
-    std::cout << normal << std::endl;
-               
     // Add a cutting plane at this point.
     manta_interface->addTransaction("Add Cutting Plane",
                                    
Callback::create(this,&FMantaWindow::mantaAddCuttingPlane,point,normal));
@@ -703,7 +727,7 @@
 
     // Check to see if picking is supported.
     if (kdtree->isPickingEnabled()) {
-      int result = manta_frame->shootOneRay( x, y, point, normal );
+      int result = manta_frame->shootOneRay( x, y, point, normal, false );
       if (!result) {
         kdtree->resetPicking();
        // hide_selected_check->disable();
@@ -721,7 +745,7 @@
     
     // Check to see if picking is supported.
     if (kdtree->isPickingEnabled()) {
-      int result = manta_frame->shootOneRay( x, y, point, normal );
+      int result = manta_frame->shootOneRay( x, y, point, normal, false );
       if (!result) {
        // std::cerr << "reset picking" << std::endl;
         kdtree->resetPicking();
@@ -765,7 +789,7 @@
   
   // Check to see if this object is either a transparent or normal kdtree.
     
-  int result = manta_frame->shootOneRay( x, y, point, normal );
+  int result = manta_frame->shootOneRay( x, y, point, normal, false );
   if (result) {
     Point  eye[4];
     Point  lookat[4];

Modified: trunk/fox/FManta/FMantaWindow.h
==============================================================================
--- trunk/fox/FManta/FMantaWindow.h     (original)
+++ trunk/fox/FManta/FMantaWindow.h     Tue Jan 24 04:02:49 2006
@@ -58,6 +58,7 @@
     FXRealSlider  *speed_slider;
     FXRealSlider  *cutting_slider;
     int cutting_snap;
+    int debug_packet;
                
     // Camera options.
     FXListBox     *camera_bookmark_list;
@@ -179,6 +180,7 @@
     long onTraverser      ( FXObject *sender, FXSelector key, void *data );
     long onTraverserText  ( FXObject *sender, FXSelector key, void *data );
     long onAddCuttingPlane( FXObject *sender, FXSelector key, void *data );
+    long onDebugPacketMode( FXObject *sender, FXSelector key, void *data );
     long onHideSelected( FXObject *sender, FXSelector key, void *data );
     long onUnHideAll( FXObject *sender, FXSelector key, void *data );
     long onPick( FXObject *sender, FXSelector key, void *data );

Modified: trunk/fox/dm_demo/dm_demo.cc
==============================================================================
--- trunk/fox/dm_demo/dm_demo.cc        (original)
+++ trunk/fox/dm_demo/dm_demo.cc        Tue Jan 24 04:02:49 2006
@@ -134,7 +134,7 @@
 
        // Add an FMantaWindow.
        FMantaWindow manta_window( &app, 
-                             "Open-Source MANTA. Silicon Graphics Inc. and 
SCI Institute, University of Utah", 
+                             argv[0], 
                              true,
                              width, height );
        
@@ -297,7 +297,6 @@
   
     // Check to see if the default scene was a kdtree.
        
-       
     
/////////////////////////////////////////////////////////////////////////////
     // Create any necessary dialogs now since everything else should be 
initialized.
     KDTree *kdtree = 0;
@@ -317,12 +316,18 @@
       manta_window.addExtraOptionsDialog( "Transparency",
                                           new FMantaTransparentDialog( 
&manta_window, kdtree, transparent_kdtree, "Transparency" ));
 
+      // Use the transparent renderer by default
+      manta_window.setSceneObject( kdtree );
+    }
+
+    // Add a kdtree debugger.
+    KDTreeDebug *kdtree_debug = 0;
+    if ((kdtree_debug = dynamic_cast<KDTreeDebug *>( root_object ))) {
+
       // Create a kdtree explorer dialog.
       manta_window.addExtraOptionsDialog( "kd-Tree Explorer",
-                                          new FMantaKdExplorerDialog( 
&manta_window, kdtree, "kd-Tree Explorer" ));
+                                          new FMantaKdExplorerDialog( 
&manta_window, kdtree_debug, "kd-Tree Explorer" ));
 
-      // Use the transparent renderer by default
-      manta_window.setSceneObject( transparent_kdtree );
     }
 
   }

Modified: trunk/scenes/boeing777.cc
==============================================================================
--- trunk/scenes/boeing777.cc   (original)
+++ trunk/scenes/boeing777.cc   Tue Jan 24 04:02:49 2006
@@ -75,7 +75,12 @@
 using namespace SCIRun;
 
 enum CuttingPlaneType { CUTTING_NONE, CUTTING_DEFAULT, CUTTING_SPECIFIED };
-enum MtlType          { MTL_PHONG, MTL_AMBIENT, MTL_FLAT };
+enum MtlType          { MTL_PHONG,
+                        MTL_AMBIENT,
+                        MTL_FLAT,
+                        MTL_NORMAL,
+                        MTL_WIRE,
+                        MTL_RAYDIRECTION };
 enum TraversalType    { TRAVERSAL_SINGLE, TRAVERSAL_VERTICAL };
 
 ///////////////////////////////////////////////////////////////////////////
@@ -135,9 +140,18 @@
         throw IllegalArgument("boeing777 -ambient <max dist> <secondary 
rays>", i, args);
       }
     }
+    else if (args[i] == "-normal") {
+      material_type = MTL_NORMAL;
+    }    
     else if (args[i] == "-flat") {
       material_type = MTL_FLAT;
     }
+    else if (args[i] == "-wire") {
+      material_type = MTL_WIRE;
+    }
+    else if (args[i] == "-raydirection") {
+      material_type = MTL_RAYDIRECTION;
+    }
                else if (args[i] == "-cutting") {
                        string cutting_string;
                        if (getPointArg(i, args, plane_point ) && 
getVectorArg(i, args, plane_normal)) { 
@@ -157,15 +171,20 @@
       traversal = TRAVERSAL_VERTICAL; 
     }
                else {
-                       cerr << "Valid options for boeing777:" << endl;
+                       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 << "-alpha <alpha>"               << endl;
       cerr << "-phong <exp> <reflection> **default**" << endl;
       cerr << "-ambient <max dist> <secondary rays>"  << endl;
-      cerr << "-bg marble  Currently only marble is supported.\n";
+      cerr << "-normal   -- Use normal material.\n";
       cerr << "-flat\n";
+      cerr << "-wire\n";
+      cerr << "-raydirection\n";
+      cerr << "-bg marble  Currently only marble is supported.\n";
+      cerr << "Traversals:------------------------------------\n";
       cerr << "-vertical -- Use vertical traversal code.\n";
       
                        throw IllegalArgument( "boeing777", i, args );
@@ -192,6 +211,17 @@
     break;
   case MTL_FLAT:
     kd_material = new Flat( new KDTreeTexture );
+    break;
+    
+  case MTL_NORMAL:
+    kd_material = new NormalMaterial( );
+    break;
+  case MTL_RAYDIRECTION:
+    kd_material = new RayDirectionMaterial();
+    break;
+  case MTL_WIRE:
+    kd_material = new WireFrameMaterial<KDTree::ScratchPadInfo>();
+    break;
   };
        
        KDTree *kdtree = new KDTree( kd_material );




  • [MANTA] r862 - in trunk: . Interface Model/Groups Model/Materials fox/FManta fox/dm_demo scenes, abe, 01/24/2006

Archive powered by MHonArc 2.6.16.

Top of page