[Scummvm-cvs-logs] CVS: scummvm/scumm boxes.cpp,1.57,1.58 scumm.h,1.296,1.297

Max Horn fingolfin at users.sourceforge.net
Tue Sep 9 10:07:22 CEST 2003


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1:/tmp/cvs-serv27764

Modified Files:
	boxes.cpp scumm.h 
Log Message:
added convertScaleTableToScaleSlot method, preparing to replace scale items with scale slots

Index: boxes.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/boxes.cpp,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- boxes.cpp	13 Aug 2003 02:21:36 -0000	1.57
+++ boxes.cpp	9 Sep 2003 16:55:25 -0000	1.58
@@ -159,7 +159,7 @@
 	if (_version == 8) {
 		int slot = FROM_LE_32(ptr->v8.scaleSlot);
 		if (slot) {
-			assert(1 <= slot && slot <= 20);
+			assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
 			int scaleX = 0, scaleY = 0;
 			ScaleSlot &s = _scaleSlots[slot-1];
 
@@ -248,16 +248,121 @@
 			tmp = 255;
 		*ptr++ = tmp;
 	}
+/*	
+	// TEST!
+	printf("setScaleItem(%d, %d, %d, %d, %d)\n", slot, y1, scale1, y2, scale2);
+	convertScaleTableToScaleSlot(slot);
+*/
+}
+
+void Scumm::convertScaleTableToScaleSlot(int slot) {
+	assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
+
+	byte *resptr = getResourceAddress(rtScaleTable, slot);
+	ScaleSlot &s = _scaleSlots[slot-1];
+
+	int lowerIdx, upperIdx;
+	float m, oldM;
+	
+	if (resptr[0] == resptr[199]) {
+		// The scale is constant This usually means we encountered one of the
+		// "broken" cases. We set pseudo scale item values which lead to a 
+		// constant scale of 255.
+		// TODO
+		printf("Broken case!\n");
+		s.y1 = 0;
+		s.y2 = 199;
+		s.scale1 = s.scale2 = 255;
+		return;
+	}
+	
+	/*
+	 * Essentially, what we are doing here is some kind of "line fitting"
+	 * algorithm. The data in the scale table represents a linear graph. What
+	 * we want to find is the slope and (vertical) offset of this line. Things
+	 * are complicated by the fact that the line is cut of vertically at 1 and
+	 * 255. We have to be careful in handling this and some border cases.
+	 * 
+	 * Some typical graphs look like these:
+	 *       ---         ---     ---
+	 *       /         ---           \ 
+	 *  ___/       ---               \___
+	 * 
+	 * The method used here is to compute the slope of secants fixed at the
+	 * left and right end. For most cases this detects the cut-over points
+	 * quite accurately. 
+	 */
+	
+	// Search for the bend on the left side
+	m = (resptr[199] - resptr[0]) / 199.0;
+	for (lowerIdx = 0; lowerIdx < 199 && (resptr[lowerIdx] == 1 || resptr[lowerIdx] == 255); lowerIdx++) {
+		oldM = m;
+		m = (resptr[199] - resptr[lowerIdx+1]) / (float)(199 - (lowerIdx+1));
+		if (m > 0) {
+			if (m <= oldM)
+				break;
+		} else {
+			if (m >= oldM)
+				break;
+		}
+	}
+	
+	// Search for the bend on the right side
+	m = (resptr[199] - resptr[0]) / 199.0;
+	for (upperIdx = 199; upperIdx > 1 && (resptr[upperIdx] == 1 || resptr[upperIdx] == 255); upperIdx--) {
+		oldM = m;
+		m = (resptr[upperIdx-1] - resptr[0]) / (float)(upperIdx-1);
+		if (m > 0) {
+			if (m <= oldM)
+				break;
+		} else {
+			if (m >= oldM)
+				break;
+		}
+	}
+
+	// If lowerIdx and upperIdx are equal, we assume that there
+	// was no bend at all, and go for the maximum range.
+	if (lowerIdx == upperIdx) {
+		lowerIdx = 0;
+		upperIdx = 199;
+	}
+
+	// The values of y1 and y2, as well as the scale, can now easily be computed
+	s.y1 = lowerIdx;
+	s.y2 = upperIdx;
+	s.scale1 = resptr[lowerIdx];
+	s.scale2 = resptr[upperIdx];
+
+	
+	// Compute the variance, for debugging. It shouldn't exceed 1
+	int y;
+	int sum = 0;
+	int scale;
+	float variance;
+	for (y = 0; y < 200; y++) {
+		scale = (s.scale2 - s.scale1) * (y - s.y1) / (s.y2 - s.y1) + s.scale1;
+		if (scale < 1)
+			scale = 1;
+		else if (scale > 255)
+			scale = 255;
+
+		sum += (resptr[y] - scale) * (resptr[y] - scale);
+	}
+	variance = sum / (200.0 - 1.0);
+	if (variance > 1)
+		warning("scale item %d, variance %f exceeds 1 (room %d)\n", slot, variance, _currentRoom);
 }
 
 void Scumm::setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2) {
-	assert(1 <= slot && slot <= 20);
-	_scaleSlots[slot-1].x2 = x2;
-	_scaleSlots[slot-1].y2 = y2;
-	_scaleSlots[slot-1].scale2 = scale2;
-	_scaleSlots[slot-1].x1 = x1;
-	_scaleSlots[slot-1].y1 = y1;
-	_scaleSlots[slot-1].scale1 = scale1;
+	assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
+	ScaleSlot &s = _scaleSlots[slot-1];
+	s.x2 = x2;
+	s.y2 = y2;
+	s.scale2 = scale2;
+	s.x1 = x1;
+	s.y1 = y1;
+	s.scale1 = scale1;
 }
 
 byte Scumm::getNumBoxes() {

Index: scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
retrieving revision 1.296
retrieving revision 1.297
diff -u -d -r1.296 -r1.297
--- scumm.h	9 Sep 2003 00:13:19 -0000	1.296
+++ scumm.h	9 Sep 2003 16:55:25 -0000	1.297
@@ -1054,14 +1054,15 @@
 	void setScaleItem(int slot, int a, int b, int c, int d);
 
 protected:
-	// V8 scaling stuff: should be in V8 class
+	// Scaling slots/items
 	struct ScaleSlot {
 		int x1, y1, scale1;
 		int x2, y2, scale2;
 	};
-	ScaleSlot _scaleSlots[20];	// FIXME - not sure if this limit is right, but based on my observations it is
+	ScaleSlot _scaleSlots[20];
 	void setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2);
 	void setBoxScaleSlot(int box, int slot);
+	void convertScaleTableToScaleSlot(int slot);
 
 	void createBoxMatrix();
 	bool areBoxesNeighbours(int i, int j);





More information about the Scummvm-git-logs mailing list