Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r427 - in branches/itanium2: . Core Core/Geometry Engine/Control Engine/Display Interface Model/Groups Model/Materials Model/Primitives Model/Readers Model/Readers/glm StandAlone fox scenes


Chronological Thread 
  • From: abe@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r427 - in branches/itanium2: . Core Core/Geometry Engine/Control Engine/Display Interface Model/Groups Model/Materials Model/Primitives Model/Readers Model/Readers/glm StandAlone fox scenes
  • Date: Sat, 9 Jul 2005 13:54:03 -0600 (MDT)

Author: abe
Date: Sat Jul  9 13:53:42 2005
New Revision: 427

Added:
   branches/itanium2/Model/Groups/RealisticBvh.cc
   branches/itanium2/Model/Groups/RealisticBvh.h
   branches/itanium2/Model/Readers/glm/
   branches/itanium2/Model/Readers/glm/glm.cc
   branches/itanium2/Model/Readers/glm/glm.h
   branches/itanium2/scenes/objviewer.cc
Modified:
   branches/itanium2/CMakeLists.txt
   branches/itanium2/Core/CMakeLists.txt
   branches/itanium2/Core/Geometry/BBox.h
   branches/itanium2/Core/Geometry/PointVector.cc
   branches/itanium2/Core/Geometry/PointVector.h
   branches/itanium2/Core/Geometry/Ray.h
   branches/itanium2/Engine/Control/RTRT.cc
   branches/itanium2/Engine/Display/CMakeLists.txt
   branches/itanium2/Engine/Display/GLXImageDisplay.cc
   branches/itanium2/Interface/Context.h
   branches/itanium2/Interface/Material.h
   branches/itanium2/Interface/Object.h
   branches/itanium2/Interface/Primitive.h
   branches/itanium2/Interface/RTRTInterface.h
   branches/itanium2/Model/Groups/CMakeLists.txt
   branches/itanium2/Model/Groups/kdtree.cc
   branches/itanium2/Model/Groups/varray.h
   branches/itanium2/Model/Materials/CMakeLists.txt
   branches/itanium2/Model/Materials/Dielectric.cc
   branches/itanium2/Model/Materials/Lambertian.cc
   branches/itanium2/Model/Materials/Lambertian.h
   branches/itanium2/Model/Primitives/PrimitiveCommon.h
   branches/itanium2/Model/Primitives/Triangle.h
   branches/itanium2/Model/Readers/CMakeLists.txt
   branches/itanium2/StandAlone/manta.cc
   branches/itanium2/StandAlone/manta_tile_size.pl
   branches/itanium2/fox/CMakeLists.txt
   branches/itanium2/fox/FMantaWindow.cc
   branches/itanium2/fox/FMantaWindow.h
   branches/itanium2/fox/fox_manta.cc
   branches/itanium2/scenes/CMakeLists.txt
Log:



A    scenes/objviewer.cc
M    scenes/CMakeLists.txt

Added test scene which will load a wavefront obj file.

M    Core/Geometry/BBox.h
M    Core/Geometry/PointVector.cc
M    Core/Geometry/Ray.h
M    Core/Geometry/PointVector.h

Merged changes from trunk/Core/Geometry/

M    Core/CMakeLists.txt
M    StandAlone/manta_tile_size.pl
M    StandAlone/manta.cc

Small changes to enable simple batch script benchmarking. Also added 
benchmark script for tile sizes.

M    fox/FMantaWindow.cc
M    fox/FMantaWindow.h
M    fox/fox_manta.cc
M    fox/CMakeLists.txt

Incremental changes to demo viewer.

M    Model/Primitives/Triangle.h
M    Model/Primitives/PrimitiveCommon.h
M    Interface/Material.h
M    Interface/Context.h
M    Interface/Object.h
M    Interface/Primitive.h
M    Interface/RTRTInterface.h

*** Removed unimplemented private copy constructors/operators. 
I think I should be able to define a Manta Object and have the ability to 
copy it.

M    Model/Groups/kdtree.cc

Examined some performance issues with the kdtree code.

A    Model/Groups/RealisticBvh.cc
A    Model/Groups/RealisticBvh.h

Added a simple bvh implementation, based on that found in "Realistic Ray 
Tracing"

M    Model/Groups/varray.h
M    Model/Groups/CMakeLists.txt

M    Model/Materials/Dielectric.cc
M    Model/Materials/Lambertian.cc
M    Model/Materials/Lambertian.h
M    Model/Materials/CMakeLists.txt

Removed LitPrimitive related code, activeLights etc. I think that this code 
was broken after I implemented move-able lights.

A    Model/Readers/glm
A    Model/Readers/glm/glm.cc
A    Model/Readers/glm/glm.h

Added Nate Robin's glm obj reader. This combined with changes that James and 
I have made is a pretty complete implementation.

M    Model/Readers/CMakeLists.txt

M    Engine/Control/RTRT.cc
M    Engine/Display/GLXImageDisplay.cc

Added some debugging code to the floating point framebuffer type. This is 
used by the profiling package, which I haven't checked in yet.

M    Engine/Display/CMakeLists.txt
M    CMakeLists.txt


Modified: branches/itanium2/CMakeLists.txt
==============================================================================
--- branches/itanium2/CMakeLists.txt    (original)
+++ branches/itanium2/CMakeLists.txt    Sat Jul  9 13:53:42 2005
@@ -24,6 +24,7 @@
 ENDIF(CMAKE_SYSTEM MATCHES IRIX)
 
 
+
 IF (APPLE)
   SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -g -fgcse-sm -funroll-loops 
-fstrict-aliasing -fsched-interblock -falign-loops=16 -falign-jumps=16 
-falign-functions=16 -falign-jumps-max-skip=15 -falign-loops-max-skip=15 
-ffast-math -freorder-blocks -mpowerpc-gpopt -force_cpusubtype_ALL -mtune=G5 
-mcpu=G5 -mpowerpc64 -faltivec -mabi=altivec -mpowerpc-gfxopt" CACHE STRING 
"Optimized Flags" FORCE)
 ENDIF (APPLE)
@@ -57,9 +58,18 @@
   SUBDIRS(glfw)
 ENDIF(BUILD_GLFW)
 
+# Check to see whether the histx performance monitoring tools should
+# be built on IA64.
+SET(BUILD_HISTX_MANTA 0 CACHE BOOL "Build Histx-Manta tools")
+IF(BUILD_HISTX_MANTA)
+  SUBDIRS(histx)
+ENDIF(BUILD_HISTX_MANTA)
+
 # Check to see whether the optional fox/ directory should be included.
 SET(BUILD_FOX 0 CACHE BOOL "Build fox frontend.")
 IF(BUILD_FOX)
   SUBDIRS(fox)
 ENDIF(BUILD_FOX)
+
+
 

Modified: branches/itanium2/Core/CMakeLists.txt
==============================================================================
--- branches/itanium2/Core/CMakeLists.txt       (original)
+++ branches/itanium2/Core/CMakeLists.txt       Sat Jul  9 13:53:42 2005
@@ -8,6 +8,7 @@
 SET (CORE_SOURCES ${CORE_SOURCES}
      Geometry/PointVector.h
      Geometry/PointVector.cc
+     Geometry/BBox.h
      )
 SET (CORE_SOURCES ${CORE_SOURCES}
      Exceptions/BadPrimitive.h

Modified: branches/itanium2/Core/Geometry/BBox.h
==============================================================================
--- branches/itanium2/Core/Geometry/BBox.h      (original)
+++ branches/itanium2/Core/Geometry/BBox.h      Sat Jul  9 13:53:42 2005
@@ -4,6 +4,12 @@
 
 #include <SCIRun/Core/Math/MiscMath.h>
 
+#include <sgi_stl_warnings_off.h>
+#include <limits>
+#include <sgi_stl_warnings_on.h>
+
+#include <assert.h>
+
 namespace Manta {
   class BBox {
   public:
@@ -13,9 +19,21 @@
       bounds[0] = min_;
       bounds[1] = max_;
     }
-    BBox()  { }
-    ~BBox() { }
-
+    BBox() {
+      // Need to initialize min and max.
+      reset();
+    }
+    ~BBox() {
+    }
+               
+    // This resets min and max to an uninitialized state that will
+    // accept new bounds [MAX, -MAX].
+    void reset() {
+      Real max_val = std::numeric_limits<Real>::max();
+      bounds[0] = Point( max_val,  max_val,  max_val);
+      bounds[1] = Point(-max_val, -max_val, -max_val);
+    }
+    
     Vector diagonal() const {
       return bounds[1] - bounds[0];
     }
@@ -33,7 +51,7 @@
     void extendByPoint(const PointT<T,3>& p) {
       bounds[0] = Min(bounds[0], 
Point((Point::ScalarType)p[0],(Point::ScalarType)p[1],(Point::ScalarType)p[2]));
       bounds[1] = Max(bounds[1], 
Point((Point::ScalarType)p[0],(Point::ScalarType)p[1],(Point::ScalarType)p[2]));
-    }
+               }
                
     void extendBySphere(const Point& p, Real radius) {
       bounds[0] = Min(bounds[0], p-Vector(radius, radius, radius));

Modified: branches/itanium2/Core/Geometry/PointVector.cc
==============================================================================
--- branches/itanium2/Core/Geometry/PointVector.cc      (original)
+++ branches/itanium2/Core/Geometry/PointVector.cc      Sat Jul  9 13:53:42 
2005
@@ -1,17 +1,20 @@
 
 #include <Core/Geometry/PointVector.h>
+
+#include <sgi_stl_warnings_off.h>
 #include <iostream>
+#include <sgi_stl_warnings_on.h>
 
 namespace Manta {
   template<typename T, int Dim>
-  inline std::ostream &operator<< (std::ostream &os, const VectorT<T,Dim> 
&v) {
+  std::ostream &operator<< (std::ostream &os, const VectorT<T,Dim> &v) {
     for (int i=0;i<Dim;++i)
       os << v[i] << " ";
     return os;
   }
 
   template<typename T, int Dim>
-  inline std::ostream &operator<< (std::ostream &os, const PointT<T,Dim> &v) 
{
+  std::ostream &operator<< (std::ostream &os, const PointT<T,Dim> &v) {
     for (int i=0;i<Dim;++i)
       os << v[i] << " ";
     return os;

Modified: branches/itanium2/Core/Geometry/PointVector.h
==============================================================================
--- branches/itanium2/Core/Geometry/PointVector.h       (original)
+++ branches/itanium2/Core/Geometry/PointVector.h       Sat Jul  9 13:53:42 
2005
@@ -17,10 +17,14 @@
                        
     VectorT() {
     }
+#ifndef SWIG
     VectorT(T x, T y) {
+      typedef char unnamed[ Dim == 2 ? 1 : 0 ];
       data[0] = x; data[1] = y;
     }
+#endif      
     VectorT(T x, T y, T z) {
+      typedef char unnamed[ Dim == 3 ? 1 : 0 ];
       data[0] = x; data[1] = y; data[2] = z;
     }
 
@@ -36,12 +40,13 @@
         data[i] = (T)copy[i];
     }
 
-               template< typename S >
-    VectorT<T, Dim>& operator=(const VectorT<S, Dim>& copy) {
+#ifndef SWIG
+    VectorT<T, Dim>& operator=(const VectorT<T, Dim>& copy) {
       for(int i=0;i<Dim;i++)
         data[i] = (T)copy[i];
       return *this;
     }
+#endif
 
     ~VectorT() {
     }
@@ -50,20 +55,30 @@
       return data[0];
     }
     T y() const {
+      typedef char unnamed[ Dim >=2 ? 1 : 0 ];
       return data[1];
     }
     T z() const {
+      typedef char unnamed[ Dim >= 3 ? 1 : 0 ];
       return data[2];
     }
+#ifndef SWIG
     const T &operator[](int i) const {
       return data[i];
     }
     T &operator[] ( int i ) {
       return data[i];
-    }
-               
+    }          
                const T *operator &() const { return data; }
                
+#else
+    %extend {
+      T& __getitem__( int i ) {
+        return self->operator[](i);
+      }
+    }
+#endif
+
     VectorT<T, Dim> operator+(const VectorT<T, Dim>& v) const {
       VectorT<T, Dim> result;
       for(int i=0;i<Dim;i++)
@@ -227,11 +242,14 @@
     PointT() {
     }
 
+#ifndef SWIG
     PointT(T x, T y) {
-      char unnamed[ Dim == 2 ? 1 : 0 ];
+      typedef char unnamed[ Dim == 2 ? 1 : 0 ];
       data[0] = x; data[1] = y;
     }
+#endif
     PointT(T x, T y, T z) {
+      typedef char unnamed[ Dim == 3 ? 1 : 0 ];
       data[0] = x; data[1] = y; data[2] = z;
     }
     
@@ -245,13 +263,15 @@
       for (int i=0;i<Dim;++i)
         data[i] = copy[i];
     }
-               
+
+#ifndef SWIG
                template< typename S >
     PointT<T, Dim>& operator=(const PointT<S, Dim>& copy) {
       for(int i=0;i<Dim;i++)
         data[i] = (T)copy[i];
       return *this;
     }
+#endif
 
     ~PointT() {
     }
@@ -263,8 +283,10 @@
       return data[1];
     }
     T z() const {
+      typedef char unnamed[ Dim == 3 ? 1 : 0 ];
       return data[2];
     }
+#ifndef SWIG
     T operator[](int i) const {
       return data[i];
     }
@@ -273,6 +295,13 @@
     }
                
                const T *operator& () const { return data; };
+#else
+    %extend {
+      T& __getitem__( int i ) {
+        return self->operator[](i);
+      }
+    }
+#endif
 
     VectorT<T, Dim> operator-(const PointT<T, Dim>& p) const {
       VectorT<T, Dim> result;

Modified: branches/itanium2/Core/Geometry/Ray.h
==============================================================================
--- branches/itanium2/Core/Geometry/Ray.h       (original)
+++ branches/itanium2/Core/Geometry/Ray.h       Sat Jul  9 13:53:42 2005
@@ -15,12 +15,14 @@
     {
     }
 
+#ifndef SWIG
     Ray& operator=(const Ray& copy)
     {
       orig=copy.orig;
       dir=copy.dir;
       return *this;
     }
+#endif
 
     void set(const Point& origin, const Vector& direction)
     {

Modified: branches/itanium2/Engine/Control/RTRT.cc
==============================================================================
--- branches/itanium2/Engine/Control/RTRT.cc    (original)
+++ branches/itanium2/Engine/Control/RTRT.cc    Sat Jul  9 13:53:42 2005
@@ -678,7 +678,7 @@
     if(depth == 1 && context.getMaxDepth() > 1)
       depth = 2; // Prefer double-buffering
     
-               cerr << "RTRT::setupPipelines:: depth = "<< depth << "\n";
+               //cerr << "RTRT::setupPipelines:: depth = "<< depth << "\n";
     
                // Set the pipeline depth.
                channel->pipelineDepth = depth;
@@ -994,18 +994,18 @@
   }
   Scene* newScene = 0;
        
-  std::cout << "Scene suffix: " << suffix << std::endl;
+  std::cerr << "Scene suffix: " << suffix << std::endl;
   
   if((suffix == "mo") || (suffix == "so") || (suffix == "dylib")) {
     // Do this twice - once silently and once printing errors
-    std::cout << "Reading .mo or .so scene" << std::endl;
+    std::cerr << "Reading .mo or .so scene" << std::endl;
     
     newScene = readMOScene(name, args, false);
     if(!newScene)
       readMOScene(name, args, true);
   } else {
     // Try reading it as an MO
-    std::cout << "Appending .mo to scene" << std::endl;
+    std::cerr << "Appending .mo to scene" << std::endl;
     
     newScene = readMOScene(name+".mo", args, false);
                

Modified: branches/itanium2/Engine/Display/CMakeLists.txt
==============================================================================
--- branches/itanium2/Engine/Display/CMakeLists.txt     (original)
+++ branches/itanium2/Engine/Display/CMakeLists.txt     Sat Jul  9 13:53:42 
2005
@@ -10,6 +10,7 @@
      Display/FileDisplay.cc
      Display/GLXImageDisplay.h
      Display/GLXImageDisplay.cc
-
+     Display/GLXMultipipeImageDisplay.h
+     Display/GLXMultipipeImageDisplay.cc
 
      )

Modified: branches/itanium2/Engine/Display/GLXImageDisplay.cc
==============================================================================
--- branches/itanium2/Engine/Display/GLXImageDisplay.cc (original)
+++ branches/itanium2/Engine/Display/GLXImageDisplay.cc Sat Jul  9 13:53:42 
2005
@@ -79,6 +79,7 @@
 
                image->getResolution( stereo, xres, yres );
 
+               
                // This code is from OpenGLImageDisplay.
                glViewport(0, 0, xres, yres);
                glMatrixMode(GL_PROJECTION);
@@ -118,6 +119,34 @@
                        }
                } else if(typeid(*image) == 
typeid(SimpleImage<RGBAfloatPixel>)){
                        const SimpleImage<RGBAfloatPixel>* si = 
dynamic_cast<const SimpleImage<RGBAfloatPixel>*>(image);
+
+
+                       
///////////////////////////////////////////////////////////////////////////
+                       // Assuming this is a performance image: normalize 
the image values.
+                       int total_size = xres * yres;
+                       RGBAfloatPixel *pixel = si->getRaw(0);
+                       
+                       float max_p, min_p;
+                       max_p = min_p = pixel[0].r;
+                       
+                       // Determine min and max.
+                       for (int i=1;i<total_size;++i) {
+                               if (pixel[i].r > max_p) max_p = pixel[i].r;
+                               else if (pixel[i].r < min_p) min_p = 
pixel[i].r;
+                       }
+                       
+                       // Determine scale and bias.
+                       float scale = 1.0 / (max_p - min_p);
+                       
+                       for (int i=0;i<total_size;++i) {
+                               float v = (pixel[i].r - min_p) * scale;
+                               pixel[i].r = pixel[i].g = pixel[i].b = 
pixel[i].a = v; 
+                       }
+                       
+                       
///////////////////////////////////////////////////////////////////////////
+                       
+
+
                        if(stereo){
                                glDrawBuffer(GL_BACK_LEFT);
                                glRasterPos2i(0,0);

Modified: branches/itanium2/Interface/Context.h
==============================================================================
--- branches/itanium2/Interface/Context.h       (original)
+++ branches/itanium2/Interface/Context.h       Sat Jul  9 13:53:42 2005
@@ -164,6 +164,7 @@
   };
   class PreprocessContext {
   public:
+               PreprocessContext() {  }; // Lights are dynamic now. This 
context isn't needed.
     PreprocessContext(RTRTInterface* /*rtrt_int*/, LightSet* globalLights)
       : globalLights(globalLights)
     {

Modified: branches/itanium2/Interface/Material.h
==============================================================================
--- branches/itanium2/Interface/Material.h      (original)
+++ branches/itanium2/Interface/Material.h      Sat Jul  9 13:53:42 2005
@@ -18,8 +18,8 @@
     virtual void preprocess(const PreprocessContext&) = 0;
     virtual void shade(const RenderContext& context, RayPacket& rays) const 
= 0;
   private:
-    Material(const Material&);
-    Material& operator=(const Material&);
+    // Material(const Material&);
+    // Material& operator=(const Material&);
   };
 }
 

Modified: branches/itanium2/Interface/Object.h
==============================================================================
--- branches/itanium2/Interface/Object.h        (original)
+++ branches/itanium2/Interface/Object.h        Sat Jul  9 13:53:42 2005
@@ -3,6 +3,7 @@
 #define Manta_Interface_Object_h
 
 namespace Manta {
+
   class BBox;
   class PreprocessContext;
   class RayPacket;
@@ -14,12 +15,11 @@
     virtual ~Object();
 
     virtual void preprocess(const PreprocessContext& context) = 0;
-    virtual void computeBounds(const PreprocessContext& context,
-                               BBox& bbox) const = 0;
+    virtual void computeBounds(const PreprocessContext& context, BBox& bbox) 
const = 0;
     virtual void intersect(const RenderContext& context, RayPacket& rays) 
const = 0;
   private:
-    Object(const Object&);
-    Object& operator=(const Object&);
+    // Object(const Object&);
+    // Object& operator=(const Object&);
   };
 }
 

Modified: branches/itanium2/Interface/Primitive.h
==============================================================================
--- branches/itanium2/Interface/Primitive.h     (original)
+++ branches/itanium2/Interface/Primitive.h     Sat Jul  9 13:53:42 2005
@@ -19,8 +19,9 @@
                               RayPacket& rays) const = 0;
     virtual void setTexCoordMapper(const TexCoordMapper* new_tex) = 0;
   private:
-    Primitive(const Primitive&);
-    Primitive& operator=(const Primitive&);
+         // These undefined private methods make it so that primitives 
cannot be copied.
+    // Primitive(const Primitive&);
+    // Primitive& operator=(const Primitive&);
   };
 }
 

Modified: branches/itanium2/Interface/RTRTInterface.h
==============================================================================
--- branches/itanium2/Interface/RTRTInterface.h (original)
+++ branches/itanium2/Interface/RTRTInterface.h Sat Jul  9 13:53:42 2005
@@ -74,6 +74,7 @@
     virtual listType listLoadBalancers() const = 0;
 
     // PixelSamplers
+               virtual void setPixelSampler( PixelSampler *sampler_ ) = 0;
     typedef PixelSampler* (*PixelSamplerCreator)(const vector<string>& args);
     virtual bool selectPixelSampler(const string& spec) = 0;
     virtual void registerComponent(const string& name, PixelSamplerCreator 
creator) = 0;

