Tissue Forge C++ 0.2.1
Interactive, particle-based physics, chemistry and biology modeling and simulation environment
Loading...
Searching...
No Matches
tfArcBallCamera.h
1/*******************************************************************************
2 * This file is part of Tissue Forge.
3 * Copyright (c) 2022-2024 T.J. Sego
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 ******************************************************************************/
19
50#ifndef Magnum_Examples_ArcBallCamera_h
51#define Magnum_Examples_ArcBallCamera_h
52
53#include <Corrade/Containers/EnumSet.h>
54#include <Corrade/Containers/LinkedList.h>
55
56#include <Magnum/Magnum.h>
57#include <limits>
58
59#include "tfArcBall.h"
60
61
62namespace TissueForge::rendering {
63
64
65 /* Arcball camera implementation integrated into the SceneGraph */
66 class ArcBallCamera : public ArcBall {
67 public:
68
69 enum class AspectRatioPolicy : UnsignedByte {
71 Extend,
72 Clip
73 };
74
76 const Vector3& cameraPosition, const Vector3& viewCenter,
77 const Vector3& upDir, Deg fov, const Magnum::Vector2i& windowSize,
78 const Magnum::Vector2i& viewportSize,
79 float nearClip = 0.01f, float farClip = std::numeric_limits<float>::infinity()
80 ) :
81 ArcBall{cameraPosition, viewCenter, upDir, fov, windowSize}
82 {
83 setAspectRatioPolicy(AspectRatioPolicy::Extend);
84 setProjectionMatrix(Matrix4::perspectiveProjection(fov, Vector2{windowSize}.aspectRatio(), nearClip, farClip));
85 setViewport(viewportSize);
86 }
87
88 /* Update screen and viewport size after the window has been resized */
89 void reshape(const Magnum::Vector2i& windowSize, const Magnum::Vector2i& viewportSize) {
90 _windowSize = windowSize;
91 setViewport(viewportSize);
92 }
93
94 auto cameraMatrix() {
95 return viewMatrix();
96 }
97
98 auto projectionMatrix() {
99 return _projectionMatrix;
100 }
101
102 void rotateDelta(const float *deltaX=NULL, const float *deltaY=NULL, const float *deltaZ=NULL) {
103 if(deltaZ) _targetQRotation = Magnum::Quaternion::rotation(Magnum::Rad(*deltaZ), Magnum::Vector3::zAxis()) * _targetQRotation;
104 if(deltaY) _targetQRotation = Magnum::Quaternion::rotation(Magnum::Rad(*deltaY), Magnum::Vector3::yAxis()) * _targetQRotation;
105 if(deltaX) _targetQRotation = Magnum::Quaternion::rotation(Magnum::Rad(*deltaX), Magnum::Vector3::xAxis()) * _targetQRotation;
106 }
107
108 void translateDelta(const Vector3 &deltaPos, const bool &absolute=false) {
109 if(absolute) _targetPosition += deltaPos;
110 else _targetPosition += _targetQRotation.inverted().transformVector(deltaPos);
111 }
112
113 void translateToOrigin() {
114 _targetPosition = Vector3(0.0);
115 }
116
117 void viewBottom(const float &viewDistance) {
118 rotateToAxis(Vector3::xAxis(-1.0f), viewDistance);
119 rotateByEulerAngles({0, 0, M_PI});
120 }
121
122 void viewTop(const float &viewDistance) {
123 rotateToAxis(Vector3::xAxis(), viewDistance);
124 }
125
126 void viewLeft(const float &viewDistance) {
127 viewTop(viewDistance);
128 rotateByEulerAngles({-0.5f*M_PI, 0, 0.5f*M_PI});
129 }
130
131 void viewRight(const float &viewDistance) {
132 viewLeft(viewDistance);
133 rotateByEulerAngles({0, 0, M_PI});
134 }
135
136 void viewBack(const float &viewDistance) {
137 viewTop(viewDistance);
138 rotateByEulerAngles({-0.5f*M_PI, 0, M_PI});
139 }
140
141 void viewFront(const float &viewDistance) {
142 viewBack(viewDistance);
143 rotateByEulerAngles({0, 0, M_PI});
144 }
145
146 fVector3 cposition() {
147 return _currentPosition;
148 }
149
150 fQuaternion crotation() {
151 return _currentQRotation;
152 }
153
154 float czoom() {
155 return _currentZooming;
156 }
157
158 void setViewParameters(const fVector3 &position, const fQuaternion &rotation, const float &zoom) {
159 _targetPosition = position;
160 _targetQRotation = rotation;
161 _targetZooming = zoom;
162 }
163
164 private:
165
166 Magnum::Matrix4 _projectionMatrix;
167
168 Magnum::Matrix4 _rawProjectionMatrix;
169
170 AspectRatioPolicy _aspectRatioPolicy;
171
172 Magnum::Vector2i _viewport;
173
174 void setViewport(const Magnum::Vector2i& size) {
175 _viewport = size;
176 fixAspectRatio();
177 }
178
179 void setProjectionMatrix(const Matrix4& matrix) {
180 _rawProjectionMatrix = matrix;
181 fixAspectRatio();
182 }
183
184 void setAspectRatioPolicy(AspectRatioPolicy policy) {
185 _aspectRatioPolicy = policy;
186 fixAspectRatio();
187 }
188
189 static Matrix4 aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionScale, const Magnum::Vector2i& viewport) {
190
191 /* Don't divide by zero / don't preserve anything */
192 if(projectionScale.x() == 0 || projectionScale.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved)
193 return {};
194
195 CORRADE_INTERNAL_ASSERT((projectionScale > Vector2(0)).all() && (viewport > Magnum::Vector2i(0)).all());
196
197 Vector2 relativeAspectRatio = Vector2(viewport)*projectionScale;
198
199 /* Extend on larger side = scale larger side down
200 Clip on smaller side = scale smaller side up */
201 return Matrix4::scaling(Vector3::pad(
202 (relativeAspectRatio.x() > relativeAspectRatio.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ?
203 Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), float(1)) :
204 Vector2(float(1), relativeAspectRatio.x()/relativeAspectRatio.y()), float(1)));
205
206 };
207
208 void fixAspectRatio() {
209 _projectionMatrix = aspectRatioFix(_aspectRatioPolicy, {Math::abs(_rawProjectionMatrix[0].x()), Math::abs(_rawProjectionMatrix[1].y())}, _viewport)*_rawProjectionMatrix;
210 }
211
212 };
213
214}
215
216#endif
Definition tfArcBallCamera.h:66
AspectRatioPolicy
Definition tfArcBallCamera.h:69
Definition tfArcBall.h:68
void rotateByEulerAngles(const Vector3 &eulerAngles)
Tissue Forge rendering and visualization.
Definition tfAngle.h:38