diff --git a/engines/titanic/star_control/camera_auto_mover.cpp b/engines/titanic/star_control/camera_auto_mover.cpp index bcb94d27c28f..aa29fa0e8ecc 100644 --- a/engines/titanic/star_control/camera_auto_mover.cpp +++ b/engines/titanic/star_control/camera_auto_mover.cpp @@ -50,10 +50,7 @@ void CCameraAutoMover::proc2(const FVector &oldPos, const FVector &newPos, _destPos = newPos; _posDelta = _destPos - _srcPos; float temp = 0.0; - if (!_posDelta.normalize(temp)) { // Do the normalization, put the scale amount in temp, - // but if it is unsuccessful, crash - assert(temp); - } + _posDelta.normalize(temp); // Do the normalization, put the scale amount in temp _distance = temp; _active = false; _field34 = false; @@ -92,24 +89,25 @@ void CCameraAutoMover::setPath(const FVector &srcV, const FVector &destV, const _transitionPercent = 1.0; } -void CCameraAutoMover::proc6(int val1, int val2, float val) { +void CCameraAutoMover::calcSpeeds(int val1, int val2, float distance) { + // Usually val1 and val2 are small where as distance can be large _field44 = val1; - _field4C = val1 + 62; - _field38 = val / (double)(val1 + val2 * 2); - _field40 = 31; - _field48 = 31; + _field4C = val1 + 2 * nMoverTransitions; // For _nMoverTransitions = 32 this second value was 64, + // should it always be x2 _nMoverTransitions? + _field38 = distance / (double)(val1 + val2 * 2); + _field40 = nMoverTransitions-1; + _field48 = nMoverTransitions-1; _field3C = (double)val2 * _field38; // Calculate the speeds for a graduated movement between stars - double base = 0.0, total = 0.0; - _speeds.resize(32); - for (int idx = 31; idx >= 0; --idx) { - _speeds[idx] = pow(base, 4.0); + double base = 0.0, total = 0.0, power = 4.0, baseInc = 0.03125; + for (int idx = nMoverTransitions - 1; idx >= 0; --idx) { + _speeds[idx] = pow(base, power); total += _speeds[idx]; - base += 0.03125; + base += baseInc; } - for (int idx = 0; idx < 32; ++idx) { + for (int idx = 0; idx < nMoverTransitions; ++idx) { _speeds[idx] = _speeds[idx] * _field3C / total; } } diff --git a/engines/titanic/star_control/camera_auto_mover.h b/engines/titanic/star_control/camera_auto_mover.h index dc9cf6df454b..210bd7409100 100644 --- a/engines/titanic/star_control/camera_auto_mover.h +++ b/engines/titanic/star_control/camera_auto_mover.h @@ -31,6 +31,7 @@ namespace Titanic { class CErrorCode; class FMatrix; +const int nMoverTransitions = 32; // The number of vector transitions when doing a mover change is fixed /** * Base class for automatic movement of the starview camera @@ -49,7 +50,7 @@ class CCameraAutoMover { int _field44; int _field48; int _field4C; - Common::Array _speeds; + double _speeds[nMoverTransitions]; int _field54; double _transitionPercent; double _transitionPercentInc; @@ -63,7 +64,11 @@ class CCameraAutoMover { virtual void proc3(const FMatrix &srcOrient, const FMatrix &destOrient); virtual void setPath(const FVector &srcV, const FVector &destV, const FMatrix &orientation); virtual int proc5(CErrorCode &errorCode, FVector &pos, FMatrix &orientation) { return 2; } - virtual void proc6(int val1, int val2, float val); + /** + * Given a distance to cover, determines a bunch of speeds for a gradual transition + * from one position to another (the mover). The speeds go from fast to slow + */ + virtual void calcSpeeds(int val1, int val2, float distance); bool isActive() const { return _active; } }; diff --git a/engines/titanic/star_control/fmatrix.cpp b/engines/titanic/star_control/fmatrix.cpp index 470569c88d62..e633db5dd07f 100644 --- a/engines/titanic/star_control/fmatrix.cpp +++ b/engines/titanic/star_control/fmatrix.cpp @@ -124,7 +124,7 @@ void FMatrix::set(const DVector &row1, const DVector &row2, const DVector &row3) void FMatrix::set(const FVector &v) { _row3 = v; - _row2 = _row3.fn1(); + _row2 = _row3.swapComponents(); _row1 = _row3.crossProduct(_row2); diff --git a/engines/titanic/star_control/fvector.cpp b/engines/titanic/star_control/fvector.cpp index 75d30748d215..142d9ea3c05d 100644 --- a/engines/titanic/star_control/fvector.cpp +++ b/engines/titanic/star_control/fvector.cpp @@ -31,7 +31,7 @@ namespace Titanic { FVector::FVector(const DVector &src) : _x(src._x), _y(src._y), _z(src._z) { } -FVector FVector::fn1() const { +FVector FVector::swapComponents() const { return FVector( (ABS(_x - _y) < 0.00001 && ABS(_y - _z) < 0.00001 && ABS(_x - _z) < 0.00001) ? -_y : _y, @@ -78,7 +78,7 @@ float FVector::getDistance(const FVector &src) const { return sqrt(xd * xd + yd * yd + zd * zd); } -FVector FVector::fn5(const FPose &pose) const { +FVector FVector::MatProdRowVect(const FPose &pose) const { FVector v; v._x = pose._row2._x * _y + pose._row3._x * _z + pose._row1._x * _x + pose._vector._x; v._y = pose._row2._y * _y + pose._row3._y * _z + pose._row1._y * _x + pose._vector._y; diff --git a/engines/titanic/star_control/fvector.h b/engines/titanic/star_control/fvector.h index f93ac60c26fc..ed5789ac7e48 100644 --- a/engines/titanic/star_control/fvector.h +++ b/engines/titanic/star_control/fvector.h @@ -51,7 +51,12 @@ class FVector { _x = _y = _z = 0.0; } - FVector fn1() const; + /** + * Returns a vector with all components of this vector circularlly rotated up 1. + * this x being _y, this y being _z, and this z being _x. A sign change may also + * be done on x/_y based on some conditions. + */ + FVector swapComponents() const; /** * Calculates the cross-product between this matrix and a passed one @@ -80,7 +85,11 @@ class FVector { */ float getDistance(const FVector &src) const; - FVector fn5(const FPose &pose) const; + /** + * Returns a vector that is this vector on the left as a row vector + * times the 3x4 affine matrix on the right. + */ + FVector MatProdRowVect(const FPose &pose) const; /** * Returns true if the passed vector equals this one diff --git a/engines/titanic/star_control/marked_auto_mover.cpp b/engines/titanic/star_control/marked_auto_mover.cpp index e3ab2b4f2006..0a1a7e4d4964 100644 --- a/engines/titanic/star_control/marked_auto_mover.cpp +++ b/engines/titanic/star_control/marked_auto_mover.cpp @@ -32,24 +32,22 @@ void CMarkedAutoMover::proc2(const FVector &oldPos, const FVector &newPos, CCameraAutoMover::proc2(oldPos, newPos, oldOrientation, newOrientation); double distance = _distance; - if (distance > 0.0) { + _active = true; + _field34 = true; + calcSpeeds(120, 4, distance); + + + _orientationChanger.load(oldOrientation, newOrientation); + _transitionPercent = 0.0; + + if (_field4C == 0) { + _transitionPercentInc = 0.1; + _active = true; + } else { + _transitionPercentInc = 1.0 / _field4C; _active = true; - _field34 = true; - proc6(120, 4, distance); } - if (newPos != oldPos) { - _orientationChanger.load(oldOrientation, newOrientation); - _transitionPercent = 0.0; - - if (_field4C == 0) { - _transitionPercentInc = 0.1; - _active = true; - } else { - _transitionPercentInc = 1.0 / _field4C; - _active = true; - } - } } int CMarkedAutoMover::proc5(CErrorCode &errorCode, FVector &pos, FMatrix &orientation) { @@ -76,7 +74,7 @@ int CMarkedAutoMover::proc5(CErrorCode &errorCode, FVector &pos, FMatrix &orient errorCode.set(); return 1; } else if (_field48 >= 0) { - double speedVal = _speeds[31 - _field48]; + double speedVal = _speeds[nMoverTransitions - 1 - _field48]; pos += _posDelta * speedVal; getVectorOnPath(pos); diff --git a/engines/titanic/star_control/star_camera.cpp b/engines/titanic/star_control/star_camera.cpp index f1bf24b90e36..68427a34522d 100644 --- a/engines/titanic/star_control/star_camera.cpp +++ b/engines/titanic/star_control/star_camera.cpp @@ -269,10 +269,10 @@ void CStarCamera::setViewportAngle(const FPoint &angles) { tempV5 -= row1; tempV6 -= row1; - tempV1 = tempV1.fn5(pose); - tempV4 = tempV4.fn5(pose); - tempV5 = tempV5.fn5(pose); - tempV6 = tempV6.fn5(pose); + tempV1 = tempV1.MatProdRowVect(pose); + tempV4 = tempV4.MatProdRowVect(pose); + tempV5 = tempV5.MatProdRowVect(pose); + tempV6 = tempV6.MatProdRowVect(pose); tempV4 -= tempV1; tempV5 -= tempV1; @@ -450,9 +450,9 @@ void CStarCamera::deleteHandler() { } } -void CStarCamera::lockMarker1(FVector v1, FVector v2, FVector v3) { +bool CStarCamera::lockMarker1(FVector v1, FVector v2, FVector v3) { if (_starLockState != ZERO_LOCKED) - return; + return true; FVector tempV; double val1, val2, val3, val4, val5; @@ -487,11 +487,12 @@ void CStarCamera::lockMarker1(FVector v1, FVector v2, FVector v3) { CStarVector *sv = new CStarVector(this, v2); _mover->setVector(sv); + return true; } -void CStarCamera::lockMarker2(CViewport *viewport, const FVector &v) { +bool CStarCamera::lockMarker2(CViewport *viewport, const FVector &v) { if (_starLockState != ONE_LOCKED) - return; + return true; DAffine m2(X_AXIS, _matrix._row1); DVector tempV1 = v - _matrix._row1; @@ -567,7 +568,7 @@ void CStarCamera::lockMarker2(CViewport *viewport, const FVector &v) { m4._col2 -= m4._col1; m4._col4 -= m4._col1; - FMatrix m6 = _viewport.getOrientation(); + double unusedScale=0.0; if (!m4._col2.normalize(unusedScale) || @@ -581,32 +582,39 @@ void CStarCamera::lockMarker2(CViewport *viewport, const FVector &v) { m5.set(m4._col3, m4._col2, m4._col4); FVector newPos = m4._col1; - - if (_viewport._position != newPos) { - // Only change view if positions are different + FMatrix m6 = _viewport.getOrientation(); + + if (minDistance > 1.0e8) { + // The transition will do poorly in this case. + //removeLockedStar(); // undo locking 2nd star + _mover->proc8(_viewport._position, _viewport._position, m6, m6); + //CStarVector *sv = new CStarVector(this, v); + //_mover->setVector(sv); + return false; + } + else { _mover->proc8(_viewport._position, newPos, m6, m5); + CStarVector *sv = new CStarVector(this, v); + _mover->setVector(sv); + } - - CStarVector *sv = new CStarVector(this, v); - _mover->setVector(sv); + return true; } -void CStarCamera::lockMarker3(CViewport *viewport, const FVector &v) { +bool CStarCamera::lockMarker3(CViewport *viewport, const FVector &v) { if (_starLockState != TWO_LOCKED) - return; + return true; FMatrix newOr = viewport->getOrientation(); FMatrix oldOr = _viewport.getOrientation(); FVector newPos = viewport->_position; FVector oldPos = _viewport._position; - if (oldPos != newPos) { - // Only change view if positions are different - _mover->proc8(oldPos, newPos, oldOr, newOr); - } + _mover->proc8(oldPos, newPos, oldOr, newOr); CStarVector *sv = new CStarVector(this, v); _mover->setVector(sv); + return true; } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_camera.h b/engines/titanic/star_control/star_camera.h index 2d4ce57699ff..572995fc1be7 100644 --- a/engines/titanic/star_control/star_camera.h +++ b/engines/titanic/star_control/star_camera.h @@ -207,17 +207,17 @@ class CStarCamera { /** * Lock in the first matched star marker */ - void lockMarker1(FVector v1, FVector v2, FVector v3); + bool lockMarker1(FVector v1, FVector v2, FVector v3); /** * Lock in the second matched star marker */ - void lockMarker2(CViewport *viewport, const FVector &v); + bool lockMarker2(CViewport *viewport, const FVector &v); /** * Lock in the third and final matched star marker */ - void lockMarker3(CViewport *viewport, const FVector &v); + bool lockMarker3(CViewport *viewport, const FVector &v); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_view.cpp b/engines/titanic/star_control/star_view.cpp index 578cc00898d5..ec972d12b57d 100644 --- a/engines/titanic/star_control/star_view.cpp +++ b/engines/titanic/star_control/star_view.cpp @@ -397,6 +397,7 @@ void CStarView::lockStar() { CSurfaceArea surfaceArea(_videoSurface); FVector v1, v2, v3; double val = _starField->fn5(&surfaceArea, &_camera, v1, v2, v3); + bool lockSuccess = false; if (val > -1.0) { v1 -= surfaceArea._centroid; @@ -405,19 +406,22 @@ void CStarView::lockStar() { switch (_starField->getMatchedIndex()) { case -1: // First star match - _camera.lockMarker1(v1, v2, v3); + lockSuccess = _camera.lockMarker1(v1, v2, v3); + assert(lockSuccess); // lockMarker1 should always succeed _starField->incMatches(); break; case 0: // Second star match - _camera.lockMarker2(&_photoViewport, v2); - _starField->incMatches(); + lockSuccess = _camera.lockMarker2(&_photoViewport, v2); + if (lockSuccess) // lockMarker2 may have issues + _starField->incMatches(); break; case 1: // Third star match - _camera.lockMarker3(&_photoViewport, v2); + lockSuccess = _camera.lockMarker3(&_photoViewport, v2); + assert(lockSuccess); // lockMarker3 should always succeed _starField->incMatches(); break; diff --git a/engines/titanic/star_control/unmarked_auto_mover.cpp b/engines/titanic/star_control/unmarked_auto_mover.cpp index 71063fa615fd..424e143b58e1 100644 --- a/engines/titanic/star_control/unmarked_auto_mover.cpp +++ b/engines/titanic/star_control/unmarked_auto_mover.cpp @@ -42,7 +42,7 @@ void CUnmarkedAutoMover::setPath(const FVector &srcV, const FVector &destV, cons if (_distance > 8000.0) { _active = true; _field34 = 1; - proc6(120, 4, _distance - 8000.0); + calcSpeeds(120, 4, _distance - 8000.0); } FVector row3 = orientation._row3; @@ -148,7 +148,7 @@ int CUnmarkedAutoMover::proc5(CErrorCode &errorCode, FVector &pos, FMatrix &orie } if (_field48 >= 0) { - double speedVal = _speeds[31 - _field48]; + double speedVal = _speeds[nMoverTransitions - 1 - _field48]; v1._y = v2._y * speedVal; v1._z = v2._z * speedVal; v1._x = v2._x * speedVal; diff --git a/engines/titanic/star_control/viewport.cpp b/engines/titanic/star_control/viewport.cpp index 130d59d8d6c8..529b4bec3a7f 100644 --- a/engines/titanic/star_control/viewport.cpp +++ b/engines/titanic/star_control/viewport.cpp @@ -107,7 +107,7 @@ void CViewport::setPosition(const FVector &v) { } void CViewport::setPosition(const FPose &pose) { - _position = _position.fn5(pose); + _position = _position.MatProdRowVect(pose); _flag = false; } @@ -215,7 +215,7 @@ FVector CViewport::fn16(int index, const FVector &src) { FVector CViewport::fn17(int index, const FVector &src) { FVector dest; FPose pose = getPose(); - FVector tv = src.fn5(pose); + FVector tv = src.MatProdRowVect(pose); dest._x = (_valArray[index] + tv._x) * _centerVector._x / (_centerVector._y * tv._z); @@ -227,7 +227,7 @@ FVector CViewport::fn17(int index, const FVector &src) { FVector CViewport::fn18(int index, const FVector &src) { FVector dest; FPose pose = getRawPose(); - FVector tv = src.fn5(pose); + FVector tv = src.MatProdRowVect(pose); dest._x = (_valArray[index] + tv._x) * _centerVector._x / (_centerVector._y * tv._z);