Modified: branches/itanium2/Model/Groups/CMakeLists.txt
==============================================================================
--- branches/itanium2/Model/Groups/CMakeLists.txt       (original)
+++ branches/itanium2/Model/Groups/CMakeLists.txt       Sat Jul  9 13:53:42 
2005
@@ -2,8 +2,8 @@
 SET (Manta_Groups_SRCS
      Groups/BVH.h
      Groups/BVH.cc
-#     Groups/Bvh.h
-#     Groups/Bvh.cc
+     Groups/RealisticBvh.h
+     Groups/RealisticBvh.cc
      Groups/Group.h
      Groups/Group.cc
      Groups/kdtree.h

Added: branches/itanium2/Model/Groups/RealisticBvh.cc
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Groups/RealisticBvh.cc      Sat Jul  9 13:53:42 
2005
@@ -0,0 +1,173 @@
+
+#include <Interface/Context.h>
+#include <Interface/RayPacket.h>
+
+#include <Model/Groups/RealisticBvh.h>
+#include <Model/Intersections/AxisAlignedBox.h>
+
+
+using namespace Manta;
+
+RealisticBvh::RealisticBvh( Object *child0, Object *child1 ) { 
+
+       child[0] = child0;
+       child[1] = child1;
+       
+       PreprocessContext context;
+       
+       // Update the bounding box of this node.
+       child0->computeBounds( context, bounds );
+       child1->computeBounds( context, bounds );
+}
+
+// Rearrange the pointers in the input array around a pivot point.
+int RealisticBvh::qsplit( Object **array, int size, Real pivot, int axis ) {
+
+       PreprocessContext context;
+
+       int ret_val = 0;
+       for (int i=0; i<size;++i) {
+       
+               // Get the bounds of the object.
+               BBox bounds;
+               array[i]->computeBounds( context, bounds );
+               
+               // Find the centroid of those bounds.
+               Real centroid = (bounds[0][axis] + bounds[1][axis]) * 0.5;
+               
+               if (centroid < pivot) {
+                       Object *tmp = array[i];
+                       array[i]    = array[ret_val];
+                       array[ret_val] = tmp;
+                       ++ret_val;
+               }
+       }
+       
+       if ((ret_val == 0) || (ret_val == size)) 
+               ret_val = size / 2;
+               
+       return ret_val;
+}
+
+Object *RealisticBvh::build_branch( Object **array, int size, int axis ) {
+       
+       // Check to exit conditions.
+       if (size == 1)
+               return array[0];
+       if (size == 2)
+               return new RealisticBvh( array[0], array[1] );
+       
+       // Create a new node.
+       RealisticBvh *new_node = new RealisticBvh();
+       
+       PreprocessContext context;
+       
+       // Compute the bounds of the array.
+       for (int i=0;i<size;++i) {
+               array[i]->computeBounds( context, new_node->bounds );
+       }
+       
+       // new_node->bounds.extendByPoint( 
new_node->bounds[0]+(Vector(new_node->bounds[0])*0.1) );
+       // new_node->bounds.extendByPoint( 
new_node->bounds[1]+(Vector(new_node->bounds[1])*0.1) );
+       
+       // Find a pivot point.
+       Point pivot((Vector(new_node->bounds[0]) + 
Vector(new_node->bounds[1])) * 0.5);
+       
+       // Split along the axis.
+       int mid_point = qsplit( array, size, pivot[axis], axis );
+       
+       // Create new left and right children.
+       new_node->child[0] = build_branch( array, mid_point, (axis+1)%3 );
+       new_node->child[1] = build_branch( array+mid_point, size-mid_point, 
(axis+1)%3 );
+       
+       return new_node;
+}
+
+// Construct a bvh given an array of object pointers.
+RealisticBvh::RealisticBvh( Object **array, int size ) {
+
+       // Check to exit conditions.
+       PreprocessContext context;
+       
+       // Compute the bounds of the array.
+       for (int i=0;i<size;++i) {
+               array[i]->computeBounds( context, bounds );
+       }
+       
+       // Find a pivot point.
+       Point pivot((Vector(bounds[0]) + Vector(bounds[1])) * 0.5);
+       
+       // Split along the axis.
+       int mid_point = qsplit( array, size, pivot[0], 0 );
+       
+       // Create new left and right children.
+       child[0] = build_branch( array, mid_point, 1 );
+       child[1] = build_branch( array+mid_point, size-mid_point, 1 );
+               
+}
+
+void RealisticBvh::preprocess(const PreprocessContext& context) {
+
+       // Build occurs in the constructor.
+}
+
+void RealisticBvh::computeBounds(const PreprocessContext& context, BBox& 
bbox) const {
+
+       // Bound the bvh.
+       bbox.extendByBox( bounds );
+}
+
+void RealisticBvh::intersect(const RenderContext& context, RayPacket& rays) 
const {
+       
+       rays.computeInverseDirections();
+
+       // Intersect the ray packet with the bounds of this node.
+       bool bbox_intersect[RayPacket::MaxSize];
+       
+       for(int i=0;i<rays.getSize();i++) {
+               
+               RayPacket::Element& e = rays.get(i);
+
+               // Check to see if the ray hits this node's bounding box.
+               Real min_t, max_t;
+               bbox_intersect[i] = Intersection::intersectAaBox( bounds, 
min_t, max_t, e.ray, 
+                                                                             
                                                                              
                                                      e.signMask, 
e.inverseDirection );
+       }
+       
+       // Find runs of rays which intersect this bounding box and intersect 
those 
+       // with the children.
+       int begin = 0;
+       int end   = 0;
+
+       while (begin < rays.getSize()) {
+       
+               // Find the beginning of a run.
+               while ((begin < rays.getSize()) && (!bbox_intersect[begin]))
+                       ++begin;
+       
+               // Find the end of this run.
+               end = begin;
+               while ((end < rays.getSize()) && (bbox_intersect[end]))
+                       ++end;
+
+               if ((end > begin) && (begin < rays.getSize())) {
+                       // Create a sub packet.
+                       RayPacket sub_packet( rays, begin, end );
+                               
+                       // Intersect with both children.
+                       child[0]->intersect( context, sub_packet );
+                       child[1]->intersect( context, sub_packet );
+                       
+               }
+               
+               begin = end;
+       }
+
+}
+
+
+
+
+
+
+

Added: branches/itanium2/Model/Groups/RealisticBvh.h
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Groups/RealisticBvh.h       Sat Jul  9 13:53:42 
2005
@@ -0,0 +1,40 @@
+
+
+
+#ifndef Manta_Model_RealisticBvh__H
+#define Manta_Model_RealisticBvh__H
+
+#include <Interface/Object.h>
+#include <Core/Geometry/BBox.h>
+
+namespace Manta {
+
+       // This class follows the implementation from
+       // "Realistic Ray Tracing"
+       
+       // This bvh contains pointers to objects in it's leaves.
+       class RealisticBvh : public Object {
+       protected:
+               BBox bounds;      // Bounds of this node.
+               Object *child[2]; // Childern of this node.
+               
+               // Protected constructors.
+               RealisticBvh( Object *child0, Object *child1 );
+               RealisticBvh() { child[0] = child[1] = 0; };
+
+               static int qsplit( Object **array, int size, Real pivot, int 
axis );
+               static Object *build_branch( Object **array, int size, int 
axis );
+               
+       public:
+               // Construct a BVH from an array of objects.
+               RealisticBvh( Object **array, int size );
+
+               // Public interface.
+    void preprocess   (const PreprocessContext& context);
+    void computeBounds(const PreprocessContext& context, BBox& bbox) const;
+    void intersect    (const RenderContext& context, RayPacket& rays) const; 
          
+       };
+};
+
+#endif
+

Modified: branches/itanium2/Model/Groups/kdtree.cc
==============================================================================
--- branches/itanium2/Model/Groups/kdtree.cc    (original)
+++ branches/itanium2/Model/Groups/kdtree.cc    Sat Jul  9 13:53:42 2005
@@ -31,7 +31,7 @@
                                                                              
                                                          float *t, float *u, 
float *v,
                                                                              
                                                          const float *edge1, 
const float *edge2);
 
-inline int intersectTriangle3Edge(const Ray &ray, const Triangle &tri,
+int intersectTriangle3Edge(const Vectorf &direction, const Pointf &origin, 
const Triangle &tri,
                                                                              
                                                          float &t, float &u, 
float &v );
 
 
///////////////////////////////////////////////////////////////////////////////
@@ -80,6 +80,7 @@
                                        _rawData += 3;
                                }
                        }
