Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[Manta] r1687 - trunk/Model/Primitives


Chronological Thread 
  • From: aek@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [Manta] r1687 - trunk/Model/Primitives
  • Date: Wed, 29 Aug 2007 14:44:14 -0600 (MDT)

Author: aek
Date: Wed Aug 29 14:44:14 2007
New Revision: 1687

Added:
   trunk/Model/Primitives/KenslerShirleyTriangle.cc
   trunk/Model/Primitives/KenslerShirleyTriangle.h
Log:
Adding "KenslerShirley" triangle intersector for meshes to the set of
primitives.  Leaving out of the CMakeLists.txt until compiling can actually
be tried on a machine with SSE.



Added: trunk/Model/Primitives/KenslerShirleyTriangle.cc
==============================================================================
--- (empty file)
+++ trunk/Model/Primitives/KenslerShirleyTriangle.cc    Wed Aug 29 14:44:14 
2007
@@ -0,0 +1,350 @@
+#include <Model/Primitives/KenslerShirleyTriangle.h>
+#include <Interface/Context.h>
+#include <Interface/RayPacket.h>
+#include <Core/Geometry/BBox.h>
+#include <Core/Util/Preprocessor.h>
+#include <SCIRun/Core/Util/Assert.h>
+#include <sgi_stl_warnings_off.h>
+#include <iostream>
+#include <sgi_stl_warnings_on.h>
+
+using namespace Manta;
+using namespace std;
+
+KenslerShirleyTriangle::KenslerShirleyTriangle() : myID(0), mesh(NULL)
+{
+}
+
+KenslerShirleyTriangle::KenslerShirleyTriangle(Mesh *mesh, unsigned int id) :
+  myID(id), mesh(mesh)
+{
+  update();
+}
+
+void KenslerShirleyTriangle::attachMesh(Mesh *mesh)
+{
+  this->mesh = mesh;
+}
+
+void KenslerShirleyTriangle::attachMesh(Mesh *mesh, unsigned int id)
+{
+  this->mesh = mesh;
+  myID = id;
+}
+
+void KenslerShirleyTriangle::update()
+{
+  const unsigned int index = myID*3;
+  p0 = mesh->vertices[mesh->vertex_indices[index+0]];
+  p1 = mesh->vertices[mesh->vertex_indices[index+1]];
+  p2 = mesh->vertices[mesh->vertex_indices[index+2]];
+}
+
+KenslerShirleyTriangle* KenslerShirleyTriangle::clone(CloneDepth depth, 
Clonable* incoming)
+{
+  KenslerShirleyTriangle *copy;
+  if (incoming)
+    copy = static_cast<KenslerShirleyTriangle*>(incoming);
+  else
+    copy = new KenslerShirleyTriangle();
+  copy->p0 = p0;
+  copy->p1 = p1;
+  copy->p2 = p2;
+  copy->myID = myID;
+  copy->mesh = mesh;
+
+  return copy;
+}
+
+Interpolable::InterpErr KenslerShirleyTriangle::serialInterpolate(const 
std::vector<keyframe_t> &keyframes)
+{
+  //We assume that the mesh has already been interpolated.
+  update();
+  return success;
+}
+
+void KenslerShirleyTriangle::computeBounds(const PreprocessContext& context,
+                                 BBox& bbox) const
+{
+  bbox.extendByBox(mesh->getBBox(myID));
+}
+
+void KenslerShirleyTriangle::preprocess(const PreprocessContext& context)
+{
+  if (context.proc != 0) { context.done(); return; }
+  //TODO: this materials->preprocess might end up getting called lots
+  //of times (imagine all the triangles share the same
+  //material). Would be nice to have the preprocess for this in the
+  //mesh class and just iterate over the materials. Not sure how to do
+  //that, so we will do extra work for now.
+  mesh->materials[mesh->face_material[myID]]->preprocess(context);
+  update();
+  context.done();
+}
+
+void KenslerShirleyTriangle::computeTexCoords2(const RenderContext&, 
RayPacket& rays) const
+{
+  const int which = myID*3;
+
+  const unsigned int index0 = mesh->texture_indices[which];
+
+  if (index0 == Mesh::kNoTextureIndex) {
+    // NOTE(boulos): Assume that if the first index is invalid, they
+    // all are.  In this case, set the texture coordinates to be the
+    // barycentric coordinates of the triangle.
+    for(int ray=rays.begin(); ray<rays.end(); ray++) {
+      float a = rays.getScratchpad<float>(SCRATCH_U)[ray];
+      float b = rays.getScratchpad<float>(SCRATCH_V)[ray];
+      float c = (1.0 - a - b);
+
+      rays.setTexCoords(ray, Vector(a, b, c));
+    }
+    rays.setFlag( RayPacket::HaveTexture2|RayPacket::HaveTexture3 );
+    return;
+  }
+
+  const unsigned int index1 = mesh->texture_indices[which+1];
+  const unsigned int index2 = mesh->texture_indices[which+2];
+
+
+  const Vector &tex0 = mesh->texCoords[index0];
+  const Vector &tex1 = mesh->texCoords[index1];
+  const Vector &tex2 = mesh->texCoords[index2];
+
+  for(int ray=rays.begin(); ray<rays.end(); ray++) {
+    float a = rays.getScratchpad<float>(SCRATCH_U)[ray];
+    float b = rays.getScratchpad<float>(SCRATCH_V)[ray];
+    float c = (1.0 - a - b);
+
+    rays.setTexCoords(ray, (tex1 * a) + (tex2 * b) + (tex0 * c));
+  }
+  rays.setFlag( RayPacket::HaveTexture2|RayPacket::HaveTexture3 );
+}
+
+#ifdef MANTA_SSE
+
+void KenslerShirleyTriangle::intersect( const RenderContext& context, 
RayPacket& rays ) const {
+
+  RayPacketData *data = rays.data;
+  const int ray_begin = rays.begin();
+  const int ray_end   = rays.end();
+  const int sse_begin = ( ray_begin + 3 ) & ( ~3 );
+  const int sse_end   = ( ray_end ) & ( ~3 );
+
+  const sse_t eps4 = set4( T_EPSILON );
+
+  const sse_t p1x = set4( p1[ 0 ] );
+  const sse_t p1y = set4( p1[ 1 ] );
+  const sse_t p1z = set4( p1[ 2 ] );
+
+  const sse_t p0x = set4( p0[ 0 ] );
+  const sse_t p0y = set4( p0[ 1 ] );
+  const sse_t p0z = set4( p0[ 2 ] );
+
+  const sse_t edge0x = sub4( p1x, p0x );
+  const sse_t edge0y = sub4( p1y, p0y );
+  const sse_t edge0z = sub4( p1z, p0z );
+
+  const sse_t p2x = set4( p2[ 0 ] );
+  const sse_t p2y = set4( p2[ 1 ] );
+  const sse_t p2z = set4( p2[ 2 ] );
+
+  const sse_t edge1x = sub4( p0x, p2x );
+  const sse_t edge1y = sub4( p0y, p2y );
+  const sse_t edge1z = sub4( p0z, p2z );
+
+  sse_t normalx, normaly, normalz;
+  cross4( normalx, normaly, normalz, edge0x, edge0y, edge0z, edge1x, edge1y, 
edge1z );
+
+  for ( int ray = sse_begin; ray < sse_end; ray += 4 ) {
+
+    const sse_t ox = load44( &data->origin[ 0 ][ ray ] );
+    const sse_t oy = load44( &data->origin[ 1 ][ ray ] );
+    const sse_t oz = load44( &data->origin[ 2 ][ ray ] );
+
+    const sse_t oldt = load44( &data->minT[ ray ] );
+
+    const sse_t dx = load44( &data->direction[ 0 ][ ray ] );
+    const sse_t dy = load44( &data->direction[ 1 ][ ray ] );
+    const sse_t dz = load44( &data->direction[ 2 ][ ray ] );
+
+    const sse_t det = dot4( normalx, normaly, normalz, dx, dy, dz );
+    const sse_t rcp = reciprocal4( det );
+
+    const sse_t edge2x = sub4( p0x, ox );
+    const sse_t edge2y = sub4( p0y, oy );
+    const sse_t edge2z = sub4( p0z, oz );
+
+    const sse_t t = dot4( normalx, normaly, normalz, edge2x, edge2y, edge2z 
);
+    const sse_t toverd = mul4( rcp, t );
+    const sse_t tmaskb = cmp4_lt( toverd, sub4( oldt, eps4 ) );
+    const sse_t tmaska = cmp4_gt( toverd, eps4 );
+    sse_t mask = and4( tmaska, tmaskb );
+    if ( getmask4( mask ) == 0x0 )
+      continue;
+
+    sse_t intermx, intermy, intermz;
+    cross4( intermx, intermy, intermz, edge2x, edge2y, edge2z, dx, dy, dz );
+
+    const sse_t u = dot4( intermx, intermy, intermz, edge1x, edge1y, edge1z 
);
+    const sse_t uoverd = mul4( rcp, u );
+    const sse_t umask = cmp4_ge( uoverd, _mm_zero );
+    mask = and4( mask, umask );
+    if ( getmask4( mask ) == 0x0 )
+      continue;
+
+    const sse_t v = dot4( intermx, intermy, intermz, edge0x, edge0y, edge0z 
);
+    const sse_t uplusv = add4( u, v );
+    const sse_t uvmask = cmp4_le( mul4( uplusv, det ), mul4( det, det ) );
+    const sse_t voverd = mul4( rcp, v );
+    const sse_t vmask = cmp4_ge( voverd, _mm_zero );
+
+    mask = and4( mask, uvmask );
+    mask = and4( mask, vmask );
+    if ( getmask4( mask ) == 0x0 )
+      continue;
+
+    rays.hitWithoutTminCheck( ray, mask, toverd,
+                              mesh->materials[ mesh->face_material[ myID ] ],
+                              this, this );
+    float *udata = &rays.getScratchpad< float >( SCRATCH_U )[ ray ];
+    float *vdata = &rays.getScratchpad< float >( SCRATCH_V )[ ray ];
+    store44( udata, mask4( mask, uoverd, load44( udata ) ) );
+    store44( vdata, mask4( mask, voverd, load44( vdata ) ) );
+
+  }
+
+  if ( ray_begin < sse_begin || ray_end > sse_end )
+  {
+    const Vector edge0 = p1 - p0;
+    const Vector edge1 = p0 - p2;
+    const Vector normal = Cross( edge0, edge1 );
+    for ( int ray = ray_begin; ray < sse_begin; ++ray ) {
+      const Vector o = Vector( data->origin[ 0 ][ ray ],
+                               data->origin[ 1 ][ ray ],
+                               data->origin[ 2 ][ ray ] );
+      const float oldt = data->minT[ ray ];
+      const Vector d = Vector( data->direction[ 0 ][ ray ],
+                               data->direction[ 1 ][ ray ],
+                               data->direction[ 2 ][ ray ] );
+      const float rcp = 1.0f / Dot( normal, d );
+      const Vector edge2 = p0 - o;
+      const float toverd = Dot( normal, edge2 ) * rcp;
+      if ( toverd > oldt - T_EPSILON ||
+           toverd < T_EPSILON )
+        continue;
+      const Vector interm = Cross( edge2, d );
+      const float uoverd = Dot( interm, edge1 ) * rcp;
+      if ( uoverd < 0.0f )
+        continue;
+      const float voverd = Dot( interm, edge0 ) * rcp;
+      if ( uoverd + voverd > 1.0f || voverd < 0.0f )
+        continue;
+      if ( rays.hit( ray, toverd,
+                     mesh->materials[ mesh->face_material[ myID ] ],
+                     this, this ) ) {
+        rays.getScratchpad< float >( SCRATCH_U )[ ray ] = uoverd;
+        rays.getScratchpad< float >( SCRATCH_V )[ ray ] = voverd;
+      }
+    }
+    for ( int ray = sse_end; ray < ray_end; ++ray ) {
+      const Vector o = Vector( data->origin[ 0 ][ ray ],
+                               data->origin[ 1 ][ ray ],
+                               data->origin[ 2 ][ ray ] );
+      const float oldt = data->minT[ ray ];
+      const Vector d = Vector( data->direction[ 0 ][ ray ],
+                               data->direction[ 1 ][ ray ],
+                               data->direction[ 2 ][ ray ] );
+      const float rcp = 1.0f / Dot( normal, d );
+      const Vector edge2 = p0 - o;
+      const float toverd = Dot( normal, edge2 ) * rcp;
+      if ( toverd > oldt - T_EPSILON ||
+           toverd < T_EPSILON )
+        continue;
+      const Vector interm = Cross( edge2, d );
+      const float uoverd = Dot( interm, edge1 ) * rcp;
+      if ( uoverd < 0.0f )
+        continue;
+      const float voverd = Dot( interm, edge0 ) * rcp;
+      if ( uoverd + voverd > 1.0f || voverd < 0.0f )
+        continue;
+      if ( rays.hit( ray, toverd,
+                     mesh->materials[ mesh->face_material[ myID ] ],
+                     this, this ) ) {
+        rays.getScratchpad< float >( SCRATCH_U )[ ray ] = uoverd;
+        rays.getScratchpad< float >( SCRATCH_V )[ ray ] = voverd;
+      }
+    }
+  }
+
+}
+
+#else // MANTA_SSE
+
+void KenslerShirleyTriangle::intersect( const RenderContext& context, 
RayPacket& rays ) const {
+  RayPacketData *data = rays.data;
+  const int ray_begin = rays.begin();
+  const int ray_end   = rays.end();
+  const Vector edge0 = p1 - p0;
+  const Vector edge1 = p0 - p2;
+  const Vector normal = Cross( edge0, edge1 );
+  for ( int ray = ray_begin; ray < ray_end; ++ray ) {
+    const Vector o = Vector( data->origin[ 0 ][ ray ],
+                             data->origin[ 1 ][ ray ],
+                             data->origin[ 2 ][ ray ] );
+    const float oldt = data->minT[ ray ];
+    const Vector d = Vector( data->direction[ 0 ][ ray ],
+                             data->direction[ 1 ][ ray ],
+                             data->direction[ 2 ][ ray ] );
+    const float rcp = 1.0f / Dot( normal, d );
+    const Vector edge2 = p0 - o;
+    const float toverd = Dot( normal, edge2 ) * rcp;
+    if ( toverd > oldt - T_EPSILON ||
+         toverd < T_EPSILON )
+      continue;
+    const Vector interm = Cross( edge2, d );
+    const float uoverd = Dot( interm, edge1 ) * rcp;
+    if ( uoverd < 0.0f )
+      continue;
+    const float voverd = Dot( interm, edge0 ) * rcp;
+    if ( uoverd + voverd > 1.0f || voverd < 0.0f )
+      continue;
+    if ( rays.hit( ray, toverd,
+                   mesh->materials[ mesh->face_material[ myID ] ],
+                   this, this ) ) {
+      rays.getScratchpad< float >( SCRATCH_U )[ ray ] = uoverd;
+      rays.getScratchpad< float >( SCRATCH_V )[ ray ] = voverd;
+    }
+  }
+}
+
+#endif // MANTA_SSE
+
+void KenslerShirleyTriangle::computeNormal(const RenderContext& context, 
RayPacket &rays) const
+{
+  if (mesh->hasVertexNormals()) {
+    for(int ray=rays.begin(); ray<rays.end(); ray++) {
+      const float a = rays.getScratchpad<float>(SCRATCH_U)[ray];
+      const float b = rays.getScratchpad<float>(SCRATCH_V)[ray];
+      const float c = (1.0 - a - b);
+      const Vector &n0 = mesh->vertexNormals[mesh->normal_indices[myID*3+0]];
+      const Vector &n1 = mesh->vertexNormals[mesh->normal_indices[myID*3+1]];
+      const Vector &n2 = mesh->vertexNormals[mesh->normal_indices[myID*3+2]];
+      const Vector normal = (n1*a) + (n2*b) + (n0*c);
+      rays.setNormal(ray, normal);
+    }
+  } else {
+    const Vector edge0 = p1 - p0;
+    const Vector edge1 = p2 - p0;
+    const Vector normal = Cross(edge0, edge1);
+    for(int ray=rays.begin(); ray<rays.end(); ray++)
+      rays.setNormal(ray, normal);
+  }
+}
+
+Vector KenslerShirleyTriangle::getVertex(unsigned int which)
+{
+  ASSERT(which < 3);
+  const unsigned int index = myID*3;
+  return mesh->vertices[mesh->vertex_indices[index+which]];
+}

