Skip to content

Commit a39b590

Browse files
committed
Add rotate_up command & binding
1 parent 687118c commit a39b590

5 files changed

Lines changed: 100 additions & 2 deletions

File tree

library/private/window_impl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ class window_impl : public window
7373
*/
7474
void InitializeUpVector();
7575

76+
/**
77+
* Implementation only API.
78+
* Rotate the up vector around the specified axis.
79+
* @param axis 0=X, 1=Y, 2=Z
80+
* @param angleDegrees rotation angle in degrees
81+
*/
82+
void RotateUpVector(int axis, double angleDegrees);
83+
7684
/**
7785
* Implementation only API.
7886
* Set the importer on the internal renderer

library/src/interactor_impl.cxx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,35 @@ interactor& interactor_impl::initCommands()
11131113
},
11141114
command_documentation_t{ "azimuth_camera value", "tilt the camera right or left" });
11151115

1116+
this->addCommand(
1117+
"rotate_up",
1118+
[&](const std::vector<std::string>& args)
1119+
{
1120+
check_args(args, 2, "rotate_up");
1121+
int axis = -1;
1122+
if (args[0] == "x" || args[0] == "X")
1123+
{
1124+
axis = 0;
1125+
}
1126+
else if (args[0] == "y" || args[0] == "Y")
1127+
{
1128+
axis = 1;
1129+
}
1130+
else if (args[0] == "z" || args[0] == "Z")
1131+
{
1132+
axis = 2;
1133+
}
1134+
else
1135+
{
1136+
throw interactor::invalid_args_exception("rotate_up: axis must be x, y, or z");
1137+
}
1138+
double angle = options::parse<double>(args[1]);
1139+
this->Internals->Window.RotateUpVector(axis, angle);
1140+
this->Internals->Style->ResetTemporaryUp();
1141+
},
1142+
command_documentation_t{ "rotate_up x/y/z angle", "rotate the scene up vector around an axis" },
1143+
std::bind(complNames, std::placeholders::_1, std::vector<std::string>{ "x", "y", "z" }));
1144+
11161145
this->addCommand(
11171146
"increase_light_intensity",
11181147
[&](const std::vector<std::string>&) { this->Internals->IncreaseLightIntensity(false); },
@@ -1608,9 +1637,11 @@ interactor& interactor_impl::initBindings()
16081637
this->addBinding({mod_t::ANY, "1"}, "set_camera front", "Camera", std::bind(docStr, "Front View camera"));
16091638
this->addBinding({mod_t::ANY, "2"}, "elevation_camera -90", "Camera", std::bind(docStr, "Rotate camera down"));
16101639
this->addBinding({mod_t::ANY, "3"}, "set_camera right", "Camera", std::bind(docStr, "Right View camera"));
1611-
this->addBinding({mod_t::ANY, "4"}, "roll_camera -90", "Camera", std::bind(docStr, "Rotate camera right"));
1640+
this->addBinding({mod_t::NONE, "4"}, "roll_camera -90", "Camera", std::bind(docStr, "Rotate camera right"));
1641+
this->addBinding({mod_t::CTRL, "4"}, "rotate_up x 90", "Scene", std::bind(docStr, "Rotate scene up +90 around X"));
16121642
this->addBinding({mod_t::ANY, "5"}, "toggle scene.camera.orthographic", "Camera", std::bind(docTglOpt, "Orthographic Projection", std::cref(opts.scene.camera.orthographic)), f3d::interactor::BindingType::TOGGLE);
1613-
this->addBinding({mod_t::ANY, "6"}, "roll_camera 90", "Camera", std::bind(docStr, "Rotate camera left"));
1643+
this->addBinding({mod_t::NONE, "6"}, "roll_camera 90", "Camera", std::bind(docStr, "Rotate camera left"));
1644+
this->addBinding({mod_t::CTRL, "6"}, "rotate_up x -90", "Scene", std::bind(docStr, "Rotate scene up -90 around X"));
16141645
this->addBinding({mod_t::ANY, "7"}, "set_camera top", "Camera", std::bind(docStr, "Top View camera"));
16151646
this->addBinding({mod_t::ANY, "8"}, "elevation_camera 90", "Camera", std::bind(docStr, "Rotate camera up"));
16161647
this->addBinding({mod_t::ANY, "9"}, "set_camera isometric", "Camera", std::bind(docStr, "Isometric View camera"));

library/src/window_impl.cxx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ void window_impl::InitializeUpVector()
211211
this->Internals->Renderer->InitializeUpVector(this->Internals->Options.scene.up_direction);
212212
}
213213

214+
//----------------------------------------------------------------------------
215+
void window_impl::RotateUpVector(int axis, double angleDegrees)
216+
{
217+
this->Internals->Renderer->RotateUpVector(axis, angleDegrees);
218+
}
219+
214220
//----------------------------------------------------------------------------
215221
window_impl::Type window_impl::getType()
216222
{

vtkext/private/module/vtkF3DRenderer.cxx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,51 @@ void vtkF3DRenderer::InitializeUpVector(const std::vector<double>& upVec)
405405
this->SetEnvironmentRight(this->RightVector);
406406
}
407407

408+
//----------------------------------------------------------------------------
409+
void vtkF3DRenderer::RotateUpVector(int axis, double angleDegrees)
410+
{
411+
if (axis < 0 || axis > 2)
412+
{
413+
F3DLog::Print(F3DLog::Severity::Warning, "Invalid axis for rotate_up, must be 0 (X), 1 (Y), or 2 (Z)");
414+
return;
415+
}
416+
417+
vtkNew<vtkTransform> rotationTransform;
418+
double axisVec[3] = { 0.0, 0.0, 0.0 };
419+
axisVec[axis] = 1.0;
420+
rotationTransform->RotateWXYZ(angleDegrees, axisVec);
421+
422+
double newUp[3];
423+
rotationTransform->TransformPoint(this->UpVector, newUp);
424+
vtkMath::Normalize(newUp);
425+
426+
double newRight[3];
427+
rotationTransform->TransformPoint(this->RightVector, newRight);
428+
vtkMath::Normalize(newRight);
429+
430+
double front[3];
431+
vtkMath::Cross(newRight, newUp, front);
432+
vtkMath::Normalize(front);
433+
434+
vtkMath::Cross(newUp, front, newRight);
435+
vtkMath::Normalize(newRight);
436+
437+
this->UpVector[0] = newUp[0];
438+
this->UpVector[1] = newUp[1];
439+
this->UpVector[2] = newUp[2];
440+
this->RightVector[0] = newRight[0];
441+
this->RightVector[1] = newRight[1];
442+
this->RightVector[2] = newRight[2];
443+
444+
this->SkyboxActor->SetFloorPlane(this->UpVector[0], this->UpVector[1], this->UpVector[2], 0.0);
445+
this->SkyboxActor->SetFloorRight(front[0], front[1], front[2]);
446+
447+
this->SetEnvironmentUp(this->UpVector);
448+
this->SetEnvironmentRight(this->RightVector);
449+
450+
this->GridConfigured = false;
451+
}
452+
408453
//----------------------------------------------------------------------------
409454
void vtkF3DRenderer::ConfigureRenderPasses()
410455
{

vtkext/private/module/vtkF3DRenderer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ class vtkF3DRenderer : public vtkOpenGLRenderer
208208
*/
209209
void InitializeUpVector(const std::vector<double>& upVec);
210210

211+
/**
212+
* Rotate the up vector around the specified axis by the given angle (degrees).
213+
* Updates skybox and environment orientation. Does NOT reset camera.
214+
* @param axis 0=X, 1=Y, 2=Z
215+
* @param angleDegrees rotation angle in degrees
216+
*/
217+
void RotateUpVector(int axis, double angleDegrees);
218+
211219
/**
212220
* Compute bounds of visible props as transformed by given matrix.
213221
*/

0 commit comments

Comments
 (0)