+
                        // Otherwise don't swap.
                        else {
                                for (int j=0; j<3; ++j) {
@@ -112,10 +113,7 @@
                        (**tris)[i].payload = ((r<<16)+(g<<8)+b);
                        
                        // Compute the normal.
-                       Vectorf v01, v02;
-                       v01 = (**tris)[i][1] - (**tris)[i][0];
-                       v02 = (**tris)[i][2] - (**tris)[i][0];
-                       (*perVertNormals)[3*i] = Cross(v01, v02).normal();
+                       (*perVertNormals)[3*i] = Cross((**tris)[i].edge1, 
(**tris)[i].edge2).normal();
                        
                        // Copy normals to each vertex.
                        (*perVertNormals)[3*i+1] = (*perVertNormals)[3*i+2] = 
(*perVertNormals)[3*i];
@@ -254,8 +252,6 @@
 
 int LoadBin_V3C1(const char *filename, VArray<Triangle> **tris, /*Vectorf 
**perVertNormals,*/ Vectorf **perVertNormals, BBox &bounds, int np ) {
        
-       
-       
        FILE *f;
        if ((f=fopen(filename, "r")) == NULL) {
                fprintf(stderr, "Cannot open file: %s\n", filename);
@@ -270,17 +266,6 @@
        int nFloats = fileSize/4;
        float *rawData = new float [fileSize / 4];
        
-       //
-       // touch data for good distribution
-       //
-       long i;
-       
-       // #pragma omp parallel for private (i)
-       
-       // for (i=0; i<nFloats; i+=1024*4) {
-       //      rawData[i] = 0;
-       // }
-       
        fseek(f, 0, SEEK_SET);
        
        double time_begin = Time::currentSeconds();
@@ -315,8 +300,6 @@
        // Create worker threads to preprocess and bound the data.
        Thread **workers = new Thread *[ np ];
        
-       
-       
        CacheAlignedBBox *worker_box = new CacheAlignedBBox[ np ];
        
        int work_per_thread = nTris / np;
@@ -357,77 +340,9 @@
        delete [] workers;
        delete [] worker_box;
        
-#if 0  
-       float *_rawData;
-       // #pragma omp parallel for private (_rawData, i)
-       for (i=0; i<nTris; i++) {
-               
-               // Offset into the data.
-               _rawData = rawData + 12 * i;
-               
-               // Check to see if we are on a big endian system
-               // Data was generate on Altix (little endian)
-               if (is_big_endian()) {
-                       for (int j=0; j<3; ++j) {
-                               (**tris)[i][j] = Pointf( endian_swap( 
_rawData[0] ), 
-                                                        endian_swap( 
_rawData[1] ), 
-                                                                             
                                                   endian_swap( _rawData[2] 
));
-                               _rawData += 3;
-                       }
-               }
-               // Otherwise don't swap.
-               else {
-                       for (int j=0; j<3; ++j) {
-                               (**tris)[i][j] = Pointf( _rawData[0], 
_rawData[1], _rawData[2] );
-                               _rawData += 3;
-                       }
-               }
-               
-               long r, g, b;
-               
-               // Check for big endian data.
-               if (is_big_endian()) {
-                       r = int(endian_swap(_rawData[0]) * 255 + .5f);
-                       g = int(endian_swap(_rawData[1]) * 255 + .5f);
-                       b = int(endian_swap(_rawData[2]) * 255 + .5f);
-                       _rawData += 3;
-               }
-               else {
-                       r = int(_rawData[0] * 255 + .5f);
-                       g = int(_rawData[1] * 255 + .5f);
-                       b = int(_rawData[2] * 255 + .5f);
-                       _rawData += 3;                  
-               }
-               
-               // Compute edges.
-               (**tris)[i].edge1 = (**tris)[i][1] - (**tris)[i][0]; 
-               (**tris)[i].edge2 = (**tris)[i][2] - (**tris)[i][0];
-               
-               // 
-               (**tris)[i].payload = ((r<<16)+(g<<8)+b);
-               
-               // Compute the normal.
-               Vectorf v01, v02;
-               v01 = (**tris)[i][1] - (**tris)[i][0];
-               v02 = (**tris)[i][2] - (**tris)[i][0];
-               (*perVertNormals)[3*i] = Cross(v01, v02).normal();
-               
-               // Copy normals to each vertex.
-               (*perVertNormals)[3*i+1] = (*perVertNormals)[3*i+2] = 
(*perVertNormals)[3*i];
-               
-               // Update the bounding box of the whole scene
-               for (long j=0; j<3; j++) {
-                       Triangle &tri = (**tris)[i];
-                       bounds.extendByPoint( tri[0] );
-                       bounds.extendByPoint( tri[1] );
-                       bounds.extendByPoint( tri[2] ); 
-               }
-               
-       }
-#endif 
        time_end = Time::currentSeconds();
        
-       std::cout << "Time to parse triangles: " << (time_end - 
time_begin)/60.0 << " Minutes." << std::endl;
+       std::cout << "Time to parse triangles: " << (time_end - time_begin) 
<< " Seconds." << std::endl;
        std::cout << "Triangles loaded: " << nTris << std::endl;
        
        time_begin = Time::currentSeconds();
@@ -466,7 +381,7 @@
        long long totalNumFloats = nFloatPerTri * nTris;
        float *rawData = new float [totalNumFloats];
        long i;
-#pragma omp parallel for private (i)
+// #pragma omp parallel for private (i)
        
        // Zero out the raw data.
        memset( rawData, 0x0, totalNumFloats*sizeof(float) );
@@ -482,7 +397,7 @@
        *perVertNormals = new Vectorf [nTris*3];
        
        float *_rawData;
-#pragma omp parallel for private (_rawData, i)
+// #pragma omp parallel for private (_rawData, i)
        for (i=0; i<nTris; i++) {
                _rawData = rawData + 12 * i;
                
@@ -659,39 +574,40 @@
        return 1;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// INTERSECT TRIANGLES  INTERSECT TRIANGLES  INTERSECT TRIANGLES  INTERSECT 
TRI
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 int KDTree::intersectTriangles(const Ray* ray, unsigned int listBegin, int 
listSize, float maxDist, void *userData) const
 {
        int i;
        RayTriIntersectUserData *ud = (RayTriIntersectUserData*)userData;
        float nearest_u, nearest_v;
-       int nearest_tri=-1;
+       int nearest_tri = -1;
+
+       Vectorf direction = ray->direction();
+       Pointf  origin    = ray->origin();      
        
-       /* Intersect the ray with all the bounding boxes */
+       // Intersect the ray with all the triangles. 
        int listEnd = listBegin+listSize;
        for (i = listBegin; i < listEnd; i++) {
                int triIdx = triIndices->get(i);
                Triangle &tri = tris->get(triIdx);
                float t, u, v;
                
-               // if (intersectTriangle3Edge( *ray, tri, t, u, v )) {
-               
-               Vectorf direction = ray->direction();
-               Pointf  origin    = ray->origin();
+               if (intersectTriangle3Edge( direction, origin, tri, t, u, v 
)) {
+               // if(intersect_triangle3_edge( &origin, &direction, &tri[0], 
&tri[1], &tri[2], &t, &u, &v, &tri.edge1, &tri.edge2 )) {
                
-               if(intersect_triangle3(
-                                                                             
                           &origin, &direction,
-                                                                             
                           &tri[0], &tri[1], &tri[2],
-                                                                             
                           &t, &u, &v/*,
-                                                                             
                           &tri.edge1, &tri.edge2*/)) {
-                       
+                       // Check to see if the t value is closer.
                        if (t < maxDist) {
                                maxDist = t;
-                               nearest_u= u;
-                               nearest_v= v;
+                               nearest_u = u;
+                               nearest_v = v;
                                nearest_tri = triIdx;
                        }
                }
-               }
+       }
        
        if (nearest_tri >= 0) {
                ud->rayHit.t = maxDist;
@@ -699,9 +615,11 @@
                ud->rayHit.v = nearest_v;
                ud->rayHitTriIndex = nearest_tri;
                return 1;
-       } else 
+               
+       } else { 
                return 0;
        }
+}
 
 // Traversal Stack Entry.
 struct TravStackEntry {
@@ -712,8 +630,10 @@
 };
 
 
///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 // This is the Manta interface method.
 
///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 void KDTree::intersect(const RenderContext& context, RayPacket& rays) const
 {
        
@@ -743,38 +663,8 @@
                        // Send the ray to the _intersect function.
                        isectData.rayHitTriIndex = -1;
                        _intersect( &e.ray, e, isectData, (float)minDist, 
(float)maxDist);
-#if 0                  
-                       // Check to see if the ray hit any triangles.
-                       if (isectData.rayHitTriIndex >= 0) {
-                               
-                               e.normal = 
normals[isectData.rayHitTriIndex*3]; // Is this safe??? What if the hit() 
function fails?
-                               
-                               // Check against the hit record, Note that 
tex coord mapper is null.
-                               if (e.hitInfo.hit(isectData.rayHit.t, 
lambMat, this, 0 )) {
-                                       
e.hitInfo.scratchpad<ScratchPadInfo>().normal  = 
normals[isectData.rayHitTriIndex*3];
-                                       
e.hitInfo.scratchpad<ScratchPadInfo>().payload = 
tris->get(isectData.rayHitTriIndex).payload;
-                               }
-                       }
-#endif
-               }
-#if 0
-               
-               // Send the ray to the _intersect function.
-               isectData.rayHitTriIndex = -1;
-               _intersect( &e.ray, e, &isectData, 0, 
numeric_limits<float>::max());
-               
-               // Check to see if the ray hit any triangles.
-               if (isectData.rayHitTriIndex >= 0) {
-                       
-                       e.normal = normals[isectData.rayHitTriIndex*3]; // Is 
this safe??? What if the hit() function fails?
-                       
-                       // Check against the hit record, Note that tex coord 
mapper is null.
-                       if (e.hitInfo.hit(isectData.rayHit.t, lambMat, this, 
0 )) {
-                               e.hitInfo.scratchpad<ScratchPadInfo>().normal 
 = normals[isectData.rayHitTriIndex*3];
-                               
e.hitInfo.scratchpad<ScratchPadInfo>().payload = 
tris->get(isectData.rayHitTriIndex).payload;
-                       }
+
                }
-#endif         
        }
 }
 
@@ -791,10 +681,11 @@
 
 
 
///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 // This function performs the KD-Tree Traversal.
 
///////////////////////////////////////////////////////////////////////////////
-void KDTree::_intersect(
-                                                                             
                  const Ray* ray, RayPacket::Element &e, 
RayTriIntersectUserData &isectData,
+///////////////////////////////////////////////////////////////////////////////
+void KDTree::_intersect(const Ray* ray, RayPacket::Element &e, 
RayTriIntersectUserData &isectData,
                                                                              
                  float minDist, float maxDist) const
 {
        
@@ -861,7 +752,7 @@
                        if (intersectTriangles(ray, nearNode->listBegin(), 
nearNode->listSize(), travStack[exitPos].t, &isectData) && 
                                        (isectData.rayHitTriIndex >= 0)) {
                                
-                               e.normal = 
normals[isectData.rayHitTriIndex*3]; // Is this safe??? What if the hit() 
function fails?
+                               e.normal = 
normals[isectData.rayHitTriIndex*3];
                                
                                // Check against the hit record, Note that 
tex coord mapper is null.
                                if (e.hitInfo.hit(isectData.rayHit.t, 
lambMat, this, 0 )) {
@@ -913,189 +804,6 @@
 (dest)[0]=(v1)[0]-(v2)[0]; \
 (dest)[1]=(v1)[1]-(v2)[1]; \
 (dest)[2]=(v1)[2]-(v2)[2]; 
-#if 0
-
-/* the original jgt code */
-inline int intersect_triangle(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)
-{
-       float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-       float det,inv_det;
-       
-       /* find vectors for two edges sharing vert0 */
-       SUB(edge1, vert1, vert0);
-       SUB(edge2, vert2, vert0);
-       
-       /* begin calculating determinant - also used to calculate U parameter 
*/
-       CROSS(pvec, dir, edge2);
-       
-       /* if determinant is near zero, ray lies in plane of triangle */
-       det = DOT(edge1, pvec);
-       
-       if (det > -EPSILON && det < EPSILON)
-               return 0;
-       inv_det = 1.0f/ det;
-       
-       /* calculate distance from vert0 to ray origin */
-       SUB(tvec, orig, vert0);
-       
-       /* calculate U parameter and test bounds */
-       *u = DOT(tvec, pvec) * inv_det;
-       if (*u < 0.0f || *u > 1.0)
-               return 0;
-       
-       /* prepare to test V parameter */
-       CROSS(qvec, tvec, edge1);
-       
-       /* calculate V parameter and test bounds */
-       *v = DOT(dir, qvec) * inv_det;
-       if (*v < 0.0f || *u + *v > 1.0)
-               return 0;
-       
-       /* calculate t, ray intersects triangle */
-       *t = DOT(edge2, qvec) * inv_det;
-       
-       return 1;
-}
-
-
-/* code rewritten to do tests on the sign of the determinant */
-/* the division is at the end in the code                    */
-inline int intersect_triangle1(float orig[3], float dir[3],
-                                                                             
                                           float vert0[3], float vert1[3], 
float vert2[3],
-                                                                             
                                           float *t, float *u, float *v)
-{
-       float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-       float det,inv_det;
-       
-       /* find vectors for two edges sharing vert0 */
-       SUB(edge1, vert1, vert0);
-       SUB(edge2, vert2, vert0);
-       
-       /* begin calculating determinant - also used to calculate U parameter 
*/
-       CROSS(pvec, dir, edge2);
-       
-       /* if determinant is near zero, ray lies in plane of triangle */
-       det = DOT(edge1, pvec);
-       
-       if (det > EPSILON)
-       {
-               /* calculate distance from vert0 to ray origin */
-               SUB(tvec, orig, vert0);
-               
-               /* calculate U parameter and test bounds */
-               *u = DOT(tvec, pvec);
-               if (*u < 0.0f || *u > det)
-                                               return 0;
-               
-               /* prepare to test V parameter */
-               CROSS(qvec, tvec, edge1);
-               
-               /* calculate V parameter and test bounds */
-               *v = DOT(dir, qvec);
-               if (*v < 0.0f || *u + *v > det)
-                                               return 0;
-               
-       }
-       else if(det < -EPSILON)
-       {
-               /* calculate distance from vert0 to ray origin */
-               SUB(tvec, orig, vert0);
-               
-               /* calculate U parameter and test bounds */
-               *u = DOT(tvec, pvec);
-               /*      printf("*u=%f\n",(float)*u); */
-               /*      printf("det=%f\n",det); */
-               if (*u > 0.0f || *u < det)
-                                               return 0;
-               
-               /* prepare to test V parameter */
-               CROSS(qvec, tvec, edge1);
-               
-               /* calculate V parameter and test bounds */
-               *v = DOT(dir, qvec) ;
-               if (*v > 0.0f || *u + *v < det)
-                                               return 0;
-       }
-       else return 0;  /* ray is parallell to the plane of the triangle */
-       
-       
-       inv_det = 1.0f/ det;
-       
-       /* calculate t, ray intersects triangle */
-       *t = DOT(edge2, qvec) * inv_det;
-       (*u) *= inv_det;
-       (*v) *= inv_det;
-       
-       return 1;
-}
-
-/* code rewritten to do tests on the sign of the determinant */
-/* the division is before the test of the sign of the det    */
-inline int intersect_triangle2(float orig[3], float dir[3],
-                                                                             
                                           float vert0[3], float vert1[3], 
float vert2[3],
-                                                                             
                                           float *t, float *u, float *v)
-{
-       float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-       float det,inv_det;
-       
-       /* find vectors for two edges sharing vert0 */
-       SUB(edge1, vert1, vert0);
-       SUB(edge2, vert2, vert0);
-       
-       /* begin calculating determinant - also used to calculate U parameter 
*/
-       CROSS(pvec, dir, edge2);
-       
-       /* if determinant is near zero, ray lies in plane of triangle */
-       det = DOT(edge1, pvec);
-       
-       /* calculate distance from vert0 to ray origin */
-       SUB(tvec, orig, vert0);
-       inv_det = 1.0f/ det;
-       
-       if (det > EPSILON)
-       {
-               /* calculate U parameter and test bounds */
-               *u = DOT(tvec, pvec);
-               if (*u < 0.0f || *u > det)
-                                               return 0;
-               
-               /* prepare to test V parameter */
-               CROSS(qvec, tvec, edge1);
-               
-               /* calculate V parameter and test bounds */
-               *v = DOT(dir, qvec);
-               if (*v < 0.0f || *u + *v > det)
-                                               return 0;
-               
-       }
-       else if(det < -EPSILON)
-       {
-               /* calculate U parameter and test bounds */
-               *u = DOT(tvec, pvec);
-               if (*u > 0.0f || *u < det)
-                                               return 0;
-               
-               /* prepare to test V parameter */
-               CROSS(qvec, tvec, edge1);
-               
-               /* calculate V parameter and test bounds */
-               *v = DOT(dir, qvec) ;
-               if (*v > 0.0f || *u + *v < det)
-                                               return 0;
-       }
-       else return 0;  /* ray is parallell to the plane of the triangle */
-       
-       /* calculate t, ray intersects triangle */
-       *t = DOT(edge2, qvec) * inv_det;
-       (*u) *= inv_det;
-       (*v) *= inv_det;
-       
-       return 1;
-}
-
-#endif 
 
 /* code rewritten to do tests on the sign of the determinant */
 /* the division is before the test of the sign of the det    */
@@ -1216,139 +924,69 @@
        return 1;
 }
 
-inline int intersectTriangle3Edge(const Ray &ray, const Triangle &tri,
-                                                                             
                                                          float &t, float &u, 
float &v )
+int intersectTriangle3Edge(const Vectorf &direction, const Pointf &origin, 
const Triangle &tri,
+                                                                             
                           float &t, float &u, float &v )
 {
-       // float edge1[3], edge2[3];
-       Vector tvec, pvec, qvec;
-       Real det,inv_det;
+       
+       Vectorf tvec, pvec, qvec;
+       
+       
+       // Vectorf edge1 = ( tri.edge1 );
+       // Vectorf edge2 = ( tri.edge2 );
        
        /* begin calculating determinant - also used to calculate U parameter 
*/
-       pvec = Cross( ray.direction(), Vector(tri.edge2) );
+       pvec = Cross( direction, tri.edge2 );
        
        // CROSS(pvec, dir, edge2);
        
        /* if determinant is near zero, ray lies in plane of triangle */
        // det = DOT(edge1, pvec);
-       det = Dot( Vector(tri.edge1), pvec );
+       float det = Dot( tri.edge1, pvec );
        
        /* calculate distance from vert0 to ray origin */
        // SUB(tvec, orig, vert0);
-       tvec = ray.origin() - tri[0];
-       inv_det = 1.0/ det;
+       tvec = origin - tri[0];
        
-       qvec = Cross( tvec, Vector(tri.edge1) );
+       qvec = Cross( tvec, tri.edge1 );
        // CROSS(qvec, tvec, edge1);
        
        /* calculate U parameter */
        // float uu = DOT(tvec, pvec);
        // float vv;
-       Real uu = Dot( tvec, pvec );
-       Real vv;
+       float uu = Dot( tvec, pvec );
+       float vv;
        
-       if (det > 1e-5)
-       {
+       if (det > 1e-5f) {
                if (uu < 0.0 || uu > det)
-                                               return 0;
+                       return 0;
                
                /* calculate V parameter and test bounds */
-               vv = Dot( ray.direction(), qvec );
+               vv = Dot( direction, qvec );
                
                if (vv < 0.0 || uu + vv > det)
-                                               return 0;
+                       return 0;
                
        }
-       else if(det < -1e-5)
-       {
+       else if(det < -1e-5f) {
                if (uu > 0.0 || uu < det)
-                                               return 0;
+                       return 0;
                
                /* calculate V parameter and test bounds */
-               vv = Dot(ray.direction(), qvec) ;
-               if (vv > 0.0f || uu + vv < det)
-                                               return 0;
+               vv = Dot(direction, qvec) ;
+               if (vv > 0.0 || uu + vv < det)
+                       return 0;
+       }
+       else {
+               return 0;  /* ray is parallell to the plane of the triangle */
        }
-       else return 0;  /* ray is parallell to the plane of the triangle */
-       
-       t = Dot( Vector(tri.edge2), qvec ) * inv_det;
-       u = uu * inv_det;
-       v = vv * inv_det;
-       
-       return 1;
-}
-#if 0
-inline void rays_intersect_triangle3(const float orig[3], const float *dir, 
-                                                                             
                                                                   int nRays,
-                                                                             
                                                                   float 
vert0[3], float vert1[3], float vert2[3],
-                                                                             
                                                                   int 
hits[], float t[], float u[], float v[])
-{
-       float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-       float det,inv_det;
-       
-       /* find vectors for two edges sharing vert0 */
-       SUB(edge1, vert1, vert0);
-       SUB(edge2, vert2, vert0);
        
-       /* calculate distance from vert0 to ray origin */
-       SUB(tvec, orig, vert0);
+       float inv_det = 1.0f / det;
        
-       CROSS(qvec, tvec, edge1);
-       
-       float uu, vv;
-       for (int i=0; i<nRays; i++, dir+=3) {
-               /* begin calculating determinant - also used to calculate U 
parameter */
-               CROSS(pvec, dir, edge2);
-               
-               /* if determinant is near zero, ray lies in plane of triangle 
*/
-               det = DOT(edge1, pvec);
-               //fprintf(stderr, "dir:%f %f %f; det: %f\n", dir[0], dir[1], 
dir[2], det);
-               
-               /* calculate distance from vert0 to ray origin */
-               // SUB(tvec, orig, vert0);
-               inv_det = 1.0f/ det;
-               
-               // CROSS(qvec, tvec, edge1);
-               
-               /* calculate U parameter and test bounds */
-               uu = DOT(tvec, pvec);
-               if (det > EPSILON) {
-                                               if (uu < 0.0f || uu > det) {
-                                                       hits[i] = 0;
-                                                       continue;
-                                               }
-                                               
-                                               /* calculate V parameter and 
test bounds */
-                                               vv = DOT(dir, qvec);
-                                               if (vv < 0.0f || uu + vv > 
det) {
-                                                       hits[i] = 0;
-                                                       continue;
-                                               }
-               }
-               else if(det < -EPSILON)
-               {
-                                               if (uu > 0.0f || uu < det) {
-                                                       hits[i] = 0;
-                                                       continue;
-                                               }
-                                               
-                                               /* calculate V parameter and 
test bounds */
-                                               vv = DOT(dir, qvec) ;
-                                               if (vv > 0.0f || uu + vv < 
det) {
-                                                       hits[i] = 0;
-                                                       continue;
-                                               }
-               } else {
-                                               hits[i] = 0;
-                                               continue;
-               }
-               
-               t[i] = DOT(edge2, qvec) * inv_det;
-               u[i] = uu*inv_det;
-               v[i] = vv*inv_det;
-               hits[i] = 1;
-       }
+       t = (Dot( tri.edge2, qvec ) * inv_det);
+       u = (uu * inv_det);
+       v = (vv * inv_det);
        
+       return 1;
 }
-#endif
 
 

Modified: branches/itanium2/Model/Groups/varray.h
==============================================================================
--- branches/itanium2/Model/Groups/varray.h     (original)
+++ branches/itanium2/Model/Groups/varray.h     Sat Jul  9 13:53:42 2005
@@ -106,13 +106,13 @@
        }
 
        inline T &operator[](int i) { 
-               if (array && i < curLen)
+               //if (array && i < curLen)
                        return array[i];
-               else {
-                       fprintf(stderr, "VArray(%p)::[] reference out of 
bound (idx:%d size:%d)\n", this, i, curLen);
-                       assert(0);
-                       return array[0];
-               }
+               //else {
+               //      fprintf(stderr, "VArray(%p)::[] reference out of 
bound (idx:%d size:%d)\n", this, i, curLen);
+               //      assert(0);
+               //      return array[0];
+               //}
        }
 
        inline T & get(int i) {

Modified: branches/itanium2/Model/Materials/CMakeLists.txt
==============================================================================
--- branches/itanium2/Model/Materials/CMakeLists.txt    (original)
+++ branches/itanium2/Model/Materials/CMakeLists.txt    Sat Jul  9 13:53:42 
2005
@@ -2,13 +2,22 @@
 
 
 SET (Manta_Materials_SRCS
+     Materials/Checker.h
      Materials/Checker.cc
+     Materials/Dielectric.h
      Materials/Dielectric.cc
+     Materials/Flat.h
      Materials/Flat.cc
+     Materials/Lambertian.h
      Materials/Lambertian.cc
+     Materials/LitMaterial.h
      Materials/LitMaterial.cc
+     Materials/MetalMaterial.h
      Materials/MetalMaterial.cc
+     Materials/Phong.h
      Materials/Phong.cc
+     Materials/LambertianAlt.h
      Materials/LambertianAlt.cc
+     Materials/NormalMaterial.h
      Materials/NormalMaterial.cc # Shade the material using it's normal.
      )

Modified: branches/itanium2/Model/Materials/Dielectric.cc
==============================================================================
--- branches/itanium2/Model/Materials/Dielectric.cc     (original)
+++ branches/itanium2/Model/Materials/Dielectric.cc     Sat Jul  9 13:53:42 
2005
@@ -15,9 +15,9 @@
 using namespace Manta;
 
 Dielectric::Dielectric(const Color& diffuse, const Color& specular,
-                      int specpow, double n, double nt)
-  : diffuse(diffuse), specular(specular), specpow(specpow),
-    n(n), nt(nt)
+                                                                             
           int specpow, double n, double nt)
+: diffuse(diffuse), specular(specular), specpow(specpow),
+n(n), nt(nt)
 {
 }
 
@@ -31,73 +31,78 @@
   // object and are all of the same material
   
   rays.normalizeDirections();
-
+       
   // Compute normals
   rays.computeNormals(context);
-
+       
+       
+       Scene *scene = (Scene*)context.scene;
+  LightSet *activeLights = scene->getLights();
+       
   // Compute ambient contributions for all rays
   activeLights->getAmbientLight()->computeAmbient(context, rays);
-
+       
   RayPacketData data;
   int start = 0;
   do {
     RayPacket shadowRays(data, 0, rays.getDepth(), 0);
     int end = context.shadowAlgorithm->computeShadows(context, activeLights,
-                                                     rays, start, 
shadowRays);
+                                                                             
                                                                              
                                                            rays, start, 
shadowRays);
     
     if(shadowRays.getFlags() & RayPacket::NormalizedDirections){
       for(int i=start;i<end;i++){
-       RayPacket::Element& e = rays.get(i);
-       Color totalDiffuse(e.ambientLight);
-       Color totalSpecular = Color::black();
-       for(int j=e.shadowBegin;j<e.shadowEnd;j++){
-         RayPacket::Element& s = shadowRays.get(j);
-         if(!s.hitInfo.wasHit()){
-           double cos_theta = Dot(s.ray.direction(), e.normal);
-           totalDiffuse += s.light*cos_theta;
-           Vector H = s.ray.direction()-e.ray.direction();
-           H.normalize();
-           double cos_alpha = Dot(H, e.normal);
-           if(cos_alpha > 0)
-             totalSpecular += s.light * ipow(cos_alpha, specpow);
-         }
-       }
-       rays.setResult(i, diffuse*totalDiffuse+specular*totalSpecular);
+                               RayPacket::Element& e = rays.get(i);
+                               Color totalDiffuse(e.ambientLight);
+                               Color totalSpecular = Color::black();
+                               for(int j=e.shadowBegin;j<e.shadowEnd;j++){
+                                       RayPacket::Element& s = 
shadowRays.get(j);
+                                       if(!s.hitInfo.wasHit()){
+                                               double cos_theta = 
Dot(s.ray.direction(), e.normal);
+                                               totalDiffuse += 
s.light*cos_theta;
+                                               Vector H = 
s.ray.direction()-e.ray.direction();
+                                               H.normalize();
+                                               double cos_alpha = Dot(H, 
e.normal);
+                                               if(cos_alpha > 0)
+                                                       totalSpecular += 
s.light * ipow(cos_alpha, specpow);
+                                       }
+                               }
+                               rays.setResult(i, 
diffuse*totalDiffuse+specular*totalSpecular);
       }
     } else {
       for(int i=start;i<end;i++){
-       RayPacket::Element& e = rays.get(i);
-       Color totalDiffuse(e.ambientLight);
-       Color totalSpecular = Color::black();
-       for(int j=e.shadowBegin;j<e.shadowEnd;j++){
-         RayPacket::Element& s = shadowRays.get(j);
-         if(!s.hitInfo.wasHit()){
-           s.ray.normalizeDirection();
-           double cos_theta = Dot(s.ray.direction(), e.normal);
-           totalDiffuse += s.light*cos_theta;
-           Vector H = s.ray.direction()-e.ray.direction();
-           H.normalize();
-           double cos_alpha = Dot(H, e.normal);
-           if(cos_alpha > 0)
-             totalSpecular += s.light * ipow(cos_alpha, specpow);
-         }
-       }
-       rays.setResult(i, diffuse*totalDiffuse+specular*totalSpecular);
+                               RayPacket::Element& e = rays.get(i);
+                               Color totalDiffuse(e.ambientLight);
+                               Color totalSpecular = Color::black();
+                               for(int j=e.shadowBegin;j<e.shadowEnd;j++){
+                                       RayPacket::Element& s = 
shadowRays.get(j);
+                                       if(!s.hitInfo.wasHit()){
+                                               s.ray.normalizeDirection();
+                                               double cos_theta = 
Dot(s.ray.direction(), e.normal);
+                                               totalDiffuse += 
s.light*cos_theta;
+                                               Vector H = 
s.ray.direction()-e.ray.direction();
+                                               H.normalize();
+                                               double cos_alpha = Dot(H, 
e.normal);
+                                               if(cos_alpha > 0)
+                                                       totalSpecular += 
s.light * ipow(cos_alpha, specpow);
+                                       }
+                               }
+                               rays.setResult(i, 
diffuse*totalDiffuse+specular*totalSpecular);
       }
     }
     start = end;
   } while(start < rays.getSize());
-
+       
   
   int maxdepth = 5;
   if(rays.getDepth() < maxdepth) {
     // Compute refractions
-    double *c = new double[rays.getSize()];
-    double *tst = new double[rays.getSize()];
-    Color *col = new Color[rays.getSize()];
+    double c[RayPacket::MaxSize];
+    double tst[RayPacket::MaxSize];
+    Color  col[RayPacket::MaxSize];
+               
     RayPacketData rfdata;
     RayPacket refr_rays(rfdata, rays.getSize(), rays.getDepth()+1,
-                       RayPacket::NormalizedDirections);
+                                                                             
                  RayPacket::NormalizedDirections);
     refr_rays.useLocalColors();
     rays.computeHitPositions();
     
@@ -112,22 +117,22 @@
       double y = refr_dir.y()*0.00001-e.hitPosition.y();
       double z = refr_dir.z()*0.00001-e.hitPosition.z();
       r.ray.set(Point(x,y,z), refr_dir);
-
+                       
       if(Dot(d,norm) < 0) {
-       c[i] = -Dot(e.ray.direction(), e.normal);
-       col[i] = Color::white();
+                               c[i] = -Dot(e.ray.direction(), e.normal);
+                               col[i] = Color::white();
       }
       else {
-       c[i] = Dot(refr_dir, e.normal);
-       double tmpt = e.hitInfo.minT();
-       col[i] = e.color->attenuate(-tmpt);
+                               c[i] = Dot(refr_dir, e.normal);
+                               double tmpt = e.hitInfo.minT();
+                               col[i] = e.color->attenuate(-tmpt);
       }
     }
           
     // Compute reflections
     RayPacketData rdata;
     RayPacket refl_rays(rdata, rays.getSize(), rays.getDepth()+1,
-                       RayPacket::NormalizedDirections);
+                                                                             
                  RayPacket::NormalizedDirections);
     refl_rays.useLocalColors();
     double *refl = new double[rays.getSize()];
     for(int i=0;i<rays.getSize();i++) {
@@ -152,17 +157,13 @@
       RayPacket::Element& rl = refl_rays.get(i);
       RayPacket::Element& rf = refr_rays.get(i);
       if(tst[i] < 0) {
-       *e.color = col[i]*(*rl.color);
+                               *e.color += col[i]*(*rl.color);
       }
       else {
-       *e.color = col[i]*(((*rl.color) * refl[i]) +
-                  ((*rf.color) * (1-refl[i])));
+                               *e.color += col[i]*(((*rl.color) * refl[i]) +
+                                                                             
                           ((*rf.color) * (1-refl[i])));
       }
     }
     
-    delete [] c;
-    delete [] tst;
-    delete [] refl;
-    delete [] col;
   }
 }

Modified: branches/itanium2/Model/Materials/Lambertian.cc
==============================================================================
--- branches/itanium2/Model/Materials/Lambertian.cc     (original)
+++ branches/itanium2/Model/Materials/Lambertian.cc     Sat Jul  9 13:53:42 
2005
@@ -7,6 +7,7 @@
 #include <Interface/AmbientLight.h>
 #include <Interface/Context.h>
 #include <Interface/ShadowAlgorithm.h>
+#include <Interface/Scene.h>
 #include <Model/Textures/Constant.h>
 
 using namespace Manta;
@@ -38,7 +39,8 @@
   colortex->mapValues(context, rays, colors);
        
   // Compute ambient contributions for all rays
-  activeLights->getAmbientLight()->computeAmbient(context, rays);
+       Scene *scene = (Scene*)context.scene;
+  scene->getLights()->getAmbientLight()->computeAmbient(context, rays);
        
 #if 0  
        RayPacket::Iterator ray_iter = rays.begin(); // Iterate across the 
