home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.hitl.washington.edu
/
ftp.hitl.washington.edu.tar
/
ftp.hitl.washington.edu
/
pub
/
people
/
peter
/
ER
/
VideoObject.cxx
< prev
Wrap
C/C++ Source or Header
|
1998-07-07
|
8KB
|
279 lines
/*
VideoObject.cxx
The VideoObject class is implemented with the dmuVideoIn and
dmuGLTex2d classes from the Digital Media Utility library.
Documentation can be found with the classes, but basically the
process for using the classes is as follows:
A dmuVideoIn object is created that monitors the O2's video
input for new data. This class is wired to a dmuGLTex2d
object. When new data arrives, a callback is invoked which
checks to see if the new frame is valid, and if so it dumps
the frame to the GL texture memory stored in the dmuGLTex2d
object.
The video object registers a callback with WTK's 3D predraw sender,
and uses OpenGL commands to draw the texture in the simulation.
However, since this is done before the scene graph is traversed
(instead of texturing during scene graph traversal, as can be done
in OpenInventor), a dummy object must be added to the simulation to
keep track of the position and extents of the video window. This
dummy object is queried in the predraw callback for its position,
size, and orientation, and this data is used to draw the OpenGL
texture in the proper place. Since the VideoObject is a subclass of
v3dObject, the dummy object in this case is simply a block object
created with the v3dObject implementation.
*/
#include "VideoObject.h"
#include "wt.h"
#define dmuCheck(dmFunc) { \
int dmuErrID; \
if ((dmuErrID = (dmFunc)) != DMU_OK) \
fprintf(stderr,"*Error:%d:%s\n", dmuErrID, \
getErrorString(dmuErrID) ); \
}
VideoObject* VideoObject::TheVideoObject_ = 0;
// VideoObject::GetInstance
// Returns a pointer to the video object singleton.
// If the singleton doesn't exist, it creates one.
VideoObject *
VideoObject::GetInstance()
{
if (TheVideoObject_ == 0)
TheVideoObject_ = new VideoObject;
return TheVideoObject_;
}
// VideoObject::VideoObject
// Initializes the video and texture objects, and sets the callbacks
// needed to update the displays.
VideoObject::VideoObject ()
{
create_bounding_box();
initialize_video();
RegisterEventHandler(PredrawSender::GetInstance(),
PredrawSender::PREDRAW_EVENT,
&video_GL_draw_CB, 0);
handle_event_ = false;
}
void
VideoObject::create_bounding_box()
{
// Create the dummy object to keep track of the size and position
// of the video window. The initial size in unimportant, since the
// client should scale the object to fit the simulation.
imp_->CreateBlock(5, 5, 0.1, false);
// The dummy object is invisible, but still interacts with the
// rest of the simulation. It can be scaled, rotated, collided with,
// attached, etc.
v3dObject::Hide();
}
void
VideoObject::initialize_video()
{
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// Set up video texture mapping.
// -- Construction --
video_in_ = new dmuVideoIn;
video_in_->setName("Video In ");
texture_ = new dmuGLTex2d;
texture_->setName("Texture");
// -- Wire --
video_in_->addObject(texture_);
// -- Setup --
// Use current vcp setting for video source
dmuCheck(video_in_->setup(VL_ANY));
// Use ABGR_8 packing and formatting texture mapping
dmuCheck(video_in_->setPacking(VL_PACKING_ABGR_8));
dmuCheck(video_in_->setCaptureType(VL_CAPTURE_INTERLEAVED));
dmuCheck(video_in_->setFormat(VL_FORMAT_RGB));
// Texture maps need to be powers of 2.
dmuCheck(video_in_->setSize(512,512));
dmuCheck(video_in_->setOrigin(0,32));
// Use graphics layout for texture maps
dmuCheck(video_in_->setLayout(VL_LAYOUT_GRAPHICS));
fprintf (stderr, "Getting video dimensions: ");
int size_X, size_Y;
video_in_->getImageDimensions(&size_X, &size_Y);
fprintf (stderr, "Video dimensions: %d, %d\n\n", size_X, size_Y);
// Set up the texture object to have the same size
Widget window_widget = WTwindow_getwidget(WTuniverse_getwindows());
dmuCheck(texture_->setup(XtDisplay(window_widget), size_X, size_Y));
// -- Init --
fprintf (stderr, "Initializing: \n\n");
dmuCheck(video_in_->init());
// -- Start --
fprintf (stderr, "Fire it up!\n");
dmuCheck(video_in_->start());
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE_EXT);
XtAppContext app;
app = XtWidgetToApplicationContext(window_widget);
XtInputId inputID = XtAppAddInput(app, video_in_->getFD(),
(XtPointer) XtInputReadMask, handle_dmu_events_CB, NULL);
}
void
VideoObject::video_GL_draw_CB(const v3dEventMessage *message)
{
TheVideoObject_->video_GL_draw();
}
void
VideoObject::video_GL_draw()
{
if (handle_event_) {
dmuCheck(texture_->defineTex2D());
// handle_event_ = false;
glPushMatrix();
glColor3f(1.0,1.0,1.0);
glEnable( GL_TEXTURE_2D );
v3dDim obj_dim = GetSize();
v3dPos obj_pos = GetAbsolutePosition(),
top_left = v3dPos(- obj_dim.x() / 2, - obj_dim.y() / 2, 0),
top_right = top_left + v3dPos(obj_dim.x(), 0, 0),
bottom_left = top_left + v3dPos(0, obj_dim.y(), 0),
bottom_right = top_left + v3dPos(obj_dim.x(), obj_dim.y(), 0);
v3dCoordSystem obj_coord (obj_pos, GetAbsoluteOrientation());
top_left = obj_coord.LocalPosToAbsolute(top_left);
top_right = obj_coord.LocalPosToAbsolute(top_right);
bottom_left = obj_coord.LocalPosToAbsolute(bottom_left);
bottom_right = obj_coord.LocalPosToAbsolute(bottom_right);
glBegin(GL_QUADS);
glTexCoord2d(0.0,0.0); glVertex3f(bottom_left.x(),bottom_left.y(),bottom_left.z());
glTexCoord2d(1.0,0.0); glVertex3f(bottom_right.x(),bottom_right.y(),bottom_right.z());
glTexCoord2d(1.0,1.0); glVertex3f(top_right.x(),top_right.y(),top_right.z());
glTexCoord2d(0.0,1.0); glVertex3f(top_left.x(),top_left.y(),top_left.z());
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
}
void
VideoObject::handle_dmu_events_CB(XtPointer*, int *fd, XtInputId*)
{
TheVideoObject_->handle_dmu_events();
}
void
VideoObject::handle_dmu_events()
{
fd_set readFDSet;
int maxFD;
FD_ZERO(&readFDSet);
video_in_->setFD(&readFDSet, &maxFD);
int error = video_in_->handleEvents(readFDSet);
// This handles the temporary video_in_ return values. We only want
// to redraw the screen if we have a new video frame waiting for us
if (error != VIDEOIN_TRANSFER_COMPLETE) {
return;
}
// Tell the texture to setup Open GL to use the latest
// video frame as a texture map.
handle_event_ = true;
}
// VideoObject::~VideoObject
// Deletes the video object object.
VideoObject::~VideoObject ()
{
delete texture_;
delete video_in_;
}
void
VideoObject::Hide()
{
UnregisterEventHandler(PredrawSender::GetInstance(),
PredrawSender::PREDRAW_EVENT,
&video_GL_draw_CB);
hidden_ = true;
}
void
VideoObject::Show()
{
RegisterEventHandler(PredrawSender::GetInstance(),
PredrawSender::PREDRAW_EVENT,
&video_GL_draw_CB, 0);
hidden_ = false;
}
void
VideoObject::Enable()
{
RegisterEventHandler(PredrawSender::GetInstance(),
PredrawSender::PREDRAW_EVENT,
&video_GL_draw_CB, 0);
// Re-enable the bounding box so it can interact with the simulation,
// but hide it so it can't be seen.
v3dObject::Enable();
v3dObject::Hide();
disabled_ = false;
}
void
VideoObject::Disable()
{
UnregisterEventHandler(PredrawSender::GetInstance(),
PredrawSender::PREDRAW_EVENT,
&video_GL_draw_CB);
v3dObject::Disable();
}