aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Kohaut2018-11-18 14:53:21 +0100
committerPeter Kohaut2018-11-18 15:00:13 +0100
commit17246fca913938c0485e8e8f13e3cdd82fcc7a5e (patch)
treeee24fa252fb918d8d9cb0d9e6e9e216778776fc6
parenta26a82a1c06e67b506f4115a9f5dd7ef96ea18f5 (diff)
downloadscummvm-rg350-17246fca913938c0485e8e8f13e3cdd82fcc7a5e.tar.gz
scummvm-rg350-17246fca913938c0485e8e8f13e3cdd82fcc7a5e.tar.bz2
scummvm-rg350-17246fca913938c0485e8e8f13e3cdd82fcc7a5e.zip
BLADERUNNER: Fixed perspective slice rendering
Perspective projection is now working properly and character and object are now properly rendered.
-rw-r--r--engines/bladerunner/slice_renderer.cpp110
1 files changed, 58 insertions, 52 deletions
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index eca7a91537..932e02bee8 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -153,19 +153,6 @@ void SliceRenderer::calculateBoundingRect() {
return;
}
- Matrix3x2 facingRotation = calculateFacingRotationMatrix();
-
- Matrix3x2 mProjection(_view->_viewportPosition.z / bottom.z, 0.0f, 0.0f,
- 0.0f, 25.5f, 0.0f);
-
- Matrix3x2 mOffset(1.0f, 0.0f, _framePos.x,
- 0.0f, 1.0f, _framePos.y);
-
- Matrix3x2 mScale(_frameScale.x, 0.0f, 0.0f,
- 0.0f, _frameScale.y, 0.0f);
-
- _mvpMatrix = mProjection * (facingRotation * (mOffset * mScale));
-
Vector4 startScreenVector(
_view->_viewportPosition.x + (top.x / top.z) * _view->_viewportPosition.z,
_view->_viewportPosition.y + (top.y / top.z) * _view->_viewportPosition.z,
@@ -220,6 +207,21 @@ void SliceRenderer::calculateBoundingRect() {
* Calculate min and max X
*/
+ /* TODO, there is something off with X scaling when Y is high like in rc02, on sides, x seems to be ofsetted a bit more than it should. Start/top vector is doing that */
+
+ Matrix3x2 facingRotation = calculateFacingRotationMatrix();
+
+ Matrix3x2 mProjection(_view->_viewportPosition.z / bottom.z, 0.0f, 0.0f,
+ 0.0f, 25.5f, 0.0f);
+
+ Matrix3x2 mOffset(1.0f, 0.0f, _framePos.x,
+ 0.0f, 1.0f, _framePos.y);
+
+ Matrix3x2 mScale(_frameScale.x, 0.0f, 0.0f,
+ 0.0f, _frameScale.y, 0.0f);
+
+ _mvpMatrix = mProjection * (facingRotation * (mOffset * mScale));
+
Matrix3x2 mStart(
1.0f, 0.0f, startScreenVector.x,
0.0f, 1.0f, 25.5f / startScreenVector.z
@@ -236,8 +238,8 @@ void SliceRenderer::calculateBoundingRect() {
float minX = 640.0f;
float maxX = 0.0f;
- for (float i = 0.0f; i <= 256.0f; i += 255.0f) {
- for (float j = 0.0f; j <= 256.0f; j += 255.0f) {
+ for (float i = 0.0f; i <= 255.0f; i += 255.0f) {
+ for (float j = 0.0f; j <= 255.0f; j += 255.0f) {
Vector2 v1 = mStartMVP * Vector2(i, j);
minX = MIN(minX, v1.x);
maxX = MAX(maxX, v1.x);
@@ -283,15 +285,17 @@ struct SliceLineIterator {
Matrix3x2 _sliceMatrix;
int _startY;
int _endY;
+ int _currentY;
float _currentZ;
float _stepZ;
float _currentSlice;
float _stepSlice;
+
float _currentX;
float _stepX;
- int _field_38;
- int _currentY;
+
+ float _field_38;
void setup(float endScreenX, float endScreenY, float endScreenZ,
float startScreenX, float startScreenY, float startScreenZ,
@@ -306,8 +310,9 @@ void SliceLineIterator::setup(
float startScreenX, float startScreenY, float startScreenZ,
float endSlice, float startSlice,
Matrix3x2 m) {
- _startY = (int)startScreenY;
- _endY = (int)endScreenY;
+ _startY = (int)startScreenY;
+ _endY = (int)endScreenY;
+ _currentY = _startY;
float size = endScreenY - startScreenY;
@@ -324,21 +329,18 @@ void SliceLineIterator::setup(
_currentX = startScreenX;
_stepX = (endScreenX - startScreenX) / size;
- _field_38 = (int)((25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ) * 64.0f);
- _currentY = _startY;
+ _field_38 = (25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ);
float offsetX = _currentX;
float offsetZ = 25.5f / _currentZ;
- Matrix3x2 translate_matrix = Matrix3x2(1.0f, 0.0f, offsetX,
- 0.0f, 1.0f, offsetZ);
-
- Matrix3x2 scale_matrix = Matrix3x2(65536.0f, 0.0f, 0.0f,
- 0.0f, 64.0f, 0.0f);
+ Matrix3x2 mTranslate = Matrix3x2(1.0f, 0.0f, offsetX,
+ 0.0f, 1.0f, offsetZ);
- m = scale_matrix * (translate_matrix * m);
+ Matrix3x2 mScale = Matrix3x2(65536.0f, 0.0f, 0.0f, // x position is using fixed-point precisson with 16 bits
+ 0.0f, 64.0f, 0.0f); // z position is using fixed-point precisson with 6 bits
- _sliceMatrix = m;
+ _sliceMatrix = mScale * (mTranslate * m);
}
float SliceLineIterator::line() {
@@ -354,12 +356,13 @@ float SliceLineIterator::line() {
}
void SliceLineIterator::advance() {
- _currentZ += _stepZ;
- _currentSlice += _stepSlice;
- _currentX += _stepX;
- _currentY += 1;
- _sliceMatrix._m[0][2] += (int)(65536.0f * _stepX);
- _sliceMatrix._m[1][2] += _field_38;
+ _currentZ += _stepZ;
+ _currentSlice += _stepSlice;
+ _currentX += _stepX;
+ _currentY += 1;
+
+ _sliceMatrix._m[0][2] += _stepX * 65536.0f;
+ _sliceMatrix._m[1][2] += _field_38 * 64.0f;
}
static void setupLookupTable(int t[256], int inc) {
@@ -375,7 +378,8 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
assert(_setEffects);
//assert(_view);
- _vm->_sliceRenderer->setupFrameInWorld(animationId, animationFrame, position, facing);
+ setupFrameInWorld(animationId, animationFrame, position, facing);
+
assert(_sliceFramePtr);
if (_screenRectangle.isEmpty()) {
@@ -445,6 +449,8 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
uint16 *zBufferLinePtr = zbuffer + 640 * frameY;
while (sliceLineIterator._currentY <= sliceLineIterator._endY) {
+ _m13 = sliceLineIterator._sliceMatrix(0, 2);
+ _m23 = sliceLineIterator._sliceMatrix(1, 2);
sliceLine = sliceLineIterator.line();
sliceRendererLights.calculateColorSlice(Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight));
@@ -494,22 +500,22 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
float s = sin(_facing);
float c = cos(_facing);
- Matrix3x2 m_rotation(c, -s, 0.0f,
- s, c, 0.0f);
+ Matrix3x2 mRotation(c, -s, 0.0f,
+ s, c, 0.0f);
- Matrix3x2 m_frame(_frameScale.x, 0.0f, _framePos.x,
- 0.0f, _frameScale.y, _framePos.y);
+ Matrix3x2 mFrame(_frameScale.x, 0.0f, _framePos.x,
+ 0.0f, _frameScale.y, _framePos.y);
- Matrix3x2 m_scale_size_25_5(size, 0.0f, 0.0f,
- 0.0f, 25.5f, 0.0f);
+ Matrix3x2 mScale(size, 0.0f, 0.0f,
+ 0.0f, 25.5f, 0.0f);
- Matrix3x2 m_translate_x_32k(1.0f, 0.0f, screenX,
- 0.0f, 1.0f, 32768.0f);
+ Matrix3x2 mTranslate(1.0f, 0.0f, screenX,
+ 0.0f, 1.0f, 32768.0f);
- Matrix3x2 m_scale_64k_64(65536.0f, 0.0f, 0.0f,
- 0.0f, 64.0f, 0.0f);
+ Matrix3x2 mScaleFixed(65536.0f, 0.0f, 0.0f, // x position is using fixed-point precisson with 16 bits
+ 0.0f, 64.0f, 0.0f); // z position is using fixed-point precisson with 6 bits
- Matrix3x2 m = m_scale_64k_64 * (m_translate_x_32k * (m_scale_size_25_5 * (m_rotation * m_frame)));
+ Matrix3x2 m = mScaleFixed * (mTranslate * (mScale * (mRotation * mFrame)));
setupLookupTable(_m11lookup, m(0, 0));
setupLookupTable(_m12lookup, m(0, 1));
@@ -561,15 +567,15 @@ void SliceRenderer::drawSlice(int slice, bool advanced, uint16 *frameLinePtr, ui
continue;
uint32 lastVertex = vertexCount - 1;
- int lastVertexX = MAX((_m11lookup[p[3 * lastVertex]] + _m12lookup[p[3 * lastVertex + 1]] + _m13) >> 16, 0);
+ int lastVertexX = MAX((_m11lookup[p[3 * lastVertex]] + _m12lookup[p[3 * lastVertex + 1]] + _m13) / 65536, 0);
int previousVertexX = lastVertexX;
while (vertexCount--) {
- int vertexX = CLIP((_m11lookup[p[0]] + _m12lookup[p[1]] + _m13) >> 16, 0, 640);
+ int vertexX = CLIP((_m11lookup[p[0]] + _m12lookup[p[1]] + _m13) / 65536, 0, 640);
if (vertexX > previousVertexX) {
- int vertexZ = (_m21lookup[p[0]] + _m22lookup[p[1]] + _m23) >> 6;
+ int vertexZ = (_m21lookup[p[0]] + _m22lookup[p[1]] + _m23) / 64;
if (vertexZ >= 0 && vertexZ < 65536) {
int color555 = palette.color555[p[2]];
@@ -578,9 +584,9 @@ void SliceRenderer::drawSlice(int slice, bool advanced, uint16 *frameLinePtr, ui
_screenEffects->getColor(&aescColor, vertexX, y, vertexZ);
Color256 color = palette.color[p[2]];
- color.r = ((int)(_setEffectColor.r + _lightsColor.r * color.r) >> 16) + aescColor.r;
- color.g = ((int)(_setEffectColor.g + _lightsColor.g * color.g) >> 16) + aescColor.g;
- color.b = ((int)(_setEffectColor.b + _lightsColor.b * color.b) >> 16) + aescColor.b;
+ color.r = ((int)(_setEffectColor.r + _lightsColor.r * color.r) / 65536) + aescColor.r;
+ color.g = ((int)(_setEffectColor.g + _lightsColor.g * color.g) / 65536) + aescColor.g;
+ color.b = ((int)(_setEffectColor.b + _lightsColor.b * color.b) / 65536) + aescColor.b;
int bladeToScummVmConstant = 256 / 32;
color555 = _pixelFormat.RGBToColor(CLIP(color.r * bladeToScummVmConstant, 0, 255), CLIP(color.g * bladeToScummVmConstant, 0, 255), CLIP(color.b * bladeToScummVmConstant, 0, 255));