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