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

neuromancer noreply at scummvm.org
Mon May 6 20:59:27 UTC 2024


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

Summary:
7e3d2efa8e FREESCAPE: loading for some sounds in dark release for atari
14a991e6c4 FREESCAPE: expanded color handling to allow Amiga/Atari double colors per object
6098d53be1 FREESCAPE: improved support for castle
2c67f90d4b MATH: added distance function from point to AABB
d782923a3d MATH: added const qualifier to AABB collision function
e7bd1124c1 FREESCAPE: improved rendering of planar objects


Commit: 7e3d2efa8e8a7403d4c5f44b30dfd12bdd40a05a
    https://github.com/scummvm/scummvm/commit/7e3d2efa8e8a7403d4c5f44b30dfd12bdd40a05a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:08+02:00

Commit Message:
FREESCAPE: loading for some sounds in dark release for atari

Changed paths:
    engines/freescape/games/dark/atari.cpp
    engines/freescape/sound.cpp


diff --git a/engines/freescape/games/dark/atari.cpp b/engines/freescape/games/dark/atari.cpp
index 693910232cf..3770f65bb47 100644
--- a/engines/freescape/games/dark/atari.cpp
+++ b/engines/freescape/games/dark/atari.cpp
@@ -37,6 +37,7 @@ void DarkEngine::loadAssetsAtariFullGame() {
 	loadMessagesVariableSize(stream, 0x3f6f, 66);
 	loadPalettes(stream, 0x205e6);
 	loadGlobalObjects(stream, 0x32f6, 24);
+	loadSoundsFx(stream, 0x266e8, 11);
 
 	for (auto &it : _areaMap) {
 		addWalls(it._value);
diff --git a/engines/freescape/sound.cpp b/engines/freescape/sound.cpp
index a3f1faa3750..5ab6b0bfa06 100644
--- a/engines/freescape/sound.cpp
+++ b/engines/freescape/sound.cpp
@@ -407,6 +407,11 @@ void FreescapeEngine::playSoundFx(int index, bool sync) {
 		return;
 	}
 
+	if (index >= int(_soundsFx.size())) {
+		debugC(1, kFreescapeDebugMedia, "WARNING: Sound %d not available", index);
+		return;
+	}
+
 	int size = _soundsFx[index]->size;
 	int sampleRate = _soundsFx[index]->sampleRate;
 	byte *data = _soundsFx[index]->data;


Commit: 14a991e6c4ac295eed63c5a974298a49610e523e
    https://github.com/scummvm/scummvm/commit/14a991e6c4ac295eed63c5a974298a49610e523e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:08+02:00

Commit Message:
FREESCAPE: expanded color handling to allow Amiga/Atari double colors per object

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/games/dark/atari.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/gfx_opengl.cpp
    engines/freescape/gfx_opengl_shaders.cpp
    engines/freescape/gfx_tinygl.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp
    engines/freescape/objects/geometricobject.cpp
    engines/freescape/objects/geometricobject.h
    engines/freescape/objects/sensor.cpp


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 4050481c6c6..a7c16576bc4 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -325,6 +325,7 @@ bool Area::checkInSight(const Math::Ray &ray, float maxDistance) {
 			Math::Vector3d(maxDistance / 30, maxDistance / 30, maxDistance / 30), // size
 			nullptr,
 			nullptr,
+			nullptr,
 			FCLInstructionVector(),
 			"");
 
@@ -403,6 +404,7 @@ void Area::addFloor() {
 		Math::Vector3d(maxSize * 4, 1, maxSize * 4), // size
 		gColors,
 		nullptr,
+		nullptr,
 		FCLInstructionVector());
 	(*_objectsByID)[id] = obj;
 	_drawableObjects.insert_at(0, obj);
diff --git a/engines/freescape/games/dark/atari.cpp b/engines/freescape/games/dark/atari.cpp
index 3770f65bb47..cb0d9d31ca3 100644
--- a/engines/freescape/games/dark/atari.cpp
+++ b/engines/freescape/games/dark/atari.cpp
@@ -44,6 +44,16 @@ void DarkEngine::loadAssetsAtariFullGame() {
 		addECDs(it._value);
 		addSkanner(it._value);
 	}
+
+	GeometricObject *obj = nullptr;
+	obj = (GeometricObject *)_areaMap[15]->objectWithID(18);
+	assert(obj);
+	obj->_cyclingColors = true;
+
+	obj = (GeometricObject *)_areaMap[15]->objectWithID(26);
+	assert(obj);
+	obj->_cyclingColors = true;
+
 }
 
 } // End of namespace Freescape
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index d0fd53e4fe6..53178829839 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -86,7 +86,7 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
 
 	Math::Vector3d drillBaseOrigin = Math::Vector3d(0, 0, 0);
 	Math::Vector3d drillBaseSize = Math::Vector3d(3, 2, 3);
-	_drillBase = new GeometricObject(kCubeType, 0, 0, drillBaseOrigin, drillBaseSize, nullptr, nullptr, FCLInstructionVector(), "");
+	_drillBase = new GeometricObject(kCubeType, 0, 0, drillBaseOrigin, drillBaseSize, nullptr, nullptr, nullptr, FCLInstructionVector(), "");
 	assert(!_drillBase->isDestroyed() && !_drillBase->isInvisible());
 
 	if (isDemo()) {
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index fe7bf655ff8..85110d73027 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -432,11 +432,11 @@ bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	return true;
 }
 
-bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
-	if (index == _keyColor)
+bool Renderer::getRGBAt(uint8 index, uint8 ecolor, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple) {
+	if (index == _keyColor && ecolor == 0)
 		return false;
 
-	if (index == 0) {
+	if (index == 0 && ecolor == 0) {
 		readFromPalette(0, r1, g1, b1);
 		r2 = r1;
 		g2 = g1;
@@ -451,9 +451,14 @@ bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2,
 		} else
 			readFromPalette(index, r1, g1, b1);
 
-		r2 = r1;
-		g2 = g1;
-		b2 = b1;
+		if (ecolor > 0)
+			readFromPalette(ecolor, r2, g2, b2);
+		else {
+			r2 = r1;
+			g2 = g1;
+			b2 = b1;
+		}
+
 		return true;
 	} else if (_renderMode == Common::kRenderEGA)
 		return getRGBAtEGA(index, r1, g1, b1, r2, g2, b2);
@@ -525,7 +530,7 @@ bool Renderer::computeScreenViewport() {
 	return true;
 }
 
-void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, int type) {
+void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, int type) {
 	Math::Vector3d vertices[8] = { origin, origin, origin, origin, origin, origin, origin, origin };
 	switch (type) {
 	default:
@@ -603,7 +608,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 	Common::Array<Math::Vector3d> face;
 	byte *stipple = nullptr;
 	uint8 r1, g1, b1, r2, g2, b2;
-	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+	uint color = (*colours)[0];
+	uint ecolor = ecolours ? (*ecolours)[0] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -624,7 +632,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[1];
+	ecolor = ecolours ? (*ecolours)[1] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -643,8 +654,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 
 		face.clear();
 	}
+	color = (*colours)[2];
+	ecolor = ecolours ? (*ecolours)[2] : 0;
 
-	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, stipple)) {
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -663,7 +676,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[3];
+	ecolor = ecolours ? (*ecolours)[3] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -683,7 +699,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[4];
+	ecolor = ecolours ? (*ecolours)[4] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -702,7 +721,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 		face.clear();
 	}
 
-	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[5];
+	ecolor = ecolours ? (*ecolours)[5] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 
@@ -720,12 +742,15 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 	}
 }
 
-void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &size, Common::Array<uint8> *colours) {
+void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
 	byte *stipple = nullptr;
 	uint8 r1, g1, b1, r2, g2, b2;
 	Common::Array<Math::Vector3d> face;
 
-	if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+	uint color = (*colours)[0];
+	uint ecolor = ecolours ? (*ecolours)[0] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.push_back(origin);
@@ -741,7 +766,10 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[1];
+	ecolor = ecolours ? (*ecolours)[1] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
@@ -758,7 +786,10 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[2];
+	ecolor = ecolours ? (*ecolours)[2] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
@@ -775,7 +806,10 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[3];
+	ecolor = ecolours ? (*ecolours)[3] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
@@ -792,7 +826,10 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[4];
+	ecolor = ecolours ? (*ecolours)[4] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
@@ -809,7 +846,10 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 		}
 	}
 
-	if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, stipple)) {
+	color = (*colours)[5];
+	ecolor = ecolours ? (*ecolours)[5] : 0;
+
+	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		face.clear();
@@ -827,7 +867,7 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 	}
 }
 
