Text archives Help
- From: roni@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [Manta] r2228 - trunk/Engine/Renderers
- Date: Sun, 27 Apr 2008 20:56:08 -0600 (MDT)
Author: roni
Date: Sun Apr 27 20:56:07 2008
New Revision: 2228
Modified:
trunk/Engine/Renderers/NPREdges.cc
trunk/Engine/Renderers/NPREdges.h
Log:
Replaced square stencil with circular stencil; detecting lines now
works better for not axis-aligned lines.
Changed "quality" parameter (-N) to refer to how dense the stencil is.
Default is N=1; N=2 gives better quality, and N=3 seems to hit
diminishing returns.
Modified: trunk/Engine/Renderers/NPREdges.cc
==============================================================================
--- trunk/Engine/Renderers/NPREdges.cc (original)
+++ trunk/Engine/Renderers/NPREdges.cc Sun Apr 27 20:56:07 2008
@@ -30,7 +30,7 @@
lineWidth(2.0), normalThreshold(0.0),
computeCreases(true),
noshade(false),
- N(2)
+ N(1)
{
bool threshold_set = false;
@@ -65,6 +65,17 @@
if(!threshold_set)
this->setNormalThreshold(0.1);
+
+ // M is one more than the square root of the number of total
+ // samples (the "middle" sample should be omitted).
+ M = 1+2*N;
+ stencil_size = M*M-1;
+
+ // last_ring is the stencil index of the first element of the final
+ // ring of stencil rays. This is used to compute the stencil
+ // indices of the rays to be used for the normal gradient
+ // computation.
+ last_ring = (2*N-1)*(2*N-1) - 1;
}
NPREdges::~NPREdges()
@@ -125,46 +136,17 @@
// Create parallel ray packets, each containing one member of a
// "surround" for each ray in the rays parameter.
- RayPacketData *stencil_data = MANTA_STACK_ALLOC(RayPacketData, N*N);
- RayPacket *stencil = MANTA_STACK_ALLOC(RayPacket, N*N);
-
- // Each ray in each stencil raypacket is at a constant offset from
- // the rays in the sample raypacket, so they can inherit the shape
- // flag.
- for(int i=0; i<N*N; i++){
- new (stencil_data+i)RayPacketData;
- new (stencil+i)RayPacket(stencil_data[i], rays.shape, rays.begin(),
rays.end(), rays.getDepth(), RayPacket::HaveImageCoordinates);
- }
-
- // Populate the surround packets' image coordinates.
- for(int i=rays.begin(); i<rays.end(); i++){
- int eye = rays.getWhichEye(i);
-
- // (low_x, low_y) is the bottom left of a box of size (imageX,
- // imageY), with the sample ray intersecting it in the center.
- const Real inc_x = imageX / N;
- const Real inc_y = imageY / N;
- const Real low_x = rays.getImageCoordinates(i, 0) - 0.5*imageX +
0.5*inc_x;
- const Real low_y = rays.getImageCoordinates(i, 1) - 0.5*imageY +
0.5*inc_y;
-
- if(debugFlag){
- std::cout << "sample ray: (" << rays.getImageCoordinates(i, 0) << ", "
<< rays.getImageCoordinates(i, 1) << ")" << std::endl;
- }
+ RayPacketData *stencil_data = 0;
+ RayPacket *stencil = 0;
- for(int j=0; j<N; j++){
- const Real ypos = low_y + j*inc_y;
- for(int k=0; k<N; k++){
- stencil[j*N+k].setPixel(i, eye, low_x + k*inc_x, ypos);
+ stencil_data = MANTA_STACK_ALLOC(RayPacketData, stencil_size);
+ stencil = MANTA_STACK_ALLOC(RayPacket, stencil_size);
+
+ // Compute the stencil locations.
+ computeCircleStencil(stencil, stencil_data, rays);
- if(debugFlag){
- std::cout << "stencil ray (" << j << ", " << k << "): (" << (low_x
+ k*inc_x) << ", " << ypos << ")" << std::endl;
- }
- }
- }
- }
-
- // Generate camera rays for the surround and trace them.
- for(int i=0; i<N*N; i++){
+ // Generate camera rays for the stencil and trace them.
+ for(int i=0; i<stencil_size; i++){
context.camera->makeRays(context, stencil[i]);
stencil[i].resetHits();
context.scene->getObject()->intersect(context, stencil[i]);
@@ -181,7 +163,7 @@
if(debugFlag)
cerr << "count was " << count << endl;
- float lightness = Abs(count - N*N/2.0) / (N*N/2.0);
+ float lightness = Abs(count - stencil_size/2.0) / (stencil_size/2.0);
rays.setColor(i, rays.getColor(i)*lightness);
++i;
@@ -219,10 +201,10 @@
// the case but need to make sure.
//
// Check for crease line.
- RayPacket normRight(stencil[N-1], i, j);
- RayPacket normLeft(stencil[N*(N-1)], i, j);
- RayPacket normUp(stencil[N*N-1], i, j);
- RayPacket normDown(stencil[0], i, j);
+ RayPacket normRight(stencil[last_ring + 0], i, j);
+ RayPacket normUp(stencil[last_ring + 2*N], i, j);
+ RayPacket normLeft(stencil[last_ring + 4*N], i, j);
+ RayPacket normDown(stencil[last_ring + 6*N], i, j);
normRight.computeFFNormals(context);
normLeft.computeFFNormals(context);
@@ -268,13 +250,13 @@
if(sample.wasHit(i)){
// The sample ray hit a primitive; check if this is an intersection
sample.
const Primitive *hit = sample.getHitPrimitive(i);
- for(int j=0; j<N*N; j++)
+ for(int j=0; j<stencil_size; j++)
if(!(stencil[j].wasHit(i) && (stencil[j].getHitPrimitive(i) == hit)))
return Intersection;
}
else{
// The sample ray struck the background; check if this is an
intersection sample.
- for(int j=0; j<N*N; j++)
+ for(int j=0; j<stencil_size; j++)
if(stencil[j].wasHit(i))
return Intersection;
@@ -294,10 +276,21 @@
// The sample ray hit a primitive; check if this is an intersection
sample.
count = 0;
const Primitive *hit = sample.getHitPrimitive(i);
- for(int j=0; j<N*N; j++)
+
+ if(debugFlag){
+ std::cout << "hit = " << hit << std::endl;
+ }
+
+ for(int j=0; j<stencil_size; j++)
if(!(stencil[j].wasHit(i) && (stencil[j].getHitPrimitive(i) == hit))){
+ if(debugFlag){
+ std::cout << "stencil[" << j << "] off (" <<
stencil[j].getHitPrimitive(i) << ")" << std::endl;
+ }
++count;
}
+ else if(debugFlag){
+ std::cout << "stencil[" << j << "] on" << std::endl;
+ }
if(debugFlag)
std::cout << "count = " << count << std::endl;
@@ -308,9 +301,16 @@
else{
// The sample ray struck the background; check if this is an
intersection sample.
count = 0;
- for(int j=0; j<N*N; j++)
- if(stencil[j].wasHit(i))
+ for(int j=0; j<stencil_size; j++)
+ if(stencil[j].wasHit(i)){
+ if(debugFlag){
+ std::cout << "stencil[" << j << "] struck " <<
stencil[j].getHitPrimitive(i) << std::endl;
+ }
++count;
+ }
+ else if(debugFlag){
+ std::cout << "stencil[" << j << "] struck background" << std::endl;
+ }
if(count > 0)
return Intersection;
@@ -346,4 +346,51 @@
void NPREdges::setNormalThreshold(Real val){
normalThreshold = val*val*lineWidth*lineWidth;
+}
+
+void NPREdges::computeCircleStencil(RayPacket *stencil, RayPacketData
*stencil_data, const RayPacket& rays) const {
+ static Real *x = 0, *y = 0;
+ if(!x){
+ // TODO(choudhury): x and y should be data members so they can be
+ // delete'ed at destruction time.
+ x = new Real[stencil_size];
+ y = new Real[stencil_size];
+
+#ifndef NDEBUG
+ std::cout << "Stencil ray positions:" << std::endl;
+#endif
+
+ int j=0;
+ for(int r=1; r<=N; r++){
+ const int ringsize = 8*r;
+ const int start = j;
+ const int end = j+ringsize;
+
+ const float angle_inc = 2*M_PI/(ringsize);
+ const float radius = r*imageX*0.5 / N;
+
+ for(; j<end; j++){
+ x[j] = radius*cos(angle_inc*(j-start));
+ y[j] = radius*sin(angle_inc*(j-start));
+
+#ifndef NDEBUG
+ std::cout << x[j] << " " << y[j] << std::endl;
+#endif
+ }
+ }
+ }
+
+ for(int i=0; i<stencil_size; i++){
+ new (stencil_data+i)RayPacketData;
+ new (stencil+i)RayPacket(stencil_data[i], rays.shape, rays.begin(),
rays.end(), rays.getDepth(), RayPacket::HaveImageCoordinates);
+ }
+
+ for(int i=rays.begin(); i<rays.end(); i++){
+ int eye = rays.getWhichEye(i);
+
+ for(int j=0; j<stencil_size; j++)
+ stencil[j].setPixel(i-rays.begin(), eye,
+ rays.getImageCoordinates(i, 0) + x[j],
+ rays.getImageCoordinates(i, 1) + y[j]);
+ }
}
Modified: trunk/Engine/Renderers/NPREdges.h
==============================================================================
--- trunk/Engine/Renderers/NPREdges.h (original)
+++ trunk/Engine/Renderers/NPREdges.h Sun Apr 27 20:56:07 2008
@@ -11,6 +11,7 @@
namespace Manta {
class Primitive;
class Raytracer;
+ class RayPacketData;
using namespace std;
@@ -32,6 +33,9 @@
void setNormalThreshold(Real val);
protected:
+ void computeCircleStencil(RayPacket *stencil, RayPacketData
*stencil_data, const RayPacket& rays) const;
+
+ protected:
typedef enum {
Background,
Shade,
@@ -49,7 +53,8 @@
Real lineWidth, normalThreshold;
bool computeCreases, noshade;
- int N;
+ int N, M, stencil_size;
+ int last_ring;
private:
NPREdges(const NPREdges&);
- [Manta] r2228 - trunk/Engine/Renderers, roni, 04/27/2008
Archive powered by MHonArc 2.6.16.