ray packet making shadow rays.
@@ -52,7 +54,7 @@
        for (;ray_iter<ray_end;++ray_iter) {
                
                // Create a shadow ray packet.
-               ray_last = context.shadowAlgorithm->computeShadows( context, 
activeLights,
+               ray_last = context.shadowAlgorithm->computeShadows( context, 
scene->getLights(),
                                                                    ray_iter, 
ray_end,
                                                                              
                                                                              
                                                                    
shadow_rays );
                
@@ -83,7 +85,7 @@
   int start = 0;
   do {
     RayPacket shadowRays(data, 0, rays.getDepth(), 0);
-    int end = context.shadowAlgorithm->computeShadows(context, activeLights,
+    int end = context.shadowAlgorithm->computeShadows(context, 
scene->getLights(),
                                                                              
                                                                              
                                                            rays, start, 
shadowRays);
     if(shadowRays.getFlags() & RayPacket::NormalizedDirections){
       for(int i=start;i<end;i++){

Modified: branches/itanium2/Model/Materials/Lambertian.h
==============================================================================
--- branches/itanium2/Model/Materials/Lambertian.h      (original)
+++ branches/itanium2/Model/Materials/Lambertian.h      Sat Jul  9 13:53:42 
2005
@@ -13,6 +13,7 @@
   public:
     Lambertian(const Color& color);
     Lambertian(const Texture<Color>* colorfn);
+               Lambertian() {  };
     virtual ~Lambertian();
 
     virtual void shade(const RenderContext& context, RayPacket& rays) const;

Modified: branches/itanium2/Model/Primitives/PrimitiveCommon.h
==============================================================================
--- branches/itanium2/Model/Primitives/PrimitiveCommon.h        (original)
+++ branches/itanium2/Model/Primitives/PrimitiveCommon.h        Sat Jul  9 
13:53:42 2005
@@ -9,6 +9,7 @@
   class PrimitiveCommon : public Primitive {
   public:
     PrimitiveCommon(Material* material, const TexCoordMapper* tex = 0);
+               PrimitiveCommon() {  }; // Empty default constructor (used 
for an array of some primitive)
     virtual ~PrimitiveCommon();
 
     virtual void preprocess(const PreprocessContext&);

Modified: branches/itanium2/Model/Primitives/Triangle.h
==============================================================================
--- branches/itanium2/Model/Primitives/Triangle.h       (original)
+++ branches/itanium2/Model/Primitives/Triangle.h       Sat Jul  9 13:53:42 
2005
@@ -14,6 +14,7 @@
       double a,b;
     };
 
+               Triangle() {  };
     Triangle(Material* mat, const Point& _p1, const Point& _p2, const Point& 
_p3);
     virtual ~Triangle();
     

Modified: branches/itanium2/Model/Readers/CMakeLists.txt
==============================================================================
--- branches/itanium2/Model/Readers/CMakeLists.txt      (original)
+++ branches/itanium2/Model/Readers/CMakeLists.txt      Sat Jul  9 13:53:42 
2005
@@ -1,4 +1,11 @@
 
 SET (Manta_Readers_SRCS
      Readers/PlyReader.cc
-     Readers/rply/rply.c)
+     Readers/rply/rply.c
+     Readers/glm/glm.h
+     Readers/glm/glm.cc)
+
+# Apple places malloc.h in /usr/include/malloc/malloc.h
+IF (APPLE)
+   INCLUDE_DIRECTORIES(/usr/include/malloc/)
+ENDIF (APPLE)
\ No newline at end of file

Added: branches/itanium2/Model/Readers/glm/glm.cc
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Readers/glm/glm.cc  Sat Jul  9 13:53:42 2005
@@ -0,0 +1,1873 @@
+/*    
+ *  GLM library.  Wavefront .obj file format reader/writer/manipulator.
+ *
+ *  Written by Nate Robins, 1997.
+ *  email: ndr@pobox.com
+ *  www: http://www.pobox.com/~ndr
+ */
+
+
+/* includes */
+#include <Model/Readers/glm/glm.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+#include <limits.h>
+
+/* defines */
+#define T(x) model->triangles[(x)]
+
+namespace Glm {
+
+/* enums */
+enum { X, Y, Z, W };                   /* elements of a vertex */
+
+
+/* typedefs */
+
+/* _GLMnode: general purpose node
+ */
+typedef struct _GLMnode {
+  unsigned int     index;
+  bool        averaged;
+  struct _GLMnode* next;
+} GLMnode;
+
+
+/* private functions */
+
+/* _glmMax: returns the maximum of two floats */
+
+static float
+_glmMax(float a, float b) 
+{
+  if (a > b)
+    return a;
+  return b;
+}
+
+/* _glmAbs: returns the absolute value of a float */
+static float
+_glmAbs(float f)
+{
+  if (f < 0)
+    return -f;
+  return f;
+}
+
+/* _glmDot: compute the dot product of two vectors
+ *
+ * u - array of 3 floats (float u[3])
+ * v - array of 3 floats (float v[3])
+ */
+static float
+_glmDot(float* u, float* v)
+{
+  assert(u);
+  assert(v);
+
+  /* compute the dot product */
+  return u[X] * v[X] + u[Y] * v[Y] + u[Z] * v[Z];
+}
+
+/* _glmCross: compute the cross product of two vectors
+ *
+ * u - array of 3 floats (float u[3])
+ * v - array of 3 floats (float v[3])
+ * n - array of 3 floats (float n[3]) to return the cross product in
+ */
+static void
+_glmCross(float* u, float* v, float* n)
+{
+  assert(u);
+  assert(v);
+  assert(n);
+
+  /* compute the cross product (u x v for right-handed [ccw]) */
+  n[X] = u[Y] * v[Z] - u[Z] * v[Y];
+  n[Y] = u[Z] * v[X] - u[X] * v[Z];
+  n[Z] = u[X] * v[Y] - u[Y] * v[X];
+}
+
+/* _glmNormalize: normalize a vector
+ *
+ * n - array of 3 floats (float n[3]) to be normalized
+ */
+static void
+_glmNormalize(float* n)
+{
+  float l;
+
+  assert(n);
+
+  /* normalize */
+  l = (float)sqrt(n[X] * n[X] + n[Y] * n[Y] + n[Z] * n[Z]);
+  n[0] /= l;
+  n[1] /= l;
+  n[2] /= l;
+}
+
+/* _glmEqual: compares two vectors and returns true if they are
+ * equal (within a certain threshold) or false if not. An epsilon
+ * that works fairly well is 0.000001.
+ *
+ * u - array of 3 floats (float u[3])
+ * v - array of 3 floats (float v[3]) 
+ */
+static bool
+_glmEqual(float* u, float* v, float epsilon)
+{
+  if (_glmAbs(u[0] - v[0]) < epsilon &&
+      _glmAbs(u[1] - v[1]) < epsilon &&
+      _glmAbs(u[2] - v[2]) < epsilon) 
+    {
+      return true;
+    }
+  return false;
+}
+
+/* _glmWeldVectors: eliminate (weld) vectors that are within an
+ * epsilon of each other.
+ *
+ * vectors    - array of float[3]'s to be welded
+ * numvectors - number of float[3]'s in vectors
+ * epsilon    - maximum difference between vectors 
+ *
+ */
+float*
+_glmWeldVectors(float* vectors, unsigned int* numvectors, float epsilon)
+{
+  float* copies;
+  unsigned int   copied;
+  unsigned int   i, j;
+
+  copies = (float*)malloc(sizeof(float) * 3 * (*numvectors + 1));
+  memcpy(copies, vectors, (sizeof(float) * 3 * (*numvectors + 1)));
+
+  copied = 1;
+  for (i = 1; i <= *numvectors; i++) {
+    for (j = 1; j <= copied; j++) {
+      if (_glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
+       goto duplicate;
+      }
+    }
+
+    /* must not be any duplicates -- add to the copies array */
+    copies[3 * copied + 0] = vectors[3 * i + 0];
+    copies[3 * copied + 1] = vectors[3 * i + 1];
+    copies[3 * copied + 2] = vectors[3 * i + 2];
+    j = copied;                                /* pass this along for below 
*/
+    copied++;
+
+  duplicate:
+    /* set the first component of this vector to point at the correct
+       index into the new copies array */
+    vectors[3 * i + 0] = (float)j;
+  }
+
+  *numvectors = copied-1;
+  return copies;
+}
+
+/* _glmFindGroup: Find a group in the model
+ */
+GLMgroup*
+_glmFindGroup(GLMmodel* model, char* name)
+{
+  GLMgroup* group;
+
+  assert(model);
+
+  group = model->groups;
+  while(group) {
+    if (!strcmp(name, group->name))
+      break;
+    group = group->next;
+  }
+
+  return group;
+}
+
+/* _glmAddGroup: Add a group to the model
+ */
+GLMgroup*
+_glmAddGroup(GLMmodel* model, char* name)
+{
+  GLMgroup* group;
+
+  group = _glmFindGroup(model, name);
+  if (!group) {
+    group = (GLMgroup*)malloc(sizeof(GLMgroup));
+    group->name = strdup(name);
+    group->material = 0;
+    group->numtriangles = 0;
+    group->triangles = NULL;
+    group->next = model->groups;
+    model->groups = group;
+    model->numgroups++;
+  }
+
+  return group;
+}
+
+/* _glmFindGroup: Find a material in the model
+ */
+unsigned int
+_glmFindMaterial(GLMmodel* model, char* name)
+{
+  unsigned int i;
+
+  for (i = 0; i < model->nummaterials; i++) {
+    if (!strcmp(model->materials[i].name, name))
+      goto found;
+  }
+
+  /* didn't find the name, so set it as the default material */
+  printf("_glmFindMaterial():  can't find material \"%s\".\n", name);
+  i = 0;
+
+ found:
+  return i;
+}
+
+
+/* _glmDirName: return the directory given a path
+ *
+ * path - filesystem path
+ *
+ * The return value should be free'd.
+ */
+static char*
+_glmDirName(char* path)
+{
+  char* dir;
+  char* s;
+
+  dir = strdup(path);
+
+  s = strrchr(dir, '/');
+  if (s)
+    s[1] = '\0';
+  else
+    dir[0] = '\0';
+
+  return dir;
+}
+
+
+/* _glmReadMTL: read a wavefront material library file
+ *
+ * model - properly initialized GLMmodel structure
+ * name  - name of the material library
+ */
+static int
+_glmReadMTL(GLMmodel* model, char* name)
+{
+  FILE* file;
+  char* dir;
+  char* filename;
+  char  buf[128];
+  unsigned int nummaterials, i;
+
+  dir = _glmDirName(model->pathname);
+  filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
+  strcpy(filename, dir);
+  strcat(filename, name);
+  free(dir);
+
+  /* open the file */
+  file = fopen(filename, "r");
+  if (!file) {
+    fprintf(stderr, "_glmReadMTL() failed: can't open material file 
\"%s\".\n",
+           filename);
+    free(filename);
+    return 1;
+  }
+  free(filename);
+
+  /* count the number of materials in the file */
+  nummaterials = 1;
+  while(fscanf(file, "%s", buf) != EOF) {
+    switch(buf[0]) {
+    case '#':                          /* comment */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    case 'n':                          /* newmtl */
+      fgets(buf, sizeof(buf), file);
+      nummaterials++;
+      sscanf(buf, "%s %s", buf, buf);
+      break;
+    default:
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    }
+  }
+
+  rewind(file);
+
+  /* allocate memory for the materials */
+  model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * 
nummaterials);
+  model->nummaterials = nummaterials;
+
+  /* set the default material */
+  for (i = 0; i < nummaterials; i++) {
+    model->materials[i].name = NULL;
+    model->materials[i].shininess = 0;
+    model->materials[i].diffuse[0] = 0.8;
+    model->materials[i].diffuse[1] = 0.8;
+    model->materials[i].diffuse[2] = 0.8;
+    model->materials[i].diffuse[3] = 1.0;
+    model->materials[i].ambient[0] = 0.2;
+    model->materials[i].ambient[1] = 0.2;
+    model->materials[i].ambient[2] = 0.2;
+    model->materials[i].ambient[3] = 1.0;
+    model->materials[i].specular[0] = 0.0;
+    model->materials[i].specular[1] = 0.0;
+    model->materials[i].specular[2] = 0.0;
+    model->materials[i].specular[3] = 1.0;
+  }
+  model->materials[0].name = strdup("default");
+
+  /* now, read in the data */
+  nummaterials = 0;
+  while(fscanf(file, "%s", buf) != EOF) {
+    switch(buf[0]) {
+    case '#':                          /* comment */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    case 'n':                          /* newmtl */
+      fgets(buf, sizeof(buf), file);
+      sscanf(buf, "%s %s", buf, buf);
+      nummaterials++;
+      model->materials[nummaterials].name = strdup(buf);
+      break;
+    case 'N':
+      fscanf(file, "%f", &model->materials[nummaterials].shininess);
+      /* wavefront shininess is from [0, 1000], so scale for OpenGL */
+      model->materials[nummaterials].shininess /= 1000.0;
+      model->materials[nummaterials].shininess *= 128.0;
+      break;
+    case 'K':
+      switch(buf[1]) {
+      case 'd':
+       fscanf(file, "%f %f %f",
+              &model->materials[nummaterials].diffuse[0],
+              &model->materials[nummaterials].diffuse[1],
+              &model->materials[nummaterials].diffuse[2]);
+       break;
+      case 's':
+       fscanf(file, "%f %f %f",
+              &model->materials[nummaterials].specular[0],
+              &model->materials[nummaterials].specular[1],
+              &model->materials[nummaterials].specular[2]);
+       break;
+      case 'a':
+       fscanf(file, "%f %f %f",
+              &model->materials[nummaterials].ambient[0],
+              &model->materials[nummaterials].ambient[1],
+              &model->materials[nummaterials].ambient[2]);
+       break;
+      default:
+       /* eat up rest of line */
+       fgets(buf, sizeof(buf), file);
+       break;
+      }
+      break;
+    default:
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    }
+  }
+  return 0;
+}
+
+/* _glmWriteMTL: write a wavefront material library file
+ *
+ * model      - properly initialized GLMmodel structure
+ * modelpath  - pathname of the model being written
+ * mtllibname - name of the material library to be written
+ */
+static int
+_glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname)
+{
+  FILE* file;
+  char* dir;
+  char* filename;
+  GLMmaterial* material;
+  unsigned int i;
+
+  dir = _glmDirName(modelpath);
+  filename = (char*)malloc(sizeof(char) * (strlen(dir) + 
strlen(mtllibname)));
+  strcpy(filename, dir);
+  strcat(filename, mtllibname);
+  free(dir);
+
+  /* open the file */
+  file = fopen(filename, "w");
+  if (!file) {
+    fprintf(stderr, "_glmWriteMTL() failed: can't open file \"%s\".\n",
+           filename);
+    free(filename);
+    return 1;
+  }
+  free(filename);
+
+  /* spit out a header */
+  fprintf(file, "#  \n");
+  fprintf(file, "#  Wavefront MTL generated by GLM library\n");
+  fprintf(file, "#  \n");
+  fprintf(file, "#  GLM library copyright (C) 1997 by Nate Robins\n");
+  fprintf(file, "#  email: ndr@pobox.com\n");
+  fprintf(file, "#  www:   http://www.pobox.com/~ndr\n";);
+  fprintf(file, "#  \n\n");
+
+  for (i = 0; i < model->nummaterials; i++) {
+    material = &model->materials[i];
+    fprintf(file, "newmtl %s\n", material->name);
+    fprintf(file, "Ka %f %f %f\n", 
+           material->ambient[0], material->ambient[1], material->ambient[2]);
+    fprintf(file, "Kd %f %f %f\n", 
+           material->diffuse[0], material->diffuse[1], material->diffuse[2]);
+    fprintf(file, "Ks %f %f %f\n", 
+           
material->specular[0],material->specular[1],material->specular[2]);
+    fprintf(file, "Ns %f\n", material->shininess);
+    fprintf(file, "\n");
+  }
+  return 0;
+}
+
+/* _glmFirstPass: first pass at a Wavefront OBJ file that gets all the
+ * statistics of the model (such as #vertices, #normals, etc)
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static int
+_glmFirstPass(GLMmodel* model, FILE* file) 
+{
+  unsigned int    numvertices;         /* number of vertices in model */
+  unsigned int    numnormals;                  /* number of normals in model 
*/
+  unsigned int    numtexcoords;                /* number of texcoords in 
model */
+  unsigned int    numtriangles;                /* number of triangles in 
model */
+
+
+
+  GLMgroup* group;                     /* current group */
+  int       v, n, t;
+  char      buf[128];
+
+  /* make a default group */
+  group = _glmAddGroup(model, "default");
+
+  numvertices = numnormals = numtexcoords = numtriangles = 0;
+
+  while(fscanf(file, "%s", buf) != EOF) {
+    switch(buf[0]) {
+    case '#':                          /* comment */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    case 'v':                          /* v, vn, vt */
+      switch(buf[1]) {
+      case '\0':       {               /* vertex */
+        /* eat up rest of line */
+        fgets(buf, sizeof(buf), file);
+
+        // TODO: Check if colors for this vertex
+        float vx,vy,vz;
+        int   val = -1;
+        sscanf(buf,"%f %f %f %d",&vx, &vy, &vz, &val);
+        if (val >= 0) {
+          model->usePerVertexColors = true;
+        }
+
+        numvertices++;
+        break;
+      }
+      case 'n':                                /* normal */
+        /* eat up rest of line */
+        fgets(buf, sizeof(buf), file);
+        numnormals++;
+        break;
+      case 't':                                /* texcoord */
+        /* eat up rest of line */
+        fgets(buf, sizeof(buf), file);
+        numtexcoords++;
+        break;
+      default:
+        printf("_glmFirstPass(): Unknown token \"%s\".\n", buf);
+        /* Could error out here, but we'll just skip it for now.*/
+        /* return 1; */
+        break;
+      }
+      break;
+    case 'm':
+      fgets(buf, sizeof(buf), file);
+      sscanf(buf, "%s %s", buf, buf);
+      model->mtllibname = strdup(buf);
+      if (_glmReadMTL(model, buf)) {
+        /* Uh oh.  Trouble reading in the material file. */
+        return 1;
+      }
+      break;
+    case 'u':
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    case 'o':
+    case 'g':                          /* group */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      sscanf(buf, "%s", buf);
+      group = _glmAddGroup(model, buf);
+      break;
+    case 'f':                          /* face */
+      v = n = t = 0;
+      fscanf(file, "%s", buf);
+      /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+      if (strstr(buf, "//")) {
+        /* v//n */
+        sscanf(buf, "%d//%d", &v, &n);  
+        fscanf(file, "%d//%d", &v, &n); 
+        fscanf(file, "%d//%d", &v, &n); 
+        numtriangles++;
+        group->numtriangles++;
+        while(fscanf(file, "%d//%d", &v, &n) > 0) {
+          numtriangles++;
+          group->numtriangles++;
+        }
+      } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) { 
+        /* v/t/n */
+        fscanf(file, "%d/%d/%d", &v, &t, &n); 
+        fscanf(file, "%d/%d/%d", &v, &t, &n); 
+        numtriangles++;
+        group->numtriangles++;
+        while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+          numtriangles++;
+          group->numtriangles++;
+        }
+      } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+        /* v/t */
+        fscanf(file, "%d/%d", &v, &t); 
+        fscanf(file, "%d/%d", &v, &t); 
+        numtriangles++;
+        group->numtriangles++;
+        while(fscanf(file, "%d/%d", &v, &t) > 0) {
+          numtriangles++;
+          group->numtriangles++;
+        }
+      } else {
+        /* v */
+        fscanf(file, "%d", &v);
+        fscanf(file, "%d", &v);
+        numtriangles++;
+        group->numtriangles++;
+        while(fscanf(file, "%d", &v) > 0) {
+          numtriangles++;
+          group->numtriangles++;
+        }
+      }
+      break;
+
+    default:
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    }
+  }
+
+  // #if 0
+  /* announce the model statistics */
+  // printf(" Vertices: %d\n", numvertices);
+  // printf(" Normals: %d\n", numnormals);
+  // printf(" Texcoords: %d\n", numtexcoords);
+  // printf(" Triangles: %d\n", numtriangles);
+  // printf(" Groups: %d\n", model->numgroups);
+  // #endif
+
+  /* set the stats in the model structure */
+  model->numvertices  = numvertices;
+  model->numnormals   = numnormals;
+  model->numtexcoords = numtexcoords;
+  model->numtriangles = numtriangles;
+
+  /* allocate memory for the triangles in each group */
+  group = model->groups;
+  while(group) {
+    group->triangles = (unsigned int*)malloc(sizeof(unsigned int) * 
group->numtriangles);
+    group->numtriangles = 0;
+    group = group->next;
+  }
+  return 0;
+}
+
+/* _glmSecondPass: second pass at a Wavefront OBJ file that gets all
+ * the data.
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static void
+_glmSecondPass(GLMmodel* model, FILE* file) 
+{
+  unsigned int    numvertices;         /* number of vertices in model */
+  unsigned int    numnormals;                  /* number of normals in model 
*/
+  unsigned int    numtexcoords;                /* number of texcoords in 
model */
+  unsigned int    numtriangles;                /* number of triangles in 
model */
+  float*  vertices;                    /* array of vertices  */
+  unsigned char*  vertexColors;       /* array of vertex colors */
+  float*  normals;                     /* array of normals */
+  float*  texcoords;                   /* array of texture coordinates */
+  GLMgroup* group;                     /* current group pointer */
+  unsigned int    material;                    /* current material */
+  int     v, n, t;
+  char      buf[128];
+
+  /* set the pointer shortcuts */
+  vertices     = model->vertices;
+  vertexColors = model->vertexColors;
+  normals      = model->normals;
+  texcoords    = model->texcoords;
+  group        = model->groups;
+
+  /* on the second pass through the file, read all the data into the
+     allocated arrays */
+  numvertices = numnormals = numtexcoords = 1;
+  numtriangles = 0;
+  material = 0;
+  while(fscanf(file, "%s", buf) != EOF) {
+    switch(buf[0]) {
+    case '#':                          /* comment */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    case 'v':                          /* v, vn, vt */
+      switch(buf[1]) {
+      case '\0':                       /* vertex */
+        if (!model->usePerVertexColors) {
+          fscanf(file, "%f %f %f", 
+                 &vertices[3 * numvertices + X], 
+                 &vertices[3 * numvertices + Y], 
+                 &vertices[3 * numvertices + Z]);
+        }
+        else {
+          int r,g,b;
+          fscanf(file, "%f %f %f %d %d %d", 
+                 &vertices[3 * numvertices + X], 
+                 &vertices[3 * numvertices + Y], 
+                 &vertices[3 * numvertices + Z], &r, &g, &b);
+          vertexColors[3 * numvertices + X] = (unsigned char)r; 
+          vertexColors[3 * numvertices + Y] = (unsigned char)g; 
+          vertexColors[3 * numvertices + Z] = (unsigned char)b;
+        }
+        numvertices++;
+        break;
+      case 'n':                                /* normal */
+        fscanf(file, "%f %f %f", 
+               &normals[3 * numnormals + X],
+               &normals[3 * numnormals + Y], 
+               &normals[3 * numnormals + Z]);
+        numnormals++;
+        break;
+      case 't':                                /* texcoord */
+        fscanf(file, "%f %f", 
+               &texcoords[2 * numtexcoords + X],
+               &texcoords[2 * numtexcoords + Y]);
+        numtexcoords++;
+        break;
+      }
+      break;
+    case 'u':
+      fgets(buf, sizeof(buf), file);
+      sscanf(buf, "%s %s", buf, buf);
+      group->material = material = _glmFindMaterial(model, buf);
+      break;
+    case 'o':
+    case 'g':                          /* group */
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      sscanf(buf, "%s", buf);
+      group = _glmFindGroup(model, buf);
+      group->material = material;
+      break;
+    case 'f':                          /* face */
+      v = n = t = 0;
+      fscanf(file, "%s", buf);
+      /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+      if (strstr(buf, "//")) {
+        /* v//n */
+        sscanf(buf, "%d//%d", &v, &n);
+        T(numtriangles).vindices[0] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).nindices[0] = n;
+        fscanf(file, "%d//%d", &v, &n);
+        T(numtriangles).vindices[1] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).nindices[1] = n;
+        fscanf(file, "%d//%d", &v, &n);
+        T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).nindices[2] = n;
+        group->triangles[group->numtriangles++] = numtriangles;
+        numtriangles++;
+        while(fscanf(file, "%d//%d", &v, &n) > 0) {
+          T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+          T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+          T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+          T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+          T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+          T(numtriangles).nindices[2] = n;
+          group->triangles[group->numtriangles++] = numtriangles;
+          numtriangles++;
+        }
+      } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
+        /* v/t/n */
+        T(numtriangles).vindices[0] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[0] = t;
+        T(numtriangles).nindices[0] = n;
+        fscanf(file, "%d/%d/%d", &v, &t, &n);
+        T(numtriangles).vindices[1] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[1] = t;
+        T(numtriangles).nindices[1] = n;
+        fscanf(file, "%d/%d/%d", &v, &t, &n);
+        T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[2] = t;
+        T(numtriangles).nindices[2] = n;
+        group->triangles[group->numtriangles++] = numtriangles;
+        numtriangles++;
+        while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+          T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+          T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+          T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+          T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+          T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+          T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+          T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+          T(numtriangles).tindices[2] = t;
+          T(numtriangles).nindices[2] = n;
+          group->triangles[group->numtriangles++] = numtriangles;
+          numtriangles++;
+        }
+      } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+        /* v/t */
+        T(numtriangles).vindices[0] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[0] = t;
+        fscanf(file, "%d/%d", &v, &t);
+        T(numtriangles).vindices[1] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[1] = t;
+        fscanf(file, "%d/%d", &v, &t);
+        T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+        T(numtriangles).tindices[2] = t;
+        group->triangles[group->numtriangles++] = numtriangles;
+        numtriangles++;
+        while(fscanf(file, "%d/%d", &v, &t) > 0) {
+          T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+          T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+          T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+          T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+          T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+          T(numtriangles).tindices[2] = t;
+          group->triangles[group->numtriangles++] = numtriangles;
+          numtriangles++;
+        }
+      } else {
+        /* v */
+        sscanf(buf, "%d", &v);
+        T(numtriangles).vindices[0] = (v >= 0) ? v : (numvertices + v);
+        fscanf(file, "%d", &v);
+        T(numtriangles).vindices[1] = (v >= 0) ? v : (numvertices + v);
+        fscanf(file, "%d", &v);
+        T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+        group->triangles[group->numtriangles++] = numtriangles;
+        numtriangles++;
+        while(fscanf(file, "%d", &v) > 0) {
+          T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+          T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+          T(numtriangles).vindices[2] = (v >= 0) ? v : (numvertices + v);
+          group->triangles[group->numtriangles++] = numtriangles;
+          numtriangles++;
+        }
+      }
+      break;
+
+    default:
+      /* eat up rest of line */
+      fgets(buf, sizeof(buf), file);
+      break;
+    }
+  } 
+
+#if 0
+  /* announce the memory requirements */
+  printf(" Memory: %d bytes\n",
+        numvertices  * 3*sizeof(float) +
+        numnormals   * 3*sizeof(float) * (numnormals ? 1 : 0) +
+        numtexcoords * 3*sizeof(float) * (numtexcoords ? 1 : 0) +
+        numtriangles * sizeof(GLMtriangle));
+#endif
+}
+
+
+
+
+/* public functions */
+
+/* glmUnitize: "unitize" a model by translating it to the origin and
+ * scaling it to fit in a unit cube around the origin.  Returns the
+ * scalefactor used.
+ *
+ * model - properly initialized GLMmodel structure 
+ */
+float
+glmUnitize(GLMmodel* model)
+{
+  unsigned int  i;
+  float maxx, minx, maxy, miny, maxz, minz;
+  float cx, cy, cz, w, h, d;
+  float scale;
+
+  assert(model);
+  assert(model->vertices);
+
+  /* get the max/mins */
+  maxx = minx = model->vertices[3 + X];
+  maxy = miny = model->vertices[3 + Y];
+  maxz = minz = model->vertices[3 + Z];
+  for (i = 1; i <= model->numvertices; i++) {
+    if (maxx < model->vertices[3 * i + X])
+      maxx = model->vertices[3 * i + X];
+    if (minx > model->vertices[3 * i + X])
+      minx = model->vertices[3 * i + X];
+
+    if (maxy < model->vertices[3 * i + Y])
+      maxy = model->vertices[3 * i + Y];
+    if (miny > model->vertices[3 * i + Y])
+      miny = model->vertices[3 * i + Y];
+
+    if (maxz < model->vertices[3 * i + Z])
+      maxz = model->vertices[3 * i + Z];
+    if (minz > model->vertices[3 * i + Z])
+      minz = model->vertices[3 * i + Z];
+  }
+
+  /* calculate model width, height, and depth */
+  w = _glmAbs(maxx) + _glmAbs(minx);
+  h = _glmAbs(maxy) + _glmAbs(miny);
+  d = _glmAbs(maxz) + _glmAbs(minz);
+
+  /* calculate center of the model */
+  cx = (maxx + minx) / 2.0;
+  cy = (maxy + miny) / 2.0;
+  cz = (maxz + minz) / 2.0;
+
+  /* calculate unitizing scale factor */
+  scale = 2.0 / _glmMax(_glmMax(w, h), d);
+
+  /* translate around center then scale */
+  for (i = 1; i <= model->numvertices; i++) {
+    model->vertices[3 * i + X] -= cx;
+    model->vertices[3 * i + Y] -= cy;
+    model->vertices[3 * i + Z] -= cz;
+    model->vertices[3 * i + X] *= scale;
+    model->vertices[3 * i + Y] *= scale;
+    model->vertices[3 * i + Z] *= scale;
+  }
+
+  return scale;
+}
+
+/* glmDimensions: Calculates the dimensions (width, height, depth) of
+ * a model.
+ *
+ * model      - initialized GLMmodel structure
+ * dimensions - array of 3 floats (float dimensions[3])
+ */
+void
+glmDimensions(GLMmodel* model, float* dimensions)
+{
+  unsigned int i;
+  float maxx, minx, maxy, miny, maxz, minz;
+
+  assert(model);
+  assert(model->vertices);
+  assert(dimensions);
+
+  /* get the max/mins */
+  maxx = minx = model->vertices[3 + X];
+  maxy = miny = model->vertices[3 + Y];
+  maxz = minz = model->vertices[3 + Z];
+  for (i = 1; i <= model->numvertices; i++) {
+    if (maxx < model->vertices[3 * i + X])
+      maxx = model->vertices[3 * i + X];
+    if (minx > model->vertices[3 * i + X])
+      minx = model->vertices[3 * i + X];
+
+    if (maxy < model->vertices[3 * i + Y])
+      maxy = model->vertices[3 * i + Y];
+    if (miny > model->vertices[3 * i + Y])
+      miny = model->vertices[3 * i + Y];
+
+    if (maxz < model->vertices[3 * i + Z])
+      maxz = model->vertices[3 * i + Z];
+    if (minz > model->vertices[3 * i + Z])
+      minz = model->vertices[3 * i + Z];
+  }
+
+  /* calculate model width, height, and depth */
+  dimensions[X] = _glmAbs(maxx) + _glmAbs(minx);
+  dimensions[Y] = _glmAbs(maxy) + _glmAbs(miny);
+  dimensions[Z] = _glmAbs(maxz) + _glmAbs(minz);
+}
+
+/*
+ * glmBoundingBox: Calculates the min/max positions of the model
+ */
+void
+glmBoundingBox(GLMmodel *model, float *minpos, float *maxpos)
+{
+  unsigned int i;
+  float maxx, minx, maxy, miny, maxz, minz;
+
+  assert(model);
+  assert(model->vertices);
+  assert(minpos);
+  assert(maxpos);
+
+  /* get the max/mins */
+  maxx = minx = model->vertices[3 + X];
+  maxy = miny = model->vertices[3 + Y];
+  maxz = minz = model->vertices[3 + Z];
+  for (i = 1; i <= model->numvertices; i++) {
+    if (maxx < model->vertices[3 * i + X])
+      maxx = model->vertices[3 * i + X];
+    if (minx > model->vertices[3 * i + X])
+      minx = model->vertices[3 * i + X];
+
+    if (maxy < model->vertices[3 * i + Y])
+      maxy = model->vertices[3 * i + Y];
+    if (miny > model->vertices[3 * i + Y])
+      miny = model->vertices[3 * i + Y];
+
+    if (maxz < model->vertices[3 * i + Z])
+      maxz = model->vertices[3 * i + Z];
+    if (minz > model->vertices[3 * i + Z])
+      minz = model->vertices[3 * i + Z];
+  }
+
+  minpos[0] = minx;
+  minpos[1] = miny;
+  minpos[2] = minz;
+  maxpos[0] = maxx;
+  maxpos[1] = maxy;
+  maxpos[2] = maxz;
+
+}
+
+/* glmScale: Scales a model by a given amount.
+ * 
+ * model - properly initialized GLMmodel structure
+ * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+ */
+void
+glmScale(GLMmodel* model, float scale)
+{
+  unsigned int i;
+
+  for (i = 1; i <= model->numvertices; i++) {
+    model->vertices[3 * i + X] *= scale;
+    model->vertices[3 * i + Y] *= scale;
+    model->vertices[3 * i + Z] *= scale;
+  }
+}
+
+/* glmReverseWinding: Reverse the polygon winding for all polygons in
+ * this model.  Default winding is counter-clockwise.  Also changes
+ * the direction of the normals.
+ * 
+ * model - properly initialized GLMmodel structure 
+ */
+void
+glmReverseWinding(GLMmodel* model)
+{
+  unsigned int i, swap;
+
+  assert(model);
+
+  for (i = 0; i < model->numtriangles; i++) {
+    swap = T(i).vindices[0];
+    T(i).vindices[0] = T(i).vindices[2];
+    T(i).vindices[2] = swap;
+
+    if (model->numnormals) {
+      swap = T(i).nindices[0];
+      T(i).nindices[0] = T(i).nindices[2];
+      T(i).nindices[2] = swap;
+    }
+
+    if (model->numtexcoords) {
+      swap = T(i).tindices[0];
+      T(i).tindices[0] = T(i).tindices[2];
+      T(i).tindices[2] = swap;
+    }
+  }
+
+  /* reverse facet normals */
+  for (i = 1; i <= model->numfacetnorms; i++) {
+    model->facetnorms[3 * i + X] = -model->facetnorms[3 * i + X];
+    model->facetnorms[3 * i + Y] = -model->facetnorms[3 * i + Y];
+    model->facetnorms[3 * i + Z] = -model->facetnorms[3 * i + Z];
+  }
+
+  /* reverse vertex normals */
+  for (i = 1; i <= model->numnormals; i++) {
+    model->normals[3 * i + X] = -model->normals[3 * i + X];
+    model->normals[3 * i + Y] = -model->normals[3 * i + Y];
+    model->normals[3 * i + Z] = -model->normals[3 * i + Z];
+  }
+}
+
+/* glmFacetNormals: Generates facet normals for a model (by taking the
+ * cross product of the two vectors derived from the sides of each
+ * triangle).  Assumes a counter-clockwise winding.
+ *
+ * model - initialized GLMmodel structure
+ */
+void
+glmFacetNormals(GLMmodel* model)
+{
+  unsigned int  i;
+  float u[3];
+  float v[3];
+  
+  assert(model);
+  assert(model->vertices);
+
+  /* clobber any old facetnormals */
+  if (model->facetnorms)
+    free(model->facetnorms);
+
+  /* allocate memory for the new facet normals */
+  model->numfacetnorms = model->numtriangles;
+  model->facetnorms = (float*)malloc(sizeof(float) *
+                                     3 * (model->numfacetnorms + 1));
+
+  for (i = 0; i < model->numtriangles; i++) {
+    model->triangles[i].findex = i+1;
+
+    u[X] = model->vertices[3 * T(i).vindices[1] + X] -
+      model->vertices[3 * T(i).vindices[0] + X];
+    u[Y] = model->vertices[3 * T(i).vindices[1] + Y] -
+      model->vertices[3 * T(i).vindices[0] + Y];
+    u[Z] = model->vertices[3 * T(i).vindices[1] + Z] -
+      model->vertices[3 * T(i).vindices[0] + Z];
+
+    v[X] = model->vertices[3 * T(i).vindices[2] + X] -
+      model->vertices[3 * T(i).vindices[0] + X];
+    v[Y] = model->vertices[3 * T(i).vindices[2] + Y] -
+      model->vertices[3 * T(i).vindices[0] + Y];
+    v[Z] = model->vertices[3 * T(i).vindices[2] + Z] -
+      model->vertices[3 * T(i).vindices[0] + Z];
+
+    _glmCross(u, v, &model->facetnorms[3 * (i+1)]);
+    _glmNormalize(&model->facetnorms[3 * (i+1)]);
+  }
+}
+
+/* glmVertexNormals: Generates smooth vertex normals for a model.
+ * First builds a list of all the triangles each vertex is in.  Then
+ * loops through each vertex in the the list averaging all the facet
+ * normals of the triangles each vertex is in.  Finally, sets the
+ * normal index in the triangle for the vertex to the generated smooth
+ * normal.  If the dot product of a facet normal and the facet normal
+ * associated with the first triangle in the list of triangles the
+ * current vertex is in is greater than the cosine of the angle
+ * parameter to the function, that facet normal is not added into the
+ * average normal calculation and the corresponding vertex is given
+ * the facet normal.  This tends to preserve hard edges.  The angle to
+ * use depends on the model, but 90 degrees is usually a good start.
+ *
+ * model - initialized GLMmodel structure
+ * angle - maximum angle (in degrees) to smooth across
+ */
+void
+glmVertexNormals(GLMmodel* model, float angle)
+{
+  GLMnode*  node;
+  GLMnode*  tail;
+  GLMnode** members;
+  float*  normals;
+  unsigned int    numnormals;
+  float   average[3];
+  float   dot, cos_angle;
+  unsigned int    i, avg;
+
+  assert(model);
+  assert(model->facetnorms);
+
+  /* calculate the cosine of the angle (in degrees) */
+  cos_angle = cos(angle * M_PI / 180.0);
+
+  /* nuke any previous normals */
+  if (model->normals)
+    free(model->normals);
+
+  /* allocate space for new normals */
+  model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */
+  model->normals = (float*)malloc(sizeof(float)* 3* (model->numnormals+1));
+
+  /* allocate a structure that will hold a linked list of triangle
+     indices for each vertex */
+  members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1));
+  for (i = 1; i <= model->numvertices; i++)
+    members[i] = NULL;
+  
+  /* for every triangle, create a node for each vertex in it */
+  for (i = 0; i < model->numtriangles; i++) {
+    node = (GLMnode*)malloc(sizeof(GLMnode));
+    node->index = i;
+    node->next  = members[T(i).vindices[0]];
+    members[T(i).vindices[0]] = node;
+
+    node = (GLMnode*)malloc(sizeof(GLMnode));
+    node->index = i;
+    node->next  = members[T(i).vindices[1]];
+    members[T(i).vindices[1]] = node;
+
+    node = (GLMnode*)malloc(sizeof(GLMnode));
+    node->index = i;
+    node->next  = members[T(i).vindices[2]];
+    members[T(i).vindices[2]] = node;
+  }
+
+  /* calculate the average normal for each vertex */
+  numnormals = 1;
+  for (i = 1; i <= model->numvertices; i++) {
+    /* calculate an average normal for this vertex by averaging the
+       facet normal of every triangle this vertex is in */
+    node = members[i];
+    if (!node)
+      fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n");
+    average[0] = 0.0; average[1] = 0.0; average[2] = 0.0;
+    avg = 0;
+    while (node) {
+      /* only average if the dot product of the angle between the two
+         facet normals is greater than the cosine of the threshold
+         angle -- or, said another way, the angle between the two
+         facet normals is less than (or equal to) the threshold angle */
+      dot = _glmDot(&model->facetnorms[3 * T(node->index).findex],
+                   &model->facetnorms[3 * T(members[i]->index).findex]);
+      if (dot > cos_angle) {
+       node->averaged = true;
+       average[0] += model->facetnorms[3 * T(node->index).findex + 0];
+       average[1] += model->facetnorms[3 * T(node->index).findex + 1];
+       average[2] += model->facetnorms[3 * T(node->index).findex + 2];
+       avg = 1;                        /* we averaged at least one normal! */
+      } else {
+       node->averaged = false;
+      }
+      node = node->next;
+    }
+
+    if (avg) {
+      /* normalize the averaged normal */
+      _glmNormalize(average);
+
+      /* add the normal to the vertex normals list */
+      model->normals[3 * numnormals + 0] = average[0];
+      model->normals[3 * numnormals + 1] = average[1];
+      model->normals[3 * numnormals + 2] = average[2];
+      avg = numnormals;
+      numnormals++;
+    }
+
+    /* set the normal of this vertex in each triangle it is in */
+    node = members[i];
+    while (node) {
+      if (node->averaged) {
+       /* if this node was averaged, use the average normal */
+       if (T(node->index).vindices[0] == i)
+         T(node->index).nindices[0] = avg;
+       else if (T(node->index).vindices[1] == i)
+         T(node->index).nindices[1] = avg;
+       else if (T(node->index).vindices[2] == i)
+         T(node->index).nindices[2] = avg;
+      } else {
+       /* if this node wasn't averaged, use the facet normal */
+       model->normals[3 * numnormals + 0] = 
+         model->facetnorms[3 * T(node->index).findex + 0];
+       model->normals[3 * numnormals + 1] = 
+         model->facetnorms[3 * T(node->index).findex + 1];
+       model->normals[3 * numnormals + 2] = 
+         model->facetnorms[3 * T(node->index).findex + 2];
+       if (T(node->index).vindices[0] == i)
+         T(node->index).nindices[0] = numnormals;
+       else if (T(node->index).vindices[1] == i)
+         T(node->index).nindices[1] = numnormals;
+       else if (T(node->index).vindices[2] == i)
+         T(node->index).nindices[2] = numnormals;
+       numnormals++;
+      }
+      node = node->next;
+    }
+  }
+  
+  model->numnormals = numnormals - 1;
+
+  /* free the member information */
+  for (i = 1; i <= model->numvertices; i++) {
+    node = members[i];
+    while (node) {
+      tail = node;
+      node = node->next;
+      free(tail);
+    }
+  }
+  free(members);
+
+  /* pack the normals array (we previously allocated the maximum
+     number of normals that could possibly be created (numtriangles *
+     3), so get rid of some of them (usually alot unless none of the
+     facet normals were averaged)) */
+  normals = model->normals;
+  model->normals = (float*)malloc(sizeof(float)* 3* (model->numnormals+1));
+  for (i = 1; i <= model->numnormals; i++) {
+    model->normals[3 * i + 0] = normals[3 * i + 0];
+    model->normals[3 * i + 1] = normals[3 * i + 1];
+    model->normals[3 * i + 2] = normals[3 * i + 2];
+  }
+  free(normals);
+
+  printf("glmVertexNormals(): %d normals generated\n", model->numnormals);
+}
+
+
+/* glmLinearTexture: Generates texture coordinates according to a
+ * linear projection of the texture map.  It generates these by
+ * linearly mapping the vertices onto a square.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+void
+glmLinearTexture(GLMmodel* model)
+{
+  GLMgroup *group;
+  float dimensions[3];
+  float x, y, scalefactor;
+  unsigned int i;
+  
+  assert(model);
+
+  if (model->texcoords)
+    free(model->texcoords);
+  model->numtexcoords = model->numvertices;
+  model->texcoords=(float*)malloc(sizeof(float)*2*(model->numtexcoords+1));
+  
+  glmDimensions(model, dimensions);
+  scalefactor = 2.0 / 
+    _glmAbs(_glmMax(_glmMax(dimensions[0], dimensions[1]), dimensions[2]));
+
+  /* do the calculations */
+  for(i = 1; i <= model->numvertices; i++) {
+    x = model->vertices[3 * i + 0] * scalefactor;
+    y = model->vertices[3 * i + 2] * scalefactor;
+    model->texcoords[2 * i + 0] = (x + 1.0) / 2.0;
+    model->texcoords[2 * i + 1] = (y + 1.0) / 2.0;
+  }
+  
+  /* go through and put texture coordinate indices in all the triangles */
+  group = model->groups;
+  while(group) {
+    for(i = 0; i < group->numtriangles; i++) {
+      T(group->triangles[i]).tindices[0] = 
T(group->triangles[i]).vindices[0];
+      T(group->triangles[i]).tindices[1] = 
T(group->triangles[i]).vindices[1];
+      T(group->triangles[i]).tindices[2] = 
T(group->triangles[i]).vindices[2];
+    }    
+    group = group->next;
+  }
+
+#if 0
+  printf("glmLinearTexture(): generated %d linear texture coordinates\n",
+         model->numtexcoords);
+#endif
+}
+
+/* glmSpheremapTexture: Generates texture coordinates according to a
+ * spherical projection of the texture map.  Sometimes referred to as
+ * spheremap, or reflection map texture coordinates.  It generates
+ * these by using the normal to calculate where that vertex would map
+ * onto a sphere.  Since it is impossible to map something flat
+ * perfectly onto something spherical, there is distortion at the
+ * poles.  This particular implementation causes the poles along the X
+ * axis to be distorted.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+void
+glmSpheremapTexture(GLMmodel* model)
+{
+  GLMgroup* group;
+  float theta, phi, rho, x, y, z, r;
+  unsigned int i;
+  
+  assert(model);
+  assert(model->normals);
+
+  if (model->texcoords)
+    free(model->texcoords);
+  model->numtexcoords = model->numnormals;
+  model->texcoords=(float*)malloc(sizeof(float)*2*(model->numtexcoords+1));
+     
+  /* do the calculations */
+  for (i = 1; i <= model->numnormals; i++) {
+    z = model->normals[3 * i + 0];     /* re-arrange for pole distortion */
+    y = model->normals[3 * i + 1];
+    x = model->normals[3 * i + 2];
+    r = sqrt((x * x) + (y * y));
+    rho = sqrt((r * r) + (z * z));
+      
+    if(r == 0.0) {
+      theta = 0.0;
+      phi = 0.0;
+    } else {
+      if(z == 0.0)
+       phi = 3.14159265 / 2.0;
+      else
+       phi = acos(z / rho);
+      
+#if WE_DONT_NEED_THIS_CODE
+      if(x == 0.0)
+       theta = 3.14159265 / 2.0;       /* asin(y / r); */
+      else
+       theta = acos(x / r);
+#endif
+      
+      if(y == 0.0)
+       theta = 3.141592365 / 2.0;      /* acos(x / r); */
+      else
+       theta = asin(y / r) + (3.14159265 / 2.0);
+    }
+    
+    model->texcoords[2 * i + 0] = theta / 3.14159265;
+    model->texcoords[2 * i + 1] = phi / 3.14159265;
+  }
+  
+  /* go through and put texcoord indices in all the triangles */
+  group = model->groups;
+  while(group) {
+    for (i = 0; i < group->numtriangles; i++) {
+      T(group->triangles[i]).tindices[0] = 
T(group->triangles[i]).nindices[0];
+      T(group->triangles[i]).tindices[1] = 
T(group->triangles[i]).nindices[1];
+      T(group->triangles[i]).tindices[2] = 
T(group->triangles[i]).nindices[2];
+    }
+    group = group->next;
+  }
+
+#if 0  
+  printf("glmSpheremapTexture(): generated %d spheremap texture 
coordinates\n",
+        model->numtexcoords);
+#endif
+}
+
+/* glmDelete: Deletes a GLMmodel structure.
+ *
+ * model - initialized GLMmodel structure
+ */
+void
+glmDelete(GLMmodel* model)
+{
+  GLMgroup* group;
+  unsigned int i;
+
+  assert(model);
+
+  if (model->pathname)   free(model->pathname);
+  if (model->mtllibname) free(model->mtllibname);
+  if (model->vertices)   free(model->vertices);
+  if (model->normals)    free(model->normals);
+  if (model->texcoords)  free(model->texcoords);
+  if (model->facetnorms) free(model->facetnorms);
+  if (model->triangles)  free(model->triangles);
+  if (model->materials) {
+    for (i = 0; i < model->nummaterials; i++)
+      if (model->materials[i].name) free(model->materials[i].name);
+    free(model->materials);
+  }
+  while(model->groups) {
+    group = model->groups;
+    /* Take the group off the linked list. */
+    model->groups = model->groups->next;
+    if (group->name) free(group->name);
+    if (group->triangles) free(group->triangles);
+    free(group);
+  }
+
+  free(model);
+}
+
+/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+ * Returns a pointer to the created object which should be free'd with
+ * glmDelete().
+ *
+ * filename - name of the file containing the Wavefront .OBJ format data.  
+ */
+GLMmodel* 
+glmReadOBJ(const char* filename)
+{
+  GLMmodel* model;
+  FILE*     file;
+
+  /* open the file */
+  file = fopen(filename, "r");
+  if (!file) {
+    perror("glmReadOBJ() failed: can't open data file");
+    return 0;
+  }
+
+#if 0
+  /* announce the model name */
+  printf("Model: %s\n", filename);
+#endif
+
+  /* allocate a new model */
+  model = (GLMmodel*)malloc(sizeof(GLMmodel));
+  model->pathname      = strdup(filename);
+  model->mtllibname    = NULL;
+  model->numvertices   = 0;
+  model->vertices      = NULL;
+  model->numnormals    = 0;
+  model->normals       = NULL;
+  model->numtexcoords  = 0;
+  model->texcoords     = NULL;
+  model->numfacetnorms = 0;
+  model->facetnorms    = NULL;
+  model->numtriangles  = 0;
+  model->triangles     = NULL;
+  model->nummaterials  = 0;
+  model->materials     = NULL;
+  model->numgroups     = 0;
+  model->groups        = NULL;
+  model->position[0]   = 0.0;
+  model->position[1]   = 0.0;
+  model->position[2]   = 0.0;
+
+  /* make a first pass through the file to get a count of the number
+     of vertices, normals, texcoords & triangles */
+  if (_glmFirstPass(model, file)) {
+    /* There was a problem here, so cleanup and exit. */
+    glmDelete(model);
+    fclose(file);
+    return 0;
+  }
+
+  /* allocate memory */
+  model->vertices = (float*)malloc(sizeof(float) *
+                                   3 * (model->numvertices + 1));
+  model->vertexColors = (unsigned char*)malloc(sizeof(unsigned char) *
+                                               3 * (model->numvertices + 1));
+  model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
+                                         model->numtriangles);
+  if (model->numnormals) {
+    model->normals = (float*)malloc(sizeof(float) *
+                                    3 * (model->numnormals + 1));
+  }
+  if (model->numtexcoords) {
+    model->texcoords = (float*)malloc(sizeof(float) *
+                                      2 * (model->numtexcoords + 1));
+  }
+
+  /* rewind to beginning of file and read in the data this pass */
+  rewind(file);
+
+  _glmSecondPass(model, file);
+
+  /* close the file */
+  fclose(file);
+
+  return model;
+}
+
+/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+ * a file.
+ *
+ * model    - initialized GLMmodel structure
+ * filename - name of the file to write the Wavefront .OBJ format data to
+ * mode     - a bitwise or of values describing what is written to the file
+ *            GLM_NONE     -  render with only vertices
+ *            GLM_FLAT     -  render with facet normals
+ *            GLM_SMOOTH   -  render with vertex normals
+ *            GLM_TEXTURE  -  render with texture coords
+ *            GLM_COLOR    -  render with colors (color material)
+ *            GLM_MATERIAL -  render with materials
+ *            GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+int
+glmWriteOBJ(GLMmodel* model, char* filename, unsigned int mode)
+{
+  unsigned int    i;
+  FILE*     file;
+  GLMgroup* group;
+
+  assert(model);
+
+  /* do a bit of warning */
+  if (mode & GLM_FLAT && !model->facetnorms) {
+    printf("glmWriteOBJ() warning: flat normal output requested "
+          "with no facet normals defined.\n");
+    mode &= ~GLM_FLAT;
+  }
+  if (mode & GLM_SMOOTH && !model->normals) {
+    printf("glmWriteOBJ() warning: smooth normal output requested "
+          "with no normals defined.\n");
+    mode &= ~GLM_SMOOTH;
+  }
+  if (mode & GLM_TEXTURE && !model->texcoords) {
+    printf("glmWriteOBJ() warning: texture coordinate output requested "
+          "with no texture coordinates defined.\n");
+    mode &= ~GLM_TEXTURE;
+  }
+  if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+    printf("glmWriteOBJ() warning: flat normal output requested "
+          "and smooth normal output requested (using smooth).\n");
+    mode &= ~GLM_FLAT;
+  }
+
+  /* open the file */
+  file = fopen(filename, "w");
+  if (!file) {
+    fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to 
write.\n",
+           filename);
+    return 1;
+  }
+
+  /* spit out a header */
+  fprintf(file, "#  \n");
+  fprintf(file, "#  Wavefront OBJ generated by GLM library\n");
+  fprintf(file, "#  \n");
+  fprintf(file, "#  GLM library copyright (C) 1997 by Nate Robins\n");
+  fprintf(file, "#  email: ndr@pobox.com\n");
+  fprintf(file, "#  www:   http://www.pobox.com/~ndr\n";);
+  fprintf(file, "#  \n");
+
+  if (mode & GLM_MATERIAL && model->mtllibname) {
+    fprintf(file, "\nmtllib %s\n\n", model->mtllibname);
+    if (_glmWriteMTL(model, filename, model->mtllibname)) {
+      /* Problem opening up the material file for output. */
+      fclose(file);
+      return 1;
+    }
+  }
+
+  /* spit out the vertices */
+  fprintf(file, "\n");
+  fprintf(file, "# %d vertices\n", model->numvertices);
+  for (i = 1; i <= model->numvertices; i++) {
+    fprintf(file, "v %f %f %f\n", 
+           model->vertices[3 * i + 0],
+           model->vertices[3 * i + 1],
+           model->vertices[3 * i + 2]);
+  }
+
+  /* spit out the smooth/flat normals */
+  if (mode & GLM_SMOOTH) {
+    fprintf(file, "\n");
+    fprintf(file, "# %u normals\n", model->numnormals);
+    for (i = 1; i <= model->numnormals; i++) {
+      fprintf(file, "vn %f %f %f\n", 
+             model->normals[3 * i + 0],
+             model->normals[3 * i + 1],
+             model->normals[3 * i + 2]);
+    }
+  } else if (mode & GLM_FLAT) {
+    fprintf(file, "\n");
+    fprintf(file, "# %u normals\n", model->numfacetnorms);
+    for (i = 1; i <= model->numnormals; i++) {
+      fprintf(file, "vn %f %f %f\n", 
+             model->facetnorms[3 * i + 0],
+             model->facetnorms[3 * i + 1],
+             model->facetnorms[3 * i + 2]);
+    }
+  }
+
+  /* spit out the texture coordinates */
+  if (mode & GLM_TEXTURE) {
+    fprintf(file, "\n");
+    fprintf(file, "# %u texcoords\n", model->numtexcoords);
+    for (i = 1; i <= model->numtexcoords; i++) {
+      fprintf(file, "vt %f %f\n", 
+             model->texcoords[2 * i + 0],
+             model->texcoords[2 * i + 1]);
+    }
+  }
+
+  fprintf(file, "\n");
+  fprintf(file, "# %u groups\n", model->numgroups);
+  fprintf(file, "# %u faces (triangles)\n", model->numtriangles);
+  fprintf(file, "\n");
+
+  group = model->groups;
+  while(group) {
+    fprintf(file, "g %s\n", group->name);
+    if (mode & GLM_MATERIAL)
+      fprintf(file, "usemtl %s\n", model->materials[group->material].name);
+    for (i = 0; i < group->numtriangles; i++) {
+      if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) {
+       fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
+               T(group->triangles[i]).vindices[0], 
+               T(group->triangles[i]).nindices[0], 
+               T(group->triangles[i]).tindices[0],
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).nindices[1],
+               T(group->triangles[i]).tindices[1],
+               T(group->triangles[i]).vindices[2],
+               T(group->triangles[i]).nindices[2],
+               T(group->triangles[i]).tindices[2]);
+      } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) {
+       fprintf(file, "f %d/%d %d/%d %d/%d\n",
+               T(group->triangles[i]).vindices[0],
+               T(group->triangles[i]).findex,
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).findex,
+               T(group->triangles[i]).vindices[2],
+               T(group->triangles[i]).findex);
+      } else if (mode & GLM_TEXTURE) {
+       fprintf(file, "f %d/%d %d/%d %d/%d\n",
+               T(group->triangles[i]).vindices[0],
+               T(group->triangles[i]).tindices[0],
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).tindices[1],
+               T(group->triangles[i]).vindices[2],
+               T(group->triangles[i]).tindices[2]);
+      } else if (mode & GLM_SMOOTH) {
+       fprintf(file, "f %d//%d %d//%d %d//%d\n",
+               T(group->triangles[i]).vindices[0],
+               T(group->triangles[i]).nindices[0],
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).nindices[1],
+               T(group->triangles[i]).vindices[2], 
+               T(group->triangles[i]).nindices[2]);
+      } else if (mode & GLM_FLAT) {
+       fprintf(file, "f %d//%d %d//%d %d//%d\n",
+               T(group->triangles[i]).vindices[0], 
+               T(group->triangles[i]).findex,
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).findex,
+               T(group->triangles[i]).vindices[2],
+               T(group->triangles[i]).findex);
+      } else {
+       fprintf(file, "f %d %d %d\n",
+               T(group->triangles[i]).vindices[0],
+               T(group->triangles[i]).vindices[1],
+               T(group->triangles[i]).vindices[2]);
+      }
+    }
+    fprintf(file, "\n");
+    group = group->next;
+  }
+
+  fclose(file);
+  return 0;
+}
+
+/* glmWeld: eliminate (weld) vectors that are within an epsilon of
+ * each other.
+ *
+ * model      - initialized GLMmodel structure
+ * epsilon    - maximum difference between vertices
+ *              ( 0.00001 is a good start for a unitized model)
+ *
+ */
+void
+glmWeld(GLMmodel* model, float epsilon)
+{
+  float* vectors;
+  float* copies;
+  unsigned int   numvectors;
+  unsigned int   i;
+
+  /* vertices */
+  numvectors = model->numvertices;
+  vectors    = model->vertices;
+  copies = _glmWeldVectors(vectors, &numvectors, epsilon);
+
+  printf("glmWeld(): %d redundant vertices.\n", 
+        model->numvertices - numvectors - 1);
+
+  for (i = 0; i < model->numtriangles; i++) {
+    T(i).vindices[0] = (unsigned int)vectors[3 * T(i).vindices[0] + 0];
+    T(i).vindices[1] = (unsigned int)vectors[3 * T(i).vindices[1] + 0];
+    T(i).vindices[2] = (unsigned int)vectors[3 * T(i).vindices[2] + 0];
+  }
+
+  /* free space for old vertices */
+  free(vectors);
+
+  /* allocate space for the new vertices */
+  model->numvertices = numvectors;
+  model->vertices = (float*)malloc(sizeof(float) * 
+                                   3 * (model->numvertices + 1));
+
+  /* copy the optimized vertices into the actual vertex list */
+  for (i = 1; i <= model->numvertices; i++) {
+    model->vertices[3 * i + 0] = copies[3 * i + 0];
+    model->vertices[3 * i + 1] = copies[3 * i + 1];
+    model->vertices[3 * i + 2] = copies[3 * i + 2];
+  }
+
+  free(copies);
+}
+
+#if 0   /** This is left in only as a reference to how to get to the data. */
+/* glmDraw: Renders the model to the current OpenGL context using the
+ * mode specified.
+ *
+ * model    - initialized GLMmodel structure
+ * mode     - a bitwise OR of values describing what is to be rendered.
+ *            GLM_NONE     -  render with only vertices
+ *            GLM_FLAT     -  render with facet normals
+ *            GLM_SMOOTH   -  render with vertex normals
+ *            GLM_TEXTURE  -  render with texture coords
+ *            GLM_COLOR    -  render with colors (color material)
+ *            GLM_MATERIAL -  render with materials
+ *            GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLvoid
+glmDraw(GLMmodel* model, unsigned int mode)
+{
+  unsigned int i;
+  GLMgroup* group;
+
+  assert(model);
+  assert(model->vertices);
+
+  /* do a bit of warning */
+  if (mode & GLM_FLAT && !model->facetnorms) {
+    printf("glmDraw() warning: flat render mode requested "
+          "with no facet normals defined.\n");
+    mode &= ~GLM_FLAT;
+  }
+  if (mode & GLM_SMOOTH && !model->normals) {
+    printf("glmDraw() warning: smooth render mode requested "
+          "with no normals defined.\n");
+    mode &= ~GLM_SMOOTH;
+  }
+  if (mode & GLM_TEXTURE && !model->texcoords) {
+    printf("glmDraw() warning: texture render mode requested "
+          "with no texture coordinates defined.\n");
+    mode &= ~GLM_TEXTURE;
+  }
+  if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+    printf("glmDraw() warning: flat render mode requested "
+          "and smooth render mode requested (using smooth).\n");
+    mode &= ~GLM_FLAT;
+  }
+  if (mode & GLM_COLOR && !model->materials) {
+    printf("glmDraw() warning: color render mode requested "
+          "with no materials defined.\n");
+    mode &= ~GLM_COLOR;
+  }
+  if (mode & GLM_MATERIAL && !model->materials) {
+    printf("glmDraw() warning: material render mode requested "
+          "with no materials defined.\n");
+    mode &= ~GLM_MATERIAL;
+  }
+  if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
+    printf("glmDraw() warning: color and material render mode requested "
+          "using only material mode\n");
+    mode &= ~GLM_COLOR;
+  }
+  if (mode & GLM_COLOR)
+    glEnable(GL_COLOR_MATERIAL);
+  if (mode & GLM_MATERIAL)
+    glDisable(GL_COLOR_MATERIAL);
+
+  glPushMatrix();
+  glTranslatef(model->position[0], model->position[1], model->position[2]);
+
+  glBegin(GL_TRIANGLES);
+  group = model->groups;
+  while (group) {
+    if (mode & GLM_MATERIAL) {
+      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, 
+                  model->materials[group->material].ambient);
+      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
+                  model->materials[group->material].diffuse);
+      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, 
+                  model->materials[group->material].specular);
+      glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 
+                 model->materials[group->material].shininess);
+    }
+
+    if (mode & GLM_COLOR) {
+      glColor3fv(model->materials[group->material].diffuse);
+    }
+
+    for (i = 0; i < group->numtriangles; i++) {
+      if (mode & GLM_FLAT)
+        glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
+      
+      if (mode & GLM_SMOOTH)
+        glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
+      if (mode & GLM_TEXTURE)
+        
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
+
+      if (model->usePerVertexColors) {
+        glColor3ubv( &model->vertexColors[3 * 
T(group->triangles[i]).vindices[0]] );
+      }
+
+      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
+#if 0
+      printf("%f %f %f\n", 
+            model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
+            model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
+            model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
+#endif
+      
+      if (mode & GLM_SMOOTH)
+        glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
+      if (mode & GLM_TEXTURE)
+        
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
+      if (model->usePerVertexColors) {
+        glColor3ubv( &model->vertexColors[3 * 
T(group->triangles[i]).vindices[1]] );
+      }
+      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
+#if 0
+      printf("%f %f %f\n", 
+            model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
+            model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
+            model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
+#endif
+      
+      if (mode & GLM_SMOOTH)
+       glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
+      if (mode & GLM_TEXTURE)
+       
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
+      if (model->usePerVertexColors) {
+        glColor3ubv( &model->vertexColors[3 * 
T(group->triangles[i]).vindices[2]] );
+      }
+      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
+#if 0
+      printf("%f %f %f\n", 
+            model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
+            model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
+            model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
+#endif
+      
+    }
+    
+    group = group->next;
+  }
+  glEnd();
+
+  glPopMatrix();
+}
+#endif
+
+};

