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;  | 
