Text archives Help
- 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.