Added: branches/itanium2/Model/Readers/glm/glm.h
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Readers/glm/glm.h   Sat Jul  9 13:53:42 2005
@@ -0,0 +1,250 @@
+/*    
+ *  GLM library.  Wavefront .obj file format reader/writer/manipulator.
+ *
+ *  Written by Nate Robins, 1997.
+ *  email: ndr@pobox.com
+ *  www: http://www.pobox.com/~ndr
+ */
+
+#ifndef RTRT_GLM_H
+#define RTRT_GLM_H
+
+namespace Glm { 
+
+/* includes */
+
+/* defines */
+#if 0
+#define GLM_NONE     (0)               /* render with only vertices */
+#define GLM_FLAT     (1 << 0)          /* render with facet normals */
+#define GLM_SMOOTH   (1 << 1)          /* render with vertex normals */
+#define GLM_TEXTURE  (1 << 2)          /* render with texture coords */
+#define GLM_COLOR    (1 << 3)          /* render with colors */
+#define GLM_MATERIAL (1 << 4)          /* render with materials */
+#endif
+
+       enum {
+               GLM_NONE     = (0),
+               GLM_FLAT     = (1 << 0),
+               GLM_SMOOTH   = (1 << 1),
+               GLM_TEXTURE  = (1 << 2),
+               GLM_COLOR    = (1 << 3),
+               GLM_MATERIAL = (1 << 4)
+       };
+
+       /* structs */
+
+       /* GLMmaterial: Structure that defines a material in a model. 
+        */
+       typedef struct _GLMmaterial
+       {
+               char* name;                             /* name of material */
+               float diffuse[4];                       /* diffuse component 
*/
+               float ambient[4];                       /* ambient component 
*/
+               float specular[4];                      /* specular component 
*/
+               float emmissive[4];                     /* emmissive 
component */
+               float shininess;                        /* specular exponent 
*/
+       } GLMmaterial;
+
+       /* GLMtriangle: Structure that defines a triangle in a model.
+        */
+       typedef struct {
+               unsigned int vindices[3];               /* array of triangle 
vertex indices */
+               unsigned int nindices[3];               /* array of triangle 
normal indices */
+               unsigned int tindices[3];               /* array of triangle 
texcoord indices*/
+               unsigned int findex;                    /* index of triangle 
facet normal */
+       } GLMtriangle;
+
+       /* GLMgroup: Structure that defines a group in a model.
+        */
+       typedef struct _GLMgroup {
+               char*             name;         /* name of this group */
+               unsigned int      numtriangles; /* number of triangles in 
this group */
+               unsigned int*     triangles;            /* array of triangle 
indices */
+               unsigned int      material;           /* index to material 
for group */
+               struct _GLMgroup* next;         /* pointer to next group in 
model */
+       } GLMgroup;
+
+       /* GLMmodel: Structure that defines a model.
+        */
+       typedef struct {
+               char*    pathname;                      /* path to this model 
*/
+               char*    mtllibname;                    /* name of the 
material library */
+
+               unsigned int   numvertices;             /* number of vertices 
in model */
+               float* vertices;                        /* array of vertices
+                                                                             
                                                                              
                     [x1,y1,z1,x2,y2,z2...] */
+               unsigned char* vertexColors;          /* array of vertex 
colors */
+
+               unsigned int   numnormals;              /* number of normals 
in model */
+               float* normals;                 /* array of normals */
+
+               unsigned int   numtexcoords;            /* number of 
texcoords in model */
+               float* texcoords;                       /* array of texture 
coordinates */
+
+               unsigned int   numfacetnorms;           /* number of 
facetnorms in model */
+               float* facetnorms;                      /* array of 
facetnorms */
+
+               unsigned int       numtriangles;        /* number of 
triangles in model */
+               GLMtriangle* triangles;         /* array of triangles */
+
+               unsigned int       nummaterials;        /* number of 
materials in model */
+               GLMmaterial* materials;         /* array of materials */
+
+               /* This is the thing you will want to iterate over.  Each 
group has
+                        an associated list of triangles, material, and name. 
*/
+               unsigned int       numgroups;           /* number of groups 
in model */
+               GLMgroup*    groups;                    /* linked list of 
groups */
+
+               float position[3];                      /* position of the 
model */
+
+               bool usePerVertexColors;             /* Are there per vertex 
colors? */
+               
+       } GLMmodel;
+
+
+       /* public functions */
+
+       /* glmUnitize: "unitize" a model by translating it to the origin and
+        * scaling it to fit in a unit cube around the origin.  Returns the
+        * scalefactor used.
+        *
+        * model - properly initialized GLMmodel structure 
+        */
+       float
+       glmUnitize(GLMmodel* model);
+
+       /*
+        * glmBoundingBox: Calculates the min/max positions of the model
+        */
+       void
+       glmBoundingBox(GLMmodel *model, float *minpos, float *maxpos);
+
+
+       /* glmDimensions: Calculates the dimensions (width, height, depth) of
+        * a model.
+        *
+        * model      - initialized GLMmodel structure
+        * dimensions - array of 3 floats (float dimensions[3])
+        */
+       void
+       glmDimensions(GLMmodel* model, float* dimensions);
+
+       /* glmScale: Scales a model by a given amount.
+        * 
+        * model - properly initialized GLMmodel structure
+        * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+        */
+       void
+       glmScale(GLMmodel* model, float scale);
+
+       /* glmReverseWinding: Reverse the polygon winding for all polygons in
+        * this model.  Default winding is counter-clockwise.  Also changes
+        * the direction of the normals.
+        * 
+        * model - properly initialized GLMmodel structure 
+        */
+       void
+       glmReverseWinding(GLMmodel* model);
+
+       /* glmFacetNormals: Generates facet normals for a model (by taking the
+        * cross product of the two vectors derived from the sides of each
+        * triangle).  Assumes a counter-clockwise winding.
+        *
+        * model - initialized GLMmodel structure
+        */
+       void
+       glmFacetNormals(GLMmodel* model);
+
+       /* glmVertexNormals: Generates smooth vertex normals for a model.
+        * First builds a list of all the triangles each vertex is in.  Then
+        * loops through each vertex in the the list averaging all the facet
+        * normals of the triangles each vertex is in.  Finally, sets the
+        * normal index in the triangle for the vertex to the generated smooth
+        * normal.  If the dot product of a facet normal and the facet normal
+        * associated with the first triangle in the list of triangles the
+        * current vertex is in is greater than the cosine of the angle
+        * parameter to the function, that facet normal is not added into the
+        * average normal calculation and the corresponding vertex is given
+        * the facet normal.  This tends to preserve hard edges.  The angle to
+        * use depends on the model, but 90 degrees is usually a good start.
+        *
+        * model - initialized GLMmodel structure
+        * angle - maximum angle (in degrees) to smooth across
+        */
+       void
+       glmVertexNormals(GLMmodel* model, float angle);
+
+       /* glmLinearTexture: Generates texture coordinates according to a
+        * linear projection of the texture map.  It generates these by
+        * linearly mapping the vertices onto a square.
+        *
+        * model - pointer to initialized GLMmodel structure
+        */
+       void
+       glmLinearTexture(GLMmodel* model);
+
+       /* glmSpheremapTexture: Generates texture coordinates according to a
+        * spherical projection of the texture map.  Sometimes referred to as
+        * spheremap, or reflection map texture coordinates.  It generates
+        * these by using the normal to calculate where that vertex would map
+        * onto a sphere.  Since it is impossible to map something flat
+        * perfectly onto something spherical, there is distortion at the
+        * poles.  This particular implementation causes the poles along the X
+        * axis to be distorted.
+        *
+        * model - pointer to initialized GLMmodel structure
+        */
+       void
+       glmSpheremapTexture(GLMmodel* model);
+
+       /* glmDelete: Deletes a GLMmodel structure.
+        *
+        * model - initialized GLMmodel structure
+        */
+       void
+       glmDelete(GLMmodel* model);
+
+       /* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+        * Returns a pointer to the created object which should be free'd with
+        * glmDelete().
+        *
+        * filename - name of the file containing the Wavefront .OBJ format 
data.
+        *
+        * returns 0 if there was a problem reading the file.
+        */
+       GLMmodel* 
+       glmReadOBJ(const char* filename);
+
+       /* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+        * a file.
+        *
+        * model    - initialized GLMmodel structure
+        * filename - name of the file to write the Wavefront .OBJ format 
data to
+        * mode     - a bitwise or of values describing what is written to 
the file
+        *            GLM_NONE    -  write only vertices
+        *            GLM_FLAT    -  write facet normals
+        *            GLM_SMOOTH  -  write vertex normals
+        *            GLM_TEXTURE -  write texture coords
+        *            GLM_FLAT and GLM_SMOOTH should not both be specified.
+        *
+        * returns 1 if there was error, 0 otherwise.
+        * 
+        */
+       int
+       glmWriteOBJ(GLMmodel* model, char* filename, unsigned int mode);
+
+       /* glmWeld: eliminate (weld) vectors that are within an epsilon of
+        * each other.
+        *
+        * model      - initialized GLMmodel structure
+        * epsilon    - maximum difference between vertices
+        *              ( 0.00001 is a good start for a unitized model)
+        *
+        */
+       void
+       glmWeld(GLMmodel* model, float epsilon);
+
+};
+
+#endif 

