Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r1178 - in trunk: Core/Math Engine/Control Interface Model/Cameras UserInterface scenes


Chronological Thread 
  • From: cgribble@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r1178 - in trunk: Core/Math Engine/Control Interface Model/Cameras UserInterface scenes
  • Date: Tue, 15 Aug 2006 11:24:53 -0600 (MDT)

Author: cgribble
Date: Tue Aug 15 11:24:48 2006
New Revision: 1178

Added:
   trunk/Core/Math/Spline.h
   trunk/Interface/CameraPath.cc
   trunk/Interface/CameraPath.h
Modified:
   trunk/Engine/Control/RTRT.cc
   trunk/Engine/Control/RTRT.h
   trunk/Interface/CMakeLists.txt
   trunk/Interface/Camera.h
   trunk/Interface/MantaInterface.h
   trunk/Model/Cameras/PinholeCamera.cc
   trunk/Model/Cameras/PinholeCamera.h
   trunk/UserInterface/XWindowUI.cc
   trunk/UserInterface/XWindowUI.h
   trunk/scenes/dynlt.cc
Log:
Added a naive camera path implementation for XWindowUI.  Uses cubic cardinal
splines for path interpolation (with a default tension of 0.5 --> Catmull-Rom
spline).  Under the XWindowUI, press 'k' to add a knot to the path, and 'K' to
write the current set of knots to a file (defaults to "out.path").  Example 
code
showing how to create the CameraPath object is in dynlt.cc scene (see -opath 
and
-path command line options).  If the path is specified using -opath, the
CameraPath enters write mode, and will dump control points to the specified 
file.
If -path is used, the CameraPath enters read mode, and will pull control 
points
from the specified file.  The CameraPath assumes Channel Zero.

Required some tweaks to the MantaInterface and XWindowUI class.  This
functionality is, admittedly, quick and dirty but I've tried to keep it as 
clean
and well structured as possible.  Also, you don't need FOX to build and the
standard Manta camera controls apply.

Core/Math/Spline.h
Interface/CameraPath.h
Interface/CameraPath.cc
  Added implementation of classes described above

Interface/MantaInterface.h
Interface/Camera.h
Interface/CMakeLists.txt
  Added prototypes for get/set of CameraPath class to MantaInterface
  Added reset(...) to Camera class that takes a field-of-view in addition to 
