2007.3.30
10:53
作者:天行健 |
评论:0
| 阅读:0
可以基于gtkglext自行封装形成GtkWidget.
下面是封装的头文件以及其实现文件,最后是其示例。
vtkGtkRenderWindowInteractor.h
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkGtkRenderWindowInteractor.cxx,v $
Language: C++
Date: $Date: 2002/11/22 16:25:58 $
Version: $Revision: 0.1 $
Based on wvXRenderWindowInteractor and wxVTKRenderWindowInteractor.
Copyright (c) 2004 Dov Grobgeld <dov.grobgeld@weizmann.ac.il>
Based on code copyright by: Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef __vtkGtkRenderWindowInteractor_h
#define __vtkGtkRenderWindowInteractor_h
//===========================================================
// now we define the C++ class
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "gtk/gtk.h"
class VTK_RENDERING_EXPORT vtkGtkRenderWindowInteractor : public vtkRenderWindowInteractor
{
public:
// Constructor
vtkGtkRenderWindowInteractor();
// Destructor
~vtkGtkRenderWindowInteractor();
// Object factory. TBD.
static vtkGtkRenderWindowInteractor *New();
// vtkRenderWindowInteractor overrides
void Initialize();
void Enable();
void Disable();
void Start();
void UpdateSize(int x, int y);
int CreateTimer(int timertype);
int DestroyTimer();
void TerminateApp() {};
void Render();
// accessor function for drawing area used for gl interaction
GtkWidget *get_drawing_area() { return drawing_area; }
// Make all callback friends
friend void cb_realize (GtkWidget*, gpointer user_data);
friend gboolean cb_configure (GtkWidget *widget,
GdkEventConfigure *event,
gpointer user_data);
friend gboolean cb_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data);
friend gboolean cb_key_press_event(GtkWidget *widget,
GdkEventKey *event,
gpointer user_data);
friend gboolean cb_key_release_event(GtkWidget *widget,
GdkEventKey *event,
gpointer user_data);
friend gboolean cb_button_press_event(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
friend gboolean cb_button_release_event(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
friend gboolean cb_motion_notify_event(GtkWidget *widget,
GdkEventMotion *event,
gpointer user_data);
// Dov - timeout callback - will have to cast the user_data...
friend gboolean vtkGtkRenderWindowInteractorTimer(gpointer user_data);
protected:
int ActiveButton;
int RenderAllowed;
long GetHandle();
int Stereo;
private:
long Handle;
bool Created;
int RenderWhenDisabled;
int UseCaptureMouse;
GtkWidget *drawing_area;
gint last_xpos, last_ypos, last_key_state;
// Flag used to break timer loop
bool do_break_timer;
void update_mouse_pos();
};
#endif
vtkGtkRenderWindowInteractor.cxx
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkGtkRenderWindowInteractor.cxx,v $
Language: C++
Date: $Date: 2002/11/22 16:25:58 $
Version: $Revision: 0.1 $
Based on wvXRenderWindowInteractor and wxVTKRenderWindowInteractor.
Copyright (c) 2004 Dov Grobgeld <dov.grobgeld@weizmann.ac.il>
Based on code copyright by: Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkGtkRenderWindowInteractor.h"
#include "vtkCommand.h"
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <gdk/gdkx.h>
#include <gdk/gdk.h>
#include <gdk/gdkprivate.h>
// Construct an instance so that the light follows the camera motion.
vtkGtkRenderWindowInteractor::vtkGtkRenderWindowInteractor()
: vtkRenderWindowInteractor()
, RenderAllowed(false)
, RenderWhenDisabled(true)
, Created(true)
, UseCaptureMouse(false)
, Handle(0)
, Stereo(0)
, ActiveButton(0)
, last_xpos(0)
, last_ypos(0)
, last_key_state(0)
, do_break_timer(false)
{
GdkGLConfig *glconfig;
drawing_area = gtk_drawing_area_new();
GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);
gtk_widget_set_events(GTK_WIDGET(drawing_area),
GDK_EXPOSURE_MASK
| GDK_STRUCTURE_MASK
| GDK_PROPERTY_CHANGE_MASK
| GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK
| GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_KEY_PRESS_MASK
| GDK_KEY_RELEASE_MASK
| GDK_LEAVE_NOTIFY_MASK
| GDK_ENTER_NOTIFY_MASK
);
glconfig = gdk_gl_config_new_by_mode (GdkGLConfigMode(GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH |
GDK_GL_MODE_DOUBLE));
/* Set OpenGL-capability to the widget. */
gtk_widget_set_gl_capability (drawing_area,
glconfig,
NULL,
TRUE,
GDK_GL_RGBA_TYPE);
gtk_widget_set_double_buffered(drawing_area,
FALSE);
g_signal_connect(drawing_area, "realize",
G_CALLBACK(&cb_realize),
(gpointer)this);
g_signal_connect(drawing_area, "configure_event",
G_CALLBACK(&cb_configure),
(gpointer)this);
g_signal_connect(drawing_area, "expose_event",
G_CALLBACK(&cb_expose),
(gpointer)this);
g_signal_connect(drawing_area, "key_press_event",
G_CALLBACK(&cb_key_press_event),
(gpointer)this);
g_signal_connect(drawing_area, "key_release_event",
G_CALLBACK(&cb_key_release_event),
(gpointer)this);
g_signal_connect(drawing_area, "button_press_event",
G_CALLBACK(&cb_button_press_event),
(gpointer)this);
g_signal_connect(drawing_area, "button_release_event",
G_CALLBACK(&cb_button_release_event),
(gpointer)this);
g_signal_connect(drawing_area, "motion_notify_event",
G_CALLBACK(&cb_motion_notify_event),
(gpointer)this);
// Copied from wxVTKRenderWindowInteractor... What is it for?
vtkRenderWindowInteractor::SetRenderWindow(vtkRenderWindow::New());
RenderWindow->Delete();
}
vtkGtkRenderWindowInteractor * vtkGtkRenderWindowInteractor::New()
{
// we are not registered in the objectfactor
return new vtkGtkRenderWindowInteractor;
}
// Todo constructor with more options...
vtkGtkRenderWindowInteractor::~vtkGtkRenderWindowInteractor()
{
gtk_widget_destroy(drawing_area);
}
// Initializes the event handlers using a parent widget that you have
// provided. This assumes that you want to own the event loop.
void vtkGtkRenderWindowInteractor::Initialize()
{
Enable();
RenderWindow->Start();
Initialized = 1;
}
void vtkGtkRenderWindowInteractor::Enable()
{
if (Enabled)
return;
Enabled = true;
Modified();
}
void vtkGtkRenderWindowInteractor::Disable()
{
if (!Enabled)
return;
Enabled = false;
Modified();
}
void vtkGtkRenderWindowInteractor::Start()
{
fprintf(stderr, "Interactor cannot control event loop!\n");
}
void vtkGtkRenderWindowInteractor::UpdateSize(int x,int y)
{
// if the size changed send this on to the RenderWindow
if ((x != this->Size[0]) || (y != this->Size[1]))
{
this->Size[0] = x;
this->Size[1] = y;
this->RenderWindow->SetSize(x,y);
}
}
int vtkGtkRenderWindowInteractor::CreateTimer(int timertype)
{
if (timertype == VTKI_TIMER_FIRST)
{
// We use a repeating timer? Do we need to keep an id for it?
g_timeout_add(10, vtkGtkRenderWindowInteractorTimer, (gpointer)(this));
this->do_break_timer = false;
}
return 1;
}
int vtkGtkRenderWindowInteractor::DestroyTimer()
{
this->do_break_timer = true;
return 1;
}
long vtkGtkRenderWindowInteractor::GetHandle()
{
return (long)GDK_WINDOW_XWINDOW(drawing_area->window);
}
void vtkGtkRenderWindowInteractor::Render()
{
RenderAllowed = 1;
if (!RenderWhenDisabled)
{
// tbd - check if parent is enabled
}
if (RenderAllowed)
{
if (Handle && (Handle == GetHandle()) )
{
RenderWindow->Render();
}
// TBD for reparenting
}
}
void vtkGtkRenderWindowInteractor::update_mouse_pos()
{
GdkModifierType mask;
gdk_window_get_pointer(drawing_area->window,
&last_xpos,
&last_ypos,
&mask);
last_key_state = mask;
}
gboolean vtkGtkRenderWindowInteractorTimer(gpointer client_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)client_data;
if (rwi->do_break_timer) {
return FALSE;
}
if (rwi->Enabled)
{
rwi->InvokeEvent(vtkCommand::TimerEvent,NULL);
}
return TRUE;
}
void cb_realize(GtkWidget*,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
if (!rwi->Handle)
{
rwi->Handle = rwi->GetHandle();
rwi->RenderWindow->SetWindowId((void*)rwi->Handle);
}
// get vtk to render to the drawing area
// rwi->Render();
}
gboolean cb_configure(GtkWidget *widget,
GdkEventConfigure *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
rwi->UpdateSize(event->width, event->height);
if (!rwi->Enabled)
{
return TRUE;
}
rwi->InvokeEvent(vtkCommand::ConfigureEvent, NULL);
// get vtk to render to the drawing area
rwi->Render();
return TRUE;
}
// I'm rendering everytime I'm getting an expose event. Perhaps this
// is a waist of time...
gboolean cb_expose(GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
rwi->Render();
return TRUE;
}
gboolean
cb_key_press_event(GtkWidget *widget,
GdkEventKey *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
gint keyval = event->keyval;
char key = 0;
if (keyval < 256)
{
// Todo: Unicode in non-Unicode mode??
key = (char)keyval;
}
rwi->update_mouse_pos();
rwi->SetEventInformationFlipY(rwi->last_xpos,
rwi->last_ypos,
event->state & GDK_CONTROL_MASK,
event->state & GDK_SHIFT_MASK,
key,
0,
NULL);
rwi->last_key_state = event->state;
rwi->InvokeEvent(vtkCommand::KeyPressEvent, NULL);
rwi->InvokeEvent(vtkCommand::CharEvent, NULL);
return true;
}
gboolean
cb_key_release_event(GtkWidget *widget,
GdkEventKey *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
gint keyval = event->keyval;
char key = 0;
if (keyval < 256)
{
// Todo: Unicode in non-Unicode mode??
key = (char)keyval;
}
rwi->update_mouse_pos();
rwi->SetEventInformationFlipY(rwi->last_xpos,
rwi->last_ypos,
event->state & GDK_CONTROL_MASK,
event->state & GDK_SHIFT_MASK,
key,
0,
NULL);
rwi->last_key_state = event->state;
rwi->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL);
return TRUE;
}
gboolean
cb_button_press_event(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
gint button = event->button;
if (!rwi->Enabled || rwi->ActiveButton != 0)
return true;
rwi->update_mouse_pos();
rwi->SetEventInformationFlipY(rwi->last_xpos,
rwi->last_ypos,
rwi->last_key_state & GDK_CONTROL_MASK,
rwi->last_key_state & GDK_SHIFT_MASK,
'\0',
0,
NULL);
rwi->ActiveButton = button;
switch (button) {
case 1:
rwi->InvokeEvent(vtkCommand::LeftButtonPressEvent, NULL);
break;
case 2:
rwi->InvokeEvent(vtkCommand::MiddleButtonPressEvent, NULL);
break;
case 3:
rwi->InvokeEvent(vtkCommand::RightButtonPressEvent, NULL);
break;
default:
// Ignore other buttons at the moment
break;
}
// Do we need to worry about capturing the mouse
return TRUE;
}
gboolean
cb_button_release_event(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
gint button = event->button;
// is this right?
if (!rwi->Enabled || rwi->ActiveButton != button)
return true;
rwi->update_mouse_pos();
rwi->SetEventInformationFlipY(rwi->last_xpos,
rwi->last_ypos,
rwi->last_key_state & GDK_CONTROL_MASK,
rwi->last_key_state & GDK_SHIFT_MASK,
'\0',
0,
NULL);
switch (button) {
case 1:
rwi->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, NULL);
break;
case 2:
rwi->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, NULL);
break;
case 3:
rwi->InvokeEvent(vtkCommand::RightButtonReleaseEvent, NULL);
break;
default:
// Ignore other buttons at the moment
break;
}
rwi->ActiveButton = 0;
}
gboolean
cb_motion_notify_event(GtkWidget *widget,
GdkEventMotion *event,
gpointer user_data)
{
vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
rwi->update_mouse_pos();
rwi->SetEventInformationFlipY(rwi->last_xpos,
rwi->last_ypos,
rwi->last_key_state & GDK_CONTROL_MASK,
rwi->last_key_state & GDK_SHIFT_MASK,
'\0',
0,
NULL);
rwi->InvokeEvent(vtkCommand::MouseMoveEvent, NULL);
return true;
}
example.cc
//======================================================================
// An example file showing how to use the vtkGtkRenderWindowInteractor.
//
// Dov Grobgeld <dov.grobgeld@weizmann.ac.il>
// 2004-10-17
//----------------------------------------------------------------------
#include "vtkSphereSource.h"
#include "vtkCubeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkGtkRenderWindowInteractor.h"
#include "vtkInteractorStyleFlight.h"
#include "gtk/gtkgl.h"
// Creates a scene consisting of a sphere and a 3D block
vtkRenderer *create_scene()
{
// create sphere geometry
vtkSphereSource *sphere = vtkSphereSource::New();
sphere->SetRadius(1.0);
sphere->SetThetaResolution(50);
sphere->SetPhiResolution(50);
// map to graphics library
vtkPolyDataMapper *sphere_map = vtkPolyDataMapper::New();
sphere_map->SetInput(sphere->GetOutput());
// actor coordinates geometry, properties, transformation
vtkActor *sphere_actor = vtkActor::New();
sphere_actor->SetMapper(sphere_map);
sphere_actor->GetProperty()->SetColor(0,0,1); // sphere color blue
// cube
vtkCubeSource *cube = vtkCubeSource::New();
cube->SetXLength(1.5);
cube->SetYLength(1.0);
cube->SetZLength(0.5);
// map to graphics library
vtkPolyDataMapper *cube_map = vtkPolyDataMapper::New();
cube_map->SetInput(cube->GetOutput());
// actor coordinates geometry, properties, transformation
vtkActor *cube_actor = vtkActor::New();
cube_actor->SetMapper(cube_map);
cube_actor->SetPosition(2.5,0,0);
cube_actor->GetProperty()->SetColor(1,0,0); // cube color is red
// a renderer and and place the objects in it render window
vtkRenderer *ren1 = vtkRenderer::New();
ren1->AddActor(sphere_actor);
ren1->AddActor(cube_actor);
ren1->SetBackground(1,1,1); // Background color white
return ren1;
}
// Create's the gui and incorpotes the drawing area widget of
// the renderer.
void build_gui(GtkWidget *vtk_area)
{
// Build gui
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *vbox = gtk_vbox_new(0,0);
gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);
gtk_container_add (GTK_CONTAINER (window),
vbox);
gtk_box_pack_start (GTK_BOX (vbox),
vtk_area, 1,1,0);
gtk_widget_set_size_request(vtk_area, 400,400);
GtkWidget *button = gtk_button_new_with_label("Quit");
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(gtk_main_quit), NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE,FALSE,0);
gtk_widget_show_all (window);
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
gtk_gl_init(&argc, &argv);
// Create the gtk vtk interactor. This also creates the gtk widget.
vtkGtkRenderWindowInteractor *iren = vtkGtkRenderWindowInteractor::New();
// Connect the renderer to the gtk vtk rendering window
vtkRenderer *scene = create_scene();
iren->GetRenderWindow()->AddRenderer(scene);
build_gui(iren->get_drawing_area());
gtk_main();
}
你可以通过这个链接引用该篇文章:http://shenaodong.bokee.com/viewdiary.15499235.html