Modified: branches/itanium2/StandAlone/manta.cc
==============================================================================
--- branches/itanium2/StandAlone/manta.cc       (original)
+++ branches/itanium2/StandAlone/manta.cc       Sat Jul  9 13:53:42 2005
@@ -74,15 +74,15 @@
   BenchHelper(RTRTInterface* rtrt, long numFrames);
   void start(int, int);
   void stop(int, int);
-
+       
 private:
-  RTRTInterface* rtrt;
+               RTRTInterface* rtrt;
   double startTime;
   long numFrames;
 };
 
 BenchHelper::BenchHelper(RTRTInterface* rtrt, long numFrames)
-  : rtrt(rtrt), numFrames(numFrames)
+: rtrt(rtrt), numFrames(numFrames)
 {
 }
 
@@ -95,8 +95,9 @@
 {
   double dt = Time::currentSeconds()-startTime;
   double fps = static_cast<double>(numFrames)/dt;
-  cout << "Benchmark completed in " << dt << " seconds (" << numFrames << " 
frames, " << fps << " frames per second)\n";
-  rtrt->finish();
+  // cout << "Benchmark completed in " << dt << " seconds (" << numFrames << 
" frames, " << fps << " frames per second)\n";
+  std::cout << fps << std::endl;
+       rtrt->finish();
   delete this;
 }
 
