[Scummvm-git-logs] scummvm master -> 5ffee1a67cf1d56eea2c8e2ae7ca64866ff83689

OMGPizzaGuy noreply at scummvm.org
Tue Sep 19 23:24:57 UTC 2023


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

Summary:
5ffee1a67c ULTIMA8: Improve occlusion by checking for adjoined floor squares


Commit: 5ffee1a67cf1d56eea2c8e2ae7ca64866ff83689
    https://github.com/scummvm/scummvm/commit/5ffee1a67cf1d56eea2c8e2ae7ca64866ff83689
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2023-09-19T18:24:36-05:00

Commit Message:
ULTIMA8: Improve occlusion by checking for adjoined floor squares
In debug build this took average paint time from 3.9ms to 3.4ms in Central Tenebrea.

Changed paths:
    engines/ultima/ultima8/world/item_sorter.cpp
    engines/ultima/ultima8/world/item_sorter.h
    engines/ultima/ultima8/world/sort_item.h


diff --git a/engines/ultima/ultima8/world/item_sorter.cpp b/engines/ultima/ultima8/world/item_sorter.cpp
index 6388905a1ce..9700e975cf6 100644
--- a/engines/ultima/ultima8/world/item_sorter.cpp
+++ b/engines/ultima/ultima8/world/item_sorter.cpp
@@ -58,7 +58,6 @@ ItemSorter::ItemSorter(int capacity) :
 }
 
 ItemSorter::~ItemSorter() {
-	//
 	if (_itemsTail) {
 		_itemsTail->_next = _itemsUnused;
 		_itemsUnused = _items;
@@ -71,8 +70,6 @@ ItemSorter::~ItemSorter() {
 		delete _itemsUnused;
 		_itemsUnused = next;
 	}
-
-	delete [] _items;
 }
 
 void ItemSorter::BeginDisplayList(const Rect &clipWindow, int32 camx, int32 camy, int32 camz) {
@@ -160,6 +157,9 @@ void ItemSorter::AddItem(int32 x, int32 y, int32 z, uint32 shapeNum, uint32 fram
 		return;
 	}
 
+	si->_xAdjoin = nullptr;
+	si->_yAdjoin = nullptr;
+
 	// These help out with sorting. We calc them now, so it will be faster
 	si->_fbigsq = (xd == 128 && yd == 128) || (xd == 256 && yd == 256) || (xd == 512 && yd == 512);
 	si->_flat = zd == 0;
@@ -196,6 +196,25 @@ void ItemSorter::AddItem(int32 x, int32 y, int32 z, uint32 shapeNum, uint32 fram
 		if (!addpoint && si->listLessThan(*si2))
 			addpoint = si2;
 
+		// Find adjoining floor squares for better occlusion
+		if (si->_occl && si2->_occl && si->_fbigsq && si2->_fbigsq && si->_z == si2->_z) {
+			// Does this share an edge?
+			if (si->_y == si2->_y && si->_yFar == si2->_yFar) {
+				if (si->_xLeft == si2->_x) {
+					si->_xAdjoin = si2;
+				} else if (si->_x == si2->_xLeft) {
+					si2->_xAdjoin = si;
+				}
+			}
+			else if (si->_x == si2->_x && si->_xLeft == si2->_xLeft) {
+				if (si->_yFar == si2->_y) {
+					si->_yAdjoin = si2;
+				} else if (si->_y == si2->_yFar) {
+					si2->_yAdjoin = si;
+				}
+			}
+		}
+
 		// Doesn't overlap
 		if (si2->_occluded || !si->overlap(*si2))
 			continue;
@@ -254,6 +273,43 @@ void ItemSorter::AddItem(const Item *add) {
 			add->getFlags(), add->getExtFlags(), add->getObjId());
 }
 
+void ItemSorter::CheckOcclusion() {
+	for (SortItem *it = _items; it != nullptr; it = it->_next) {
+		// Check if item is part of a 4x4 adjoined square
+		if (it->_occl && it->_fbigsq && it->_xAdjoin && it->_yAdjoin &&
+			it->_xAdjoin->_yAdjoin && it->_yAdjoin->_xAdjoin &&
+			it->_xAdjoin->_yAdjoin == it->_yAdjoin->_xAdjoin) {
+
+			SortItem si;
+			si._occl = true;
+			si._fbigsq = true;
+			si._flat = it->_flat;
+			si._solid = it->_solid;
+			si._roof = it->_roof;
+			si._fixed = it->_fixed;
+			si._land = it->_land;
+
+			Box box = it->_xAdjoin->_yAdjoin->getBoxBounds();
+			box.extend(it->getBoxBounds());
+			si.setBoxBounds(box, _camSx, _camSy);
+
+			for (SortItem *si2 = _items; si2 != nullptr; si2 = si2->_next) {
+				// Skip members of the adjoined square
+				if (si2 == it || si2 == it->_xAdjoin || si2 == it->_yAdjoin || si2 == it->_xAdjoin->_yAdjoin)
+					continue;
+
+				// Doesn't overlap
+				if (si2->_occluded || !si.overlap(*si2))
+					continue;
+
+				if (si2->below(si) && si.occludes(*si2)) {
+					si2->_occluded = true;
+				}
+			}
+		}
+	}
+}
+
 void ItemSorter::PaintDisplayList(RenderSurface *surf, bool item_highlight) {
 	if (_sortLimit) {
 		// Clear the surface when debugging the sorter
@@ -261,6 +317,8 @@ void ItemSorter::PaintDisplayList(RenderSurface *surf, bool item_highlight) {
 		surf->fill32(color, _clipWindow);
 	}
 
+	CheckOcclusion();
+
 	SortItem *it = _items;
 	SortItem *end = nullptr;
 	_painted = nullptr;  // Reset the paint tracking
diff --git a/engines/ultima/ultima8/world/item_sorter.h b/engines/ultima/ultima8/world/item_sorter.h
index 8bc1db47a3a..420b3d6220f 100644
--- a/engines/ultima/ultima8/world/item_sorter.h
+++ b/engines/ultima/ultima8/world/item_sorter.h
@@ -69,6 +69,7 @@ public:
 	void IncSortLimit(int count);
 
 private:
+	void CheckOcclusion();
 	bool PaintSortItem(RenderSurface *surf, SortItem *si);
 };
 
diff --git a/engines/ultima/ultima8/world/sort_item.h b/engines/ultima/ultima8/world/sort_item.h
index 69319784344..af2bf05ca77 100644
--- a/engines/ultima/ultima8/world/sort_item.h
+++ b/engines/ultima/ultima8/world/sort_item.h
@@ -93,6 +93,9 @@ struct SortItem {
 	int32   _sxBot;      // Screenspace bounding box bottom x coord (RNB x coord) ss origin
 	int32   _syBot;      // Screenspace bounding box bottom extent  (RNB y coord) ss origin
 
+	SortItem *_xAdjoin;  // Item sharing an right x edge with the left x edge - used for occlusion
+	SortItem *_yAdjoin;  // Item sharing an near y edge with the fay y edge - used for occlusion
+
 	bool    _fbigsq : 1;         // Needs 1 bit  0
 	bool    _flat : 1;           // Needs 1 bit  1
 	bool    _occl : 1;           // Needs 1 bit  2
@@ -219,6 +222,8 @@ struct SortItem {
 	// Set worldspace bounds and calculate screenspace at center point
 	inline void setBoxBounds(const Box &box, int32 sx, int32 sy);
 
+	inline Box getBoxBounds() const;
+
 	// Check if the given point is inside the screenpace bounds.
 	inline bool contains(int32 sx, int32 sy) const;
 
@@ -276,6 +281,17 @@ inline void SortItem::setBoxBounds(const Box& box, int32 sx, int32 sy) {
 	_sr.bottom = _syBot;
 }
 
+inline Box SortItem::getBoxBounds() const {
+	Box box;
+	box._x = _x;
+	box._y = _y;
+	box._z = _z;
+	box._xd = _x - _xLeft;
+	box._yd = _y - _yFar;
+	box._zd = _zTop - _z;
+	return box;
+}
+
 inline bool SortItem::contains(int32 sx, int32 sy) const {
 	if (!_sr.contains(sx, sy))
 		return false;




More information about the Scummvm-git-logs mailing list