Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r1069 - in trunk: Core/Color Engine/Control Model/Materials Model/Textures scenes


Chronological Thread 
  • 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.

Top of page