@@ -106,13 +107,13 @@
 #if HAVE_IEEEFP_H
   fpsetmask(FP_X_OFL|FP_X_DZ|FP_X_INV);
 #endif
-
-
+       
+       
   // Copy args into a vector<string>
   vector<string> args;
   for(int i=1;i<argc;i++)
     args.push_back(argv[i]);
-
+       
   try {
     RTRTInterface* rtrt = createRTRT();
     if(getenv("MANTA_SCENEPATH"))
@@ -138,35 +139,35 @@
     int xres = 512, yres = 512;
     bool channelCreated=false;
     bool haveUI = false;
-
+               
     int argc = static_cast<int>(args.size());
     for(int i=0;i<argc;i++){
       string arg = args[i];
       if(arg == "-help"){
-       usage(rtrt);
+                               usage(rtrt);
       } else if(arg == "-bench"){
-       long numFrames = 100;
-       long warmup = 10;
-       if(getLongArg(i, args, numFrames)){
-         getLongArg(i, args, warmup);
-       }
-       BenchHelper* b = new BenchHelper(rtrt, numFrames);
-       // Ask for two callbacks, one at frame "warmup", and one at
-       // frame warmup+numFrames
-       rtrt->addOneShotCallback(RTRTInterface::Absolute, warmup,
-                                Callback::create(b, &BenchHelper::start));
-       rtrt->addOneShotCallback(RTRTInterface::Absolute, warmup+numFrames,
-                                Callback::create(b, &BenchHelper::stop));
+                               long numFrames = 100;
+                               long warmup = 10;
+                               if(getLongArg(i, args, numFrames)){
+                                       getLongArg(i, args, warmup);
+                               }
+                               BenchHelper* b = new BenchHelper(rtrt, 
numFrames);
+                               // Ask for two callbacks, one at frame 
"warmup", and one at
+                               // frame warmup+numFrames
+                               
rtrt->addOneShotCallback(RTRTInterface::Absolute, warmup,
+                                                                             
                                                   Callback::create(b, 
&BenchHelper::start));
+                               
rtrt->addOneShotCallback(RTRTInterface::Absolute, warmup+numFrames,
+                                                                             
                                                   Callback::create(b, 
&BenchHelper::stop));
       } else if(arg == "-camera"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       currentCamera = rtrt->createCamera(s);
-       if(!currentCamera){
-         cerr << "Error creating camera: " << s << ", available cameras 
are:\n";
-         printList(cerr, rtrt->listCameras());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               currentCamera = rtrt->createCamera(s);
+                               if(!currentCamera){
+                                       cerr << "Error creating camera: " << 
s << ", available cameras are:\n";
+                                       printList(cerr, rtrt->listCameras());
+                                       exit(1);
+                               }
       } else if(arg == "-idlemode"){
         string s;
         if(!getStringArg(i, args, s))
@@ -177,112 +178,112 @@
           exit(1);
         }
       } else if(arg == "-imagedisplay"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->createChannel(s, currentCamera, false, xres, yres)){
-         cerr << "Invalid image display: " << s << ", available image 
displays are:\n";
-         printList(cerr, rtrt->listImageDisplays());
-         exit(1);
-       }
-       channelCreated=true;
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->createChannel(s, currentCamera, 
false, xres, yres)){
+                                       cerr << "Invalid image display: " << 
s << ", available image displays are:\n";
+                                       printList(cerr, 
rtrt->listImageDisplays());
+                                       exit(1);
+                               }
+                               channelCreated=true;
       } else if(arg == "-imagetraverser"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectImageTraverser(s)){
-         cerr << "Invalid image traverser: " << s << ", available image 
traversers are:\n";
-         printList(cerr, rtrt->listImageTraversers());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectImageTraverser(s)){
+                                       cerr << "Invalid image traverser: " 
<< s << ", available image traversers are:\n";
+                                       printList(cerr, 
rtrt->listImageTraversers());
+                                       exit(1);
+                               }
       } else if(arg == "-imagetype"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectImageType(s)){
-         cerr << "Invalid image type: " << s << ", available image types 
are:\n";
-         printList(cerr, rtrt->listImageTypes());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectImageType(s)){
+                                       cerr << "Invalid image type: " << s 
<< ", available image types are:\n";
+                                       printList(cerr, 
rtrt->listImageTypes());
+                                       exit(1);
+                               }
       } else if(arg == "-loadbalancer"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectLoadBalancer(s)){
-         cerr << "Invalid load balancer: " << s << ", available load 
balancers are:\n";
-         printList(cerr, rtrt->listLoadBalancers());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectLoadBalancer(s)){
+                                       cerr << "Invalid load balancer: " << 
s << ", available load balancers are:\n";
+                                       printList(cerr, 
rtrt->listLoadBalancers());
+                                       exit(1);
+                               }
       } else if(arg == "-np"){
-       long np;
-       if(!getLongArg(i, args, np))
-         usage(rtrt);
-       rtrt->changeNumWorkers(static_cast<int>(np));
+                               long np;
+                               if(!getLongArg(i, args, np))
+                                       usage(rtrt);
+                               rtrt->changeNumWorkers(static_cast<int>(np));
       } else if(arg == "-pixelsampler"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectPixelSampler(s)){
-         cerr << "Invalid pixel sampler: " << s << ", available pixel 
samplers are:\n";
-         printList(cerr, rtrt->listPixelSamplers());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectPixelSampler(s)){
+                                       cerr << "Invalid pixel sampler: " << 
s << ", available pixel samplers are:\n";
+                                       printList(cerr, 
rtrt->listPixelSamplers());
+                                       exit(1);
+                               }
       } else if(arg == "-renderer"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectRenderer(s)){
-         cerr << "Invalid renderer: " << s << ", available renderers are:\n";
-         printList(cerr, rtrt->listRenderers());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectRenderer(s)){
+                                       cerr << "Invalid renderer: " << s << 
", available renderers are:\n";
+                                       printList(cerr, 
rtrt->listRenderers());
+                                       exit(1);
+                               }
       } else if(arg == "-res"){
-       if(!getResolutionArg(i, args, xres, yres)){
-         cerr << "Error parsing resolution: " << args[i+1] << '\n';
-         usage(rtrt);
-       }
+                               if(!getResolutionArg(i, args, xres, yres)){
+                                       cerr << "Error parsing resolution: " 
<< args[i+1] << '\n';
+                                       usage(rtrt);
+                               }
       } else if(arg == "-scene"){
-       if(rtrt->haveScene())
-         cerr << "WARNING: multiple scenes specified, will use last one\n";
-       string scene;
-       if(!getStringArg(i, args, scene))
-         usage(rtrt);
-       if(!rtrt->readScene(scene)){
-         cerr << "Error reading scene: " << scene << '\n';
-         exit(1);
-       }
+                               if(rtrt->haveScene())
+                                       cerr << "WARNING: multiple scenes 
specified, will use last one\n";
+                               string scene;
+                               if(!getStringArg(i, args, scene))
+                                       usage(rtrt);
+                               if(!rtrt->readScene(scene)){
+                                       cerr << "Error reading scene: " << 
scene << '\n';
+                                       exit(1);
+                               }
       } else if(arg == "-shadows"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       if(!rtrt->selectShadowAlgorithm(s)){
-         cerr << "Invalid shadow algorithm: " << s << ", available shadow 
algorithms are:\n";
-         printList(cerr, rtrt->listShadowAlgorithms());
-         exit(1);
-       }
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               if(!rtrt->selectShadowAlgorithm(s)){
+                                       cerr << "Invalid shadow algorithm: " 
<< s << ", available shadow algorithms are:\n";
+                                       printList(cerr, 
rtrt->listShadowAlgorithms());
+                                       exit(1);
+                               }
       } else if(arg == "-ui"){
-       string s;
-       if(!getStringArg(i, args, s))
-         usage(rtrt);
-       UserInterface* ui = rtrt->createUserInterface(s);
-       if(!ui){
-         cerr << "Unknown user interface: " << s << ", available user 
interfaces are:\n";
-         printList(cerr, rtrt->listUserInterfaces());
-         exit(1);
-       }
-       ui->startup();
-       haveUI = true;
+                               string s;
+                               if(!getStringArg(i, args, s))
+                                       usage(rtrt);
+                               UserInterface* ui = 
rtrt->createUserInterface(s);
+                               if(!ui){
+                                       cerr << "Unknown user interface: " << 
s << ", available user interfaces are:\n";
+                                       printList(cerr, 
rtrt->listUserInterfaces());
+                                       exit(1);
+                               }
+                               ui->startup();
+                               haveUI = true;
       } else {
-       cerr << "Unknown argument: " << arg << '\n';
-       usage(rtrt);
+                               cerr << "Unknown argument: " << arg << '\n';
+                               usage(rtrt);
       }
     }
     if(!haveUI){
       UserInterface* ui = rtrt->createUserInterface("X");
       if(!ui){
-       cerr << "Cannot find default user interface: X, available user 
interfaces are:\n";
-       printList(cerr, rtrt->listUserInterfaces());
-       exit(1);
+                               cerr << "Cannot find default user interface: 
X, available user interfaces are:\n";
+                               printList(cerr, rtrt->listUserInterfaces());
+                               exit(1);
       }
       ui->startup();
     } 
@@ -299,11 +300,11 @@
     if(e.stackTrace())
       cerr << "Stack trace: " << e.stackTrace() << '\n';
     exit(1);
-      
+               
   } catch (std::exception e){
     cerr << "Caught std exception: " << e.what() << '\n';
     exit(1);
-
+               
   } catch(...){
     cerr << "Caught unknown exception\n";
     exit(1);
@@ -331,28 +332,28 @@
   scene->setBackground(new 
ConstantBackground(ColorDB::getNamedColor("SkyBlue3")*0.5));
   Material* red=new Phong(Color(RGBColor(.6,0,0)),
                           Color(RGBColor(.6,.6,.6)), 32, 0.4);
-
+       
   Material* plane_matl = new Phong(new 
CheckerTexture<Color>(Color(RGBColor(.6,.6,.6)),
-                                                            
Color(RGBColor(0,0,0)),
-                                                            Vector(1,0,0),
-                                                            Vector(0,1,0)),
-                                  new 
Constant<Color>(Color(RGBColor(.6,.6,.6))),
-                                  32,
-                                  new CheckerTexture<double>(0.2, 0.5,
-                                                             Vector(1,0,0),
-                                                             Vector(0,1,0)));
-                                                             
-
+                                                                             
                                                                              
                                                                              
       Color(RGBColor(0,0,0)),
+                                                                             
                                                                              
                                                                              
       Vector(1,0,0),
+                                                                             
                                                                              
                                                                              
       Vector(0,1,0)),
+                                                                             
                                                           new 
Constant<Color>(Color(RGBColor(.6,.6,.6))),
+                                                                             
                                                           32,
+                                                                             
                                                           new 
CheckerTexture<double>(0.2, 0.5,
+                                                                             
                                                                              
                                                                              
              Vector(1,0,0),
+                                                                             
                                                                              
                                                                              
              Vector(0,1,0)));
+       
+       
   Group* world = new Group();
   Primitive* floor = new Parallelogram(plane_matl, Point(-20,-20,0),
-                                      Vector(40,0,0), Vector(0,40,0));
+                                                                             
                                                                           
Vector(40,0,0), Vector(0,40,0));
   // Setup world-space texture coordinates for the checkerboard floor
   UniformMapper* uniformmap = new UniformMapper();
   floor->setTexCoordMapper(uniformmap);
   world->add(floor);
   world->add(new Sphere(red, Point(0,0,1.2), 1.0));
   scene->setObject(world);