the
    eye, up, and lookat parameters, with a default implementation that does
    nothing (for cameras that don't know about field-of-view)
  Added CameraPath.{h,cc} to the CMakeLists.txt
  Added Manta_Core to TARGET_LINK_LIBRARIES

Model/Cameras/PinholeCamera.cc
Model/Cameras/PinholeCamera.h
  Added implementation of new reset(...) function that takes a field-of-view

Engine/Control/RTRT.cc
Engine/Control/RTRT.h
  Added implementation of get/set for CameraPath
  Added CameraPath* data member

UserInterface/XWindowUI.cc
UserInterface/XWindowUI.h
  Added functions that respond to 'k' and 'K' keys for adding/writing control
    points to the CameraPath

scenes/dynlt.cc
  Added command line flags for -path and -opath to read and write camera paths


Added: trunk/Core/Math/Spline.h
==============================================================================
--- (empty file)
+++ trunk/Core/Math/Spline.h    Tue Aug 15 11:24:48 2006
@@ -0,0 +1,94 @@
+
+#ifndef Manta_DynLT_Spline_h
+#define Manta_DynLT_Spline_h
+
+#include <MantaTypes.h>
+
+#include <map>
+
+namespace Manta
+{
+  // Shamelessly borrowed from MacGuyver souce code (cs7960, Fall 2006)
+  //
+  // Cubic cardinal spline.  This is a subset of piece-wise cubic
+  // Hermite splines where the tangent vectors are implicitly
+  // calculated from the difference between the neighboring knots.
+  // The tension value scales these tangents.  A tension of zero
+  // causes the curve to go straight between each knot, while higher
+  // values cause smoother interpolation.  A tension of 0.5 produces
+  // the Catmull-Rom spline.  To smooth out the time differences, the
+  // tangent adjustment described by Kochanek and Bartels is used.
+
+  template<typename T>
+  class Spline
+  {
+  public:
+    inline Spline(Real const tension=0.5) : tension(tension) { }
+    inline ~Spline(void) { /* no-op */ }
+
+    inline void addKnot(Real const time, T const& value)
+    {
+      knots.insert(std::pair<Real, T>(time, value));
+    }
+
+    inline void reset(void)
+    {
+      knots.clear();
+    }
+
+    inline T const interpolate(Real const time) const
+    {
+      typename std::map<Real, T>::const_iterator m0, m1, m2, m3;
+
+      // Pick the knots
+      m2=knots.lower_bound(time);
+      if (m2==knots.end())
+        --m2;
+      if ((m1=m2)==knots.begin())
+        ++m2;
+      else
+        --m1;
+      m3=m2;
+      ++m3;
+      if (m3==knots.end())
+        --m3;
+      if ((m0=m1) != knots.begin())
+        --m0;
+
+      // Compute the tangets
+      T p0=m0->second;
+      T p1=m1->second;
+      T p2=m2->second;
+      T p3=m3->second;
+      Real time0=m0->first;
+      Real time1=m1->first;
+      Real time2=m2->first;
+      Real time3=m3->first;
+      T t1=((p2 - p0)*(2.*tension*(time1 - time0)/(time2 - time0)));
+      T t2=((p3 - p1)*(2.*tension*(time3 - time2)/(time3 - time1)));
+
+      // Scale time to [0, 1]
+      Real scaled=(time - time1)/(time2 - time1);
+      Real scaled2=scaled*scaled;
+
+      // Compute the weights
+      Real w1=(2*scaled - 3.)*scaled2 + 1.;
+      Real w2=(-2*scaled + 3.)*scaled2;
+      Real w3=(scaled - 2.)*scaled2 + scaled;
+      Real w4=(scaled - 1.)*scaled2;
+
+      return (w1*p1 + w2*p2 + w3*t1 + w4*t2);
+    }
+
+    inline T const operator()(Real const time) const
+    {
+      return this->interpolate(time);
+    }
+
+  private:
+    std::map<Real, T> knots;
+    Real tension;
+  };
+}
+
+#endif // Manta_DynLT_Spline_h

Modified: trunk/Engine/Control/RTRT.cc
==============================================================================
--- trunk/Engine/Control/RTRT.cc        (original)
+++ trunk/Engine/Control/RTRT.cc        Tue Aug 15 11:24:48 2006
@@ -1260,6 +1260,16 @@
   scenePath = path;
 }
 
+CameraPath* RTRT::getCameraPath(void) const
+{
+  return path;
+}
+
+void RTRT::setCameraPath(CameraPath* newPath)
+{
+  path=newPath;
+}
+
 Group* RTRT::makeGroup(const string& groupSpec)
 {
   string name;

Modified: trunk/Engine/Control/RTRT.h
==============================================================================
--- trunk/Engine/Control/RTRT.h (original)
+++ trunk/Engine/Control/RTRT.h Tue Aug 15 11:24:48 2006
@@ -30,6 +30,7 @@
   using namespace std;
 
   class Camera;
+  class CameraPath;
   class Image;
   class Scene;
 
@@ -105,6 +106,10 @@
     virtual void readStack( const string &name, const vector<string> &args );
     virtual void setScenePath(const string& path);
 
+    // Camera Path
+    virtual CameraPath* getCameraPath(void) const;
+    virtual void setCameraPath(CameraPath* path);
+
     // Groups
     virtual Group* makeGroup(const string& groupSpec);
     virtual void registerObject(const string& name, GroupCreator creator);
@@ -313,6 +318,7 @@
     };
     typedef vector<Channel*> ChannelListType;
     ChannelListType channels;
+    CameraPath* path;
 
     // Thread local storage allocator.
     ThreadStorage *thread_storage;

Modified: trunk/Interface/CMakeLists.txt
==============================================================================
--- trunk/Interface/CMakeLists.txt      (original)
+++ trunk/Interface/CMakeLists.txt      Tue Aug 15 11:24:48 2006
@@ -6,6 +6,8 @@
         Background.cc
         Camera.h
         Camera.cc
+       CameraPath.h
+       CameraPath.cc
         Context.h
         Fragment.h
         IdleMode.h
@@ -55,4 +57,4 @@
         CallbackHelpers.h
         )
 
-TARGET_LINK_LIBRARIES(Manta_Interface SCIRun_Core)
+TARGET_LINK_LIBRARIES(Manta_Interface SCIRun_Core Manta_Core)

