diff options
author | Peter Kohaut | 2016-09-26 23:38:35 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2016-09-29 22:33:41 +0200 |
commit | f1cb735ee07c11785f67080ea800a72dd551ae19 (patch) | |
tree | 7f67364d748a1091164ecaa98386165a76f78a8f /engines | |
parent | cfc8ffed8af71714cc6378b412557d5fc03781d4 (diff) | |
download | scummvm-rg350-f1cb735ee07c11785f67080ea800a72dd551ae19.tar.gz scummvm-rg350-f1cb735ee07c11785f67080ea800a72dd551ae19.tar.bz2 scummvm-rg350-f1cb735ee07c11785f67080ea800a72dd551ae19.zip |
BLADERUNNER: added rendering support for lighting and effects, but its not working correctly yet
Diffstat (limited to 'engines')
-rw-r--r-- | engines/bladerunner/actor.cpp | 7 | ||||
-rw-r--r-- | engines/bladerunner/bladerunner.cpp | 32 | ||||
-rw-r--r-- | engines/bladerunner/color.h | 18 | ||||
-rw-r--r-- | engines/bladerunner/fog.cpp | 288 | ||||
-rw-r--r-- | engines/bladerunner/fog.h | 5 | ||||
-rw-r--r-- | engines/bladerunner/light.cpp | 198 | ||||
-rw-r--r-- | engines/bladerunner/light.h | 25 | ||||
-rw-r--r-- | engines/bladerunner/lights.cpp | 88 | ||||
-rw-r--r-- | engines/bladerunner/lights.h | 2 | ||||
-rw-r--r-- | engines/bladerunner/set_effects.cpp | 53 | ||||
-rw-r--r-- | engines/bladerunner/set_effects.h | 2 | ||||
-rw-r--r-- | engines/bladerunner/slice_animations.cpp | 6 | ||||
-rw-r--r-- | engines/bladerunner/slice_animations.h | 10 | ||||
-rw-r--r-- | engines/bladerunner/slice_renderer.cpp | 373 | ||||
-rw-r--r-- | engines/bladerunner/slice_renderer.h | 50 | ||||
-rw-r--r-- | engines/bladerunner/vector.h | 14 | ||||
-rw-r--r-- | engines/bladerunner/view.cpp | 6 |
17 files changed, 909 insertions, 268 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index c0c042e47f..29c83e78cb 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -399,12 +399,11 @@ bool Actor::tick(bool forceDraw) { void Actor::draw() { Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0); float draw_facing = M_PI - _facing * M_PI / 512.0; - // float draw_scale = _scale; + float draw_scale = _scale; // TODO: Handle SHORTY mode - - _vm->_sliceRenderer->setupFrame(_animationId, _animationFrame, draw_position, draw_facing); - _vm->_sliceRenderer->drawFrame(_vm->_surface2, _vm->_zBuffer2); + + _vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2); } int Actor::getSetId() { diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 45ffdd8998..41f1bb55d3 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -613,7 +613,7 @@ void BladeRunnerEngine::gameTick() { _walkSoundId = -1; } -#if _DEBUG +#if 0 //_DEBUG //draw scene objects int count = _sceneObjects->_count; if (count > 0) { @@ -667,35 +667,6 @@ void BladeRunnerEngine::gameTick() { } } - - for (Light* light = _lights->_lights; light != nullptr; light->_next) { - - Matrix4x3 matrix = light->_matrix; - - // this is all wrong - -// matrix = matrix * rotationMatrixX(float(M_PI) / 2.0f); - -// Matrix4x3 a( -// -1.0f, 0.0f, 0.0f, 0.0f, -// 0.0f, -1.0f, 0.0f, 0.0f, -// 0.0f, 0.0f, 1.0f, 0.0f); - - //matrix = a * matrix; -// matrix = invertMatrix(matrix); - - int colorR = (light->_color.r * 31.0f); - int colorG = (light->_color.g * 31.0f); - int colorB = (light->_color.b * 31.0f); - int color = (colorR << 10) + (colorG << 5) + colorB; - drawBBox( - Vector3(matrix(0, 3) - 5.0f, matrix(1, 3) - 5.0f, matrix(2, 3) - 5.0f), - Vector3(matrix(0, 3) + 5.0f, matrix(1, 3) + 5.0f, matrix(2, 3) + 5.0f), - _view, &_surface2, color - ); - light = light->_next; - - } #endif _system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480); @@ -751,6 +722,7 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) { } if (sceneObjectId == -1) { + _actors[0]->loopWalkToXYZ(mousePosition); debug("Clicked on nothing"); return; } else if (sceneObjectId >= 0 && sceneObjectId <= 73) { diff --git a/engines/bladerunner/color.h b/engines/bladerunner/color.h index eebe2dcdc0..10d3737f76 100644 --- a/engines/bladerunner/color.h +++ b/engines/bladerunner/color.h @@ -23,13 +23,27 @@ #ifndef BLADERUNNER_COLOR_H #define BLADERUNNER_COLOR_H +#include "common/system.h" + namespace BladeRunner { -struct Color -{ +struct Color { float r; float g; float b; + + + Color() { + } + + Color(float r, float g, float b) : r(r), g(g), b(b) { + } +}; + +struct Color256 { + uint8 r; + uint8 g; + uint8 b; }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp index ead7c91db2..bca548c0ef 100644 --- a/engines/bladerunner/fog.cpp +++ b/engines/bladerunner/fog.cpp @@ -4,16 +4,13 @@ namespace BladeRunner { -Fog::Fog() -{ +Fog::Fog() { } -Fog::~Fog() -{ +Fog::~Fog() { } -int Fog::readCommon(Common::ReadStream* stream) -{ +int Fog::readCommon(Common::ReadStream *stream) { int offset = stream->readUint32LE(); stream->read(_name, 20); _fogColor.r = stream->readFloatLE(); @@ -23,8 +20,7 @@ int Fog::readCommon(Common::ReadStream* stream) return offset; } -void Fog::readAnimationData(Common::ReadStream* stream, int size) -{ +void Fog::readAnimationData(Common::ReadStream *stream, int size) { _animatedParameters = stream->readUint32LE(); _animationData = new float[size / sizeof(float)]; stream->read(_animationData, size); @@ -45,12 +41,10 @@ void Fog::readAnimationData(Common::ReadStream* stream, int size) setupFrame(0); } -void Fog::reset() -{ +void Fog::reset() { } -void Fog::setupFrame(int frame) -{ +void Fog::setupFrame(int frame) { int offset = frame % _framesCount; _matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr); _matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr); @@ -67,24 +61,181 @@ void Fog::setupFrame(int frame) _inverted = invertMatrix(_matrix); } -void FogCone::read(Common::ReadStream* stream, int framesCount) -{ +void FogCone::read(Common::ReadStream *stream, int framesCount) { _framesCount = framesCount; int size = readCommon(stream); _parameter1 = stream->readFloatLE(); readAnimationData(stream, size - 52); } -void FogSphere::read(Common::ReadStream* stream, int framesCount) -{ +void FogCone::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) { + *coeficient = 0.0f; + + Vector3 positionT = this->_matrix * position; + Vector3 viewPositionT = this->_matrix * viewPosition; + + Vector3 vectorT = (viewPositionT - positionT).normalize(); + + float v67 = - positionT.x * vectorT.x - positionT.y * vectorT.y - positionT.z * vectorT.z; + float v66 = - (positionT.z * positionT.z) - (positionT.y * positionT.y) - (positionT.x * positionT.x) + (v67 * v67) + (this->_parameter1 * this->_parameter1); + + if (v66 >= 0.0f) { + float v24 = sqrt(v66); + + Vector3 v29 = positionT + (v67 - v24) * vectorT; + Vector3 v36 = positionT + (v67 + v24) * vectorT; + + Vector3 v39 = this->_inverted * v29; + Vector3 v42 = this->_inverted * v36; + + float v74 = (v39 - position).length(); + float v76 = (v42 - position).length(); + + Vector3 vector = viewPosition - position; + + float vectorLength = vector.length(); + + if (v74 < 0.0f) { + v74 = 0.0f; + } + if (v76 > vectorLength) { + v76 = vectorLength; + } + if (v76 >= v74) { + *coeficient = v76 - v74; + } + } +} + +void FogSphere::read(Common::ReadStream *stream, int framesCount) { _framesCount = framesCount; int size = readCommon(stream); _parameter1 = stream->readFloatLE(); readAnimationData(stream, size - 52); } -void FogBox::read(Common::ReadStream* stream, int framesCount) -{ +void FogSphere::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) { + *coeficient = 0.0f; + + Vector3 positionT = this->_matrix * position; + Vector3 viewPositionT = this->_matrix * viewPosition; + + Vector3 v158 = Vector3::cross(positionT, viewPositionT); + + if (v158.x != 0.0f || v158.y != 0.0f || v158.z != 0.0f) { + Vector3 v167 = v158.normalize(); + if (v167.z < 0.0f) { + v167 = -1.0f * v167; + } + + float v173 = sqrt(1.0f - v167.z * v167.z); + if (v173 > cos(this->_parameter1)) { + Vector3 v37 = Vector3(v167.y, -v167.x, 0.0f).normalize(); + + float v41 = 1.0f / v173 / v173 - 1.0f; + float v42 = sqrt(v41); + float v43 = tan(this->_parameter1); + float v44 = sqrt(v43 * v43 - v41); + + Vector3 v45 = v44 * v37; + + Vector3 v48 = Vector3( + -v37.y * v42, + v37.x * v42, + 0.0f * v42); + + Vector3 v51 = v48 + Vector3(0.0f, 0.0f, -1.0f); + + Vector3 v186 = v51 - v45; + Vector3 v183 = v51 + v45; + + Vector3 vector = viewPositionT - positionT; + + Vector3 v177 = -1.0f * positionT; + Vector3 v174 = Vector3::cross(v186, vector); + + float v189, v191; + if (fabs(v174.x) <= fabs(v174.y)) { + if (fabs(v174.y) <= fabs(v174.z)) { + v191 = v177.x * v186.y - v177.y * v186.x; + v189 = v186.y * vector.x - v186.x * vector.y; + } else { + v191 = v177.z * v186.x - v186.z * v177.x; + v189 = v186.x * vector.z - v186.z * vector.x; + } + } else { + if (fabs(v174.x) <= fabs(v174.z)) { + v191 = v177.x * v186.y - v177.y * v186.x; + v189 = v186.y * vector.x - v186.x * vector.y; + } else { + v191 = v186.z * v177.y - v186.y * v177.z; + v189 = v186.z * vector.y - v186.y * vector.z; + } + } + + float v88; + if (v189 == 0.0f) { + v88 = 0.0f; + } else { + v88 = v191 / v189; + } + + Vector3 v196 = -1.0f * positionT; + Vector3 v193 = Vector3::cross(v183, vector); + + float v190, v192; + if (fabs(v193.x) <= fabs(v193.y)) { + if (fabs(v193.y) <= fabs(v193.z)) { + v192 = v196.x * v183.y - v196.y * v183.x; + v190 = v183.y * vector.x - v183.x * vector.y; + } else { + v192 = v196.z * v183.x - v183.z * v196.x; + v190 = v183.x * vector.z - v183.z * vector.x; + } + } else { + if (fabs(v193.x) <= fabs(v193.z)) { + v192 = v196.x * v183.y - v196.y * v183.x; + v190 = v183.y * vector.x - v183.x * vector.y; + } else { + v192 = v183.z * v196.y - v183.y * v196.z; + v190 = v183.z * vector.y - v183.y * vector.z; + } + } + + float v114; + if (v190 == 0.0f) { + v114 = 0.0f; + } else { + v114 = v192 / v190; + } + + if (v114 < v88) { + float temp = v88; + v88 = v114; + v114 = temp; + } + + if (v88 <= 1.0f && v114 >= 0.0f) { + if (v88 < 0.0f) { + v88 = 0.0; + } + if (v114 > 1.0f) { + v114 = 1.0; + } + + Vector3 v139 = positionT + (v88 * vector); + Vector3 v142 = this->_inverted * v139; + + Vector3 v148 = positionT + (v114 * vector); + Vector3 v151 = this->_inverted * v148; + + *coeficient = (v151 - v142).length(); + } + } + } +} + +void FogBox::read(Common::ReadStream *stream, int framesCount) { _framesCount = framesCount; int size = readCommon(stream); _parameter1 = stream->readFloatLE(); @@ -93,4 +244,105 @@ void FogBox::read(Common::ReadStream* stream, int framesCount) readAnimationData(stream, size - 60); } +void FogBox::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) { + Vector3 v159 = this->_matrix * position; + Vector3 v146 = v159; + Vector3 v156 = this->_matrix * viewPosition; + Vector3 v153 = v156; + Vector3 v150 = v156 - v159; + + float v149 = this->_parameter1 * 0.5f; + if (v159.x < -v149) { + if (v156.x < -v149) { + return; + } + float v28 = (-v159.x - v149) / v150.x; + Vector3 v29 = v28 * v150; + v146 = v159 + v29; + } else { + if (v156.x < -v149) { + float v19 = (-v156.x - v149) / v150.x; + Vector3 v20 = v19 * v150; + v153 = v156 + v20; + } + } + if (v149 < v146.x) { + if (v149 < v153.x) { + return; + } + float v48 = (v149 - v146.x) / v150.x; + Vector3 v49 = v48 * v150; + v146 = v146 + v49; + } else { + if (v149 < v153.x) { + float v40 = (v149 - v153.x) / v150.x; + Vector3 v41 = v40 * v150; + v153 = v153 + v41; + } + } + float v162 = this->_parameter2 * 0.5f; + if (v146.y < -v162) { + if (v153.y < -v162) { + return; + } + float v71 = (-v146.y - v162) / v150.y; + Vector3 v72 = v71 * v150; + v146 = v146 + v72; + } else { + if (v153.y < -v162) { + float v62 = (-v153.y - v162) / v150.y; + Vector3 v63 = v62 * v150; + v153 = v153 + v63; + } + } + if (v162 < v146.y) { + if (v162 < v153.y) { + return; + } + float v91 = (v162 - v146.y) / v150.y; + Vector3 v92 = v91 * v150; + v146 = v146 + v92; + } else { + if (v162 < v153.y) { + float v83 = (v162 - v153.y) / v150.y; + Vector3 v84 = v83 * v150; + v153 = v153 + v84; + } + } + + if (0.0f <= v146.z) { + if (0.0f > v153.z) { + float v103 = -v153.z / v150.z; + Vector3 v104 = v103 * v150; + v153 = v153 + v104; + } + } else { + if (0.0f > v153.z) { + return; + } + float v111 = -v146.z / v150.z; + Vector3 v112 = v111 * v150; + v146 = v146 + v112; + } + + if (v146.z <= this->_parameter3) { + if (v153.z > this->_parameter3) { + float v124 = (this->_parameter3 - v153.z) / v150.z; + Vector3 v125 = v124 * v150; + v153 = v153 + v125; + } + } else { + if (v153.z <= this->_parameter3) { + float v132 = (this->_parameter3 - v146.z) / v150.z; + Vector3 v133 = v132 * v150; + v146 = v146 + v133; + } + } + + Vector3 v137 = this->_inverted * v146; + Vector3 v140 = this->_inverted * v153; + Vector3 v143 = v140 - v137; + + *coeficient = v143.length(); +} } // End of namespace BladeRunner diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h index db291e3b62..992ede56ed 100644 --- a/engines/bladerunner/fog.h +++ b/engines/bladerunner/fog.h @@ -71,7 +71,7 @@ public: virtual ~Fog(); virtual void read(Common::ReadStream *stream, int framesCount) = 0; - + virtual void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) = 0; void reset(); void setupFrame(int frame); @@ -85,16 +85,19 @@ protected: class FogCone : public Fog { void read(Common::ReadStream *stream, int framesCount); + void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient); }; class FogSphere : public Fog { void read(Common::ReadStream *stream, int framesCount); + void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient); }; class FogBox : public Fog { void read(Common::ReadStream *stream, int framesCount); + void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp index d1d79b870b..39dc3e3a27 100644 --- a/engines/bladerunner/light.cpp +++ b/engines/bladerunner/light.cpp @@ -1,17 +1,15 @@ #include "bladerunner/light.h" +#include "common/util.h" namespace BladeRunner { -Light::Light() -{ +Light::Light() { } -Light::~Light() -{ +Light::~Light() { } -void Light::read(Common::ReadStream* stream, int framesCount, int frame, int animated) -{ +void Light::read(Common::ReadStream *stream, int framesCount, int frame, int animated) { _framesCount = framesCount; _animated = animated; @@ -48,8 +46,7 @@ void Light::read(Common::ReadStream* stream, int framesCount, int frame, int ani setupFrame(frame); } -void Light::readVqa(Common::ReadStream* stream, int framesCount, int frame, int animated) -{ +void Light::readVqa(Common::ReadStream *stream, int framesCount, int frame, int animated) { _framesCount = framesCount; _animated = animated; @@ -83,8 +80,7 @@ void Light::readVqa(Common::ReadStream* stream, int framesCount, int frame, int setupFrame(frame); } -void Light::setupFrame(int frame) -{ +void Light::setupFrame(int frame) { int offset = frame % _framesCount; _matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr); _matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr); @@ -108,9 +104,185 @@ void Light::setupFrame(int frame) } -float Light::attenuation(float min, float max, float distance) -{ - return 0.0; +float Light::calculate(Vector3 start, Vector3 end) { + return calculateCoeficient(_matrix * start, _matrix * end, _field16, _field17); +} + +void Light::calculateColor(Color *outColor, Vector3 position) { + Vector3 positionT = _matrix * position; + float att = attenuation(_field16, _field17, positionT.length()); + outColor->r = _color.r * att; + outColor->g = _color.g * att; + outColor->b = _color.b * att; +} + +float Light::calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4) { + if (a4 == 0.0f) { + return 1.0e30f; + } + + if (a3 >= start.length() && a3 >= end.length()) { + return 1.0e30f; + } + + float v40 = (end - start).length(); + float v31 = 0.0f; + if (v40 != 0.0f) { + Vector3 v27 = Vector3::cross(start, end); + v31 = v27.length() / v40; + } + + if (v31 < a4) { + return 1.0f / (1.0f - (v31 / a4)); + } + return 1.0e30f; +} + +float Light::attenuation(float min, float max, float distance) { + if (max == 0.0f) { + return 1.0f; + } + if (min < max) { + distance = CLIP(distance, min, max); + float x = (max - distance) / (max - min); + return x * x * (3.0f - 2.0f * x); + } + if (min > distance) { + return 1.0f; + } + return 0.0f; +} + +float Light1::calculate(Vector3 start, Vector3 end) { + start = _matrix * start; + end = _matrix * end; + + float v40 = 0.0f; + if (_field17 != 0.0f) { + v40 = calculateCoeficient(start, end, _field16, _field17); + } + + float v41 = atan2(start.length(), -start.z); + float v42 = atan2(end.length(), -end.z); + + float v43; + if ((_field18 >= v41 && _field18 >= v42) || (_field19 <= v41 && _field19 <= v42)) { + v43 = 1.0e30f; + } else { + v43 = 2.0; + } + if (v43 < v40) { + return v40; + } else { + return v43; + } +} + +void Light1::calculateColor(Color *outColor, Vector3 position) { + Vector3 positionT = _matrix * position; + + outColor->r = 0.0f; + outColor->g = 0.0f; + outColor->b = 0.0f; + + if (positionT.z < 0.0f) { + float v12 = attenuation(_field18, _field19, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z)); + float v13 = attenuation(_field16, _field17, positionT.length()); + + outColor->r = v12 * v13 * _color.r; + outColor->g = v12 * v13 * _color.g; + outColor->b = v12 * v13 * _color.b; + } +} + +float Light2::calculate(Vector3 start, Vector3 end) { + start = _matrix * start; + end = _matrix * end; + + float v54 = 0.0f; + if (_field17 != 0.0f) { + v54 = calculateCoeficient(start, end, _field16, _field17); + } + + float v55 = atan2(fabs(start.x), -start.z); + float v58 = atan2(fabs(start.y), -start.z); + float v57 = atan2(fabs(end.x), -end.z); + float v56 = atan2(fabs(end.y), -end.z); + + float v59; + if ((_field18 >= v55 && _field18 >= v57 && _field18 >= v58 && _field18 >= v56) || (_field19 <= v55 && _field19 <= v57 && _field19 <= v58 && _field19 <= v56)) { + v59 = 1.0e30f; + } else { + v59 = 2.0f; + } + if (v59 < v54) { + return v54; + } else { + return v59; + } +} + +void Light2::calculateColor(Color *outColor, Vector3 position) { + Vector3 positionT = _matrix * position; + + outColor->r = 0.0f; + outColor->g = 0.0f; + outColor->b = 0.0f; + + if (positionT.z < 0.0f) { + float v11 = attenuation(_field18, _field19, atan2(fabs(positionT.y), -positionT.z)); + float v12 = attenuation(_field18, _field19, atan2(fabs(positionT.x), -positionT.z)); + float v13 = attenuation(_field16, _field17, positionT.length()); + + outColor->r = v11 * v12 * v13 * _color.r; + outColor->g = v11 * v12 * v13 * _color.g; + outColor->b = v11 * v12 * v13 * _color.b; + } +} + +void Light3::calculateColor(Color *outColor, Vector3 position) { + Vector3 positionT = _matrix * position; + + outColor->r = 0.0f; + outColor->g = 0.0f; + outColor->b = 0.0f; + + if (positionT.z < 0.0f) { + float v12 = attenuation(_field18, _field19, sqrt(positionT.x * positionT.x + positionT.y * positionT.y)); + float v13 = attenuation(_field16, _field17, positionT.length()); + + outColor->r = v12 * v13 * _color.r; + outColor->g = v12 * v13 * _color.g; + outColor->b = v12 * v13 * _color.b; + } +} + +void Light4::calculateColor(Color *outColor, Vector3 position) { + Vector3 positionT = _matrix * position; + + outColor->r = 0.0f; + outColor->g = 0.0f; + outColor->b = 0.0f; + + if (positionT.z < 0.0f) { + float v11 = attenuation(_field18, _field19, fabs(positionT.y)); + float v12 = attenuation(_field18, _field19, fabs(positionT.x)); + float v13 = attenuation(_field16, _field17, positionT.length()); + + outColor->r = v11 * v12 * v13 * _color.r; + outColor->g = v11 * v12 * v13 * _color.g; + outColor->b = v11 * v12 * v13 * _color.b; + } +} + +float Light5::calculate(Vector3 start, Vector3 end) { + return 1.0e30f; +} + +void Light5::calculateColor(Color *outColor, Vector3 position) { + outColor->r = _color.r; + outColor->g = _color.g; + outColor->b = _color.b; } } // End of namespace BladeRunner diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h index a6ac21eb8b..9c2cdcb45c 100644 --- a/engines/bladerunner/light.h +++ b/engines/bladerunner/light.h @@ -42,7 +42,9 @@ class Light friend class BladeRunnerEngine; #endif friend class Lights; + friend class SliceRenderer; +protected: char _name[20]; int _framesCount; int _animated; @@ -77,35 +79,42 @@ class Light public: Light(); - ~Light(); + virtual ~Light(); void read(Common::ReadStream *stream, int framesCount, int frame, int animated); void readVqa(Common::ReadStream *stream, int framesCount, int frame, int animated); void setupFrame(int frame); -private: - static float attenuation(float min, float max, float distance); + virtual float calculate(Vector3 start, Vector3 end); + virtual void calculateColor(Color *outColor, Vector3 position); + +protected: + float calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4); + float attenuation(float min, float max, float distance); }; class Light1 : public Light { - + float calculate(Vector3 start, Vector3 end); + void calculateColor(Color *outColor, Vector3 position); }; class Light2 : public Light { - + float calculate(Vector3 start, Vector3 end); + void calculateColor(Color *outColor, Vector3 position); }; class Light3 : public Light { - + void calculateColor(Color *outColor, Vector3 position); }; class Light4 : public Light { - + void calculateColor(Color *outColor, Vector3 position); }; class Light5 : public Light { - + float calculate(Vector3 start, Vector3 end); + void calculateColor(Color *outColor, Vector3 position); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp index eb18958020..0d6a1be175 100644 --- a/engines/bladerunner/lights.cpp +++ b/engines/bladerunner/lights.cpp @@ -2,8 +2,7 @@ namespace BladeRunner { -Lights::Lights(BladeRunnerEngine *vm) -{ +Lights::Lights(BladeRunnerEngine *vm) { _vm = vm; _ambientLightColor.r = 1.0; @@ -11,28 +10,25 @@ Lights::Lights(BladeRunnerEngine *vm) _ambientLightColor.b = 0.0; _lights = nullptr; + _lightsCount = 0; _frame = 0; } -Lights::~Lights() -{ +Lights::~Lights() { reset(); } -void Lights::read(Common::ReadStream *stream, int framesCount) -{ +void Lights::read(Common::ReadStream *stream, int framesCount) { _ambientLightColor.r = stream->readFloatLE(); _ambientLightColor.g = stream->readFloatLE(); _ambientLightColor.b = stream->readFloatLE(); _lightsCount = stream->readUint32LE(); int i; - for (i = 0; i < _lightsCount; i++) - { + for (i = 0; i < _lightsCount; i++) { Light *light; int type = stream->readUint32LE(); - switch (type) - { + switch (type) { case 1: light = new Light1(); break; @@ -58,24 +54,18 @@ void Lights::read(Common::ReadStream *stream, int framesCount) } } -void Lights::removeAnimated() -{ +void Lights::removeAnimated() { Light **nextLight; - Light *light; + Light *light; nextLight = &this->_lights; light = this->_lights; - if (light) - { - do - { - if (light->_animated) - { + if (light) { + do { + if (light->_animated) { *nextLight = light->_next; delete light; - } - else - { + } else { nextLight = &light->_next; } light = *nextLight; @@ -83,8 +73,7 @@ void Lights::removeAnimated() } } -void Lights::readVqa(Common::ReadStream *stream) -{ +void Lights::readVqa(Common::ReadStream *stream) { removeAnimated(); if (stream->eos()) return; @@ -93,26 +82,25 @@ void Lights::readVqa(Common::ReadStream *stream) int count = stream->readUint32LE(); for (int i = 0; i < count; i++) { int lightType = stream->readUint32LE(); - Light* light; - switch(lightType) - { - case 5: - light = new Light5(); - break; - case 4: - light = new Light4(); - break; - case 3: - light = new Light3(); - break; - case 2: - light = new Light2(); - break; - case 1: - light = new Light1(); - break; - default: - light = new Light(); + Light *light; + switch (lightType) { + case 5: + light = new Light5(); + break; + case 4: + light = new Light4(); + break; + case 3: + light = new Light3(); + break; + case 2: + light = new Light2(); + break; + case 1: + light = new Light1(); + break; + default: + light = new Light(); } light->readVqa(stream, framesCount, _frame, 1); light->_next = _lights; @@ -120,8 +108,7 @@ void Lights::readVqa(Common::ReadStream *stream) } } -void Lights::setupFrame(int frame) -{ +void Lights::setupFrame(int frame) { Light *light; if (frame == _frame) @@ -130,22 +117,19 @@ void Lights::setupFrame(int frame) if (!_lights) return; - for (light = _lights; light; light = light->_next) - { + for (light = _lights; light; light = light->_next) { light->setupFrame(frame); } } -void Lights::reset() -{ +void Lights::reset() { Light *light; Light *nextLight; if (!_lights) return; - do - { + do { light = _lights; nextLight = light->_next; delete light; diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h index 37a7b17452..2ba95b9060 100644 --- a/engines/bladerunner/lights.h +++ b/engines/bladerunner/lights.h @@ -35,6 +35,8 @@ class Lights { #if _DEBUG friend class BladeRunnerEngine; #endif + friend class SliceRenderer; + BladeRunnerEngine *_vm; Color _ambientLightColor; diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp index bc10a0fc2c..f4d2506292 100644 --- a/engines/bladerunner/set_effects.cpp +++ b/engines/bladerunner/set_effects.cpp @@ -2,7 +2,7 @@ namespace BladeRunner { -SetEffects::SetEffects(BladeRunnerEngine* vm) { +SetEffects::SetEffects(BladeRunnerEngine *vm) { _vm = vm; _distanceColor.r = 1.0f; @@ -23,7 +23,7 @@ SetEffects::~SetEffects() { reset(); } -void SetEffects::read(Common::ReadStream* stream, int framesCount) { +void SetEffects::read(Common::ReadStream *stream, int framesCount) { _distanceCoeficient = stream->readFloatLE(); _distanceColor.r = stream->readFloatLE(); _distanceColor.g = stream->readFloatLE(); @@ -33,9 +33,8 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) { int i; for (i = 0; i < _fogsCount; i++) { int type = stream->readUint32LE(); - Fog* fog = NULL; - switch (type) - { + Fog *fog = NULL; + switch (type) { case 0: fog = new FogCone(); break; @@ -46,8 +45,7 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) { fog = new FogBox(); break; } - if (!fog) - { + if (!fog) { //TODO exception, unknown fog type } fog->read(stream, framesCount); @@ -57,7 +55,7 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) { } void SetEffects::reset() { - Fog* fog, *nextFog; + Fog *fog, *nextFog; if (!_fogs) return; @@ -84,8 +82,8 @@ void SetEffects::setFadeDensity(float density) { _fadeDensity = density; } -void SetEffects::setFogColor(char* fogName, float r, float g, float b) { - Fog* fog = findFog(fogName); +void SetEffects::setFogColor(char *fogName, float r, float g, float b) { + Fog *fog = findFog(fogName); if (fog == nullptr) return; @@ -94,19 +92,46 @@ void SetEffects::setFogColor(char* fogName, float r, float g, float b) { fog->_fogColor.b = b; } -void SetEffects::setFogDensity(char* fogName, float density) { - Fog* fog = findFog(fogName); +void SetEffects::setFogDensity(char *fogName, float density) { + Fog *fog = findFog(fogName); if (fog == nullptr) return; fog->_fogDensity = density; } -Fog* SetEffects::findFog(char* fogName) { +void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor) { + float distanceCoeficient = CLIP((position - viewPosition).length() * _distanceCoeficient, 0.0f, 1.0f); + + *outCoeficient = 1.0f - distanceCoeficient; + outColor->r = _distanceColor.r * distanceCoeficient; + outColor->g = _distanceColor.g * distanceCoeficient; + outColor->b = _distanceColor.b * distanceCoeficient; + + for (Fog *fog = this->_fogs; fog != nullptr; fog = fog->_next) { + float fogCoeficient = 0.0f; + fog->calculateCoeficient(position, viewPosition, &fogCoeficient); + if (fogCoeficient > 0.0f) { + fogCoeficient = CLIP(fog->_fogDensity * fogCoeficient, 0.0f, 1.0f); + + *outCoeficient = *outCoeficient * (1.0f - fogCoeficient); + outColor->r = outColor->r * (1.0f - fogCoeficient) + fog->_fogColor.r * fogCoeficient; + outColor->g = outColor->g * (1.0f - fogCoeficient) + fog->_fogColor.g * fogCoeficient; + outColor->b = outColor->b * (1.0f - fogCoeficient) + fog->_fogColor.b * fogCoeficient; + } + } + + *outCoeficient = *outCoeficient * (1.0f - this->_fadeDensity); + outColor->r = outColor->r * (1.0f - this->_fadeDensity) + this->_fadeColor.r * this->_fadeDensity; + outColor->g = outColor->g * (1.0f - this->_fadeDensity) + this->_fadeColor.g * this->_fadeDensity; + outColor->b = outColor->b * (1.0f - this->_fadeDensity) + this->_fadeColor.b * this->_fadeDensity; +} + +Fog *SetEffects::findFog(char *fogName) { if (!_fogs) return nullptr; - Fog* fog = _fogs; + Fog *fog = _fogs; while (fog != nullptr) { if (strcmp(fogName, fog->_name) == 0) { diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h index 16317ed3e1..233009ded2 100644 --- a/engines/bladerunner/set_effects.h +++ b/engines/bladerunner/set_effects.h @@ -57,6 +57,8 @@ public: void setFadeDensity(float density); void setFogColor(char* fogName, float r, float g, float b); void setFogDensity(char* fogName, float density); + + void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor); private: Fog* findFog(char* fogName); diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp index aafd26885a..503193c2a6 100644 --- a/engines/bladerunner/slice_animations.cpp +++ b/engines/bladerunner/slice_animations.cpp @@ -51,11 +51,15 @@ bool SliceAnimations::open(const Common::String &name) { uint8 color_g = file.readByte(); uint8 color_b = file.readByte(); + _palettes[i].color[j].r = color_r; + _palettes[i].color[j].g = color_g; + _palettes[i].color[j].b = color_b; + uint16 rgb555 = ((uint16)color_r << 10) | ((uint16)color_g << 5) | (uint16)color_b; - _palettes[i][j] = rgb555; + _palettes[i].color555[j] = rgb555; } } diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h index 1e35d6b90c..0abdfb1ce0 100644 --- a/engines/bladerunner/slice_animations.h +++ b/engines/bladerunner/slice_animations.h @@ -27,16 +27,20 @@ #include "common/file.h" #include "common/str.h" #include "common/types.h" -#include "vector.h" + +#include "bladerunner/color.h" +#include "bladerunner/vector.h" + namespace BladeRunner { class BladeRunnerEngine; struct SlicePalette { - uint16 color[256]; + uint16 color555[256]; + Color256 color[256]; - uint16 &operator[](size_t i) { return color[i]; } +// uint16 &operator[](size_t i) { return color555[i]; } }; class SliceAnimations { diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp index 6bce572064..8dad519feb 100644 --- a/engines/bladerunner/slice_renderer.cpp +++ b/engines/bladerunner/slice_renderer.cpp @@ -55,6 +55,7 @@ void dump(const char *str, Matrix4x3 m) { SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) { _vm = vm; + _pixelFormat = createRGB555(); int i; for (i = 0; i < 942; i++) { // yes, its going just to 942 and not 997 @@ -88,8 +89,8 @@ void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[_animation].frameSize); - _frameFront.x = stream.readFloatLE(); - _frameFront.y = stream.readFloatLE(); + _frameScale.x = stream.readFloatLE(); + _frameScale.y = stream.readFloatLE(); _frameSliceHeight = stream.readFloatLE(); _framePos.x = stream.readFloatLE(); _framePos.y = stream.readFloatLE(); @@ -144,31 +145,33 @@ void SliceRenderer::calculateBoundingRect() { Matrix3x2 m4(_view._viewportDistance / bottom.z, 0.0f, 0.0f, 0.0f, 25.5f, 0.0f); - Matrix3x2 m2(_frameFront.x, 0.0f, _framePos.x, - 0.0f, _frameFront.y, _framePos.y); + Matrix3x2 m2(_frameScale.x, 0.0f, _framePos.x, + 0.0f, _frameScale.y, _framePos.y); _field_109E = m4 * (facingRotation * m2); - Vector4 B6(_view._viewportHalfWidth + top.x / top.z * _view._viewportDistance, + Vector4 startScreenVector( + _view._viewportHalfWidth + top.x / top.z * _view._viewportDistance, _view._viewportHalfHeight + top.y / top.z * _view._viewportDistance, 1.0f / top.z, _frameSliceCount * (1.0f / top.z)); - Vector4 C2(_view._viewportHalfWidth + bottom.x / bottom.z * _view._viewportDistance, + Vector4 endScreenVector( + _view._viewportHalfWidth + bottom.x / bottom.z * _view._viewportDistance, _view._viewportHalfHeight + bottom.y / bottom.z * _view._viewportDistance, 1.0f / bottom.z, 0.0f); - _field_10B6.x = B6.x; - _field_10B6.y = B6.y; - _field_10B6.z = B6.z; - _field_10C2.x = C2.x; - _field_10C2.y = C2.y; - _field_10C2.z = C2.z; - _field_10CE = B6.w; - _field_10D2 = C2.w; + _startScreenVector.x = startScreenVector.x; + _startScreenVector.y = startScreenVector.y; + _startScreenVector.z = startScreenVector.z; + _endScreenVector.x = endScreenVector.x; + _endScreenVector.y = endScreenVector.y; + _endScreenVector.z = endScreenVector.z; + _startSlice = startScreenVector.w; + _endSlice = endScreenVector.w; - Vector4 delta = C2 - B6; + Vector4 delta = endScreenVector - startScreenVector; if (delta.y == 0.0f) return; @@ -180,37 +183,37 @@ void SliceRenderer::calculateBoundingRect() { float screenMinY = 0.0f; float screenMaxY = 479.0f; - if (B6.y < screenMinY) { - if (C2.y < screenMinY) + if (startScreenVector.y < screenMinY) { + if (endScreenVector.y < screenMinY) return; - float f = (screenMinY - B6.y) / delta.y; - B6 = B6 + f * delta; - } else if (B6.y > screenMaxY) { - if (C2.y >= screenMaxY) + float f = (screenMinY - startScreenVector.y) / delta.y; + startScreenVector = startScreenVector + f * delta; + } else if (startScreenVector.y > screenMaxY) { + if (endScreenVector.y >= screenMaxY) return; - float f = (screenMaxY - B6.y) / delta.y; - B6 = B6 + f * delta; + float f = (screenMaxY - startScreenVector.y) / delta.y; + startScreenVector = startScreenVector + f * delta; } - if (C2.y < screenMinY) { - float f = (screenMinY - C2.y) / delta.y; - C2 = C2 + f * delta; - } else if (C2.y > screenMaxY) { - float f = (screenMaxY - C2.y) / delta.y; - C2 = C2 + f * delta; + if (endScreenVector.y < screenMinY) { + float f = (screenMinY - endScreenVector.y) / delta.y; + endScreenVector = endScreenVector + f * delta; + } else if (endScreenVector.y > screenMaxY) { + float f = (screenMaxY - endScreenVector.y) / delta.y; + endScreenVector = endScreenVector + f * delta; } - int bbox_min_y = (int)MIN(B6.y, C2.y); - int bbox_max_y = (int)MAX(B6.y, C2.y) + 1; + int bbox_min_y = (int)MIN(startScreenVector.y, endScreenVector.y); + int bbox_max_y = (int)MAX(startScreenVector.y, endScreenVector.y) + 1; /* * Calculate min and max X */ - Matrix3x2 mB6 = _field_109E + Vector2(B6.x, 25.5f / B6.z); - Matrix3x2 mC2 = _field_109E + Vector2(C2.x, 25.5f / C2.z); + Matrix3x2 mB6 = _field_109E + Vector2(startScreenVector.x, 25.5f / startScreenVector.z); + Matrix3x2 mC2 = _field_109E + Vector2(endScreenVector.x, 25.5f / endScreenVector.z); float min_x = 640.0f; float max_x = 0.0f; @@ -234,14 +237,14 @@ void SliceRenderer::calculateBoundingRect() { int bbox_min_x = MIN(MAX((int)min_x, 0), 640); int bbox_max_x = MIN(MAX((int)max_x + 1, 0), 640); - _field_10B6.x = B6.x; - _field_10B6.y = B6.y; - _field_10B6.z = B6.z; - _field_10C2.x = C2.x; - _field_10C2.y = C2.y; - _field_10C2.z = C2.z; - _field_10CE = B6.w; - _field_10D2 = C2.w; + _startScreenVector.x = startScreenVector.x; + _startScreenVector.y = startScreenVector.y; + _startScreenVector.z = startScreenVector.z; + _endScreenVector.x = endScreenVector.x; + _endScreenVector.y = endScreenVector.y; + _endScreenVector.z = endScreenVector.z; + _startSlice = startScreenVector.w; + _endSlice = endScreenVector.w; _minX = bbox_min_x; _minY = bbox_min_y; @@ -250,72 +253,74 @@ void SliceRenderer::calculateBoundingRect() { } struct SliceLineIterator { - int _field_00[2][3]; - int _field_18; - int _field_1C; - - float _field_20; - float _field_24; - float _field_28; - float _field_2C; - float _field_30; - float _field_34; + int _sliceMatrix[2][3]; + int _startY; + int _endY; + + float _currentZ; + float _stepZ; + float _currentSlice; + float _stepSlice; + float _currentX; + float _stepX; int _field_38; - int _field_3C; + int _currentY; - void setup(float arg_1, float arg_2, float arg_3, - float arg_4, float arg_5, float arg_6, - float arg_7, float arg_8, - Matrix3x2 arg_9); + void setup(float endScreenX, float endScreenY, float endScreenZ, + float startScreenX, float startScreenY, float startScreenZ, + float endSlice, float startSlice, + Matrix3x2 m); float line(); void advance(); }; void SliceLineIterator::setup( - float arg_1, float arg_2, float arg_3, - float arg_4, float arg_5, float arg_6, - float arg_7, float arg_8, - Matrix3x2 arg_9) + float endScreenX, float endScreenY, float endScreenZ, + float startScreenX, float startScreenY, float startScreenZ, + float endSlice, float startSlice, + Matrix3x2 m) { - _field_18 = (int)arg_5; - _field_1C = (int)arg_2; + _startY = (int)startScreenY; + _endY = (int)endScreenY; - float var_3 = arg_2 - arg_5; + float size = endScreenY - startScreenY; - if (var_3 <= 0.0f || arg_6 <= 0.0f) - _field_3C = _field_1C + 1; + if (size <= 0.0f || startScreenZ <= 0.0f) + _currentY = _endY + 1; - _field_20 = arg_6; - _field_24 = (arg_3 - arg_6) / var_3; - _field_2C = (arg_7 - arg_8) / var_3; - _field_28 = arg_8 - (arg_5 - floor(arg_5) - 1.0f) * _field_2C; + _currentZ = startScreenZ; + _stepZ = (endScreenZ - startScreenZ) / size; - _field_30 = arg_4; - _field_34 = (arg_1 - arg_4) / var_3; - _field_38 = (int)((25.5f / var_3) * (1.0f / arg_3 - 1.0f / arg_6) * 64.0); - _field_3C = _field_18; + _stepSlice = (endSlice - startSlice) / size; + _currentSlice = startSlice - (startScreenY - floor(startScreenY) - 1.0f) * _stepSlice; - float var_54 = _field_30; - float var_55 = 25.5f / _field_20; + _currentX = startScreenX; + _stepX = (endScreenX - startScreenX) / size; - Matrix3x2 translate_matrix = Matrix3x2(1.0f, 0.0f, var_54, - 0.0f, 1.0f, var_55); + _field_38 = (int)((25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ) * 64.0); + _currentY = _startY; + + 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); - arg_9 = scale_matrix * (translate_matrix * arg_9); + m = scale_matrix * (translate_matrix * m); for (int r = 0; r != 2; ++r) for (int c = 0; c != 3; ++c) - _field_00[r][c] = arg_9(r, c); + _sliceMatrix[r][c] = m(r, c); } float SliceLineIterator::line() { float var_0 = 0.0f; - if (_field_20 != 0.0f) - var_0 = _field_28 / _field_20; + if (_currentZ != 0.0f) + var_0 = _currentSlice / _currentZ; if (var_0 < 0.0) var_0 = 0.0f; @@ -324,12 +329,12 @@ float SliceLineIterator::line() { } void SliceLineIterator::advance() { - _field_20 += _field_24; - _field_28 += _field_2C; - _field_30 += _field_34; - _field_3C += 1; - _field_00[0][2] += (int)(65536.0f * _field_34); - _field_00[1][2] += _field_38; + _currentZ += _stepZ; + _currentSlice += _stepSlice; + _currentX += _stepX; + _currentY += 1; + _sliceMatrix[0][2] += (int)(65536.0f * _stepX); + _sliceMatrix[1][2] += _field_38; } static @@ -341,38 +346,87 @@ void setupLookupTable(int t[256], int inc) { } } -void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) { +void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) { assert(_sliceFramePtr); assert(_lights); assert(_setEffects); //assert(_view); + _vm->_sliceRenderer->setupFrame(animationId, animationFrame, position, facing); + SliceLineIterator sliceLineIterator; sliceLineIterator.setup( - _field_10C2.x, _field_10C2.y, _field_10C2.z, - _field_10B6.x, _field_10B6.y, _field_10B6.z, - _field_10D2, _field_10CE, // 2 floats + _endScreenVector.x, _endScreenVector.y, _endScreenVector.z, + _startScreenVector.x, _startScreenVector.y, _startScreenVector.z, + _endSlice, _startSlice, _field_109E // 3x2 matrix - ); + ); + + SliceRendererLights sliceRendererLights = SliceRendererLights(_lights); _lights->setupFrame(_view._frame); _setEffects->setupFrame(_view._frame); - setupLookupTable(_t1, sliceLineIterator._field_00[0][0]); - setupLookupTable(_t2, sliceLineIterator._field_00[0][1]); - setupLookupTable(_t4, sliceLineIterator._field_00[1][0]); - setupLookupTable(_t5, sliceLineIterator._field_00[1][1]); + float sliceLine = sliceLineIterator.line(); + + sliceRendererLights.calculateColorBase( + Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight), + Vector3(_position.x, _position.y, _position.z + _frameBottomZ), + sliceLineIterator._endY - sliceLineIterator._startY); + + float setEffectsColorCoeficient; + Color setEffectColor; + _setEffects->calculateColor( + _view._cameraPosition, + Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight), + &setEffectsColorCoeficient, + &setEffectColor); + + _lightsColor.r = setEffectsColorCoeficient * sliceRendererLights._finalColor.r * 65536.0f; + _lightsColor.g = setEffectsColorCoeficient * sliceRendererLights._finalColor.g * 65536.0f; + _lightsColor.b = setEffectsColorCoeficient * sliceRendererLights._finalColor.b * 65536.0f; + + _setEffectColor.r = setEffectColor.r * 31.0f * 65536.0f; + _setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f; + _setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f; + + setupLookupTable(_m11lookup, sliceLineIterator._sliceMatrix[0][0]); + setupLookupTable(_m12lookup, sliceLineIterator._sliceMatrix[0][1]); + setupLookupTable(_m21lookup, sliceLineIterator._sliceMatrix[1][0]); + setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix[1][1]); + + if(_animationsShadowEnabled[_animation]) { + //TODO: draw shadows + } - int frameY = sliceLineIterator._field_18; + int frameY = sliceLineIterator._startY; uint16 *frameLinePtr = (uint16*)surface.getPixels() + 640 * frameY; uint16 *zBufferLinePtr = zbuffer + 640 * frameY; - while (sliceLineIterator._field_3C <= sliceLineIterator._field_1C) { - _c3 = sliceLineIterator._field_00[0][2]; - _c6 = sliceLineIterator._field_00[1][2]; + 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)); + + if (sliceLineIterator._currentY & 1) { + _setEffects->calculateColor( + _view._cameraPosition, + Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight), + &setEffectsColorCoeficient, + &setEffectColor); + } - float sliceLine = sliceLineIterator.line(); + _lightsColor.r = setEffectsColorCoeficient * sliceRendererLights._finalColor.r * 65536.0f; + _lightsColor.g = setEffectsColorCoeficient * sliceRendererLights._finalColor.g * 65536.0f; + _lightsColor.b = setEffectsColorCoeficient * sliceRendererLights._finalColor.b * 65536.0f; + + _setEffectColor.r = setEffectColor.r * 31.0f * 65536.0f; + _setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f; + _setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f; if (frameY >= 0 && frameY < 480) drawSlice((int)sliceLine, frameLinePtr, zBufferLinePtr); @@ -406,21 +460,30 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP continue; uint32 lastVertex = vertexCount - 1; - int lastVertexX = MAX((_t1[p[3*lastVertex]] + _t2[p[3*lastVertex+1]] + _c3) >> 16, 0); + int lastVertexX = MAX((_m11lookup[p[3*lastVertex]] + _m12lookup[p[3*lastVertex+1]] + _m13) >> 16, 0); int previousVertexX = lastVertexX; while (vertexCount--) { - int vertexX = CLIP((_t1[p[0]] + _t2[p[1]] + _c3) >> 16, 0, 640); + int vertexX = CLIP((_m11lookup[p[0]] + _m12lookup[p[1]] + _m13) >> 16, 0, 640); if (vertexX > previousVertexX) { - int vertexZ = (_t4[p[0]] + _t5[p[1]] + _c6) >> 6; + int vertexZ = (_m21lookup[p[0]] + _m22lookup[p[1]] + _m23) >> 6; if (vertexZ >= 0 && vertexZ < 65536) { + Color256 color = palette.color[p[2]]; + + float hackMul = 8.0f; //not part of game + + color.r = (int)(_setEffectColor.r + hackMul * _lightsColor.r * color.r) >> 13; // >> 16, + color.g = (int)(_setEffectColor.g + hackMul * _lightsColor.g * color.g) >> 13; + color.b = (int)(_setEffectColor.b + hackMul * _lightsColor.b * color.b) >> 13; + + int color555 = _pixelFormat.RGBToColor(color.r/* * 8*/, color.g/* * 8*/, color.b/* * 8*/); + for (int x = previousVertexX; x != vertexX; ++x) { - // debug("\t%04x < %04x", vertexZ, zbufLinePtr[x]); if (vertexZ < zbufLinePtr[x]) { - frameLinePtr[x] = palette[p[2]]; + frameLinePtr[x] = color555; zbufLinePtr[x] = (uint16)vertexZ; } } @@ -446,4 +509,102 @@ void SliceRenderer::disableShadows(int animationsIdsList[], int listSize) { } } +SliceRenderer::SliceRendererLights::SliceRendererLights(Lights *lights) { + _finalColor.r = 0.0f; + _finalColor.g = 0.0f; + _finalColor.b = 0.0f; + + _lights = lights; + + for(int i = 0; i < 20; i++) { + _colors[i].r = 0.0f; + _colors[i].g = 0.0f; + _colors[i].b = 0.0f; + } +} + + +void SliceRenderer::SliceRendererLights::calculateColorBase(Vector3 position1, Vector3 position2, float height) { + _finalColor.r = 0.0f; + _finalColor.g = 0.0f; + _finalColor.b = 0.0f; + _hmm3 = 0; + if (_lights) { + Light *light = _lights->_lights; + int i = 0; + if (light) { + do { + if (i < 20) { + float v8 = light->calculate(position1, position2/*, height*/); + + this->_hmm2[i] = v8; + this->_hmm[i] = v8; + + Color v22; + light->calculateColor(&v22, position1); + _colors[i] = v22; + _finalColor.r += v22.r; + _finalColor.g += v22.g; + _finalColor.b += v22.b; + } + else + { + Color v23; + light->calculateColor(&v23, position1); + _finalColor.r += v23.r; + _finalColor.g += v23.g; + _finalColor.b += v23.b; + } + light = light->_next; + i++; + } while (light); + } + + _finalColor.r += _lights->_ambientLightColor.r; + _finalColor.g += _lights->_ambientLightColor.g; + _finalColor.b += _lights->_ambientLightColor.b; + } +} + +void SliceRenderer::SliceRendererLights::calculateColorSlice(Vector3 position) { + _finalColor.r = 0.0f; + _finalColor.g = 0.0f; + _finalColor.b = 0.0f; + + if (_lights) { + Light *light = _lights->_lights; + int i = 0; + if (light) { + do { + if (i < 20) { + _hmm[i] = _hmm[i] - 1.0f; + + if (_hmm[i] <= 0.0f) { + do { + _hmm[i] = _hmm[i] + _hmm2[i]; + } while (_hmm[i] <= 0.0f); + light->calculateColor(&_colors[i], position); + _hmm3++; + } + _finalColor.r += _colors[i].r; + _finalColor.g += _colors[i].g; + _finalColor.b += _colors[i].b; + } else { + Color color; + light->calculateColor(&color, position); + _hmm3++; + _finalColor.r += color.r; + _finalColor.g += color.g; + _finalColor.b += color.b; + } + light = light->_next; + i++; + } while (light); + } + _finalColor.r += _lights->_ambientLightColor.r; + _finalColor.g += _lights->_ambientLightColor.g; + _finalColor.b += _lights->_ambientLightColor.b; + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h index 3dcd92271e..9cbd3cec01 100644 --- a/engines/bladerunner/slice_renderer.h +++ b/engines/bladerunner/slice_renderer.h @@ -23,6 +23,7 @@ #ifndef BLADERUNNER_SLICE_RENDERER_H #define BLADERUNNER_SLICE_RENDERER_H +#include "bladerunner/color.h" #include "bladerunner/vector.h" #include "bladerunner/view.h" #include "bladerunner/matrix.h" @@ -55,7 +56,7 @@ class SliceRenderer { void *_sliceFramePtr; // Animation frame data - Vector2 _frameFront; + Vector2 _frameScale; float _frameBottomZ; Vector2 _framePos; float _frameSliceHeight; @@ -63,24 +64,29 @@ class SliceRenderer { uint32 _frameSliceCount; Matrix3x2 _field_109E; - Vector3 _field_10B6; - Vector3 _field_10C2; - float _field_10CE; - float _field_10D2; + Vector3 _startScreenVector; + Vector3 _endScreenVector; + float _startSlice; + float _endSlice; int _minX; int _maxX; int _minY; int _maxY; - int _t1[256]; - int _t2[256]; - int _c3; - int _t4[256]; - int _t5[256]; - int _c6; + int _m11lookup[256]; + int _m12lookup[256]; + int _m13; + int _m21lookup[256]; + int _m22lookup[256]; + int _m23; bool _animationsShadowEnabled[997]; + Color _setEffectColor; + Color _lightsColor; + + Graphics::PixelFormat _pixelFormat; + Matrix3x2 calculateFacingRotationMatrix(); void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr); @@ -95,11 +101,29 @@ public: void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f); void calculateBoundingRect(); - void drawFrame(Graphics::Surface &surface, uint16 *zbuffer); + //void drawFrame(Graphics::Surface &surface, uint16 *zbuffer); + void drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer); void preload(int animationId); - void disableShadows(int* animationsIdsList, int listSize); + void disableShadows(int *animationsIdsList, int listSize); + +private: + class SliceRendererLights { + Lights *_lights; + Color _colors[20]; + float _hmm[20]; + float _hmm2[20]; + int _hmm3; + public: + Color _finalColor; + + public: + SliceRendererLights(Lights *lights); + + void calculateColorBase(Vector3 position1, Vector3 position2, float height); + void calculateColorSlice(Vector3 position); + }; }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h index 4f4bfed778..80fd5f8e14 100644 --- a/engines/bladerunner/vector.h +++ b/engines/bladerunner/vector.h @@ -58,6 +58,20 @@ public: {} float length() { return sqrtf(x * x + y * y + z * z); } + Vector3 normalize() { + float len = length(); + if (len == 0) { + return Vector3(0.0f, 0.0f, 0.0f); + } + return Vector3(x / len, y / len, z / len); + } + + static Vector3 cross(Vector3 a, Vector3 b) { + return Vector3( + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x); + } }; inline diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp index f8acb91400..9356f046dd 100644 --- a/engines/bladerunner/view.cpp +++ b/engines/bladerunner/view.cpp @@ -60,9 +60,9 @@ void View::calculateSliceViewMatrix() { m = m * rotationMatrixX(float(M_PI) / 2.0f); - Matrix4x3 a(-1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f); + Matrix4x3 a(-1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f); m = a * m; |