Skip to content

Commit 55267ed

Browse files
committed
add orthographic camera
1 parent 3037022 commit 55267ed

File tree

8 files changed

+238
-26
lines changed

8 files changed

+238
-26
lines changed

include/sapien/sapien_renderer/camera_component.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
#include "image.h"
44
#include "sapien/math/mat.h"
55
#include "sapien/math/pose.h"
6+
#include <map>
67
#include <svulkan2/renderer/renderer_base.h>
78
#include <svulkan2/scene/camera.h>
89
#include <variant>
9-
#include <map>
1010

1111
namespace sapien {
1212
class Entity;
1313
namespace sapien_renderer {
1414
struct SapienRenderCameraInternal;
1515
class SapienRenderTexture;
1616

17+
enum class CameraMode { ePerspective, eOrthographic };
18+
1719
class SapienRenderCameraComponent : public Component {
1820
public:
1921
SapienRenderCameraComponent(uint32_t width, uint32_t height, std::string const &shaderDir);
@@ -38,6 +40,11 @@ class SapienRenderCameraComponent : public Component {
3840
inline float getPrincipalPointY() const { return mCy; }
3941
inline float getSkew() const { return mSkew; }
4042

43+
inline float getOrthoLeft() const { return mLeft; }
44+
inline float getOrthoRight() const { return mRight; }
45+
inline float getOrthoBottom() const { return mBottom; }
46+
inline float getOrthoTop() const { return mTop; }
47+
4148
Mat4 getModelMatrix() const;
4249
Mat4 getProjectionMatrix() const;
4350
Mat3 getIntrinsicMatrix() const;
@@ -54,6 +61,12 @@ class SapienRenderCameraComponent : public Component {
5461
void setPrincipalPoint(float cx, float cy);
5562
void setSkew(float s);
5663

64+
void setOrthographicParameters(float near, float far, float top);
65+
void setOrthographicParameters(float near, float far, float left, float right, float bottom,
66+
float top);
67+
68+
inline CameraMode getMode() const { return mMode; }
69+
5770
void takePicture();
5871
std::vector<std::string> getImageNames() const;
5972
SapienRenderImageCpu getImage(std::string const &name);
@@ -85,6 +98,9 @@ class SapienRenderCameraComponent : public Component {
8598
SapienRenderCameraComponent &operator=(SapienRenderCameraComponent const &&) = delete;
8699

87100
private:
101+
CameraMode mMode{CameraMode::ePerspective};
102+
void checkMode(CameraMode mode) const;
103+
88104
uint32_t mWidth{};
89105
uint32_t mHeight{};
90106
float mFx{};
@@ -94,6 +110,13 @@ class SapienRenderCameraComponent : public Component {
94110
float mNear{};
95111
float mFar{};
96112
float mSkew{};
113+
114+
// ortho only
115+
float mLeft{};
116+
float mRight{};
117+
float mBottom{};
118+
float mTop{};
119+
97120
std::string mShaderDir;
98121

99122
std::map<std::string, std::variant<int, float>> mProperties;
@@ -112,4 +135,3 @@ class SapienRenderCameraComponent : public Component {
112135

113136
} // namespace sapien_renderer
114137
} // namespace sapien
115-

include/sapien/sapien_renderer/window.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#pragma once
2+
#include "camera_component.h"
23
#include "image.h"
34
#include "material.h"
45
#include "sapien/math/mat.h"
@@ -60,6 +61,8 @@ class SapienRendererWindow {
6061
void setCameraParameters(float near, float far, float fovy);
6162
void setCameraIntrinsicParameters(float near, float far, float fx, float fy, float cx, float cy,
6263
float skew);
64+
void setCameraOrthoParameters(float near, float far, float top);
65+
CameraMode getCameraMode();
6366

6467
void setCameraPose(Pose const &pose);
6568
Pose getCameraPose();
@@ -85,6 +88,7 @@ class SapienRendererWindow {
8588
float getCameraNear();
8689
float getCameraFar();
8790
float getCameraFovy();
91+
float getCameraOrthoTop();
8892

8993
glm::mat4 getCameraProjectionMatrix();
9094
Mat4 getCameraModelMatrix();

python/py_package/__init__.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ from . import utils
3434
from . import version
3535
from . import wrapper
3636
__all__ = ['ActorBuilder', 'ArticulationBuilder', 'Component', 'CudaArray', 'Device', 'Engine', 'Entity', 'Path', 'PinocchioModel', 'Pose', 'SapienRenderer', 'Scene', 'SceneConfig', 'System', 'Widget', 'asset', 'internal_renderer', 'math', 'os', 'physx', 'pkg_resources', 'platform', 'profile', 'pysapien', 'pysapien_pinocchio', 'render', 'set_log_level', 'simsense', 'utils', 'version', 'warn', 'wrapper']
37-
__version__: str = '3.0.0.dev20240516+9b8c9cc0'
37+
__version__: str = '3.0.0.dev20240520+3037022b'
3838
__warningregistry__: dict = {'version': 0}

python/py_package/pysapien/render.pyi

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class RenderCameraComponent(sapien.pysapien.Component):
6969
"""
7070
def get_local_pose(self) -> sapien.pysapien.Pose:
7171
...
72+
def get_mode(self) -> typing.Literal['perspective', 'orthographic']:
73+
...
7274
def get_model_matrix(self) -> numpy.ndarray[tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.float32]]:
7375
"""
7476
Get model matrix (inverse of extrinsic matrix) used in rendering (Y up, Z back)
@@ -118,6 +120,12 @@ class RenderCameraComponent(sapien.pysapien.Component):
118120
...
119121
def set_near(self, near: float) -> None:
120122
...
123+
@typing.overload
124+
def set_orthographic_parameters(self, near: float, far: float, top: float) -> None:
125+
...
126+
@typing.overload
127+
def set_orthographic_parameters(self, near: float, far: float, left: float, right: float, bottom: float, top: float) -> None:
128+
...
121129
def set_perspective_parameters(self, near: float, far: float, fx: float, fy: float, cx: float, cy: float, skew: float) -> None:
122130
...
123131
def set_principal_point(self, cx: float, cy: float) -> None:
@@ -169,6 +177,21 @@ class RenderCameraComponent(sapien.pysapien.Component):
169177
def height(self) -> int:
170178
...
171179
@property
180+
def mode(self) -> typing.Literal['perspective', 'orthographic']:
181+
...
182+
@property
183+
def ortho_bottom(self) -> float:
184+
...
185+
@property
186+
def ortho_left(self) -> float:
187+
...
188+
@property
189+
def ortho_right(self) -> float:
190+
...
191+
@property
192+
def ortho_top(self) -> float:
193+
...
194+
@property
172195
def width(self) -> int:
173196
...
174197
class RenderCameraGroup:
@@ -844,6 +867,8 @@ class RenderWindow:
844867
...
845868
def resize(self, width: int, height: int) -> None:
846869
...
870+
def set_camera_orthographic_parameters(self, near: float, far: float, top: float) -> None:
871+
...
847872
def set_camera_parameters(self, near: float, far: float, fovy: float) -> None:
848873
...
849874
def set_camera_pose(self, pose: sapien.pysapien.Pose) -> None:
@@ -896,6 +921,9 @@ class RenderWindow:
896921
def alt(self) -> bool:
897922
...
898923
@property
924+
def camera_mode(self) -> typing.Literal['perspective', 'orthographic']:
925+
...
926+
@property
899927
def ctrl(self) -> bool:
900928
...
901929
@property
@@ -925,6 +953,9 @@ class RenderWindow:
925953
def near(self) -> float:
926954
...
927955
@property
956+
def ortho_top(self) -> float:
957+
...
958+
@property
928959
def shift(self) -> bool:
929960
...
930961
@property

python/py_package/utils/viewer/control_window.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ def single_step(self, _):
201201
self._single_step = True
202202

203203
def copy_camera_settings(self, _=None):
204+
if self.orthographic:
205+
print('copying from orthographic camera is not supported yet')
206+
return
207+
204208
p = self.window.get_camera_position()
205209
q = self.window.get_camera_rotation()
206210
width, height = self.window.size
@@ -276,7 +280,19 @@ def build(self):
276280
.append(
277281
self.ui_camera,
278282
self.ui_camera_image,
279-
R.UISliderAngle().Label("FOV Y").Min(1).Max(179).Bind(self, "fovy"),
283+
R.UICheckbox().Label("Orthographic").Bind(self, "orthographic"),
284+
R.UIConditional()
285+
.Bind(self, "orthographic")
286+
.append(
287+
R.UISliderFloat()
288+
.Label("Ortho Scale")
289+
.Min(0.1)
290+
.Max(10)
291+
.Bind(self, "ortho_scale"),
292+
),
293+
R.UIConditional().Bind(self, "_perspective").append(
294+
R.UISliderAngle().Label("FOV Y").Min(1).Max(179).Bind(self, "fovy"),
295+
),
280296
R.UIButton()
281297
.Label("Copy Camera Settings")
282298
.Callback(self.copy_camera_settings),
@@ -772,6 +788,35 @@ def _clear_camera_linesets(self):
772788
render_scene.remove_node(n)
773789
self.camera_linesets = []
774790

791+
@property
792+
def orthographic(self):
793+
return self.window.camera_mode == "orthographic"
794+
795+
@property
796+
def _perspective(self):
797+
return not self.orthographic
798+
799+
@orthographic.setter
800+
def orthographic(self, v):
801+
if v:
802+
self.window.set_camera_orthographic_parameters(
803+
self.window.near, self.window.far, 1
804+
)
805+
else:
806+
self.window.set_camera_parameters(
807+
self.window.near, self.window.far, np.pi / 3
808+
)
809+
810+
@property
811+
def ortho_scale(self):
812+
return self.window.ortho_top
813+
814+
@ortho_scale.setter
815+
def ortho_scale(self, v):
816+
self.window.set_camera_orthographic_parameters(
817+
self.window.near, self.window.far, v
818+
)
819+
775820
@property
776821
def fovy(self):
777822
return self.window.fovy

python/pybind/sapien_renderer.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,35 @@ using namespace sapien;
1515
using namespace sapien::sapien_renderer;
1616

1717
namespace pybind11::detail {
18+
19+
template <> struct type_caster<CameraMode> {
20+
PYBIND11_TYPE_CASTER(CameraMode, _("typing.Literal['perspective', 'orthographic']"));
21+
22+
bool load(py::handle src, bool convert) {
23+
std::string name = py::cast<std::string>(src);
24+
if (name == "perspective" || name == "pers") {
25+
value = CameraMode::ePerspective;
26+
return true;
27+
} else if (name == "orthographic" || name == "ortho") {
28+
value = CameraMode::eOrthographic;
29+
return true;
30+
}
31+
return false;
32+
}
33+
34+
static py::handle cast(CameraMode const &src, py::return_value_policy policy,
35+
py::handle parent) {
36+
switch (src) {
37+
case CameraMode::ePerspective:
38+
return py::str("perspective").release();
39+
case CameraMode::eOrthographic:
40+
return py::str("orthographic").release();
41+
default:
42+
return py::str("none").release();
43+
}
44+
}
45+
};
46+
1847
template <> struct type_caster<svulkan2::renderer::RTRenderer::DenoiserType> {
1948
PYBIND11_TYPE_CASTER(svulkan2::renderer::RTRenderer::DenoiserType,
2049
_("typing.Literal['none', 'oidn', 'optix']"));
@@ -933,10 +962,26 @@ This function waits for any pending CUDA operations on cuda stream provided by :
933962
.def("get_skew", &SapienRenderCameraComponent::getSkew)
934963
.def("set_skew", &SapienRenderCameraComponent::setSkew, py::arg("skew"))
935964

965+
.def_property_readonly("mode", &SapienRenderCameraComponent::getMode)
966+
.def("get_mode", &SapienRenderCameraComponent::getMode)
936967
.def("set_perspective_parameters", &SapienRenderCameraComponent::setPerspectiveParameters,
937968
py::arg("near"), py::arg("far"), py::arg("fx"), py::arg("fy"), py::arg("cx"),
938969
py::arg("cy"), py::arg("skew"))
939970

971+
.def("set_orthographic_parameters",
972+
py::overload_cast<float, float, float>(
973+
&SapienRenderCameraComponent::setOrthographicParameters),
974+
py::arg("near"), py::arg("far"), py::arg("top"))
975+
.def("set_orthographic_parameters",
976+
py::overload_cast<float, float, float, float, float, float>(
977+
&SapienRenderCameraComponent::setOrthographicParameters),
978+
py::arg("near"), py::arg("far"), py::arg("left"), py::arg("right"), py::arg("bottom"),
979+
py::arg("top"))
980+
.def_property_readonly("ortho_left", &SapienRenderCameraComponent::getOrthoLeft)
981+
.def_property_readonly("ortho_right", &SapienRenderCameraComponent::getOrthoRight)
982+
.def_property_readonly("ortho_bottom", &SapienRenderCameraComponent::getOrthoBottom)
983+
.def_property_readonly("ortho_top", &SapienRenderCameraComponent::getOrthoTop)
984+
940985
.def("get_intrinsic_matrix", &SapienRenderCameraComponent::getIntrinsicMatrix,
941986
"Get 3x3 intrinsic camera matrix in OpenCV format.")
942987
.def("get_extrinsic_matrix", &SapienRenderCameraComponent::getExtrinsicMatrix,
@@ -1118,6 +1163,12 @@ consumer library. Make a copy if needed.
11181163
.def("set_intrinsic_parameters", &SapienRendererWindow::setCameraIntrinsicParameters,
11191164
py::arg("near"), py::arg("far"), py::arg("fx"), py::arg("fy"), py::arg("cx"),
11201165
py::arg("cy"), py::arg("skew"))
1166+
1167+
.def("set_camera_orthographic_parameters", &SapienRendererWindow::setCameraOrthoParameters,
1168+
py::arg("near"), py::arg("far"), py::arg("top"))
1169+
.def_property_readonly("camera_mode", &SapienRendererWindow::getCameraMode)
1170+
.def_property_readonly("ortho_top", &SapienRendererWindow::getCameraOrthoTop)
1171+
11211172
.def("set_camera_pose", &SapienRendererWindow::setCameraPose, py::arg("pose"))
11221173
.def("set_camera_position", &SapienRendererWindow::setCameraPosition, py::arg("position"))
11231174
.def("set_camera_rotation", &SapienRendererWindow::setCameraRotation, py::arg("quat"))

0 commit comments

Comments
 (0)