-void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3d &originalSize, Common::Array<uint8> *colours) {
+void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3d &originalSize, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
 
 	Math::Vector3d size = originalSize;
 	if (size.x() > 0 && size.y() > 0 && size.z() > 0) {
@@ -861,10 +901,15 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
 	Common::Array<Math::Vector3d> vertices;
+	uint color = 0;
+	uint ecolor = 0;
+
 	for (int i = 0; i < 2; i++) {
 
-		// debug("rec color: %d", (*colours)[i]);
-		if (getRGBAt((*colours)[i], r1, g1, b1, r2, g2, b2, stipple)) {
+		color = (*colours)[i];
+		ecolor = ecolours ? (*ecolours)[i] : 0;
+
+		if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			vertices.clear();
@@ -906,7 +951,7 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 	polygonOffset(false);
 }
 
-void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours) {
+void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
 	if (ordinates->size() % 3 > 0 && ordinates->size() > 0)
@@ -915,8 +960,14 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 	Common::Array<Math::Vector3d> vertices;
 	polygonOffset(true);
 
-	if (ordinates->size() == 6) {                 // Line
-		assert(getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
+	uint color = 0;
+	uint ecolor = 0;
+
+	if (ordinates->size() == 6) { // Line
+		color = (*colours)[0];
+		ecolor = ecolours ? (*ecolours)[0] : 0;
+
+		assert(getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		for (uint i = 0; i < ordinates->size(); i = i + 3)
@@ -930,7 +981,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 		}
 
 		vertices.clear();
-		assert(getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
+		color = (*colours)[1];
+		ecolor = ecolours ? (*ecolours)[1] : 0;
+
+		assert(getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)); // It will never return false?
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
 		for (int i = ordinates->size(); i > 0; i = i - 3)
@@ -944,7 +998,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 		}
 
 	} else {
-		if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, stipple)) {
+		color = (*colours)[0];
+		ecolor = ecolours ? (*ecolours)[0] : 0;
+
+		if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			for (uint i = 0; i < ordinates->size(); i = i + 3) {
@@ -959,7 +1016,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 			}
 		}
 		vertices.clear();
-		if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, stipple)) {
+		color = (*colours)[1];
+		ecolor = ecolours ? (*ecolours)[1] : 0;
+
+		if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 			setStippleData(stipple);
 			useColor(r1, g1, b1);
 			for (int i = ordinates->size(); i > 0; i = i - 3) {
@@ -996,7 +1056,7 @@ void Renderer::drawBackground(uint8 color) {
 
 	byte *stipple = nullptr;
 
-	getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
+	getRGBAt(color, 0, r1, g1, b1, r2, g2, b2, stipple);
 	clear(r1, g1, b1);
 }
 
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 97b21b3e5c9..cd9d207775a 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -88,10 +88,10 @@ public:
 
 	virtual void renderCrossair(const Common::Point crossairPosition) = 0;
 
-	virtual void renderCube(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours);
-	virtual void renderRectangle(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours);
-	virtual void renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours);
-	virtual void renderPyramid(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, int type);
+	virtual void renderCube(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
+	virtual void renderRectangle(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
+	virtual void renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
+	virtual void renderPyramid(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, int type);
 	virtual void renderFace(const Common::Array<Math::Vector3d> &vertices) = 0;
 
 	void setColorRemaps(ColorReMap *colorRemaps);
@@ -111,7 +111,7 @@ public:
 	uint8 indexFromColor(uint8 r, uint8 g, uint8 b);
 	uint8 mapEGAColor(uint8 index);
 
-	bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
+	bool getRGBAt(uint8 index, uint8 ecolor, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
 	bool getRGBAtC64(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
 	bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
 	bool getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index fb0b71d0db8..d004f5f7ef6 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -284,7 +284,7 @@ void OpenGLRenderer::renderPlayerShootRay(byte color, const Common::Point positi
 void OpenGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, byte color) {
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
-	getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
+	getRGBAt(color, 0, r1, g1, b1, r2, g2, b2, stipple);
 
 	int triangleAmount = 20;
 	float twicePi = (float)(2.0 * M_PI);
@@ -447,7 +447,7 @@ void OpenGLRenderer::polygonOffset(bool enabled) {
 
 void OpenGLRenderer::setStippleData(byte *data) {
 	if (!data)
-		return;
+		data = _defaultStippleArray;
 
 	_variableStippleArray = data;
 	//for (int i = 0; i < 128; i++)
@@ -490,7 +490,7 @@ void OpenGLRenderer::clear(uint8 r, uint8 g, uint8 b, bool ignoreViewport) {
 void OpenGLRenderer::drawFloor(uint8 color) {
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple;
-	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
+	assert(getRGBAt(color, 0, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
 	glColor3ub(r1, g1, b1);
 
 	glEnableClientState(GL_VERTEX_ARRAY);
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index efcb92a79fd..142859a2754 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -298,7 +298,7 @@ void OpenGLShaderRenderer::renderPlayerShootRay(byte color, const Common::Point
 void OpenGLShaderRenderer::drawCelestialBody(Math::Vector3d position, float radius, byte color) {
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
-	getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
+	getRGBAt(color, 0, r1, g1, b1, r2, g2, b2, stipple);
 
 	useColor(r1, g1, b1);
 
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index 4edb35abec3..259c642c92f 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -262,7 +262,7 @@ void TinyGLRenderer::clear(uint8 r, uint8 g, uint8 b, bool ignoreViewport) {
 void TinyGLRenderer::drawFloor(uint8 color) {
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
-	assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
+	assert(getRGBAt(color, 0, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
 	tglColor3ub(r1, g1, b1);
 
 	tglEnableClientState(TGL_VERTEX_ARRAY);
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 3b06ed4ef84..931198264af 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -337,6 +337,11 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
 		// read the appropriate number of colours
 		int numberOfColours = GeometricObject::numberOfColoursForObjectOfType(objectType);
 		Common::Array<uint8> *colours = new Common::Array<uint8>;
+		Common::Array<uint8> *ecolours = nullptr;
+
+		if (!isDriller() && (isAmiga() || isAtariST()))
+			ecolours = new Common::Array<uint8>;
+
 		debugC(1, kFreescapeDebugParser, "Number of colors: %d", numberOfColours / 2);
 		uint8 entry;
 		for (uint8 colour = 0; colour < numberOfColours / 2; colour++) {
@@ -353,14 +358,18 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
 
 			colours->push_back(entry);
 			debugC(1, kFreescapeDebugParser, "color[%d] = %x", 2 * colour, entry);
-			if (!isDriller() && (isAmiga() || isAtariST()))
+			if (!isDriller() && (isAmiga() || isAtariST())) {
+				ecolours->push_back(extraData & 0xf);
 				debugC(1, kFreescapeDebugParser, "ecolor[%d] = %x", 2 * colour, extraData & 0xf);
+			}
 
 			entry = data >> 4;
 			colours->push_back(entry);
 			debugC(1, kFreescapeDebugParser, "color[%d] = %x", 2 * colour + 1, entry);
-			if (!isDriller() && (isAmiga() || isAtariST()))
+			if (!isDriller() && (isAmiga() || isAtariST())) {
+				ecolours->push_back(extraData >> 4);
 				debugC(1, kFreescapeDebugParser, "ecolor[%d] = %x", 2 * colour + 1, extraData >> 4);
+			}
 
 			byteSizeOfObject--;
 		}
@@ -408,6 +417,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
 			position,
 			32 * v, // size
 			colours,
+			ecolours,
 			ordinates,
 			instructions,
 			conditionSource);
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index 5045a409b4a..d04708737b0 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -22,6 +22,8 @@
 // Based on Phantasma code by Thomas Harte (2013),
 // available at https://github.com/TomHarte/Phantasma/ (MIT)
 
+#include "common/system.h"
+
 #include "freescape/objects/geometricobject.h"
 
 namespace Freescape {
@@ -119,6 +121,7 @@ GeometricObject::GeometricObject(
 	const Math::Vector3d &origin_,
 	const Math::Vector3d &size_,
 	Common::Array<uint8> *colours_,
+	Common::Array<uint8> *ecolours_,
 	Common::Array<uint16> *ordinates_,
 	FCLInstructionVector conditionInstructions_,
 	Common::String conditionSource_) {
@@ -143,6 +146,12 @@ GeometricObject::GeometricObject(
 	if (colours_)
 		_colours = colours_;
 
+	_ecolours = nullptr;
+
+	if (ecolours_)
+		_ecolours = ecolours_;
+
+	_cyclingColors = false; // This needs to be set manually
 	_ordinates = nullptr;
 	_initialOrdinates = nullptr;
 
@@ -230,12 +239,16 @@ void GeometricObject::restoreOrdinates() {
 
 Object *GeometricObject::duplicate() {
 	Common::Array<uint8> *coloursCopy = nullptr;
+	Common::Array<uint8> *ecoloursCopy = nullptr;
 	Common::Array<uint16> *ordinatesCopy = nullptr;
 	FCLInstructionVector *conditionCopy = nullptr;
 
 	if (_colours)
 		coloursCopy = new Common::Array<uint8>(*_colours);
 
+	if (_ecolours)
+		ecoloursCopy = new Common::Array<uint8>(*_ecolours);
+
 	if (_ordinates)
 		ordinatesCopy = new Common::Array<uint16>(*_ordinates);
 
@@ -249,6 +262,7 @@ Object *GeometricObject::duplicate() {
 		_origin,
 		_size,
 		coloursCopy,
+		ecoloursCopy,
 		ordinatesCopy,
 		*conditionCopy,
 		_conditionSource);
@@ -413,17 +427,25 @@ bool GeometricObject::collides(const Math::AABB &boundingBox_) {
 }
 
 void GeometricObject::draw(Renderer *gfx) {
+	if (_cyclingColors) {
+		if (g_system->getMillis() % 10 == 0)
+			for (uint i = 0; i < _colours->size(); i++) {
+				(*_colours)[i] = ((*_colours)[i] + 1) % 0xf;
+				(*_ecolours)[i] = ((*_ecolours)[i] + 1) % 0xf;
+			}
+	}
+
 	if (this->getType() == kCubeType) {
-		gfx->renderCube(_origin, _size, _colours);
+		gfx->renderCube(_origin, _size, _colours, _ecolours);
 	} else if (this->getType() == kRectangleType) {
-		gfx->renderRectangle(_origin, _size, _colours);
+		gfx->renderRectangle(_origin, _size, _colours, _ecolours);
 	} else if (isPyramid(this->getType())) {
-		gfx->renderPyramid(_origin, _size, _ordinates, _colours, this->getType());
+		gfx->renderPyramid(_origin, _size, _ordinates, _colours, _ecolours, this->getType());
 	} else if (this->isPlanar() && _type <= 14) {
 		if (this->getType() == kTriangleType)
 			assert(_ordinates->size() == 9);
 
-		gfx->renderPolygon(_origin, _size, _ordinates, _colours);
+		gfx->renderPolygon(_origin, _size, _ordinates, _colours, _ecolours);
 	}
 }
 
diff --git a/engines/freescape/objects/geometricobject.h b/engines/freescape/objects/geometricobject.h
index 900c218c733..070aa3ead1e 100644
--- a/engines/freescape/objects/geometricobject.h
+++ b/engines/freescape/objects/geometricobject.h
@@ -45,6 +45,7 @@ public:
 		const Math::Vector3d &origin,
 		const Math::Vector3d &size,
 		Common::Array<uint8> *colours,
+		Common::Array<uint8> *ecolours,
 		Common::Array<uint16> *ordinates,
 		FCLInstructionVector conditionInstructions,
 		Common::String conditionSource = "");
@@ -60,12 +61,14 @@ public:
 	void draw(Freescape::Renderer *gfx) override;
 	bool isDrawable() override;
 	bool isPlanar() override;
+	bool _cyclingColors;
 
 	Common::String _conditionSource;
 	FCLInstructionVector _condition;
 
 private:
 	Common::Array<uint8> *_colours;
+	Common::Array<uint8> *_ecolours;
 	Common::Array<uint16> *_ordinates;
 	Common::Array<uint16> *_initialOrdinates;
 };
diff --git a/engines/freescape/objects/sensor.cpp b/engines/freescape/objects/sensor.cpp
index b391d633324..7e6180594b3 100644
--- a/engines/freescape/objects/sensor.cpp
+++ b/engines/freescape/objects/sensor.cpp
@@ -50,14 +50,14 @@ Sensor::Sensor(
 	_isShooting = false;
 }
 
-Object *Sensor::duplicate() { 
-	Sensor *sensor = new Sensor(_objectID, _origin, _rotation, (*_colours)[0], _firingInterval, _firingRange, _axis, _flags, _condition, _conditionSource);  
+Object *Sensor::duplicate() {
+	Sensor *sensor = new Sensor(_objectID, _origin, _rotation, (*_colours)[0], _firingInterval, _firingRange, _axis, _flags, _condition, _conditionSource);
 	return sensor;
 }
 
 void Sensor::draw(Freescape::Renderer *gfx) {
 	Math::Vector3d origin(_origin.x() - 1, _origin.y() - 1, _origin.z() - 1);
-	gfx->renderCube(_origin, _size, _colours);
+	gfx->renderCube(_origin, _size, _colours, nullptr);
 }
 
 bool Sensor::playerDetected(const Math::Vector3d &position, Area *area) {


Commit: 6098d53be1350adcd0cbe39e23e13b1b1e3046f9
    https://github.com/scummvm/scummvm/commit/6098d53be1350adcd0cbe39e23e13b1b1e3046f9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:08+02:00

Commit Message:
FREESCAPE: improved support for castle

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/area.h
    engines/freescape/games/castle/castle.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp
    engines/freescape/objects/group.cpp
    engines/freescape/objects/group.h


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index a7c16576bc4..4f1d7daa5ed 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -368,7 +368,7 @@ void Area::removeObject(int16 id) {
 }
 
 void Area::addObjectFromArea(int16 id, Area *global) {
-	debugC(1, kFreescapeDebugParser, "Adding object %d to room structure", id);
+	debugC(1, kFreescapeDebugParser, "Adding object %d to room structure in area %d", id, _areaID);
 	Object *obj = global->objectWithID(id);
 	if (!obj) {
 		assert(global->entranceWithID(id));
@@ -388,6 +388,26 @@ void Area::addObjectFromArea(int16 id, Area *global) {
 	}
 }
 
+void Area::addGroupFromArea(int16 id, Area *global) {
+	debugC(1, kFreescapeDebugParser, "Adding group %d to room structure in area %d", id, _areaID);
+	Object *obj = global->objectWithID(id);
+	assert(obj);
+	assert(obj->getType() == ObjectType::kGroupType);
+
+	addObjectFromArea(id, global);
+	//Group *group = (Group *)objectWithID(id);
+	for (auto &it : ((Group *)obj)->_objectIds) {
+		if (it == 0 || it == 0xffff)
+			break;
+		if (!global->objectWithID(it))
+			continue;
+
+		addObjectFromArea(it, global);
+		//group->linkObject(objectWithID(it));
+	}
+}
+
+
 void Area::addFloor() {
 	int id = 0;
 	assert(!_objectsByID->contains(id));
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 68515c21ccf..f3e2aa29b7a 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -61,6 +61,7 @@ public:
 	ObjectArray checkCollisions(const Math::AABB &boundingBox);
 	Math::Vector3d resolveCollisions(Math::Vector3d const &lastPosition, Math::Vector3d const &newPosition, int playerHeight);
 	void addObjectFromArea(int16 id, Area *global);
+	void addGroupFromArea(int16 id, Area *global);
 	void addObject(Object *obj);
 	void addFloor();
 	void addStructure(Area *global);
diff --git a/engines/freescape/games/castle/castle.cpp b/engines/freescape/games/castle/castle.cpp
index f85fc26a81b..ef6e61db99e 100644
--- a/engines/freescape/games/castle/castle.cpp
+++ b/engines/freescape/games/castle/castle.cpp
@@ -193,6 +193,19 @@ void CastleEngine::loadAssetsDOSFullGame() {
 		delete stream;
 	} else
 		error("Not implemented yet");
+
+	for (auto &it : _areaMap) {
+		for (auto &sensor : it._value->getSensors()) {
+			if (sensor->getObjectID() == 125)
+				_areaMap[it._key]->addGroupFromArea(195, _areaMap[255]);
+			else if (sensor->getObjectID() == 126)
+				_areaMap[it._key]->addGroupFromArea(191, _areaMap[255]);
+			else if (sensor->getObjectID() == 127)
+				_areaMap[it._key]->addGroupFromArea(182, _areaMap[255]);
+			else
+				debugC(1, kFreescapeDebugParser, "Sensor %d in area %d", sensor->getObjectID(), it._key);
+		}
+	}
 	// CPC
 	// file = gameDir.createReadStreamForMember("cm.bin");
 	// if (file == nullptr)
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 931198264af..711e1f601f5 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -626,11 +626,13 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
 	}
 
 	// Link all groups
-	for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it) {
-		if (it->_value->getType() == ObjectType::kGroupType) {
-			Group *group = (Group *)it->_value;
-			for (ObjectMap::iterator itt = objectsByID->begin(); itt != objectsByID->end(); ++itt)
-				group->linkObject(itt->_value);
+	if (areaNumber != 255) { // Do not link objects in the room structure
+		for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it) {
+			if (it->_value->getType() == ObjectType::kGroupType) {
+				Group *group = (Group *)it->_value;
+				for (ObjectMap::iterator itt = objectsByID->begin(); itt != objectsByID->end(); ++itt)
+					group->linkObject(itt->_value);
+			}
 		}
 	}
 
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
index 598769cee0c..ed1adfe40ba 100644
--- a/engines/freescape/objects/group.cpp
+++ b/engines/freescape/objects/group.cpp
@@ -55,6 +55,15 @@ Group::~Group() {
 		delete _operations[i];
 }
 
+Object *Group::duplicate() {
+	return new Group(
+		_objectID,
+		_flags,
+		_objectIds,
+		_operations
+		);
+}
+
 void Group::linkObject(Object *obj) {
 	int objectIndex = -1;
 	for (int i = 0; i < int(_objectIds.size()) ; i++) {
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 158b7a11520..9ae894a9497 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -63,7 +63,7 @@ public:
 	bool isDrawable() override { return true; }
 	void draw(Renderer *gfx) override;
 	void scale(int scale_) override { _scale = scale_; };
-	Object *duplicate() override { error("cannot duplicate Group"); };
+	Object *duplicate() override;
 };
 
 } // End of namespace Freescape


Commit: 2c67f90d4bd3bd42726c918c1a0c25274ca44564
    https://github.com/scummvm/scummvm/commit/2c67f90d4bd3bd42726c918c1a0c25274ca44564
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:08+02:00

Commit Message:
MATH: added distance function from point to AABB

Changed paths:
    math/aabb.cpp
    math/aabb.h


diff --git a/math/aabb.cpp b/math/aabb.cpp
index 01a22510042..a44b347e720 100644
--- a/math/aabb.cpp
+++ b/math/aabb.cpp
@@ -86,4 +86,17 @@ bool AABB::collides(const AABB &aabb) {
 			getMin().z() < aabb.getMax().z());
 }
 
+Math::Vector3d AABB::distance(const Math::Vector3d &point) const {
+	double dx = MAX(getMin().x() - point.x(), point.x() - getMax().x());
+	dx = MAX(dx, 0.0);
+
+	double dy = MAX(getMin().y() - point.y(), point.y() - getMax().y());
+	dy = MAX(dy, 0.0);
+
+	double dz = MAX(getMin().z() - point.z(), point.z() - getMax().z());
+	dz = MAX(dz, 0.0);
+
+	return Math::Vector3d(dx, dy, dz);
+}
+
 }
diff --git a/math/aabb.h b/math/aabb.h
index e49411693fe..e1137794d5e 100644
--- a/math/aabb.h
+++ b/math/aabb.h
@@ -41,6 +41,7 @@ public:
 	Math::Vector3d getSize() const { return _max - _min; }
 	bool isValid() const { return _valid; }
 	bool collides(const AABB &aabb);
+	Math::Vector3d distance(const Math::Vector3d &point) const;
 
 private:
 	Math::Vector3d _min, _max;


Commit: d782923a3d584f18ee6b0b2866857da93f9ca02b
    https://github.com/scummvm/scummvm/commit/d782923a3d584f18ee6b0b2866857da93f9ca02b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:08+02:00

Commit Message:
MATH: added const qualifier to AABB collision function

Changed paths:
    math/aabb.cpp
    math/aabb.h


diff --git a/math/aabb.cpp b/math/aabb.cpp
index a44b347e720..6db3c070381 100644
--- a/math/aabb.cpp
+++ b/math/aabb.cpp
@@ -77,7 +77,7 @@ void AABB::transform(const Math::Matrix4 &matrix) {
 	}
 }
 
-bool AABB::collides(const AABB &aabb) {
+bool AABB::collides(const AABB &aabb) const {
 	return (getMax().x() > aabb.getMin().x() &&
 			getMin().x() < aabb.getMax().x() &&
 			getMax().y() > aabb.getMin().y() &&
diff --git a/math/aabb.h b/math/aabb.h
index e1137794d5e..5409537668f 100644
--- a/math/aabb.h
+++ b/math/aabb.h
@@ -40,7 +40,7 @@ public:
 	Math::Vector3d getMax() const { return _max; }
 	Math::Vector3d getSize() const { return _max - _min; }
 	bool isValid() const { return _valid; }
-	bool collides(const AABB &aabb);
+	bool collides(const AABB &aabb) const;
 	Math::Vector3d distance(const Math::Vector3d &point) const;
 
 private:


Commit: e7bd1124c1a26971da0890ed91cc6d2b179e3327
    https://github.com/scummvm/scummvm/commit/e7bd1124c1a26971da0890ed91cc6d2b179e3327
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-05-06T22:57:09+02:00

Commit Message:
FREESCAPE: improved rendering of planar objects

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/area.h
    engines/freescape/freescape.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/objects/connections.h
    engines/freescape/objects/entrance.h
    engines/freescape/objects/geometricobject.cpp
    engines/freescape/objects/geometricobject.h
    engines/freescape/objects/global.h
    engines/freescape/objects/group.cpp
    engines/freescape/objects/group.h
    engines/freescape/objects/object.h
    engines/freescape/objects/sensor.cpp
    engines/freescape/objects/sensor.h


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 4f1d7daa5ed..364523534d0 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -23,6 +23,7 @@
 // available at https://github.com/TomHarte/Phantasma/ (MIT)
 
 #include "common/algorithm.h"
+#include "common/hash-ptr.h"
 
 #include "freescape/freescape.h"
 #include "freescape/area.h"
@@ -221,18 +222,68 @@ void Area::resetArea() {
 }
 
 
-void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks) {
+void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d camera, Math::Vector3d direction) {
 	bool runAnimation = animationTicks != _lastTick;
 	assert(_drawableObjects.size() > 0);
+	ObjectArray planarObjects;
+	ObjectArray nonPlanarObjects;
+
 	for (auto &obj : _drawableObjects) {
 		if (!obj->isDestroyed() && !obj->isInvisible()) {
-			if (obj->getType() != ObjectType::kGroupType)
-				obj->draw(gfx);
-			else {
+			if (obj->getType() == ObjectType::kGroupType) {
 				drawGroup(gfx, (Group *)obj, runAnimation);
+				continue;
 			}
+
+			if (obj->isPlanar() && (obj->getType() != ObjectType::kSensorType))
+				planarObjects.push_back(obj);
+			else
+				nonPlanarObjects.push_back(obj);
+		}
+	}
+
+	Common::HashMap<Object *, float> offsetMap;
+	for (auto &planar : planarObjects)
+		offsetMap[planar] = 0;
+
+	for (auto &planar : planarObjects) {
+		Math::Vector3d centerPlanar = planar->_boundingBox.getMin() + planar->_boundingBox.getMax();
+		centerPlanar /= 2;
+		Math::Vector3d distance;
+		for (auto &object : nonPlanarObjects) {
+			distance = object->_boundingBox.distance(centerPlanar);
+			if (distance.length() > 0)
+				continue;
+
+			float offset = 1;
+			if (planar->getSize().x() == 0) {
+				if (object->getOrigin().x() >= centerPlanar.x())
+					offsetMap[planar] = -offset;
+				else
+					offsetMap[planar] = offset;
+			} else if (planar->getSize().y() == 0) {
+				if (object->getOrigin().y() >= centerPlanar.y())
+					offsetMap[planar] = -offset;
+				else
+					offsetMap[planar] = offset;
+			} else if (planar->getSize().z() == 0) {
+				if (object->getOrigin().z() >= centerPlanar.z())
+					offsetMap[planar] = -offset;
+				else
+					offsetMap[planar] = offset;
+			} else
+				; //It was not really planar?!
 		}
 	}
+
+	for (auto &pair : offsetMap) {
+		pair._key->draw(gfx, pair._value);
+	}
+
+	for (auto &obj : nonPlanarObjects) {
+		obj->draw(gfx);
+	}
+
 	_lastTick = animationTicks;
 }
 
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index f3e2aa29b7a..32dd19b8e06 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -52,7 +52,7 @@ public:
 	uint8 getScale();
 	void remapColor(int index, int color);
 	void unremapColor(int index);
-	void draw(Renderer *gfx, uint32 animationTicks);
+	void draw(Renderer *gfx, uint32 animationTicks, Math::Vector3d camera, Math::Vector3d direction);
 	void drawGroup(Renderer *gfx, Group *group, bool runAnimation);
 	void show();
 
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 7143c7cf716..9f9d66bb0c3 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -348,7 +348,7 @@ void FreescapeEngine::drawFrame() {
 
 	drawBackground();
 	if (_avoidRenderingFrames == 0) // Avoid rendering inside objects
-		_currentArea->draw(_gfx, _ticks / 10);
+		_currentArea->draw(_gfx, _ticks / 10, _position, _cameraFront);
 	else
 		_avoidRenderingFrames--;
 
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 85110d73027..141f458d5b4 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -742,7 +742,9 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
 	}
 }
 
-void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
+void Renderer::renderCube(const Math::Vector3d &originalOrigin, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
+	Math::Vector3d origin = originalOrigin;
+
 	byte *stipple = nullptr;
 	uint8 r1, g1, b1, r2, g2, b2;
 	Common::Array<Math::Vector3d> face;
@@ -750,6 +752,14 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 	uint color = (*colours)[0];
 	uint ecolor = ecolours ? (*ecolours)[0] : 0;
 
+	if (size.x() <= 1) {
+		origin.x() += offset;
+	} else if (size.y() <= 1) {
+		origin.y() += offset;
+	} else if (size.z() <= 1) {
+		origin.z() += offset;
+	}
+
 	if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
 		setStippleData(stipple);
 		useColor(r1, g1, b1);
@@ -867,9 +877,11 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
 	}
 }
 
-void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3d &originalSize, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
+void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math::Vector3d &originalSize, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
 
 	Math::Vector3d size = originalSize;
+	Math::Vector3d origin = originalOrigin;
+
 	if (size.x() > 0 && size.y() > 0 && size.z() > 0) {
 		/* According to https://www.shdon.com/freescape/
 		If the bounding box is has all non-zero dimensions
@@ -895,8 +907,6 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 			error("Invalid size!");
 	}
 
-	polygonOffset(true);
-
 	float dx, dy, dz;
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
@@ -904,6 +914,14 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 	uint color = 0;
 	uint ecolor = 0;
 
+	if (size.x() == 0) {
+		origin.x() += offset;
+	} else if (size.y() == 0) {
+		origin.y() += offset;
+	} else if (size.z() == 0) {
+		origin.z() += offset;
+	}
+
 	for (int i = 0; i < 2; i++) {
 
 		color = (*colours)[i];
@@ -951,19 +969,21 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
 	polygonOffset(false);
 }
 
-void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours) {
+void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *originalOrdinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
+	Common::Array<uint16> *ordinates = new Common::Array<uint16>(*originalOrdinates);
+
 	uint8 r1, g1, b1, r2, g2, b2;
 	byte *stipple = nullptr;
 	if (ordinates->size() % 3 > 0 && ordinates->size() > 0)
 		error("Invalid polygon with size %f %f %f and ordinates %d", size.x(), size.y(), size.z(), ordinates->size());
 
 	Common::Array<Math::Vector3d> vertices;
-	polygonOffset(true);
 
 	uint color = 0;
 	uint ecolor = 0;
 
 	if (ordinates->size() == 6) { // Line
+		polygonOffset(true);
 		color = (*colours)[0];
 		ecolor = ecolours ? (*ecolours)[0] : 0;
 
@@ -996,8 +1016,25 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 			renderFace(vertices);
 			useStipple(false);
 		}
-
+		polygonOffset(false);
 	} else {
+		if (size.x() == 0) {
+			for (int i = 0; i < int(ordinates->size()); i++) {
+				if (i % 3 == 0)
+					(*ordinates)[i] += (offset);
+			}
+		} else if (size.y() == 0) {
+			for (int i = 0; i < int(ordinates->size()); i++) {
+				if (i % 3 == 1)
+					(*ordinates)[i] += (offset);
+			}
+		} else if (size.z() == 0) {
+			for (int i = 0; i < int(ordinates->size()); i++) {
+				if (i % 3 == 2)
+					(*ordinates)[i] += (offset);
+			}
+		}
+
 		color = (*colours)[0];
 		ecolor = ecolours ? (*ecolours)[0] : 0;
 
@@ -1036,6 +1073,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 	}
 
 	polygonOffset(false);
+	delete(ordinates);
 }
 
 void Renderer::drawBackground(uint8 color) {
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index cd9d207775a..40b6bc9d008 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -88,9 +88,9 @@ public:
 
 	virtual void renderCrossair(const Common::Point crossairPosition) = 0;
 
-	virtual void renderCube(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
-	virtual void renderRectangle(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
-	virtual void renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours);
+	virtual void renderCube(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset = 0.0);
+	virtual void renderRectangle(const Math::Vector3d &position, const Math::Vector3d &size, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset = 0.0);
+	virtual void renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset = 0.0);
 	virtual void renderPyramid(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, int type);
 	virtual void renderFace(const Common::Array<Math::Vector3d> &vertices) = 0;
 
diff --git a/engines/freescape/objects/connections.h b/engines/freescape/objects/connections.h
index ea14f559c7a..ef0cbaf0934 100644
--- a/engines/freescape/objects/connections.h
+++ b/engines/freescape/objects/connections.h
@@ -35,7 +35,7 @@ public:
 	}
 
 	ObjectType getType() override { return ObjectType::kEntranceType; };
-	void draw(Freescape::Renderer *gfx) override { error("cannot render AreaConnections"); };
+	void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render AreaConnections"); };
 	void scale(int factor) override { /* Nothing */ };
 	Object *duplicate() override { error("cannot duplicate AreaConnections"); };
 };
diff --git a/engines/freescape/objects/entrance.h b/engines/freescape/objects/entrance.h
index eef6dba37cc..af7bca54f3c 100644
--- a/engines/freescape/objects/entrance.h
+++ b/engines/freescape/objects/entrance.h
@@ -50,7 +50,7 @@ public:
 	ObjectType getType() override { return ObjectType::kEntranceType; };
 	Math::Vector3d getRotation() { return _rotation; }
 
-	void draw(Freescape::Renderer *gfx) override { error("cannot render Entrance"); };
+	void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render Entrance"); };
 };
 
 } // End of namespace Freescape
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index d04708737b0..0b33db69d42 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -178,7 +178,8 @@ GeometricObject::GeometricObject(
 			_ordinates->push_back(_origin.y() + _size.y());
 			_ordinates->push_back(_origin.z() + _size.z());
 		}
-	}
+	} else if (isPyramid(_type))
+		assert(_size.x() > 0 && _size.y() > 0 && _size.z() > 0);
 
 	computeBoundingBox();
 }
@@ -426,7 +427,7 @@ bool GeometricObject::collides(const Math::AABB &boundingBox_) {
 	return _boundingBox.collides(boundingBox_);
 }
 
-void GeometricObject::draw(Renderer *gfx) {
+void GeometricObject::draw(Renderer *gfx, float offset) {
 	if (_cyclingColors) {
 		if (g_system->getMillis() % 10 == 0)
 			for (uint i = 0; i < _colours->size(); i++) {
@@ -436,16 +437,16 @@ void GeometricObject::draw(Renderer *gfx) {
 	}
 
 	if (this->getType() == kCubeType) {
-		gfx->renderCube(_origin, _size, _colours, _ecolours);
+		gfx->renderCube(_origin, _size, _colours, _ecolours, offset);
 	} else if (this->getType() == kRectangleType) {
-		gfx->renderRectangle(_origin, _size, _colours, _ecolours);
+		gfx->renderRectangle(_origin, _size, _colours, _ecolours, offset);
 	} else if (isPyramid(this->getType())) {
 		gfx->renderPyramid(_origin, _size, _ordinates, _colours, _ecolours, this->getType());
 	} else if (this->isPlanar() && _type <= 14) {
 		if (this->getType() == kTriangleType)
 			assert(_ordinates->size() == 9);
 
-		gfx->renderPolygon(_origin, _size, _ordinates, _colours, _ecolours);
+		gfx->renderPolygon(_origin, _size, _ordinates, _colours, _ecolours, offset);
 	}
 }
 
diff --git a/engines/freescape/objects/geometricobject.h b/engines/freescape/objects/geometricobject.h
index 070aa3ead1e..3b164d4e986 100644
--- a/engines/freescape/objects/geometricobject.h
+++ b/engines/freescape/objects/geometricobject.h
@@ -58,7 +58,7 @@ public:
 	void scale(int factor) override;
 	void computeBoundingBox();
 	bool collides(const Math::AABB &boundingBox);
-	void draw(Freescape::Renderer *gfx) override;
+	void draw(Freescape::Renderer *gfx, float offset = 0.0) override;
 	bool isDrawable() override;
 	bool isPlanar() override;
 	bool _cyclingColors;
diff --git a/engines/freescape/objects/global.h b/engines/freescape/objects/global.h
index 4fa29de6fee..2e983d564a0 100644
--- a/engines/freescape/objects/global.h
+++ b/engines/freescape/objects/global.h
@@ -35,7 +35,7 @@ public:
 	}
 
 	ObjectType getType() override { return ObjectType::kEntranceType; };
-	void draw(Freescape::Renderer *gfx) override { error("cannot render GlobalStructure"); };
+	void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render GlobalStructure"); };
 	void scale(int factor) override { /* Nothing */ };
 	Object *duplicate() override { error("cannot duplicate GlobalStructure"); };
 };
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
index ed1adfe40ba..c6f4099df03 100644
--- a/engines/freescape/objects/group.cpp
+++ b/engines/freescape/objects/group.cpp
@@ -138,7 +138,7 @@ void Group::reset() {
 	}
 }
 
-void Group::draw(Renderer *gfx) {
+void Group::draw(Renderer *gfx, float offset) {
 	uint32 groupSize = _objects.size();
 	for (uint32 i = 0; i < groupSize ; i++) {
 		if (!_objects[i]->isDestroyed() && !_objects[i]->isInvisible())
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 9ae894a9497..f1514eb8424 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -61,7 +61,7 @@ public:
 
 	ObjectType getType() override { return ObjectType::kGroupType; };
 	bool isDrawable() override { return true; }
-	void draw(Renderer *gfx) override;
+	void draw(Renderer *gfx, float offset = 0.0) override;
 	void scale(int scale_) override { _scale = scale_; };
 	Object *duplicate() override;
 };
diff --git a/engines/freescape/objects/object.h b/engines/freescape/objects/object.h
index 0fced4e8009..bdf82e53128 100644
--- a/engines/freescape/objects/object.h
+++ b/engines/freescape/objects/object.h
@@ -81,7 +81,7 @@ public:
 	virtual ~Object() {}
 	virtual Object *duplicate() = 0;
 
-	virtual void draw(Freescape::Renderer *gfx) = 0;
+	virtual void draw(Freescape::Renderer *gfx, float offset = 0.0) = 0;
 
 	uint16 _flags;
 	ObjectType _type;
diff --git a/engines/freescape/objects/sensor.cpp b/engines/freescape/objects/sensor.cpp
index 7e6180594b3..16b841296df 100644
--- a/engines/freescape/objects/sensor.cpp
+++ b/engines/freescape/objects/sensor.cpp
@@ -55,7 +55,7 @@ Object *Sensor::duplicate() {
 	return sensor;
 }
 
-void Sensor::draw(Freescape::Renderer *gfx) {
+void Sensor::draw(Freescape::Renderer *gfx, float offset) {
 	Math::Vector3d origin(_origin.x() - 1, _origin.y() - 1, _origin.z() - 1);
 	gfx->renderCube(_origin, _size, _colours, nullptr);
 }
diff --git a/engines/freescape/objects/sensor.h b/engines/freescape/objects/sensor.h
index 8ba7c491390..bb8ff22de3c 100644
--- a/engines/freescape/objects/sensor.h
+++ b/engines/freescape/objects/sensor.h
@@ -64,7 +64,7 @@ public:
 	Math::Vector3d getRotation() { return _rotation; }
 	void shouldShoot(bool shooting) { _isShooting = shooting; }
 
-	void draw(Freescape::Renderer *gfx) override;
+	void draw(Freescape::Renderer *gfx, float offset = 0.0) override;
 
 	bool playerDetected(const Math::Vector3d &position, Area *area);
 




More information about the Scummvm-git-logs mailing list