Modified: trunk/Interface/Camera.h
==============================================================================
--- trunk/Interface/Camera.h    (original)
+++ trunk/Interface/Camera.h    Tue Aug 15 11:24:48 2006
@@ -70,6 +70,8 @@
     virtual void reset( const Vector& eye_,
                         const Vector& up_,
                         const Vector& lookat_ ) = 0;
+    virtual void reset(Vector const& eye_, Vector const& up_,
+                       Vector const& lookat_, Real const hfov_) { }
 
     enum TransformCenter {
       LookAt,

Added: trunk/Interface/CameraPath.cc
==============================================================================
--- (empty file)
+++ trunk/Interface/CameraPath.cc       Tue Aug 15 11:24:48 2006
@@ -0,0 +1,120 @@
+
+#include <Core/Exceptions/InputError.h>
+#include <Core/Exceptions/OutputError.h>
+#include <Interface/CameraPath.h>
+
+#include <fstream>
+#include <iostream>
+
+using namespace Manta;
+
+CameraPath::CameraPath(MantaInterface* interface, string const& fname,
+                       Mode mode) :
+  interface(interface), fname(fname)
+{
+  if (mode==ReadKnots) {
+    // Read control points
+    readKnots();
+
+    // Register interpolate function
+    interface->registerSerialAnimationCallback(Callback::create(this, 
&CameraPath::interpolate));
+  }
+}
+
+CameraPath::~CameraPath(void)
+{
+  knots.clear();
+  eyes.reset();
+  lookats.reset();
+  ups.reset();
+  fovs.reset();
+}
+
+void CameraPath::interpolate(int, int, bool&)
+{
+  // Serial animation callback to update camera parameters
+  int frame=interface->getCurrentFrame();
+  int time=frame%max_frame;
+  Camera* camera=interface->getCamera(0);
+  camera->reset(eyes.interpolate(time), ups.interpolate(time),
+                lookats.interpolate(time), fovs.interpolate(time));
+}
+
+void CameraPath::addKnot(Real const time, BasicCameraData const& data)
+{
+  Knot knot;
+  knot.time=time;
+  knot.data=data;
+
+  knots.push_back(knot);
+}
+
+void CameraPath::readKnots(void)
+{
+  // Open input file
+  std::ifstream in(fname.c_str());
+  if (!in)
+    throw InputError("Failed to open \"" + fname + "\" for reading");
+
+  // Read data
+  unsigned int total_knots;
+  in>>total_knots;
+
+  max_frame=0;
+  unsigned int nknots=0;
+  while (nknots<total_knots) {
+    Real frame;
+    Real ex, ey, ez;
+    Real lx, ly, lz;
+    Real ux, uy, uz;
+    Real fov;
+
+    in>>frame;
+    in>>ex>>ey>>ez;
+    in>>lx>>ly>>lz;
+    in>>ux>>uy>>uz;
+    in>>fov;
+
+    // Add knot to paths
+    eyes.addKnot(frame, Vector(ex, ey, ez));
+    lookats.addKnot(frame, Vector(lx, ly, lz));
+    ups.addKnot(frame, Vector(ux, uy, uz));
+    fovs.addKnot(frame, fov);
+
+    if (frame>max_frame)
+      max_frame=frame;
+
+    ++nknots;
+  }
+
+  in.close();
+
+  std::cerr<<"Read "<<nknots<<" control points from \""<<fname<<"\"\n";
+}
+
+void CameraPath::writeKnots(void) const
+{
+  if (knots.size()==0) {
+    std::cerr<<"No control points have been added, ignoring\n";
+    return;
+  }
+
+  // Open output file
+  std::ofstream out(fname.c_str());
+  if (!out)
+    throw OutputError("Failed to open \"" + fname + "\" for writing");
+
+  // Write data
+  out<<knots.size()<<'\n';
+  for (unsigned int i=0; i<knots.size(); ++i) {
+    out<<knots[i].time<<' '
+       <<knots[i].data.eye<<' '
+       <<knots[i].data.lookat<<' '
+       <<knots[i].data.up<<' '
+       <<knots[i].data.hfov<<'\n';
+  }
+
+  out.close();
+
+  std::cerr<<"Wrote "<<knots.size()<<" control points to \""<<fname<<"\"\n";
+}

Added: trunk/Interface/CameraPath.h
==============================================================================
--- (empty file)
+++ trunk/Interface/CameraPath.h        Tue Aug 15 11:24:48 2006
@@ -0,0 +1,48 @@
+
+#ifndef Manta_Interface_CameraPath_h
+#define Manta_Interface_CameraPath_h
+
+#include <Core/Math/Spline.h>
+#include <Interface/Camera.h>
+#include <Interface/MantaInterface.h>
+
+#include <string>
+#include <vector>
+
+namespace Manta
+{
+  class CameraPath
+  {
+  public:
+    typedef enum { ReadKnots, WriteKnots } Mode;
+
+    CameraPath(MantaInterface* interface, string const& fname,
+               Mode mode=WriteKnots);
+    ~CameraPath(void);
+
+    void interpolate(int, int, bool&);
+
+    void addKnot(Real const time, BasicCameraData const& data);
+    void readKnots(void);
+    void writeKnots(void) const;
+
+  private:
+    MantaInterface* interface;
+    std::string fname;
+
+    struct Knot
+    {
+      Real time;
+      BasicCameraData data;
+    };
+    std::vector<Knot> knots;
+
+    Spline<Vector> eyes;
+    Spline<Vector> lookats;
+    Spline<Vector> ups;
+    Spline<Real> fovs;
+    int max_frame;
+  };
+}
+
+#endif // Manta_Interface_CameraPath_h

Modified: trunk/Interface/MantaInterface.h
==============================================================================
--- trunk/Interface/MantaInterface.h    (original)
+++ trunk/Interface/MantaInterface.h    Tue Aug 15 11:24:48 2006
@@ -16,6 +16,7 @@
   using namespace std;
 
   class Camera;
+  class CameraPath;
   class Group;
   class IdleMode;
   class ImageDisplay;
@@ -123,6 +124,10 @@
     virtual Group* makeGroup(const string& groupSpec) = 0;
     virtual void registerObject(const string& name, GroupCreator creator) = 
0;
     virtual listType listGroups() const = 0;
+
+    // Camera path
+    virtual CameraPath* getCameraPath(void) const = 0;
+    virtual void setCameraPath(CameraPath* path) = 0;
 
     // Callbacks
     enum Whence {

Modified: trunk/Model/Cameras/PinholeCamera.cc
==============================================================================
--- trunk/Model/Cameras/PinholeCamera.cc        (original)
+++ trunk/Model/Cameras/PinholeCamera.cc        Tue Aug 15 11:24:48 2006
@@ -422,6 +422,16 @@
   setup();
 }
 
+void PinholeCamera::reset(Vector const& eye_, Vector const& up_,
+                          Vector const& lookat_, Real const hfov_)
+{
+  eye=eye_;
+  up=up_;
+  lookat=lookat_;
+  hfov=hfov_;
+  setup();
+}
+
 void PinholeCamera::getBasicCameraData(BasicCameraData& cam) const
 {
   // fov doesn't make sense for this camera - use a reasonable default

Modified: trunk/Model/Cameras/PinholeCamera.h
==============================================================================
--- trunk/Model/Cameras/PinholeCamera.h (original)
+++ trunk/Model/Cameras/PinholeCamera.h Tue Aug 15 11:24:48 2006
@@ -42,6 +42,8 @@
                
     virtual void reset( const Vector& eye_, const Vector& up_,
                         const Vector& lookat_ );
+    virtual void reset(Vector const& eye_, Vector const& up_,
+                       Vector const& lookat_, Real const hfov_);
 
     void setStereoOffset( Real stereo_offset_ ) { stereo_offset = 
stereo_offset_; }
     Real getStereoOffset() const { return stereo_offset; }

Modified: trunk/UserInterface/XWindowUI.cc
==============================================================================
--- trunk/UserInterface/XWindowUI.cc    (original)
+++ trunk/UserInterface/XWindowUI.cc    Tue Aug 15 11:24:48 2006
@@ -1,6 +1,7 @@
 #include <UserInterface/XWindowUI.h>
 #include <Core/Util/Args.h>
 #include <Interface/Camera.h>
+#include <Interface/CameraPath.h>
 #include <Interface/Context.h>
 #include <Interface/MantaInterface.h>
 #include <Interface/Transaction.h>
@@ -420,6 +421,12 @@
   register_key(0, XStringToKeysym("B"),
                "add bookmark",
                Callback::create(this, &XWindowUI::add_bookmark));
+  register_key(0, XStringToKeysym("k"),
+               "add knot",
+               Callback::create(this, &XWindowUI::add_knot));
+  register_key(0, XStringToKeysym("K"),
+               "write knots",
+               Callback::create(this, &XWindowUI::write_knots));
   register_key(0, XStringToKeysym("c"),
                "output camera",
                Callback::create(this, &XWindowUI::output_camera));           
                                   
@@ -514,6 +521,29 @@
   BasicCameraData bookmark;
   camera->getBasicCameraData(bookmark);
   rtrt_interface->getScene()->addBookmark("user added", bookmark);
+}
+
+void XWindowUI::add_knot(unsigned int, unsigned long, int channel)
+{
+  CameraPath* path=rtrt_interface->getCameraPath();
+  if (!path) {
+    cerr<<"Creating a new CameraPath; writing knots to \"out.path\"\n";
+    path=new CameraPath(rtrt_interface, "out.path", CameraPath::WriteKnots);
+    rtrt_interface->setCameraPath(path);
+  }
+
+  BasicCameraData data;
+  rtrt_interface->getCamera(channel)->getBasicCameraData(data);
+  path->addKnot(rtrt_interface->getCurrentFrame(), data);
+}
+
+void XWindowUI::write_knots(unsigned int, unsigned long, int)
+{
+  CameraPath* path=rtrt_interface->getCameraPath();
+  if (!path)
+    return;
+
+  path->writeKnots();
 }
 
 void XWindowUI::output_camera(unsigned int, unsigned long, int channel)

Modified: trunk/UserInterface/XWindowUI.h
==============================================================================
--- trunk/UserInterface/XWindowUI.h     (original)
+++ trunk/UserInterface/XWindowUI.h     Tue Aug 15 11:24:48 2006
@@ -75,6 +75,8 @@
 
     void next_bookmark(unsigned int, unsigned long, int);              
     void add_bookmark(unsigned int, unsigned long, int);               
+    void add_knot(unsigned int, unsigned long, int);
+    void write_knots(unsigned int, unsigned long, int);
     void output_camera(unsigned int, unsigned long, int);
 
     void mouse_fov(unsigned int, unsigned int, int, int, int, int);

Modified: trunk/scenes/dynlt.cc
==============================================================================
--- trunk/scenes/dynlt.cc       (original)
+++ trunk/scenes/dynlt.cc       Tue Aug 15 11:24:48 2006
@@ -10,6 +10,7 @@
 #include <DynLT/DynLTQueue.h>
 #include <DynLT/DynLTStatsCollector.h>
 #include <DynLT/DynLTWorker.h>
+#include <Interface/CameraPath.h>
 #include <Interface/Context.h>
 #include <Interface/LightSet.h>
 #include <Interface/MantaInterface.h>
@@ -120,6 +121,16 @@
         static_threads=true;
         if (!getIntArg(i, args, nthreads))
           throw IllegalArgument("scene dynplt -nthreads", i, args);
+      } else if (arg=="-opath") {
+        string fname;
+        if (!getStringArg(i, args, fname))
+          throw IllegalArgument("scene dynplt -path", i, args);
+        context.manta_interface->setCameraPath(new 
CameraPath(context.manta_interface, fname, CameraPath::WriteKnots));
+      } else if (arg=="-path") {
+        string fname;
+        if (!getStringArg(i, args, fname))
+          throw IllegalArgument("scene dynplt -path", i, args);
+        context.manta_interface->setCameraPath(new 
CameraPath(context.manta_interface, fname, CameraPath::ReadKnots));
       } else if (arg=="-radius") {
         if (!getDoubleArg(i, args, radius))
           throw IllegalArgument("scene dynplt -radius", i, args);
@@ -158,6 +169,8 @@
         cerr<<"  -ngroups <int>                    number of sample 
groups\n";
         cerr<<"  -nsamples <int>                   number of 
samples/texel\n";
         cerr<<"  -nthreads <int>                   number of static dynplt 
workers\n";
+        cerr<<"  -opath <string>                   output filename of camera 
path\n";
+        cerr<<"  -path <string>                    input filename of camera 
path\n";
         cerr<<"  -qsize <int>                      maximum queue qsize\n";
         cerr<<"  -radius <float>                   particle radius\n";
         cerr<<"  -ridx <int>                       radius index\n";




  • [MANTA] r1178 - in trunk: Core/Math Engine/Control Interface Model/Cameras UserInterface scenes, cgribble, 08/15/2006

Archive powered by MHonArc 2.6.16.

Top of page