diff options
author | Peter Kohaut | 2018-03-11 11:41:21 +0100 |
---|---|---|
committer | Peter Kohaut | 2018-03-11 11:54:01 +0100 |
commit | bbe4ef44749038293ba86de3ed001f5ff4ce2145 (patch) | |
tree | 30bf2523e118421d853fa928c69fdd24987477bb /engines | |
parent | 782d4fbb06d5cb9cd2bae75f085d8c43231c9834 (diff) | |
download | scummvm-rg350-bbe4ef44749038293ba86de3ed001f5ff4ce2145.tar.gz scummvm-rg350-bbe4ef44749038293ba86de3ed001f5ff4ce2145.tar.bz2 scummvm-rg350-bbe4ef44749038293ba86de3ed001f5ff4ce2145.zip |
BLADERUNNER: Added shadows
Diffstat (limited to 'engines')
-rw-r--r-- | engines/bladerunner/actor.cpp | 4 | ||||
-rw-r--r-- | engines/bladerunner/bladerunner.cpp | 8 | ||||
-rw-r--r-- | engines/bladerunner/matrix.h | 25 | ||||
-rw-r--r-- | engines/bladerunner/scene_objects.cpp | 4 | ||||
-rw-r--r-- | engines/bladerunner/slice_renderer.cpp | 207 | ||||
-rw-r--r-- | engines/bladerunner/slice_renderer.h | 13 | ||||
-rw-r--r-- | engines/bladerunner/view.cpp | 15 | ||||
-rw-r--r-- | engines/bladerunner/view.h | 5 |
8 files changed, 213 insertions, 68 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index a55d94bd55..d4c4eeaee3 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 de7d82498a..ea663b53bc 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 5fe7fc2a01..5343eb6b8e 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 64cb04f40c..87320a3fa4 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 42aaf253fe..15633f6581 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 cf3066f9e8..d2de61e279 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 11cd99c9fc..d304b92bb1 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 9d53d0852f..e0695b78f0 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); |