-
+       
   LightSet* lights = new LightSet();
   lights->add(new PointLight(Point(0,5,8), Color(RGBColor(.6,.1,.1))));
   lights->add(new PointLight(Point(5,0,8), Color(RGBColor(.1,.6,.1))));

Modified: branches/itanium2/StandAlone/manta_tile_size.pl
==============================================================================
--- branches/itanium2/StandAlone/manta_tile_size.pl     (original)
+++ branches/itanium2/StandAlone/manta_tile_size.pl     Sat Jul  9 13:53:42 
2005
@@ -1,14 +1,21 @@
 #!/usr/bin/perl
 
-
+# Perl script for testing different tile sizes.
+# Use 
+# cat manta_tile_size_1_to_32.txt | unu save -f nrrd | unu reshape -s 32 32 
| unu rmap -m ~/data/colormap/rainbow3x12.nrrd | unu resample -s = 512 512 -k 
box | unu quantize -b 8 | unu save -f png -o tile.png
+# to produce a nice colormapped image.
+# 
+# Abe Stephens abe@sgi.com
 
 ######################################################################
 # Default args.
-$np    = 1;
-@min   = (1, 1);
-@max   = (32, 32);
-@bench = (5, 5);
-$file  = 0;
+$np     = 1;
+@min    = (1, 1);
+@max    = (32, 32);
+@bench  = (5, 5);
+$file   = 0;
+$scene  = 0;
+$camera = 0;
 
 ######################################################################
 # Parse args.
@@ -44,6 +51,12 @@
        $bench[0] = $ARGV[++$i];
        $bench[1] = $ARGV[++$i];
     }    
+    elsif ($ARGV[$i] eq "-camera") {
+       $camera   = $ARGV[++$i];
+    }
+    elsif ($ARGV[$i] eq "-scene") {
+       $scene   = $ARGV[++$i];
+    }
 }
 
 # Determine output file.
@@ -88,6 +101,14 @@
            " -bench " . $bench[0] . " " . $bench[1] . " " .
            " -imagetraverser \"tiled( -tilesize " . $x . "x" . $y . " )\" ";
 
+       if ($camera) {
+           $command = $command . " -camera \"$camera\"";
+       }
+
+       if ($scene) {
+           $command = $command . " -scene \"$scene\"";
+       }
+
        print "" . ($iter+1) . " of " . $total . 
              " (" . (($iter+1)/$total*100) . "%)\n";
        print $command . "\n";
@@ -108,5 +129,8 @@
     }
 } 
 
+
+# Produce a plot.
+print "cat $file | unu save -f nrrd | unu reshape -s 32 32 | unu rmap -m 
~/data/colormap/rainbow3x12.nrrd | unu resample -s = 512 512 -k box | unu 
quantize -b 8 | unu save -f png -o tile.png\n"
 
 

Modified: branches/itanium2/fox/CMakeLists.txt
==============================================================================
--- branches/itanium2/fox/CMakeLists.txt        (original)
+++ branches/itanium2/fox/CMakeLists.txt        Sat Jul  9 13:53:42 2005
@@ -7,7 +7,13 @@
   SET(FOX_STATIC  FOX-1.5 CACHE STRING "")
 
   INCLUDE_DIRECTORIES(${FOX_INCLUDE})
-  LINK_DIRECTORIES   (${FOX_LIB} )
+  LINK_DIRECTORIES   (${FOX_LIB})
+
+  # Check to see if histx should be included.
+  IF(HISTX_PATH)
+    INCLUDE_DIRECTORIES(${HISTX_INCLUDE})
+    LINK_DIRECTORIES   (${HISTX_LIB} )     
+  ENDIF(HISTX_PATH)
 
   ADD_EXECUTABLE(fox_manta fox_manta.cc
                            FMantaImageFrame.cc
@@ -40,4 +46,9 @@
                                 -lm
                                 -lXcursor
                                 -lXrandr)
+  IF(HISTX_PATH)
+    TARGET_LINK_LIBRARIES(fox_manta Manta_histx
+                                    ${HISTX_LINK} )
+  ENDIF(HISTX_PATH)
+
 ENDIF(FOX_PATH)

Modified: branches/itanium2/fox/FMantaWindow.cc
==============================================================================
--- branches/itanium2/fox/FMantaWindow.cc       (original)
+++ branches/itanium2/fox/FMantaWindow.cc       Sat Jul  9 13:53:42 2005
@@ -4,6 +4,7 @@
 #include <fox/FMantaImageFrame.h>
 
 #include <SCIRun/Core/Thread/Thread.h>
+#include <Core/Exceptions/IllegalArgument.h>
 
 #include <Interface/Scene.h>
 #include <Interface/Object.h>
@@ -49,6 +50,9 @@
        FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_JITTER8_SAMPLER, 
FMantaWindow::onPixelSampler ),
        FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_TEXT_SAMPLER,    
FMantaWindow::onPixelSamplerText ),
 
+       // Traversers
+       FXMAPFUNC(SEL_COMMAND, FMantaWindow::ID_TEXT_TRAVERSER,  
FMantaWindow::onTraverserText ),
+
        // Cutting planes.
        FXMAPFUNC(SEL_LEFTBUTTONPRESS, FMantaImageFrame::ID_PIXEL_SELECT, 
FMantaWindow::onAddCuttingPlane )
 };
@@ -94,6 +98,11 @@
        new FXMenuCommand( sampler_menu, "Jitter 8 Samples", 0, this, 
ID_JITTER8_SAMPLER );
        new FXMenuCommand( sampler_menu, "Enter Text...", 0, this,    
ID_TEXT_SAMPLER );
        new FXMenuTitle( menu_bar, "Samplers", 0, sampler_menu );
+       
+       // Traverser Menu.
+       traverser_menu = new FXMenuPane( this );
+       new FXMenuCommand( traverser_menu, "Enter Text...", 0, this,  
ID_TEXT_TRAVERSER );
+       new FXMenuTitle( menu_bar, "Traversers", 0, traverser_menu );
 
        // Options menu.
        options_menu = new FXMenuPane( this );
@@ -131,7 +140,7 @@
        camera_bookmark_list = new FXListBox( frame, this, ID_BOOKMARK_LIST, 
LAYOUT_FILL_X|LAYOUT_BOTTOM|COMBOBOX_REPLACE,0,0,0,20 );
        camera_bookmark_list->setNumVisible( 5 );
        
-       new FXButton( frame, "Add", 0, this, ID_ADD_BOOKMARK );
+       // new FXButton( frame, "Add", 0, this, ID_ADD_BOOKMARK );
 }
 
 // Quit the program.
@@ -316,6 +325,18 @@
        return 1;
 }
 
+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 )) {
+               manta_interface->addTransaction("Image Traverser.",
+                                                                             
                                                                  
Callback::create(this,&FMantaWindow::mantaTraverser,string(description.text())));
+       }
+       
+       return 1;
+}
+
 long FMantaWindow::onAddCuttingPlane( FXObject *sender, FXSelector key, void 
*data ) {
 
        FXEvent *event = (FXEvent *)data;
@@ -453,7 +474,7 @@
        delete old_camera;
        
        // This is unsafe.
-manta_frame->getNavigator()->resetToCamera( 
new_camera->getPosition(),new_camera->getLookAt(),new_camera->getUp());
+       manta_frame->getNavigator()->resetToCamera( 
new_camera->getPosition(),new_camera->getLookAt(),new_camera->getUp());
 }
 
 void FMantaWindow::mantaShadowAlgorithm( const string text ) const {
@@ -461,10 +482,14 @@
        // Determine the channel number.
        int channel = manta_frame->getMantaChannel();
        
-       // Update the shadow algorithm.
-       if (!manta_interface->selectShadowAlgorithm( text )) {
-               std::cout << "Could not select shadow algorithm " << text << 
std::endl;
+       try {
+               if (!manta_interface->selectShadowAlgorithm( text )) {
+                       std::cout << "Could not select shadow algorithm " << 
text << std::endl;
+               }
        }
+       catch (IllegalArgument e) {
+               std::cout << "Caught IllegalArgument exception" << std::endl;
+       };
 }
 
 void FMantaWindow::mantaPixelSampler( const string text ) const {
@@ -472,9 +497,30 @@
        // Determine the channel number.
        int channel = manta_frame->getMantaChannel();
        
-       if (!manta_interface->selectPixelSampler( text )) {
-               std::cout << "Could not select pixel sampler " << text << 
std::endl;
+       try {
+               if (!manta_interface->selectPixelSampler( text )) {
+                       std::cout << "Could not select pixel sampler " << 
text << std::endl;
+               }
+       }
+       catch (IllegalArgument e) {
+                       std::cout << "Caught IllegalArgument exception" << 
std::endl;
+       };
+}
+
+
+void FMantaWindow::mantaTraverser( const string text ) const {
+       
+       // Determine the channel number.
+       int channel = manta_frame->getMantaChannel();
+       
+       try {
+               if (!manta_interface->selectImageTraverser( text )) {
+                       std::cout << "Could not select pixel sampler " << 
text << std::endl;
+               }
        }
+       catch (IllegalArgument e) {
+               std::cout << "Caught IllegalArgument exception" << std::endl;
+       };
 }
 
 
///////////////////////////////////////////////////////////////////////////////

Modified: branches/itanium2/fox/FMantaWindow.h
==============================================================================
--- branches/itanium2/fox/FMantaWindow.h        (original)
+++ branches/itanium2/fox/FMantaWindow.h        Sat Jul  9 13:53:42 2005
@@ -37,6 +37,7 @@
                FXMenuPane *camera_menu;
                FXMenuPane *shadow_menu;
                FXMenuPane *sampler_menu;
+               FXMenuPane *traverser_menu;
                FXMenuPane *options_menu;
                FXMenuCommand *cutting_flip;
                
@@ -89,6 +90,9 @@
                        ID_JITTER8_SAMPLER,
                        ID_TEXT_SAMPLER,    // User wants to enter a 
description manually.
                        
+                       // Image traverser options.
+                       ID_TEXT_TRAVERSER,
+                       
                        // Cutting planes.
                        ID_ADD_CUTTING_PLANE,
                        
@@ -122,6 +126,7 @@
                long onShadowAlgorithmText( FXObject *sender, FXSelector key, 
void *data );
                long onPixelSampler   ( FXObject *sender, FXSelector key, 
void *data );
                long onPixelSamplerText( FXObject *sender, FXSelector key, 
void *data );
+               long onTraverserText  ( FXObject *sender, FXSelector key, 
void *data );
                long onAddCuttingPlane( FXObject *sender, FXSelector key, 
void *data );
                
                // Accessors.
@@ -144,6 +149,9 @@
                
                // This method is called by the manta thread to replace the 
shadow algorithm.
                void mantaPixelSampler( const string shadow_text ) const;
+               
+               // This method is called by the manta thread to replace the 
image traverser.
+               void mantaTraverser( const string shadow_text ) const;
                
                // This method is called by the manta thread to add a cutting 
plane.
                void mantaAddCuttingPlane( Point point, Vector normal ) const;

Modified: branches/itanium2/fox/fox_manta.cc
==============================================================================
--- branches/itanium2/fox/fox_manta.cc  (original)
+++ branches/itanium2/fox/fox_manta.cc  Sat Jul  9 13:53:42 2005
@@ -15,6 +15,8 @@
 #include <fox/FMantaQuakeNav.h>
 #include <fox/FMantaTrackballNav.h>
 
+#include <histx/SingleSamplerCounter.h>
+
 #include <string>
 #include <stdlib.h>
 
@@ -70,9 +72,11 @@
        manta_interface->setScenePath         (".");
        manta_interface->changeNumWorkers     ( np );
        manta_interface->selectImageType      ( "rgba8" );
+       // manta_interface->selectImageType      ( "rgbafloat" );
        manta_interface->selectLoadBalancer   ( "workqueue" );
        manta_interface->selectImageTraverser ( "tiled" );
-       //manta_interface->selectPixelSampler   ( "jittersample( 
-numberOfSamples 4 )" );
+       // manta_interface->selectPixelSampler   ( "jittersample( 
-numberOfSamples 4 )" );
+       // manta_interface->setPixelSampler      ( new 
Histx_Manta::SingleSamplerCounter );
        manta_interface->selectPixelSampler   ( "singlesample" );
        manta_interface->selectRenderer       ( "raytracer" );
        manta_interface->selectShadowAlgorithm( "hard" );

Modified: branches/itanium2/scenes/CMakeLists.txt
==============================================================================
--- branches/itanium2/scenes/CMakeLists.txt     (original)
+++ branches/itanium2/scenes/CMakeLists.txt     Sat Jul  9 13:53:42 2005
@@ -50,5 +50,11 @@
    TARGET_LINK_LIBRARIES(scene_boeing777 ${manta_scene_link})
 ENDIF(SCENE_BOEING777)
 
+SET(SCENE_OBJVIEWER 0 CACHE BOOL "Wavefront Obj file viewer.")
+IF(SCENE_OBJVIEWER)
+   ADD_LIBRARY(scene_objviewer objviewer.cc)
+   TARGET_LINK_LIBRARIES(scene_objviewer ${manta_scene_link})
+ENDIF(SCENE_OBJVIEWER)
+
 ############################################################
 

Added: branches/itanium2/scenes/objviewer.cc
==============================================================================
--- (empty file)
+++ branches/itanium2/scenes/objviewer.cc       Sat Jul  9 13:53:42 2005
@@ -0,0 +1,214 @@
+
+#include <MantaTypes.h>
+
+#include <Core/Geometry/PointVector.h>
+#include <Core/Exceptions/IllegalArgument.h>
+#include <Core/Util/Args.h>
+
+#include <Interface/Context.h>
+#include <Interface/LightSet.h>
+#include <Interface/RTRTInterface.h>
+#include <Interface/Scene.h>
+#include <Interface/Material.h>
+
+#include <Model/Primitives/Triangle.h>
+#include <Model/Primitives/Parallelogram.h>
+#include <Model/Primitives/Cube.h>
+#include <Model/Materials/Lambertian.h>
+#include <Model/Materials/Phong.h>
+#include <Model/Materials/Dielectric.h>
+#include <Model/Materials/NormalMaterial.h>
+#include <Model/Groups/Group.h>
+#include <Model/Groups/RealisticBvh.h>
+#include <Model/Lights/HeadLight.h>
+#include <Model/AmbientLights/ConstantAmbient.h>
+#include <Model/Backgrounds/ConstantBackground.h>
+#include <Model/Readers/glm/glm.h>
+#include <Model/Textures/CheckerTexture.h>
+#include <Model/Textures/Constant.h>
+
+#include <SCIRun/Core/Thread/Time.h>
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+using namespace Manta;
+using namespace SCIRun;
+using namespace Glm;
+
+///////////////////////////////////////////////////////////////////////////
+// This function loads a specified .obj file into a runtime acceleration
+// structure for rendering.
+extern "C" 
+Scene* make_scene(const ReadContext& context, const vector<string>& args) {
+
+       string file_name;
+
+       // Check the arguments.
+       for (int i=0;i<args.size();++i) {
+       
+               if (args[i] == "-file") {
+                       // Read in the file name.
+                       if (!getStringArg(i, args, file_name))
+                               throw IllegalArgument("objviewer -file 
<filename>", i, args);
+               }
+       }
+       
+       // Load in the file using glm.
+       GLMmodel *model = glmReadOBJ( file_name.c_str() );
+       if (model == 0) {
+               std::cout << "Error cannot read model from file." << 
std::endl;
+               return 0;
+       }
+       
+       // Flip the face winding.
+       glmReverseWinding( model );
+       // glmScale( model, 10.0 );
+       
+       
/////////////////////////////////////////////////////////////////////////////
+       // Allocate storage for primitives and materials.
+       int total_triangles = model->numtriangles;
+       Triangle *triangle_array = new Triangle[ total_triangles ];
+       Material **material_array = new Material *[ model->nummaterials ];
+       
+       int tri = 0;
+       int mtl = 0;
+       
+       // Read in the materials.
+       for (int i=0;i<model->nummaterials;++i) {
+               
+               float c0 = model->materials[i].diffuse[0];
+               float c1 = model->materials[i].diffuse[1];
+               float c2 = model->materials[i].diffuse[2];
+               
+               Color diffuse(RGB( c0, c1, c2 ));
+               
+               // Check the material name.
+               string mtl_name = model->materials[i].name;
+               if (mtl_name.find("Clear")==0) {
+               
+                       // Note that the first material added by blender is 
always an
+                       // unused default material..
+                       material_array[i-1] = new Dielectric( diffuse, 
Color(RGB(0.6,0.6,0.8)), 128, 1.2, 1.2 );
+               }
+               else {
+                       material_array[i-1] = new Lambertian( diffuse );
+               }
+       }
+       
+       // Lambertian *default_material = new Lambertian( Color(RGB( 1.0, 
0.0, 0.0 ) )  );
+       Material *default_material = new NormalMaterial();
+       
+       // Read in the groups.
+       GLMgroup *group = model->groups;
+       while (group != 0) {
+       
+               // Determine the material for this group.
+               Material *material;
+               if ((group->material-1) < model->nummaterials) {
+                       material = material_array[group->material-1];
+               }
+               else {
+                       material = default_material;
+               }
+       
+               // Copy out triangles.
+               int total_faces = group->numtriangles;
+               for (int i=0;i<total_faces;++i) {
+                       
+                       Point vertex[3];
+                       for (int v=0;v<3;++v) {
+                               int    index = model->triangles[ 
group->triangles[i] ].vindices[v];
+                               float *f     = model->vertices+(index*3);
+                               // Copy out the vertex.
+                               vertex[v][0] = f[0];
+                               vertex[v][1] = f[1];
+                               vertex[v][2] = f[2];
+                       }
+                       
+                       // Create a new triangle.
+                       triangle_array[tri++] = 
+                               Triangle( material, vertex[0], vertex[1], 
vertex[2] );
+               }
+       
+               // Move to the next group.
+               group = group->next;
+               ++mtl;
+       }
+       
+       std::cerr << "Total triangles added: " << tri << std::endl;
+       
+       
/////////////////////////////////////////////////////////////////////////////
+       // Create an acceleration structure.
+       double time_begin = Time::currentSeconds();
+       
+       // Make an array of pointers to triangles for input to the bvh.
+       Object **triangle_ptr_array = new Object *[ total_triangles ];
+       for (int i=0;i<total_triangles;++i) {
+               triangle_ptr_array[i] = triangle_array+i;
+       }
+       
+       // Construct the bvh.
+       RealisticBvh *bvh = new RealisticBvh( triangle_ptr_array, 
total_triangles );
+       
+       double time_end = Time::currentSeconds();
+       
+       std::cerr << "Bvh creation time: " << (time_end - time_begin) 
+                 << " seconds." << std::endl;
+       
+       
+       
/////////////////////////////////////////////////////////////////////////////
+       // Check the size of bounding boxes.
+       PreprocessContext p_context;
+       
+       BBox bounds;
+       bvh->computeBounds( p_context, bounds );                        
+                                                                             
                                  
+       std::cerr << "Bvh: Bounding box " << bounds[0] << " : " << bounds[1] 
<< std::endl;
+                                                                             
                                                                              
                                                                              
                                              
+       
/////////////////////////////////////////////////////////////////////////////
+       // Create the scene.
+       Scene *scene = new Scene();
+       
+       // 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(0.2,0.2,0.2) 
) ));
+       scene->setLights( lights );
+       
+       Material* red=new Lambertian(Color(RGBColor(.6,0,0)));
+       Material* yellow=new Lambertian(Color(RGBColor(.6,.6,0)));
+       
+       
+       // Add a checkerboard floor.
+       Material* plane_matl = new Phong(new 
CheckerTexture<Color>(Color(RGBColor(.6,.6,0)),
+                                                                             
                                                                              
                                                                              
       Color(RGBColor(0,0,0)),
+                                                                             
                                                                              
                                                                              
       Vector(1,0,0),
+                                                                             
                                                                              
                                                                              
       Vector(0,1,0)),
+                                                                             
                                                           new 
Constant<Color>(Color(RGBColor(.6,.6,.6))),
+                                                                             
                                                           32,
+                                                                             
                                                           new 
CheckerTexture<double>(0.2, 0.5,
+                                                                             
                                                                              
                                                                              
              Vector(1,0,0),
+                                                                             
                                                                              
                                                                              
              Vector(0,1,0)));
+       
+  Parallelogram* floor = new Parallelogram(plane_matl, 
Point(-20,-20,bounds[0][2]),
+                                                                             
                                                                           
Vector(40,0,0), Vector(0,40,0));
+       Group *manta_group = new Group();
+       manta_group->add( floor );
+       // manta_group->add( new Cube( red, bounds[0], bounds[1] ) );
+       manta_group->add( bvh );
+       
+       // Add the bvh to the scene.
+       scene->setObject( manta_group );
+       
+       // Background.
+       scene->setBackground( new ConstantBackground( Color(RGB(0.8, 0.8, 
0.8)) ) );
+       
+       return scene;
+}
+
+
+
+       
\ No newline at end of file




  • [MANTA] r427 - in branches/itanium2: . Core Core/Geometry Engine/Control Engine/Display Interface Model/Groups Model/Materials Model/Primitives Model/Readers Model/Readers/glm StandAlone fox scenes, abe, 07/09/2005

Archive powered by MHonArc 2.6.16.

Top of page