Text archives Help
- From: cgribble@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r1069 - in trunk: Core/Color Engine/Control Model/Materials Model/Textures scenes
- Date: Wed, 17 May 2006 14:27:14 -0600 (MDT)
Author: cgribble
Date: Wed May 17 14:27:13 2006
New Revision: 1069
Modified:
trunk/Core/Color/ColorSpace.h
trunk/Core/Color/GrayTraits.h
trunk/Engine/Control/DynPLTWorker.cc
trunk/Engine/Control/DynPLTWorker.h
trunk/Model/Materials/DynPLTMaterial.cc
trunk/Model/Textures/DynPLT.cc
trunk/Model/Textures/DynPLT.h
trunk/scenes/dynplt.cc
Log:
Core/Color/GrayTraits.h
Core/Color/ColorSpace.h
Fixed two minor bugs
Model/Materials/DynPLTMaterial.cc
Changed queue->send(...) to queue->trySend(...) in order not to block the
rendering threads when the queue is full
Fleshed out code for using the DynPLTs during shading
Model/Textures/DynPLT.cc
Model/Textures/DynPLT.h
Engine/Control/DynPLTWorker.cc
Engine/Control/DynPLTWorker.h
scenes/dynplt.cc
Implemented the main loop of the texture generation threads; there are a few
issues, but it's mostly working (as in it doesn't crash)
Modified: trunk/Core/Color/ColorSpace.h
==============================================================================
--- trunk/Core/Color/ColorSpace.h (original)
+++ trunk/Core/Color/ColorSpace.h Wed May 17 14:27:13 2006
@@ -22,7 +22,7 @@
ColorSpace(const ColorSpace<Traits>& copy)
{
- for(int i=0;i<3;i++)
+ for(int i=0;i<NumComponents;i++)
data[i]=copy.data[i];
}
#ifndef SWIG
Modified: trunk/Core/Color/GrayTraits.h
==============================================================================
--- trunk/Core/Color/GrayTraits.h (original)
+++ trunk/Core/Color/GrayTraits.h Wed May 17 14:27:13 2006
@@ -16,7 +16,7 @@
data = gray.grayValue();
}
- template <class C> static void convertFrom(ComponentType data[3],
+ template <class C> static void convertFrom(ComponentType data,
const C& color) {
GrayColor gray;
convertColor(gray, color);
Modified: trunk/Engine/Control/DynPLTWorker.cc
==============================================================================
--- trunk/Engine/Control/DynPLTWorker.cc (original)
+++ trunk/Engine/Control/DynPLTWorker.cc Wed May 17 14:27:13 2006
@@ -1,36 +1,45 @@
+#include <Interface/Background.h>
+#include <Interface/Context.h>
+#include <Interface/Scene.h>
#include <Engine/Control/DynPLTWorker.h>
+#include <Engine/Shadows/HardShadows.h>
#include <Model/Primitives/DynPLTParticle.h>
#include <Model/Textures/DynPLT.h>
#include <SCIRun/Core/Math/MiscMath.h>
+#include <string>
+
using namespace Manta;
+using namespace std;
DynPLTContext::DynPLTContext(SCIRun::Mailbox<const DynPLTParticle*>* queue,
+ Scene* scene, unsigned int res,
unsigned int ngroups, unsigned int nsamples,
unsigned int max_depth) :
- queue(queue), ngroups(ngroups), nsamples(nsamples), max_depth(max_depth)
+ queue(queue), scene(scene), res(res), ngroups(ngroups), nsamples(nsamples),
+ max_depth(max_depth)
{
- // Ensure nsamples is a perfect square
+ // Ensure that the number of samples is a perfect square
nsamples_root=static_cast<int>(SCIRun::Ceil(SCIRun::Sqrt(static_cast<Real>(nsamples))));
unsigned int squared=nsamples_root*nsamples_root;
if (squared != nsamples)
nsamples=squared;
}
-DynPLTWorker::DynPLTWorker(DynPLTContext* dynplt_ctx, unsigned int id) :
- dynplt_ctx(dynplt_ctx), id(id)
+DynPLTWorker::DynPLTWorker(const DynPLTContext* context, unsigned int id) :
+ context(context), id(id)
{
// Seed the random number generator
rng.seed_rng(100 + id);
// Generate groups of random 2D sample points
- sample_groups.resize(dynplt_ctx->ngroups);
- for (unsigned int i=0; i<dynplt_ctx->ngroups; ++i) {
- sample_groups[i].resize(dynplt_ctx->nsamples);
+ sample_groups.resize(context->ngroups);
+ for (unsigned int i=0; i<context->ngroups; ++i) {
+ sample_groups[i].resize(context->nsamples);
// Generate random (u, v) offsets into the texel
unsigned int idx=0;
- unsigned int nsamples_root=dynplt_ctx->nsamples_root;
+ unsigned int nsamples_root=context->nsamples_root;
Real delta=1/static_cast<Real>(nsamples_root);
Real u=0;
for (unsigned int j=0; j<nsamples_root; ++j) {
@@ -45,7 +54,7 @@
}
// Shuffle the sample points
- unsigned int nsamples=dynplt_ctx->nsamples;
+ unsigned int nsamples=context->nsamples;
unsigned int max_idx=nsamples - 1;
for (unsigned int j=0; j<nsamples; ++j) {
unsigned int target=static_cast<unsigned int>(max_idx*rng.gendrand());
@@ -54,14 +63,18 @@
sample_groups[i][target]=tmp;
}
}
+
+ // Allocate sample group indices for picking a group of sample points on
the
+ // hemisphere at each depth
+ hidx=new int[context->max_depth];
}
DynPLTWorker::~DynPLTWorker(void)
{
- // Do nothing
+ delete [] hidx;
}
-#define TEMPORARY 1
+// #define TEMPORARY 1
#if TEMPORARY
#include <iostream>
#include <unistd.h>
@@ -69,74 +82,238 @@
void DynPLTWorker::run(void)
{
+ // Create a render context
+ Scene* scene=context->scene;
+ vector<string> args;
+ HardShadows shadowAlgorithm(args);
+ // RenderContext(MantaInterface*, int, int, int, const FrameState*,
+ // LoadBalancer*, PixelSampler*, Renderer*, ShadowAlgorithm*,
+ // const Camera*, const Scene*, ThreadStorage*);
+ RenderContext rctx(0, 0, 0, 0, 0, 0, 0, 0, &shadowAlgorithm, 0, scene, 0);
+
const DynPLTParticle* particle;
- while (particle=dynplt_ctx->queue->receive()) {
+ while (particle=context->queue->receive()) {
+#if TEMPORARY
+ cerr<<"DynPLTWorker["<<id<<"]::run - "<<context->queue->numItems()
+ <<" left in queue\n";
+#endif
+
if (particle->valid)
continue;
-#if TEMPORARY
- unsigned int time=static_cast<unsigned int>(5*rng.gendrand());
- std::cerr<<"DynPLTWorker["<<id<<"]::run - sleeping for "<<time<<"
seconds\n";
+#if 0
+ unsigned int time=static_cast<unsigned int>(3*rng.gendrand());
+ cerr<<"DynPLTWorker["<<id<<"]::run - sleeping for "<<time<<" seconds\n";
sleep(time);
#endif
- // Render particle's texture
- // DynPLT* texture=new DynPLT();
+ // Grab useful information from the DynPLT context
+ unsigned int res=context->res;
+ unsigned int ngroups=context->ngroups;
+ unsigned int nsamples=context->nsamples;
+ unsigned int max_depth=context->max_depth;
+ Real inv_res=1/static_cast<Real>(res);
+ Real inv_nsamples=1/static_cast<Real>(nsamples);
+ // Generate particle's texture
Vector center=particle->getCenter();
Real radius=particle->getRadius();
#if TEMPORARY
- std::cerr<<"DynPLTWorker["<<id<<"]::run - particle(<"<<center<<">,
"<<radius
- <<")\n";
+ cerr<<"DynPLTWorker["<<id<<"]::run - particle(<"<<center<<">, "<<radius
+ <<")\n";
+#endif
+
+ DynPLT* texture=new DynPLT(res);
+ for (unsigned int v=0; v<res; ++v) {
+ for (unsigned int u=0; u<res; ++u) {
+ // Pick a random sample group for surface points
+ unsigned int sidx=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ // Pick random sample groups for points on the hemisphere at each
depth
+ for (int d=0; d<=max_depth; ++d)
+ hidx[d]=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ for (unsigned int s=0; s<nsamples; s += RayPacket::MaxSize) {
+ // Initialize a ray packet
+ int size=RayPacket::MaxSize;
+ if (size >= nsamples - s) {
+ // Number of samples/texel isn't large enough to fill a ray
packet,
+ // so set the size of the ray packet to the number of samples
that
+ // remain
+ size=nsamples - s;
+ }
+
+ int depth=0;
+ int flags=RayPacket::NormalizedDirections;
+
+ RayPacketData raydata;
+ RayPacket rays(raydata, RayPacket::UnknownShape, 0, size, depth,
+ flags);
+
+ // Fill in the ray origins, surface normals at sample points
+ for (int i=rays.begin(); i<rays.end(); ++i) {
+ // Project surface sample point onto particle's surface
+ Vector2D surface=sample_groups[sidx][i];
+
+ // Range of 2*M_PI*(u + surface.x)/res --> [0, 2*Pi]
+ // Range of M_PI*(v + surface.y)/res --> [0, Pi]
+ Real phi=2*M_PI*((u + surface.x()))*inv_res;
+ Real theta=M_PI*((v + surface.y()))*inv_res;
+
+ Real x=cos(phi)*sin(theta);
+ Real z=sin(phi)*sin(theta);
+ Real y=cos(theta);
+
+ rays.setOrigin(i, center + radius*Vector(x, y, z));
+ normals.set(i, Vector(x, y, z).normal());
+ }
+
+ // Iteratively trace the ray packet
+ GrayValue result;
+ for (unsigned int d=0; d<max_depth; ++d) {
+ // Compute direct lighting at sample points
+ ShadowAlgorithm::StateBuffer stateBuffer;
+ bool firstTime=true;
+ bool done;
+ int count=0;
+ do {
+ RayPacketData shadowData;
+ RayPacket shadowRays(shadowData, RayPacket::UnknownShape, 0, 0,
+ rays.getDepth(), 0);
+
+ // Call the shadow algorithm (SA) to generate shadow rays. We
+ // may not be able to compute all of them, so we pass along a
+ // buffer for the SA object to store it's state. The firstTime
+ // flag tells the SA to fill in the state rather than using
+ // anything in the state buffer. Most SAs will only need to
+ // store an int or two in the statebuffer.
+ const LightSet* activeLights=scene->getLights();
+#if 0
+ // XXX: causes segfaults, undoubtedly related to the (nearly
+ // empty) RenderContext
+ done=rctx.shadowAlgorithm->computeShadows(rctx, activeLights,
+ rays, shadowRays,
+ firstTime,
+ stateBuffer);
+#else
+ done=true;
#endif
+
+ // Normalize directions for proper dot product computation
+ shadowRays.normalizeDirections();
+
+ for (int i=shadowRays.begin(); i<shadowRays.end(); ++i) {
+ if (!shadowRays.wasHit(i)) {
+ // Not in shadow, so compute the diffuse contribution
+ Vector normal=normals.get(i);
+ Vector shadowdir=shadowRays.getDirection(i);
+ ColorComponent cos_theta=Dot(shadowdir, normal);
+ Color light=shadowRays.getColor(i);
+ // result += light.luminance()*cos_theta;
+ }
+ }
+
+ firstTime=false;
+ } while(!done);
+
+ // Fill in the ray directions by generating random directions on
the
+ // hemisphere
+ for (int i=rays.begin(); i<rays.end(); ++i) {
+ Vector normal=normals.get(i);
+ Vector v0(Cross(normal, Vector(1,0,0)));
+ if (v0.length2()==0)
+ v0=Cross(normal, Vector(0,1,0));
+ Vector v1=Cross(normal, v0);
+ v0.normalize();
+ v1.normalize();
+
+ Vector2D hemi=sample_groups[hidx[d]][i];
+ Real hphi=2.0*M_PI*hemi.x();
+ Real r=SCIRun::Sqrt(hemi.y());
+ Real hx=r*cos(hphi);
+ Real hy=r*sin(hphi);
+ Real hz=SCIRun::Sqrt(1 - hx*hx - hy*hy);
+
+ Vector out=Vector(hx, hy, hz).normal();
+ Vector dir=v0*out.x() + v1*out.y() + normal*out.z();
+ dir.normalize();
+
+ rays.setDirection(i, dir);
+ }
+
+ // Intersect rays with the geometry
+ rays.resetHits();
+ scene->getObject()->intersect(rctx, rays);
+
+ // Compute hit positions and normals
+ rays.computeHitPositions();
+ // XXX: causes segfaults, undoubtedly related to the (nearly
+ // empty) RenderContext
+ // rays.computeNormals(rctx);
+
+ // Fill in the ray origins, surface normals for next iteration
+ unsigned int validRays=0;
+ for (unsigned int i=rays.begin(); i<rays.end();) {
+ if (rays.wasHit(i)) {
+ // Check for a valid hit
+ Real dotprod=Dot(rays.getNormal(i), -rays.getDirection(i));
+ if (dotprod>0) {
+ normals.set(validRays, rays.getNormal(i));
+ rays.setOrigin(validRays, rays.getHitPosition(i));
+ ++validRays;
+ } else {
+ // An invalid hit, resulting from:
+ //
+ // 1. Intersecting spheres---Ray origin is inside of one
+ // sphere and it hits the inside surface of the other
+ //
+ // 2. Ray origin is coincident with the surface of a
+ // neighboring sphere---May result in some crazy
math,
+ // and thus a negative dot product
+ //
+ // Either way, ignore the hit and mark the texel for
dilation
+ // inside(u, v) += 1;
+ }
+
+ ++i;
+ } else {
+ // Find a run of rays that didn't hit anything and shade them
+ unsigned int end=i + 1;
+ while (end < rays.end() && !rays.wasHit(end))
+ ++end;
+ RayPacket subPacket(rays, i, end);
+ scene->getBackground()->shade(rctx, subPacket);
+
+ // Accumulate background color
+ for (unsigned int j=i; j<end; ++j)
+ // result += rays.getColor(j).luminance();
+ ;
+
+ i=end;
+ }
+ }
+
+ // Terminate ray tracing, if necessary
+ if (validRays==0)
+ break;
+
+ // Resize the ray packet, loop to next depth
+ rays.resize(validRays);
+ }
+
+ // Store the result
+ // texture(u, v) += result;
+ }
+
+ // Normalize the texel
+ // texture(u, v) *= inv_nsamples;
+ }
+ }
- // for each texel
- // for each sample in texel
- // Vector2D point=sample_groups[texel][sample];
- // Project sample point onto particle's surface
- /*
- // Range of 2*M_PI*(u + point.x)/width --> [0, 2*Pi]
- Real phi=2*M_PI*((u + point.x()))*inv_width;
-
- // Range of M_PI*(v + point.y)/height -->[0, Pi]
- Real theta=M_PI*((v + point.y()))*inv_height;
-
- Real x=cos(phi)*sin(theta);
- Real z=sin(phi)*sin(theta);
- Real y=cos(theta);
-
- Vector origin=center + radius*Vector(x, y, z);
- Vector normal=Vector(x, y, z).normal();
- */
- // XXX: how to handle this with ray packets?
- // for (depth=0; depth<max_depth; ++depth)
- // compte direct lighting at origin
- // dir = generate random cosine-weighted direction on the
hemisphere
- // dir.normalize();
- // Ray ray(origin, dir);
- // trace ray into geometry
- // if intersect
- // set origin = ray.origin() + hit.min_t*ray.direction();
- // set normal = hit.hit_prim->normal(origin);
- // set dotprod = dot(normal, -ray.direction());
- // if (dotprod < 0)
- // either inside another sphere or point is coincident with
another
- // sphere: inside(u, v) += 1;
- // break;
- // else
- // accumulate bg color
- // end loop over depth
- //
- // store result: texture(u, v) += result;
- // end loop over samples
- //
- // normalize result: texture(u, v) *= inv_num_samples
- // end loop over texels
- //
- // if (dilate)
- // texture->dilate();
+ if (context->dilate)
+ texture->dilate(context);
particle->valid=true;
- // particle->plt=texture;
+ particle->plt=texture;
}
}
Modified: trunk/Engine/Control/DynPLTWorker.h
==============================================================================
--- trunk/Engine/Control/DynPLTWorker.h (original)
+++ trunk/Engine/Control/DynPLTWorker.h Wed May 17 14:27:13 2006
@@ -4,6 +4,7 @@
#include <Core/Math/MT_RNG.h>
#include <Core/Math/vector2d.h>
+#include <Interface/Packet.h>
#include <SCIRun/Core/Containers/Array1.h>
#include <SCIRun/Core/Containers/Array2.h>
#include <SCIRun/Core/Thread/Mailbox.h>
@@ -12,19 +13,25 @@
namespace Manta
{
class DynPLTParticle;
+ class RayPacket;
+ class Scene;
class DynPLTContext
{
public:
- DynPLTContext(SCIRun::Mailbox<const DynPLTParticle*>* queue,
- unsigned int ngroups, unsigned int nsamples,
+ DynPLTContext(SCIRun::Mailbox<const DynPLTParticle*>* queue, Scene*
scene,
+ unsigned int res, unsigned int ngroups, unsigned int
nsamples,
unsigned int max_depth);
~DynPLTContext(void) { }
// DynPLT work queue
SCIRun::Mailbox<const DynPLTParticle*>* queue;
+ // Manta scene
+ Scene* scene;
+
// Texture generation parameters
+ unsigned int res;
unsigned int ngroups;
unsigned int nsamples;
unsigned int nsamples_root;
@@ -40,16 +47,18 @@
class DynPLTWorker : public SCIRun::Runnable
{
public:
- DynPLTWorker(DynPLTContext* dynplt_ctx, unsigned int id);
+ DynPLTWorker(const DynPLTContext* context, unsigned int id);
virtual ~DynPLTWorker(void);
virtual void run(void);
private:
- DynPLTContext* dynplt_ctx;
+ const DynPLTContext* context;
unsigned int id;
MT_RNG rng;
SCIRun::Array1<SCIRun::Array1<Vector2D> > sample_groups;
+ int* hidx;
+ Packet<Vector> normals;
};
}
Modified: trunk/Model/Materials/DynPLTMaterial.cc
==============================================================================
--- trunk/Model/Materials/DynPLTMaterial.cc (original)
+++ trunk/Model/Materials/DynPLTMaterial.cc Wed May 17 14:27:13 2006
@@ -51,21 +51,26 @@
__FILE__, __LINE__);
if (particle->valid) {
- // Particle's texture is valid
#if 0
+ // Compute diffuse colors
+ Packet<Color> diffuse;
+ colortex->mapValues(diffuse, context, subPacket);
+
+ // Compute textured luminance
Packet<GrayValue> luminance;
- texture->mapValues(luminance, context, subPacket);
+ particle->plt->mapValues(luminance, context, subPacket);
+
for (int j=subPacket.begin(); j<subPacket.end(); ++j)
- rays.setColor(j, Color(luminance[j])));
+ rays.setColor(j, luminance[j]*diffuse[j]);
#else
for (int j=subPacket.begin(); j<subPacket.end(); ++j)
rays.setColor(j, Color(RGB(1, 0, 0)));
#endif
} else {
- // Particle's texture is invalid
+ // Request texture generation, if necessary
if (!particle->requested) {
- particle->requested=true;
- queue->send(particle);
+ if (queue->trySend(particle))
+ particle->requested=true;
}
// Use Lambertian shading while texture is invalid
Modified: trunk/Model/Textures/DynPLT.cc
==============================================================================
--- trunk/Model/Textures/DynPLT.cc (original)
+++ trunk/Model/Textures/DynPLT.cc Wed May 17 14:27:13 2006
@@ -4,7 +4,7 @@
using namespace Manta;
DynPLT::DynPLT(unsigned int res) :
- texture(res, res), inside(res, res)
+ res(res), texture(res, res), inside(res, res)
{
texture.setUEdgeBehavior(ImageTexture<GrayValue>::Wrap);
texture.setVEdgeBehavior(ImageTexture<GrayValue>::Wrap);
@@ -15,7 +15,7 @@
inside.setInterpolationMethod(ImageTexture<GrayValue>::Bilinear);
}
-void dilate(void)
+void DynPLT::dilate(const DynPLTContext* context)
{
// Do nothing
}
Modified: trunk/Model/Textures/DynPLT.h
==============================================================================
--- trunk/Model/Textures/DynPLT.h (original)
+++ trunk/Model/Textures/DynPLT.h Wed May 17 14:27:13 2006
@@ -6,10 +6,14 @@
#include <Model/Textures/ImageTexture.h>
namespace Manta {
+ class DynPLTContext;
+
class DynPLT
{
public:
- DynPLT(unsigned int res=16);
+ DynPLT(unsigned int res);
+
+ void dilate(const DynPLTContext* context);
void mapValues(Packet<GrayValue>& results, const RenderContext& context,
RayPacket& rays) const
@@ -17,9 +21,8 @@
texture.mapValues(results, context, rays);
}
- void dilate(void);
-
private:
+ unsigned int res;
ImageTexture<GrayValue> texture;
ImageTexture<GrayValue> inside;
};
Modified: trunk/scenes/dynplt.cc
==============================================================================
--- trunk/scenes/dynplt.cc (original)
+++ trunk/scenes/dynplt.cc Wed May 17 14:27:13 2006
@@ -20,6 +20,8 @@
#include <iostream>
#include <sgi_stl_warnings_on.h>
+#define RENDER_THREAD_STACKSIZE 8*1024*1024
+
using namespace Manta;
using namespace SCIRun;
using namespace std;
@@ -67,25 +69,29 @@
if (!world)
world=new Group();
+ // Create a scene
+ Scene* scene=new Scene();
+
// Create DynPLT work queue
unsigned int size=100; // XXX: this should be a cmdln parameter
Mailbox<const DynPLTParticle*>* queue=new Mailbox<const
DynPLTParticle*>("DynPLT Work Queue", size);
// Create DynPLTContext
+ unsigned int res=16; // XXX: this should be a cmdln parameter
unsigned int ngroups=100; // XXX: this should be a cmdln parameter
unsigned int nsamples=49; // XXX: this should be a cmdln parameter
unsigned int max_depth=3; // XXX: this should be a cmdln parameter
- DynPLTContext*dynplt_ctx=new DynPLTContext(queue, ngroups, nsamples,
- max_depth);
+ DynPLTContext* dpltctx=new DynPLTContext(queue, scene, res, ngroups,
nsamples,
+ max_depth);
// Create DynPLTWorker threads
// workers.resize(nthreads);
for (unsigned int i=0; i<nthreads; ++i) {
ostringstream name;
name<<"DynPLT Worker "<<i;
- Thread* thread=new Thread(new DynPLTWorker(dynplt_ctx, i),
+ Thread* thread=new Thread(new DynPLTWorker(dpltctx, i),
name.str().c_str(), 0, Thread::NotActivated);
- // thread->setStackSize(RENDER_THREAD_STACKSIZE);
+ thread->setStackSize(RENDER_THREAD_STACKSIZE);
thread->activate(false);
// workers[i]=thread;
}
@@ -106,8 +112,7 @@
world->add(new DynPLTParticle(dynplt, Vector(x, y, z), radius));
}
- // Create scene
- Scene* scene=new Scene();
+ // Initialize the scene
scene->setBackground(new ConstantBackground(Color(RGB(0, 0, 0))));
scene->setObject(world);
- [MANTA] r1069 - in trunk: Core/Color Engine/Control Model/Materials Model/Textures scenes, cgribble, 05/17/2006
Archive powered by MHonArc 2.6.16.