| 1300 | }; |
| 1301 | |
| 1302 | class Camera3D_Orbit : public Camera3D |
| 1303 | { |
| 1304 | public: |
| 1305 | inline void Pan(const olc::vf3d& vScreenMoved) |
| 1306 | { |
| 1307 | vecTarget -= vScreenMoved * fCameraRadius; |
| 1308 | vecPosition -= vScreenMoved * fCameraRadius; |
| 1309 | } |
| 1310 | |
| 1311 | inline void Zoom(const float fZoomDelta) |
| 1312 | { |
| 1313 | fCameraRadius *= fZoomDelta; |
| 1314 | } |
| 1315 | |
| 1316 | |
| 1317 | inline void Spin(const olc::vf2d& vScreenMoved) |
| 1318 | { |
| 1319 | vSpin = 2.0f * (vScreenMoved / vScreenSize) * fProjection_AspectRatio; |
| 1320 | } |
| 1321 | |
| 1322 | |
| 1323 | void Update() override |
| 1324 | { |
| 1325 | // Calculate where camera is given, target, position and up as usual |
| 1326 | vecViewForward = -(GetTarget() - GetPosition()).norm(); |
| 1327 | vecViewUp = (vecAxisUp - (vecAxisUp.dot(vecViewForward) * vecViewForward)).norm(); |
| 1328 | vecViewRight = vecViewUp.cross(vecViewForward); |
| 1329 | |
| 1330 | // Turn screen space gesture into projected 3D action... |
| 1331 | float fDirectionOfRotation = -std::atan2(vSpin.y, vSpin.x); |
| 1332 | float fMagnitudeOfRotation = vSpin.mag(); |
| 1333 | // Create an axis of rotation through the camera, that corresponds to gesture |
| 1334 | // Consider this a plane through the camera where mouse movement defines orthogonality |
| 1335 | olc::vf3d vRotation = vecViewUp * std::sin(fDirectionOfRotation) - vecViewRight * std::cos(fDirectionOfRotation); |
| 1336 | // Which gives us a 3rd "new" axis to complete lhr |
| 1337 | olc::vf3d vNewAxis = vecViewForward.cross(vRotation); |
| 1338 | |
| 1339 | // See https://github.com/processing/p5.js/blob/v1.11.3/src/webgl/p5.Camera.js#L3854 for |
| 1340 | // inspiration, but modified here in OLC land. Here we generate the Up vector around the |
| 1341 | // new axis to implement tilt, i.e. rotate the Up |
| 1342 | float s = std::sin(fMagnitudeOfRotation); |
| 1343 | float c = std::cos(fMagnitudeOfRotation); |
| 1344 | float dotFront = vecAxisUp.dot(vecViewForward); |
| 1345 | float dotSide = vecAxisUp.dot(vRotation); |
| 1346 | float ux = dotFront * c + dotSide * s; |
| 1347 | float uy = -dotFront * s + dotSide * c; |
| 1348 | float uz = vecAxisUp.dot(vNewAxis); |
| 1349 | // Forward + Side (Tilt Axis) + Tilted Up |
| 1350 | vecViewUp = ux * vecViewForward + uy * vRotation + uz * vNewAxis; |
| 1351 | |
| 1352 | // Panning, Recall Forward is normed and 90 degrees to Rotation |
| 1353 | vRotation *= -s; |
| 1354 | vecViewForward *= c; |
| 1355 | vecViewForward += vRotation; |
| 1356 | |
| 1357 | // Offset back to user's expectation of distance away from target |
| 1358 | vecViewForward *= fCameraRadius; |
| 1359 | vecPosition = vecViewForward + vecTarget; |
nothing calls this directly
no outgoing calls
no test coverage detected