Added: trunk/Model/Primitives/KenslerShirleyTriangle.h
==============================================================================
--- (empty file)
+++ trunk/Model/Primitives/KenslerShirleyTriangle.h     Wed Aug 29 14:44:14 
2007
@@ -0,0 +1,65 @@
+#ifndef Manta_Model_KenslerShirleyTriangle_h
+#define Manta_Model_KenslerShirleyTriangle_h
+
+#include <Interface/MeshTriangle.h>
+#include <Interface/RayPacket.h>
+#include <Core/Geometry/Vector.h>
+#include <Core/Geometry/Ray.h>
+#include <Core/Geometry/BBox.h>
+#include <Model/Groups/Mesh.h>
+
+namespace Manta
+{
+  class KenslerShirleyTriangle : public MeshTriangle, public TexCoordMapper
+  {
+  public:
+
+    // Scratch pad structure for KenslerShirley Triangle.
+    enum {
+      SCRATCH_U = 0,
+      SCRATCH_V,
+      SCRATCH_LAST // Dependent classes may use this identifier to
+                   // avoid conflicts.
+    };
+
+    KenslerShirleyTriangle();
+    KenslerShirleyTriangle(Mesh *mesh, unsigned int id);
+
+    void attachMesh(Mesh *mesh);
+    void attachMesh(Mesh *mesh, unsigned int id);
+
+    void update();
+
+    virtual KenslerShirleyTriangle* clone(CloneDepth depth, Clonable* 
incoming=NULL);
+    virtual InterpErr serialInterpolate(const std::vector<keyframe_t> 
&keyframes);
+
+    void computeBounds(const PreprocessContext& context,
+                       BBox& bbox) const;
+
+    virtual void preprocess(const PreprocessContext& context);
+
+    virtual void setTexCoordMapper(const TexCoordMapper* new_tex) {
+      //we always use ourselves as the TexCoordMapper
+    }
+    virtual void computeTexCoords2(const RenderContext&, RayPacket& rays) 
const;
+    virtual void computeTexCoords3(const RenderContext& context, RayPacket& 
rays) const {
+      computeTexCoords2(context, rays);
+    }
+
+    void intersect(const RenderContext& context, RayPacket& rays) const;
+
+    void computeNormal(const RenderContext& context, RayPacket &rays) const;
+
+    //which is 0, 1, or 2.
+    Vector getVertex(unsigned int which);
+
+  protected:
+
+    Vector p0, p1, p2;
+
+    unsigned int myID;
+    Mesh *mesh;
+  };
+}
+
+#endif




  • [Manta] r1687 - trunk/Model/Primitives, aek, 08/29/2007

Archive powered by MHonArc 2.6.16.

Top of page