4 #include <vtkRenderWindow.h> 5 #include <vtkRenderWindowInteractor.h> 6 #include <vtkInteractorStyleTrackballCamera.h> 7 #include <vtkWindowToImageFilter.h> 8 #include <vtkPNGWriter.h> 9 #include <vtkCommand.h> 10 #include <vtkProperty.h> 11 #include <vtkProperty2D.h> 12 #include <vtkObjectBase.h> 13 #include <vtkPropCollection.h> 14 #include <vtkContextScene.h> 34 for (
auto & subframe: frame.second->subframes)
35 subframe.renderer->RemoveAllViewProps();
36 frame.second->window->Finalize();
55 char* port_string= getenv(
"VTKFIG_PORT_NUMBER");
56 char* wtime_string=getenv(
"VTKFIG_WAIT_SECONDS");
57 char *debug_string=getenv(
"VTKFIG_DEBUG");
58 char *multi_string=getenv(
"VTKFIG_MULTITHREADED");
59 char *dbuff_string=getenv(
"VTKFIG_DOUBLEBUFFER");
69 if (multi_string!=0 && atoi(multi_string))
72 cout <<
"overriding multithreading default (off) on APPLE" << endl;
77 if (multi_string!=0 && !atoi(multi_string))
80 cout <<
"overriding multithreading default (on) on" << endl;
89 wtime=atoi(wtime_string);
94 int port=atoi(port_string);
96 throw std::runtime_error(
"Invalid port number for server");
107 cout << sc<<
" try running multithreaded" << endl;
109 cout << sc<<
" try running single threaded" << endl;
118 cout <<
"Server start listening on port "<< port << endl;
124 cout <<
"Server connected" << endl;
127 cout <<
"Nobody is listening ... giving up" << endl;
128 throw std::runtime_error(
"Server connection failed");
137 cout <<
" ~mt" << endl;
140 std::this_thread::sleep_for(std::chrono::milliseconds(10));
142 std::this_thread::sleep_for(std::chrono::milliseconds(10));
163 frame->mainthread=
this;
195 assert(frame==
framemap[frame->number_in_frame_list]);
197 frame->number_in_frame_list=-1;
214 std::this_thread::sleep_for (std::chrono::milliseconds(10));
226 cout <<
"mt " << from <<
" " << number_in_frame_list << endl;
230 this->
iframe=number_in_frame_list;
233 std::unique_lock<std::mutex> lock(this->
mutex);
254 std::vector<Figure*>edited_figures;
257 bool edit_mode =
false;
260 bool left_button_down=
false;
291 for (
auto & figure: frame->figures)
293 for (
auto & actor: figure->ctxactors)
294 actor->GetScene()->SetDirty(
true);
296 vtkInteractorStyleTrackballCamera::OnConfigure();
308 this->left_button_down=
true;
309 lastx=this->Interactor->GetEventPosition()[0];
310 lasty=this->Interactor->GetEventPosition()[1];
313 vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
319 for (
auto &figure: frame->figures)
322 if (frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
323 figure->RTShowActive();
325 figure->RTShowInActive();
326 frame->window->Render();
330 if (this->left_button_down)
331 this->left_button_down=
false;
333 vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
342 if (this->left_button_down)
346 int thisx=this->Interactor->GetEventPosition()[0];
347 int thisy=this->Interactor->GetEventPosition()[1];
352 for (
auto figure:this->edited_figures)
353 figure->RTProcessMove(dx,dy);
356 this->Interactor->Render();
363 vtkInteractorStyleTrackballCamera::OnMouseMove();
370 std::string key = this->Interactor->GetKeySym();
386 for (
auto & subframe: this->frame->subframes)
388 if (subframe.renderer==this->CurrentRenderer)
390 frame->RTResetCamera(subframe);
393 this->Interactor->Render();
399 for (
auto &figure: this->frame->figures)
400 if (this->frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
402 figure->state.wireframe=!figure->state.wireframe;
403 if (figure->state.wireframe)
404 for (
auto & actor: figure->actors) actor->GetProperty()->SetRepresentationToWireframe();
406 for (
auto& actor: figure->actors) actor->GetProperty()->SetRepresentationToSurface();
407 this->Interactor->Render();
417 auto now = std::chrono::system_clock::now();
418 auto time = std::chrono::system_clock::to_time_t(now);
419 std::tm * ttm = localtime(&time);
420 char time_str[] =
"yyyy-mm-ddTHH:MM:SS ";
421 strftime(time_str, strlen(time_str),
"%Y-%m-%dT%H:%M:%S", ttm);
422 auto fname=frame->parameter.wintitle+
"-"+time_str+
".png";
424 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
425 imgfilter->SetInput(frame->window);
428 auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
429 pngwriter->SetInputConnection(imgfilter->GetOutputPort());
430 pngwriter->SetFileName(fname.c_str());
432 this->Interactor->Render();
435 cout <<
"Frame written to "<< fname << endl;
439 else if (key ==
"x" || key==
"y" || key==
"z" || key==
"l" || key==
"a")
441 if (!this->edit_mode)
444 this->edit_mode=
true;
448 for (
auto &figure: frame->figures)
452 frame->subframes[figure->framepos].renderer==this->CurrentRenderer
465 this->edited_figures.push_back(figure);
470 for (
auto figure : this->edited_figures)
471 figure->RTProcessKey(key);
472 this->Interactor->Render();
477 else if(key ==
"Left" || key==
"Down")
481 for (
auto figure : this->edited_figures)
482 figure->RTProcessMove(-1,-1);
483 this->Interactor->Render();
488 else if(key ==
"Right" || key==
"Up")
492 for (
auto figure : this->edited_figures)
493 figure->RTProcessMove(1,1);
494 this->Interactor->Render();
499 else if(key ==
"Return" || key==
"Delete")
503 for (
auto figure : this->edited_figures)
504 figure->RTProcessKey(key);
505 this->Interactor->Render();
510 else if(key ==
"Escape")
512 this->edit_mode=
false;
513 for (
auto figure : this->edited_figures)
515 figure->RTProcessKey(key);
516 figure->RTMessage(
"");
518 this->Interactor->Render();
519 this->edited_figures.resize(0);
520 this->Interactor->Render();
524 else if(key ==
"I" || key==
"L" || key ==
"E" || key ==
"S" || key ==
"slash" || key ==
"B" || key ==
"C" || key ==
"O"|| key ==
"A")
526 for (
auto &figure: frame->figures)
527 if (frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
528 figure->RTProcessKey(key);
530 this->Interactor->Render();
534 else if (key==
"space")
536 frame->mainthread->communication_blocked=!frame->mainthread->communication_blocked;
537 if(frame->mainthread->communication_blocked)
538 frame->title_actor->SetText(6,
"-|-");
540 frame->title_actor->SetText(6,
"---");
541 frame->title_actor->Modified();
542 frame->window->Render();
546 else if (key==
"BackSpace")
548 frame->mainthread->communication_blocked=!frame->mainthread->communication_blocked;
549 if (!frame->mainthread->communication_blocked)
550 frame->step_number=std::max(frame->step_number-2,0);
554 else if (key==
"asterisk")
556 if (!frame->single_subframe_view)
557 for(
int i=0;i<this->frame->subframes.size();i++)
559 if (this->frame->subframes[i].renderer==this->CurrentRenderer)
560 this->frame->active_subframe=i;
563 frame->single_subframe_view=!frame->single_subframe_view;
564 frame->RTSetSingleView(frame->single_subframe_view);
565 this->Interactor->Render();
569 else if (frame->single_subframe_view && key==
"Next")
571 frame->RTSetActiveSubFrame(frame->active_subframe-1,
true);
572 this->Interactor->Render();
575 else if (frame->single_subframe_view && key==
"Prior")
577 frame->RTSetActiveSubFrame(frame->active_subframe+1,
true);
578 this->Interactor->Render();
584 else if(key ==
"h" or key ==
"question")
592 vtkInteractorStyleTrackballCamera::OnChar();
608 vtkSmartPointer<vtkRenderWindowInteractor> Interactor=0;
614 vtkObject *vtkNotUsed(caller),
615 unsigned long eventId,
616 void *vtkNotUsed(callData)
627 vtkCommand::TimerEvent == eventId
635 std::unique_lock<std::mutex> lock(this->mainthread->
mutex);
638 switch(mainthread->
cmd)
653 for (
auto & subframe: frame->subframes)
654 subframe.renderer->RemoveAllViewProps();
656 frame->window->Finalize();
658 mainthread->
framemap.erase(frame->number_in_frame_list);
668 for (
auto & framepair: mainthread->
framemap)
669 framepair.second->RTAddFigures();
673 for (
auto & framepair: mainthread->
framemap)
675 auto frame=framepair.second;
677 if(frame->mainthread->communication_blocked)
678 frame->title_actor->SetText(6,
"-|-");
680 frame->title_actor->SetText(6,
"---");
682 frame->title_actor->Modified();
686 frame->window->Render();
687 if (frame->videowriter && ! frame->mainthread->communication_blocked)
689 this->Interactor->Render();
690 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
691 imgfilter->SetInput(frame->window);
693 frame->videowriter->SetInputConnection(imgfilter->GetOutputPort());
694 this->Interactor->Render();
695 frame->videowriter->Write();
706 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
707 auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
709 pngwriter->SetInputConnection(imgfilter->GetOutputPort());
710 pngwriter->SetFileName(frame->parameter.filename.c_str());
712 imgfilter->SetInput(frame->window);
715 this->Interactor->Render();
725 frame->videowriter = vtkSmartPointer<vtkOggTheoraWriter>::New();
726 frame->videowriter->SetFileName(frame->parameter.filename.c_str());
727 frame->videowriter->Start();
734 frame->videowriter->End();
735 frame->videowriter=0;
742 frame->RTRemoveFigure(frame->parameter.current_figure);
750 frame->RTSetLayout(frame->parameter.nvpx,frame->parameter.nvpy);
751 frame->RTResetRenderers(
false);
758 frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
766 frame->RTSetActiveSubFrame(frame->parameter.active_subframe,
false);
774 auto& subframe=frame->subframes[frame->parameter.active_subframe];
775 frame->RTSetActiveSubFrameCameraViewAngle(subframe,frame->parameter.camera_view_angle);
783 auto& subframe=frame->subframes[frame->parameter.active_subframe];
784 frame->RTSetActiveSubFrameCameraPosition(subframe,frame->parameter.camera_position);
792 auto& subframe=frame->subframes[frame->parameter.active_subframe];
793 frame->RTSetActiveSubFrameCameraFocalPoint(subframe,frame->parameter.camera_focal_point);
800 frame->RTSetSingleView(frame->parameter.single_subframe_view);
810 frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
819 frame->title_actor->SetText(7,frame->parameter.frametitle.c_str());
820 frame->title_actor->Modified();
829 frame->window->SetWindowName(frame->parameter.wintitle.c_str());
837 auto renderer=mainthread->
framemap[mainthread->
iframe]->subframes[frame->parameter.camlinkthisframepos].renderer;
838 auto lrenderer=mainthread->
framemap[frame->parameter.camlinkframenum]->subframes[frame->parameter.camlinkframepos].renderer;
839 renderer->SetActiveCamera(lrenderer->GetActiveCamera());
847 for (
auto & framepair: mainthread->
framemap)
848 framepair.second->window->Finalize();
852 this->Interactor->TerminateApp();
885 frame->window = vtkSmartPointer<vtkRenderWindow>::New();
886 frame->window->SetWindowName(
"vtkfig");
889 frame->window->DoubleBufferOn();
891 frame->window->DoubleBufferOff();
893 frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
894 frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
896 frame->RTResetRenderers(
true);
899 frame->title_subframe.renderer->AddActor(frame->title_actor);
900 frame->title_actor->SetText(6,
"---");
901 frame->title_actor->SetText(7,frame->parameter.frametitle.c_str());
910 mainthread->
interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
911 auto style = vtkSmartPointer<MyInteractorStyle>::New();
912 style->SetFrame(frame);
913 mainthread->
interactor->SetInteractorStyle(style);
915 mainthread->
interactor->SetRenderWindow(frame->window);
917 auto callback = vtkSmartPointer<MyTimerCallback>::New();
920 mainthread->
interactor->AddObserver(vtkCommand::TimerEvent,callback);
953 std::this_thread::sleep_for (std::chrono::milliseconds(10));
974 std::unique_lock<std::mutex> lock(mainthread->
mutex);
977 cout <<
"s cmd: " <<
static_cast<int>(mainthread->
cmd) <<
" frame: " <<mainthread->
iframe<< endl;
983 switch(mainthread->
cmd)
995 mainthread->
communicator->SendInt(frame->parameter.nvpx);
996 mainthread->
communicator->SendInt(frame->parameter.nvpy);
997 frame->nvpx=frame->parameter.nvpx;
998 frame->nvpy=frame->parameter.nvpy;
1005 mainthread->
communicator->SendInt(frame->parameter.active_subframe);
1017 for (
auto framepair: mainthread->
framemap)
1018 for (
auto & figure: framepair.second->figures)
1030 mainthread->
communicator->SendString(frame->parameter.filename);
1037 mainthread->
communicator->SendInt(frame->parameter.winsize_x);
1038 mainthread->
communicator->SendInt(frame->parameter.winsize_y);
1045 mainthread->
communicator->SendInt(frame->parameter.winposition_x);
1046 mainthread->
communicator->SendInt(frame->parameter.winposition_y);
1053 mainthread->
communicator->SendString(frame->parameter.frametitle);
1061 mainthread->
communicator->SendString(frame->parameter.wintitle);
1069 mainthread->
communicator->SendString(frame->parameter.current_figure->SubClassName());
1070 mainthread->
communicator->SendInt(frame->parameter.current_figure->framepos);
1077 mainthread->
communicator->SendString(frame->parameter.current_figure->SubClassName());
1078 mainthread->
communicator->SendInt(frame->parameter.current_figure->framepos);
1086 mainthread->
communicator->SendInt(frame->parameter.camlinkthisframepos);
1087 mainthread->
communicator->SendInt(frame->parameter.camlinkframenum);
1088 mainthread->
communicator->SendInt(frame->parameter.camlinkframepos);
1108 cout <<
"s term" << endl;
1119 cout <<
"s cmd: " <<
static_cast<int>(mainthread->
cmd) << endl;
1120 throw std::runtime_error(
"wrong command on server");
1142 std::this_thread::sleep_for (std::chrono::milliseconds(5));
void Terminate(void)
Terminate thread.
vtkSmartPointer< Communicator > communicator
Communicator object for communication with cliend.
int lastframenum
Number of last frame created.
virtual void OnChar()
Overwrite keyboard callback.
bool communication_blocked
space down state ?
static MainThread * CreateMainThread()
Start thread.
double timer_interval
Timer interval for timer callback.
static MyTimerCallback * New()
static MainThread * mainthread
"This" thread
void Show()
Show all frames aka nonblocking event loop.
vtkSmartPointer< vtkRenderWindowInteractor > interactor
void OpenConnection(int port, int wtime)
Open connection to client.
virtual void OnConfigure()
void Start()
Spawn parallel thread for rendering or communication.
Communicator::Command cmd
Communication command.
std::condition_variable condition_variable
Condition variable signalizing finished command.
std::mutex mutex
Mutex to organize communication.
static void PrepareCommunicatorThread(MainThread *)
Prepare comm thread before start.
void Update()
Update all figures in all frames.
std::shared_ptr< std::thread > thread
std::thread which runs rendering resp. communication
bool double_buffering
Use of double buffering.
bool connection_open
State of connection to client.
friend class MyInteractorStyle
static void PrepareRenderThread(MainThread *)
Prepare render thread before start.
virtual void OnMouseMove()
Overwrite mouse move.
Timer callback handling communication with render thread.
int debug_level
Debug level for client communication.
friend class MyTimerCallback
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId, void *vtkNotUsed(callData))
virtual void OnLeftButtonUp()
Overwrite left button up.
void Interact()
Blocking event loop demanding user interaction unblocked by space key.
void AddFrame(Frame *frame)
Add frame to be handeled by thread.
static void RenderThread(MainThread *)
Callback function for render thread.
Main communication thread.
bool try_running_multithreaded
Toggle multithreaded/single (at startup)
static MyInteractorStyle * New()
void RemoveFrame(Frame *frame)
Remove frame from thread.
Provide a framework wrapping window+interactor+renderers from vtk.
static void DeleteMainThread()
Kill the thread.
virtual void OnLeftButtonDown()
Overwrite left button down.
void SendCommand(int iframe, const std::string from, Communicator::Command cmd)
Communication with render thread.
static void CommunicatorThread(MainThread *)
Callback function for communicator thread.
std::map< int, Frame * > framemap
Map of all frames handeled by thread.
bool running_multithreaded
Thread state.
int iframe
Frame number as parameter during communication.
Define Frame class providing a window for rendering.
static void CommunicatorThreadCallback(MainThread *)
Callback function for communicator thread if multithreading is off.
vtkfig specific keybord and mouse interaction
static void RTAddFrame(MainThread *mt, int iframe)
Add frame, to be called from render thread.
static constexpr const char * KeyboardHelp
Help string printed when pressing "h"/"?".