diff --git a/bindings/pycvc/pycvc_scene.cpp b/bindings/pycvc/pycvc_scene.cpp index 1769a56..cc7aeb5 100644 --- a/bindings/pycvc/pycvc_scene.cpp +++ b/bindings/pycvc/pycvc_scene.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,38 @@ void render_png(SceneGraph &sg, const std::string &path, int width, int height) window->Finalize(); } +void render_png_camera(SceneGraph &sg, const std::string &path, int width, int height, double eye_x, + double eye_y, double eye_z, double focal_x, double focal_y, double focal_z, + double up_x, double up_y, double up_z, double view_angle, double clip_near, + double clip_far) { + // Like render_png, but sets an EXPLICIT camera (eye / focal / up + view angle + + // clip range) instead of ResetCamera() — so a caller can script a chase camera + // for frame-by-frame offscreen capture. Needs a GL context (offscreen is fine). + vtkNew renderer; + vtkNew window; + window->SetOffScreenRendering(1); + window->AddRenderer(renderer); + window->SetSize(width, height); + sg.setRenderer(renderer); + sg.processEvents(); + vtkCamera *cam = renderer->GetActiveCamera(); + cam->SetPosition(eye_x, eye_y, eye_z); + cam->SetFocalPoint(focal_x, focal_y, focal_z); + cam->SetViewUp(up_x, up_y, up_z); + cam->SetViewAngle(view_angle); + cam->SetClippingRange(clip_near, clip_far); + window->Render(); + vtkNew w2i; + w2i->SetInput(window); + w2i->Update(); + vtkNew writer; + writer->SetFileName(path.c_str()); + writer->SetInputConnection(w2i->GetOutputPort()); + writer->Write(); + sg.setRenderer(nullptr); + window->Finalize(); +} + void show(SceneGraph &sg, const std::string &title, int width, int height) { vtkNew renderer; vtkNew window; diff --git a/bindings/pycvc/pycvc_scene.h b/bindings/pycvc/pycvc_scene.h index 57ab4f9..fdd1e88 100644 --- a/bindings/pycvc/pycvc_scene.h +++ b/bindings/pycvc/pycvc_scene.h @@ -28,6 +28,14 @@ namespace pycvc { // events + frames the camera first. Needs a GL context (offscreen is fine). void render_png(SceneGraph &sg, const std::string &path, int width = 1024, int height = 768); +// Render one offscreen frame with an EXPLICIT camera (eye / focal-point / up + +// view angle + clip range) instead of auto-framing — for scripting a chase camera +// across a sequence of frames (e.g. capturing a drive to video). Offscreen is fine. +void render_png_camera(SceneGraph &sg, const std::string &path, int width, int height, double eye_x, + double eye_y, double eye_z, double focal_x, double focal_y, double focal_z, + double up_x, double up_y, double up_z, double view_angle = 30.0, + double clip_near = 1.0, double clip_far = 1e5); + // Open a blocking interactive window on `sg` (needs a display); returns when the // window closes. Don't call this in the embedded case — the host owns the loop. void show(SceneGraph &sg, const std::string &title = "pycvc_gl", int width = 1024,