[Scummvm-git-logs] scummvm master -> bbe4ef44749038293ba86de3ed001f5ff4ce2145

peterkohaut peterkohaut at users.noreply.github.com
Sun Mar 11 11:55:05 CET 2018


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
bbe4ef4474 BLADERUNNER: Added shadows


Commit: bbe4ef44749038293ba86de3ed001f5ff4ce2145
    https://github.com/scummvm/scummvm/commit/bbe4ef44749038293ba86de3ed001f5ff4ce2145
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2018-03-11T11:54:01+01:00

Commit Message:
BLADERUNNER: Added shadows

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/matrix.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/view.cpp
    engines/bladerunner/view.h


diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index a55d94b..d4c4eea 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -773,7 +773,7 @@ void Actor::setBoundingBox(const Vector3 &position, bool retired) {
 
 float Actor::distanceFromView(View *view) const{
 	float xDist = _position.x - view->_cameraPosition.x;
-	float zDist = _position.z + view->_cameraPosition.z;
+	float zDist = _position.z + view->_cameraPosition.y; // y<->z is intentional, not a bug
 	return sqrt(xDist * xDist + zDist * zDist);
 }
 
@@ -859,7 +859,7 @@ void Actor::faceXYZ(const Vector3 &pos, bool animate) {
 }
 
 void Actor::faceCurrentCamera(bool animate) {
-	faceXYZ(_vm->_view->_cameraPosition.x, _vm->_view->_cameraPosition.y, -_vm->_view->_cameraPosition.z, animate);
+	faceXYZ(_vm->_view->_cameraPosition.x, _vm->_view->_cameraPosition.z, -_vm->_view->_cameraPosition.y, animate); // y<->z is intentional, not a bug
 }
 
 void Actor::faceHeading(int heading, bool animate) {
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index de7d824..ea663b5 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -242,10 +242,6 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	_obstacles = new Obstacles(this);
 
-	// TODO: slice renderer shadow
-
-	// TODO: voight-kampf script
-
 	_sceneScript = new SceneScript(this);
 
 	_debugger = new Debugger(this);
@@ -620,9 +616,6 @@ void BladeRunnerEngine::shutdown() {
 
 	_playerActor = nullptr;
 
-	delete _zbuffer;
-	_zbuffer = nullptr;
-
 	delete _gameInfo;
 	_gameInfo = nullptr;
 
@@ -640,7 +633,6 @@ void BladeRunnerEngine::shutdown() {
 	// TODO: Delete Timer
 
 
-
 	// These are static objects in original game
 
 	delete _debugger;
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
index 5fe7fc2..5343eb6 100644
--- a/engines/bladerunner/matrix.h
+++ b/engines/bladerunner/matrix.h
@@ -44,12 +44,12 @@ public:
 inline Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b) {
 	Matrix3x2 t;
 
-	t(0,0) = a(0,0)*b(0,0) + a(0,1)*b(1,0);
-	t(0,1) = a(0,0)*b(0,1) + a(0,1)*b(1,1);
-	t(0,2) = a(0,0)*b(0,2) + a(0,1)*b(1,2) + a(0,2);
-	t(1,0) = a(1,0)*b(0,0) + a(1,1)*b(1,0);
-	t(1,1) = a(1,0)*b(0,1) + a(1,1)*b(1,1);
-	t(1,2) = a(1,0)*b(0,2) + a(1,1)*b(1,2) + a(1,2);
+	t(0, 0) = a(0, 0) * b(0, 0) + a(0, 1) * b(1, 0);
+	t(0, 1) = a(0, 0) * b(0, 1) + a(0, 1) * b(1, 1);
+	t(0, 2) = a(0, 0) * b(0, 2) + a(0, 1) * b(1, 2) + a(0, 2);
+	t(1, 0) = a(1, 0) * b(0, 0) + a(1, 1) * b(1, 0);
+	t(1, 1) = a(1, 0) * b(0, 1) + a(1, 1) * b(1, 1);
+	t(1, 2) = a(1, 0) * b(0, 2) + a(1, 1) * b(1, 2) + a(1, 2);
 
 	return t;
 }
@@ -66,8 +66,8 @@ inline Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b) {
 inline Vector2 operator*(const Matrix3x2 &a, Vector2 b) {
 	Vector2 t;
 
-	t.x = a(0,0) * b.x + a(0,1) * b.y + a(0,2);
-	t.y = a(1,0) * b.x + a(1,1) * b.y + a(1,2);
+	t.x = a(0, 0) * b.x + a(0, 1) * b.y + a(0, 2);
+	t.y = a(1, 0) * b.x + a(1, 1) * b.y + a(1, 2);
 
 	return t;
 }
@@ -96,11 +96,10 @@ inline Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b) {
 	Matrix4x3 t;
 
 	for (int i = 0; i !=3; ++i) {
-		// printf("t(%d,0) = %7.2f*%7.2f + %7.2f*%7.2f + %7.2f*%7.2f\n", i, a(i,0), b(0,0), a(i,0), b(1,0), a(i,0), b(2,0));
-		t(i,0) = a(i,0)*b(0,0) + a(i,1)*b(1,0) + a(i,2)*b(2,0);
-		t(i,1) = a(i,0)*b(0,1) + a(i,1)*b(1,1) + a(i,2)*b(2,1);
-		t(i,2) = a(i,0)*b(0,2) + a(i,1)*b(1,2) + a(i,2)*b(2,2);
-		t(i,3) = a(i,0)*b(0,3) + a(i,1)*b(1,3) + a(i,2)*b(2,3) + a(i,3);
+		t(i, 0) = a(i, 0) * b(0, 0) + a(i, 1) * b(1, 0) + a(i, 2) * b(2, 0);
+		t(i, 1) = a(i, 0) * b(0, 1) + a(i, 1) * b(1, 1) + a(i, 2) * b(2, 1);
+		t(i, 2) = a(i, 0) * b(0, 2) + a(i, 1) * b(1, 2) + a(i, 2) * b(2, 2);
+		t(i, 3) = a(i, 0) * b(0, 3) + a(i, 1) * b(1, 3) + a(i, 2) * b(2, 3) + a(i, 3);
 	}
 
 	return t;
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 64cb04f..87320a3 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -194,9 +194,9 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject
 	_sceneObjects[index].isMoving        = isMoving;
 	_sceneObjects[index].isRetired       = isRetired;
 
-	float centerZ = (_sceneObjects[index].boundingBox->getZ0() + _sceneObjects[index].boundingBox->getZ1()) / 2.0;
+	float centerZ = (_sceneObjects[index].boundingBox->getZ0() + _sceneObjects[index].boundingBox->getZ1()) / 2.0f;
 
-	float distanceToCamera = fabs(_view->_cameraPosition.z - centerZ);
+	float distanceToCamera = fabs(-centerZ - _view->_cameraPosition.y); // y<->z is intentional, not a bug
 	_sceneObjects[index].distanceToCamera = distanceToCamera;
 
 	// insert according to distance from camera
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 42aaf25..15633f6 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -60,6 +60,23 @@ SliceRenderer::SliceRenderer(BladeRunnerEngine *vm) {
 	_endSlice          = 0.0f;
 	_m13               = 0;
 	_m23               = 0;
+
+	_shadowPolygonDefault[ 0] = Vector3( 16.0f,  96.0f, 0.0f);
+	_shadowPolygonDefault[ 1] = Vector3( 16.0f, 160.0f, 0.0f);
+	_shadowPolygonDefault[ 2] = Vector3( 64.0f, 192.0f, 0.0f);
+	_shadowPolygonDefault[ 3] = Vector3( 80.0f, 240.0f, 0.0f);
+	_shadowPolygonDefault[ 4] = Vector3(160.0f, 240.0f, 0.0f);
+	_shadowPolygonDefault[ 5] = Vector3(192.0f, 192.0f, 0.0f);
+	_shadowPolygonDefault[ 6] = Vector3(240.0f, 160.0f, 0.0f);
+	_shadowPolygonDefault[ 7] = Vector3(240.0f,  96.0f, 0.0f);
+	_shadowPolygonDefault[ 8] = Vector3(192.0f,  64.0f, 0.0f);
+	_shadowPolygonDefault[ 9] = Vector3(160.0f,  16.0f, 0.0f);
+	_shadowPolygonDefault[10] = Vector3( 96.0f,  16.0f, 0.0f);
+	_shadowPolygonDefault[11] = Vector3( 64.0f,  64.0f, 0.0f);
+
+	for (int i = 0; i < 12; ++i) {
+		_shadowPolygonCurrent[i] = Vector3(0.0f, 0.0f, 0.0f);
+	}
 }
 
 SliceRenderer::~SliceRenderer() {
@@ -100,19 +117,18 @@ void SliceRenderer::getScreenRectangle(Common::Rect *screenRectangle, int animat
 Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
 	assert(_sliceFramePtr);
 
-	Matrix4x3 viewMatrix = _view->_sliceViewMatrix;
-	Vector3 viewPos = viewMatrix * _position;
+	Vector3 viewPos = _view->_sliceViewMatrix * _position;
 	float dir = atan2f(viewPos.x, viewPos.z) + _facing;
 	float s = sinf(dir);
 	float c = cosf(dir);
 
-	Matrix3x2 rotation( c, -s, 0.0f,
+	Matrix3x2 mRotation( c, -s, 0.0f,
 	                    s,  c, 0.0f);
 
-	Matrix3x2 viewRotation(viewMatrix(0,0), viewMatrix(0,1), 0.0f,
-	                       viewMatrix(2,0), viewMatrix(2,1), 0.0f);
+	Matrix3x2 mView(_view->_sliceViewMatrix(0,0), _view->_sliceViewMatrix(0,1), 0.0f,
+	                _view->_sliceViewMatrix(2,0), _view->_sliceViewMatrix(2,1), 0.0f);
 
-	return viewRotation * rotation;
+	return mView * mRotation;
 }
 
 void SliceRenderer::calculateBoundingRect() {
@@ -133,29 +149,32 @@ void SliceRenderer::calculateBoundingRect() {
 
 	top = bottom + _scale * (top - bottom);
 
-	if (bottom.z < 0.0f || top.z < 0.0f) {
+	if (bottom.z <= 0.0f || top.z <= 0.0f) {
 		return;
 	}
 
 	Matrix3x2 facingRotation = calculateFacingRotationMatrix();
 
-	Matrix3x2 m_projection(_view->_viewportDistance / bottom.z,  0.0f, 0.0f,
-	                                                     0.0f, 25.5f, 0.0f);
+	Matrix3x2 mProjection(_view->_viewportPosition.z / bottom.z,  0.0f, 0.0f,
+	                                                       0.0f, 25.5f, 0.0f);
 
-	Matrix3x2 m_frame(_frameScale.x,          0.0f, _framePos.x,
-	                           0.0f, _frameScale.y, _framePos.y);
+	Matrix3x2 mOffset(1.0f, 0.0f, _framePos.x,
+                      0.0f, 1.0f, _framePos.y);
 
-	_modelMatrix = m_projection * (facingRotation * m_frame);
+	Matrix3x2 mScale(_frameScale.x,          0.0f, 0.0f,
+	                          0.0f, _frameScale.y, 0.0f);
+
+	_modelMatrix = mProjection * (facingRotation * (mOffset * mScale));
 
 	Vector4 startScreenVector(
-	           _view->_viewportHalfWidth   + top.x / top.z * _view->_viewportDistance,
-	           _view->_viewportHalfHeight  + top.y / top.z * _view->_viewportDistance,
+	           _view->_viewportPosition.x + top.x / top.z * _view->_viewportPosition.z,
+	           _view->_viewportPosition.y + top.y / top.z * _view->_viewportPosition.z,
 	           1.0f / top.z,
 	           _frameSliceCount * (1.0f / top.z));
 
 	Vector4 endScreenVector(
-	           _view->_viewportHalfWidth   + bottom.x / bottom.z * _view->_viewportDistance,
-	           _view->_viewportHalfHeight  + bottom.y / bottom.z * _view->_viewportDistance,
+	           _view->_viewportPosition.x + bottom.x / bottom.z * _view->_viewportPosition.z,
+	           _view->_viewportPosition.y + bottom.y / bottom.z * _view->_viewportPosition.z,
 	           1.0f / bottom.z,
 	           0.0f);
 
@@ -377,8 +396,6 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 		_modelMatrix
 	);
 
-	Vector3 cameraPosition(_view->_cameraPosition.x, _view->_cameraPosition.z, _view->_cameraPosition.y); // not a bug
-
 	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
 
 	_lights->setupFrame(_view->_frame);
@@ -394,7 +411,7 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 	float setEffectsColorCoeficient;
 	Color setEffectColor;
 	_setEffects->calculateColor(
-		cameraPosition,
+		_view->_cameraPosition,
 		Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
 		&setEffectsColorCoeficient,
 		&setEffectColor);
@@ -414,9 +431,18 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 	setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix[1][1]);
 	_m23 = sliceLineIterator._sliceMatrix[1][2];
 
+	if (_animationsShadowEnabled[_animation]) {
+		float coeficientShadow;
+		Color colorShadow;
+		_setEffects->calculateColor(
+				_view->_cameraPosition,
+				_position,
+				&coeficientShadow,
+				&colorShadow);
+
+		int transparency = 32.0f * sqrt(setEffectColor.r * setEffectColor.r + setEffectColor.g * setEffectColor.g + setEffectColor.b * setEffectColor.b);
 
-	if(_animationsShadowEnabled[_animation]) {
-		//TODO: draw shadows
+		drawShadowInWorld(transparency, surface, zbuffer);
 	}
 
 	int frameY = sliceLineIterator._startY;
@@ -431,7 +457,7 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 
 		if (sliceLineIterator._currentY & 1) {
 			_setEffects->calculateColor(
-				cameraPosition,
+				_view->_cameraPosition,
 				Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
 				&setEffectsColorCoeficient,
 				&setEffectColor);
@@ -578,16 +604,145 @@ void SliceRenderer::drawSlice(int slice, bool advanced, uint16 *frameLinePtr, ui
 	}
 }
 
+void SliceRenderer::drawShadowInWorld(int transparency, Graphics::Surface &surface, uint16 *zbuffer) {
+	Matrix4x3 mOffset(
+		1.0f, 0.0f, 0.0f, _framePos.x,
+		0.0f, 1.0f, 0.0f, _framePos.y,
+		0.0f, 0.0f, 1.0f, 0.0f);
+
+	Matrix4x3 mTransition(
+		1.0f, 0.0f, 0.0f, _position.x,
+		0.0f, 1.0f, 0.0f, _position.y,
+		0.0f, 0.0f, 1.0f, _position.z);
+
+	Matrix4x3 mRotation(
+		cosf(_facing), -sinf(_facing), 0.0f, 0.0f,
+		sinf(_facing),  cosf(_facing), 0.0f, 0.0f,
+		          0.0f,          0.0f, 1.0f, 0.0f);
+
+	Matrix4x3 mScale(
+		_frameScale.x,          0.0f,              0.0f, 0.0f,
+		         0.0f, _frameScale.y,              0.0f, 0.0f,
+		         0.0f,          0.0f, _frameSliceHeight, 0.0f);
+
+	Matrix4x3 m = _view->_sliceViewMatrix * (mTransition * (mRotation * (mOffset * mScale)));
+
+	for (int i = 0; i < 12; ++i) {
+		Vector3 t = m * _shadowPolygonDefault[i];
+		if (t.z > 0.0f) {
+			_shadowPolygonCurrent[i] = Vector3(
+				_view->_viewportPosition.x + t.x / t.z * _view->_viewportPosition.z,
+				_view->_viewportPosition.y + t.y / t.z * _view->_viewportPosition.z,
+				t.z * 25.5f
+			);
+		} else {
+			_shadowPolygonCurrent[i] = Vector3(0.0f, 0.0f, 0.0f);
+		}
+	}
+
+	drawShadowPolygon(transparency, surface, zbuffer);
+}
+
+void SliceRenderer::drawShadowPolygon(int transparency, Graphics::Surface &surface, uint16 *zbuffer) {
+	// this simplified polygon drawing algo is in the game
+
+	int yMax = 0;
+	int yMin = 480;
+	uint16 zMin = 65535;
+
+	int polygonLeft[480] = {};
+	int polygonRight[480] = {};
+
+	int iNext = 11;
+	for (int i = 0; i < 12; ++i) {
+		int xCurrent = _shadowPolygonCurrent[i].x;
+		int yCurrent = _shadowPolygonCurrent[i].y;
+		int xNext = _shadowPolygonCurrent[iNext].x;
+		int yNext = _shadowPolygonCurrent[iNext].y;
+
+		if (yCurrent < yMin) {
+			yMin = yCurrent;
+		}
+		if (yCurrent > yMax) {
+			yMax = yCurrent;
+		}
+		if (_shadowPolygonCurrent[i].z < zMin) {
+			zMin = _shadowPolygonCurrent[i].z;
+		}
+
+		int xDelta = abs(xNext - xCurrent);
+		int yDelta = abs(yNext - yCurrent);
+
+		int xDirection = -1;
+		if (xCurrent < xNext) {
+			xDirection = 1;
+		}
+
+		int xCounter = 0;
+
+		int x = xCurrent;
+		int y = yCurrent;
+
+		if (yCurrent > yNext) {
+			while (y >= yNext) {
+				if (y >= 0 && y < 480) {
+					polygonLeft[y] = x;
+				}
+				xCounter += xDelta;
+				while (xCounter >= yDelta) {
+					x += xDirection;
+					xCounter -= yDelta;
+				}
+				--y;
+			}
+		} else if (yCurrent < yNext) {
+			while (y <= yNext) {
+				if (y >= 0 && y < 480) {
+					polygonRight[y] = x;
+				}
+				xCounter += xDelta;
+				while (xCounter >= yDelta) {
+					x += xDirection;
+					xCounter -= yDelta;
+				}
+				++y;
+			}
+		}
+		iNext = (iNext + 1) % 12;
+	}
+
+	yMax = CLIP(yMax, 0, 480);
+	yMin = CLIP(yMin, 0, 480);
+
+	int ditheringFactor[] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 };
+
+	for (int y = yMin; y < yMax; ++y) {
+		int xMin = CLIP(polygonLeft[y], 0, 640);
+		int xMax = CLIP(polygonRight[y], 0, 640);
+
+		for (int x = MIN(xMin, xMax); x < MAX(xMin, xMax); ++x) {
+			uint16 z = zbuffer[x + y * 640];
+			uint16 *pixel = (uint16*)surface.getBasePtr(x, y);
+
+			if (z >= zMin) {
+				int index = (x & 3) + ((y & 3) << 2);
+				if (transparency - ditheringFactor[index] <= 0) {
+					*pixel = ((*pixel & 0x7BDE) >> 1) + ((*pixel & 0x739C) >> 2);
+				}
+			}
+		}
+	}
+}
+
 void SliceRenderer::preload(int animationId) {
-	int i;
 	int frameCount = _vm->_sliceAnimations->getFrameCount(animationId);
-	for (i = 0; i < frameCount; i++)
+	for (int i = 0; i < frameCount; ++i) {
 		_vm->_sliceAnimations->getFramePtr(animationId, i);
+	}
 }
 
 void SliceRenderer::disableShadows(int animationsIdsList[], int listSize) {
-	int i;
-	for (i = 0; i < listSize; i++) {
+	for (int i = 0; i < listSize; ++i) {
 		_animationsShadowEnabled[animationsIdsList[i]] = false;
 	}
 }
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index cf3066f..d2de61e 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -83,14 +83,14 @@ class SliceRenderer {
 
 	bool _animationsShadowEnabled[997];
 
+	Vector3 _shadowPolygonDefault[12];
+	Vector3 _shadowPolygonCurrent[12];
+
 	Color _setEffectColor;
 	Color _lightsColor;
 
 	Graphics::PixelFormat _pixelFormat;
 
-	Matrix3x2 calculateFacingRotationMatrix();
-	void drawSlice(int slice, bool advanced, uint16 *frameLinePtr, uint16 *zbufLinePtr, int y);
-
 public:
 	SliceRenderer(BladeRunnerEngine *vm);
 	~SliceRenderer();
@@ -103,7 +103,6 @@ public:
 	void setupFrameInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale = 1.0f);
 	void getScreenRectangle(Common::Rect *screenRectangle, int animationId, int animationFrame, Vector3 position, float facing, float scale);
 	void drawInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
-
 	void drawOnScreen(int animationId, int animationFrame, int screenX, int screenY, float facing, float scale, Graphics::Surface &surface);
 
 	void preload(int animationId);
@@ -111,9 +110,13 @@ public:
 	void disableShadows(int *animationsIdsList, int listSize);
 
 private:
-
 	void calculateBoundingRect();
+	Matrix3x2 calculateFacingRotationMatrix();
 	void loadFrame(int animation, int frame);
+
+	void drawSlice(int slice, bool advanced, uint16 *frameLinePtr, uint16 *zbufLinePtr, int y);
+	void drawShadowInWorld(int transparency, Graphics::Surface &surface, uint16 *zbuffer);
+	void drawShadowPolygon(int transparency, Graphics::Surface &surface, uint16 *zbuffer);
 };
 
 class SliceRendererLights {
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index 11cd99c..d304b92 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -48,10 +48,9 @@ bool View::readVqa(Common::ReadStream *stream) {
 void View::setFovX(float fovX) {
 	_fovX = fovX;
 
-	_viewportHalfWidth = 320.0f;
-	_viewportHalfHeight = 240.0f;
-
-	_viewportDistance = 320.0f / tanf(_fovX / 2.0f);
+	_viewportPosition.x = 320.0f;
+	_viewportPosition.y = 240.0f;
+	_viewportPosition.z = 320.0f / tanf(_fovX / 2.0f);
 }
 
 void View::calculateSliceViewMatrix() {
@@ -72,15 +71,15 @@ void View::calculateCameraPosition() {
 	Matrix4x3 invertedMatrix = invertMatrix(_sliceViewMatrix);
 
 	_cameraPosition.x = invertedMatrix(0, 3);
-	_cameraPosition.z = invertedMatrix(1, 3); // this is not a bug, it Z & Y are inverted in original source
-	_cameraPosition.y = invertedMatrix(2, 3);
+	_cameraPosition.y = invertedMatrix(1, 3);
+	_cameraPosition.z = invertedMatrix(2, 3);
 }
 
 Vector3 View::calculateScreenPosition(Vector3 worldPosition) {
 	Vector3 viewPosition = _frameViewMatrix * worldPosition;
 	return Vector3(
-		this->_viewportHalfWidth - viewPosition.x / viewPosition.z * _viewportDistance,
-		this->_viewportHalfHeight - viewPosition.y / viewPosition.z * _viewportDistance,
+		_viewportPosition.x - viewPosition.x / viewPosition.z * _viewportPosition.z,
+		_viewportPosition.y - viewPosition.y / viewPosition.z * _viewportPosition.z,
 		viewPosition.z
 	);
 }
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index 9d53d08..e0695b7 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -39,10 +39,7 @@ public:
 	uint32    _frame;
 
 	Vector3   _cameraPosition;
-
-	float     _viewportHalfWidth;
-	float     _viewportHalfHeight;
-	float     _viewportDistance;
+	Vector3   _viewportPosition;
 
 	bool readVqa(Common::ReadStream *stream);
 	Vector3 calculateScreenPosition(Vector3 worldPosition);





More information about the Scummvm-git-logs mailing list