[Scummvm-git-logs] scummvm master -> db4eb789e70135c22f20107c9c83e7706e135d91
mgerhardy
noreply at scummvm.org
Fri Sep 2 15:08:59 UTC 2022
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:
db4eb789e7 TWINE: added missing clip functionality
Commit: db4eb789e70135c22f20107c9c83e7706e135d91
https://github.com/scummvm/scummvm/commit/db4eb789e70135c22f20107c9c83e7706e135d91
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2022-09-02T17:08:43+02:00
Commit Message:
TWINE: added missing clip functionality
see https://bugs.scummvm.org/ticket/12074
but this doesn't yet fix the holomap clipping bug
Changed paths:
engines/twine/renderer/renderer.cpp
engines/twine/renderer/renderer.h
diff --git a/engines/twine/renderer/renderer.cpp b/engines/twine/renderer/renderer.cpp
index 4f51bb15500..aa5f1202e4f 100644
--- a/engines/twine/renderer/renderer.cpp
+++ b/engines/twine/renderer/renderer.cpp
@@ -20,13 +20,7 @@
*/
#include "twine/renderer/renderer.h"
-#include "common/memstream.h"
-#include "common/stream.h"
-#include "common/textconsole.h"
-#include "common/util.h"
#include "twine/menu/interface.h"
-#include "twine/menu/menu.h"
-#include "twine/parser/body.h"
#include "twine/renderer/redraw.h"
#include "twine/renderer/shadeangletab.h"
#include "twine/resources/resources.h"
@@ -383,55 +377,375 @@ static FORCEINLINE int16 clamp(int16 x, int16 a, int16 b) {
return x < a ? a : (x > b ? b : x);
}
-bool Renderer::computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices) { // ComputePolyMinMax
- uint8 vertexParam1 = vertices[numVertices - 1].colorIndex;
- int16 currentVertexX = vertices[numVertices - 1].x;
- int16 currentVertexY = vertices[numVertices - 1].y;
+int16 Renderer::leftClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices) {
+ const Common::Rect &clip = _engine->_interface->_clip;
+ Vertex *pTabPolyClip = offTabPoly[1];
+ Vertex *pTabPoly = offTabPoly[0];
+ int16 newNbPoints = 0;
+
+ // invert the pointers to continue on the clipped vertices in the next method
+ offTabPoly[0] = pTabPolyClip;
+ offTabPoly[1] = pTabPoly;
+
+ for (; numVertices > 0; --numVertices, pTabPoly++) {
+ const Vertex *p0 = pTabPoly;
+ const Vertex *p1 = p0 + 1;
+
+ // clipFlag :
+ // 0x00 : none clipped
+ // 0x01 : point 0 clipped
+ // 0x02 : point 1 clipped
+ // 0x03 : both clipped
+ uint8 clipFlag = (p1->x < clip.left) ? 2 : 0;
+
+ if (p0->x < clip.left) {
+ if (clipFlag) {
+ continue; // both clipped, skip point 0
+ }
+ clipFlag |= 1;
+ } else {
+ // point 0 not clipped, store it
+ *pTabPolyClip++ = *pTabPoly;
+ ++newNbPoints;
+ }
+
+ if (clipFlag) {
+ // point 0 or 1 is clipped, apply clipping
+ if (p1->x >= p0->x) {
+ p0 = p1;
+ p1 = pTabPoly;
+ }
+
+ const int32 dx = p1->x - p0->x;
+ const int32 dy = p1->y - p0->y;
+ const int32 dxClip = clip.left - p0->x;
+
+ pTabPolyClip->y = (int16)(p0->y + ((dxClip * dy) / dx));
+ pTabPolyClip->x = (int16)clip.left;
+
+ if (polyRenderType >= POLYGONTYPE_GOURAUD) {
+ pTabPolyClip->colorIndex = (int16)(p0->colorIndex + (((p1->colorIndex - p0->colorIndex) * dxClip) / dx));
+ }
+
+ ++pTabPolyClip;
+ ++newNbPoints;
+ }
+ }
+
+ // copy first vertex to the end
+ *pTabPolyClip = *offTabPoly[0];
+ return newNbPoints;
+}
+
+int16 Renderer::rightClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices) {
+ const Common::Rect &clip = _engine->_interface->_clip;
+ Vertex *pTabPolyClip = offTabPoly[1];
+ Vertex *pTabPoly = offTabPoly[0];
+ int16 newNbPoints = 0;
+
+ // invert the pointers to continue on the clipped vertices in the next method
+ offTabPoly[0] = pTabPolyClip;
+ offTabPoly[1] = pTabPoly;
+
+ for (; numVertices > 0; --numVertices, pTabPoly++) {
+ const Vertex *p0 = pTabPoly;
+ const Vertex *p1 = p0 + 1;
+
+ // clipFlag :
+ // 0x00 : none clipped
+ // 0x01 : point 0 clipped
+ // 0x02 : point 1 clipped
+ // 0x03 : both clipped
+ uint8 clipFlag = (p1->x > clip.right) ? 2 : 0;
+
+ if (p0->x > clip.right) {
+ if (clipFlag) {
+ continue; // both clipped, skip point 0
+ }
+ clipFlag |= 1;
+ } else {
+ // point 0 not clipped, store it
+ *pTabPolyClip++ = *pTabPoly;
+ ++newNbPoints;
+ }
+
+ if (clipFlag) {
+ // point 0 or 1 is clipped, apply clipping
+ if (p1->x >= p0->x) {
+ p0 = p1;
+ p1 = pTabPoly;
+ }
+
+ const int32 dx = p1->x - p0->x;
+ const int32 dy = p1->y - p0->y;
+ const int32 dxClip = clip.right - p0->x;
+
+ pTabPolyClip->y = (int16)(p0->y + ((dxClip * dy) / dx));
+ pTabPolyClip->x = (int16)clip.right;
+
+ if (polyRenderType >= POLYGONTYPE_GOURAUD) {
+ pTabPolyClip->colorIndex = (int16)(p0->colorIndex + (((p1->colorIndex - p0->colorIndex) * dxClip) / dx));
+ }
+
+ ++pTabPolyClip;
+ ++newNbPoints;
+ }
+ }
+
+ // copy first vertex to the end
+ *pTabPolyClip = *offTabPoly[0];
+ return newNbPoints;
+}
+
+int16 Renderer::topClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices) {
+ const Common::Rect &clip = _engine->_interface->_clip;
+ Vertex *pTabPolyClip = offTabPoly[1];
+ Vertex *pTabPoly = offTabPoly[0];
+ int16 newNbPoints = 0;
+
+ // invert the pointers to continue on the clipped vertices in the next method
+ offTabPoly[0] = pTabPolyClip;
+ offTabPoly[1] = pTabPoly;
+
+ for (; numVertices > 0; --numVertices, pTabPoly++) {
+ const Vertex *p0 = pTabPoly;
+ const Vertex *p1 = p0 + 1;
+
+ // clipFlag :
+ // 0x00 : none clipped
+ // 0x01 : point 0 clipped
+ // 0x02 : point 1 clipped
+ // 0x03 : both clipped
+ uint8 clipFlag = (p1->y < clip.top) ? 2 : 0;
+
+ if (p0->y < clip.top) {
+ if (clipFlag) {
+ continue; // both clipped, skip point 0
+ }
+ clipFlag |= 1;
+ } else {
+ // point 0 not clipped, store it
+ *pTabPolyClip++ = *pTabPoly;
+ ++newNbPoints;
+ }
+
+ if (clipFlag) {
+ // point 0 or 1 is clipped, apply clipping
+ if (p1->y >= p0->y) {
+ p0 = p1;
+ p1 = pTabPoly;
+ }
+
+ const int32 dx = p1->x - p0->x;
+ const int32 dy = p1->y - p0->y;
+ const int32 dyClip = clip.top - p0->y;
+
+ pTabPolyClip->x = (int16)(p0->x + ((dyClip * dx) / dy));
+ pTabPolyClip->y = (int16)clip.top;
+
+ if (polyRenderType >= POLYGONTYPE_GOURAUD) {
+ pTabPolyClip->colorIndex = (int16)(p0->colorIndex + (((p1->colorIndex - p0->colorIndex) * dyClip) / dy));
+ }
+
+ ++pTabPolyClip;
+ ++newNbPoints;
+ }
+ }
+
+ // copy first vertex to the end
+ *pTabPolyClip = *offTabPoly[0];
+ return newNbPoints;
+}
+
+int16 Renderer::bottomClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices) {
+ const Common::Rect &clip = _engine->_interface->_clip;
+ Vertex *pTabPolyClip = offTabPoly[1];
+ Vertex *pTabPoly = offTabPoly[0];
+ int16 newNbPoints = 0;
+
+ // invert the pointers to continue on the clipped vertices in the next method
+ offTabPoly[0] = pTabPolyClip;
+ offTabPoly[1] = pTabPoly;
+
+ for (; numVertices > 0; --numVertices, pTabPoly++) {
+ const Vertex *p0 = pTabPoly;
+ const Vertex *p1 = p0 + 1;
+
+ // clipFlag :
+ // 0x00 : none clipped
+ // 0x01 : point 0 clipped
+ // 0x02 : point 1 clipped
+ // 0x03 : both clipped
+ uint8 clipFlag = (p1->y > clip.bottom) ? 2 : 0;
+
+ if (p0->y > clip.bottom) {
+ if (clipFlag) {
+ continue; // both clipped, skip point 0
+ }
+ clipFlag |= 1;
+ } else {
+ // point 0 not clipped, store it
+ *pTabPolyClip++ = *pTabPoly;
+ ++newNbPoints;
+ }
+
+ if (clipFlag) {
+ // point 0 or 1 is clipped, apply clipping
+ if (p1->y >= p0->y) {
+ p0 = p1;
+ p1 = pTabPoly;
+ }
+
+ const int32 dx = p1->x - p0->x;
+ const int32 dy = p1->y - p0->y;
+ const int32 dyClip = clip.bottom - p0->y;
+
+ pTabPolyClip->x = (int16)(p0->x + ((dyClip * dx) / dy));
+ pTabPolyClip->y = (int16)clip.bottom;
+
+ if (polyRenderType >= POLYGONTYPE_GOURAUD) {
+ pTabPolyClip->colorIndex = (int16)(p0->colorIndex + (((p1->colorIndex - p0->colorIndex) * dyClip) / dy));
+ }
+
+ ++pTabPolyClip;
+ ++newNbPoints;
+ }
+ }
+
+ // copy first vertex to the end
+ *pTabPolyClip = *offTabPoly[0];
+ return newNbPoints;
+}
+
+int32 Renderer::computePolyMinMax(int16 polyRenderType, Vertex **offTabPoly, int32 numVertices) {
+ const Common::Rect &clip = _engine->_interface->_clip;
+ if (clip.isEmpty()) {
+ return numVertices;
+ }
+
+ int32 minsx = SCENE_SIZE_MAX;
+ int32 maxsx = SCENE_SIZE_MIN;
+ int32 minsy = SCENE_SIZE_MAX;
+ int32 maxsy = SCENE_SIZE_MIN;
+
+ Vertex* pTabPoly = offTabPoly[0];
+ for (int32 i = 0; i < numVertices; i++) {
+ if (pTabPoly[i].x < minsx) {
+ minsx = pTabPoly[i].x;
+ }
+ if (pTabPoly[i].x > maxsx) {
+ maxsx = pTabPoly[i].x;
+ }
+ if (pTabPoly[i].y < minsy) {
+ minsy = pTabPoly[i].y;
+ }
+ if (pTabPoly[i].y > maxsy) {
+ maxsy = pTabPoly[i].y;
+ }
+ }
+
+ // no vertices
+ if (minsy > maxsy || maxsx < clip.left || minsx > clip.right || maxsy < clip.top || minsy > clip.bottom) {
+ debug(10, "Clipped %i:%i:%i:%i, clip rect(%i:%i:%i:%i)", minsx, minsy, maxsx, maxsy, clip.left, clip.top, clip.right, clip.bottom);
+ return 0;
+ }
+
+ pTabPoly[numVertices] = *offTabPoly[0];
+
+ bool hasBeenClipped = false;
+
+ int32 clippedNumVertices = numVertices;
+ if (minsx < clip.left) {
+ clippedNumVertices = leftClip(polyRenderType, offTabPoly, clippedNumVertices);
+ if (!clippedNumVertices) {
+ return 0;
+ }
+
+ hasBeenClipped = true;
+ }
+
+ if (maxsx > clip.right) {
+ clippedNumVertices = rightClip(polyRenderType, offTabPoly, clippedNumVertices);
+ if (!clippedNumVertices) {
+ return 0;
+ }
+
+ hasBeenClipped = true;
+ }
+
+ if (minsy < clip.top) {
+ clippedNumVertices = topClip(polyRenderType, offTabPoly, clippedNumVertices);
+ if (!clippedNumVertices) {
+ return 0;
+ }
+
+ hasBeenClipped = true;
+ }
+
+ if (maxsy > clip.bottom) {
+ clippedNumVertices = bottomClip(polyRenderType, offTabPoly, clippedNumVertices);
+ if (!clippedNumVertices) {
+ return 0;
+ }
+
+ hasBeenClipped = true;
+ }
+
+ if (hasBeenClipped) {
+ minsy = 32767;
+ maxsy = -32768;
+
+ for (int32 i = 0; i < clippedNumVertices; i++) {
+ if (offTabPoly[0][i].y < minsy) {
+ minsy = offTabPoly[0][i].y;
+ }
+
+ if (offTabPoly[0][i].y > maxsy) {
+ maxsy = offTabPoly[0][i].y;
+ }
+ }
+
+ if (minsy >= maxsy) {
+ return 0;
+ }
+ }
+
+ return clippedNumVertices;
+}
+
+bool Renderer::computePoly(int16 polyRenderType, const Vertex *vertices, int32 numVertices) {
const int16 *polyTabBegin = _polyTab;
const int16 *polyTabEnd = &_polyTab[_polyTabSize - 1];
const int16 *colProgressBufStart = _colorProgressionBuffer;
const int16 *colProgressBufEnd = &_colorProgressionBuffer[_polyTabSize - 1];
const int screenHeight = _engine->height();
- const Common::Rect &clip = _engine->_interface->_clip;
- if (!clip.isEmpty()) {
- int32 vleft;
- int32 vright;
- int32 vtop;
- int32 vbottom;
-
- vleft = vtop = SCENE_SIZE_MAX;
- vright = vbottom = SCENE_SIZE_MIN;
-
- for (int32 i = 0; i < numVertices; i++) {
- if (vertices[i].x < vleft)
- vleft = vertices[i].x;
- if (vertices[i].x > vright)
- vright = vertices[i].x;
- if (vertices[i].y < vtop)
- vtop = vertices[i].y;
- if (vertices[i].y > vbottom)
- vbottom = vertices[i].y;
- }
- // no vertices
- if (vtop > vbottom) {
- return false;
- }
- if (vright <= clip.left || vleft >= clip.right || vbottom <= clip.top || vtop >= clip.bottom) {
- debug(10, "Clipped %i:%i:%i:%i, clip rect(%i:%i:%i:%i)", vleft, vtop, vright, vbottom, clip.left, clip.top, clip.right, clip.bottom);
- return false;
- }
+ assert(numVertices < ARRAYSIZE(_clippedPolygonVertices1));
+ for (int i = 0; i < numVertices; ++i) {
+ _clippedPolygonVertices1[i] = vertices[i];
}
+ Vertex *offTabPoly[] = {_clippedPolygonVertices1, _clippedPolygonVertices2};
+
+ numVertices = computePolyMinMax(polyRenderType, offTabPoly, numVertices);
+ if (numVertices == 0) {
+ return false;
+ }
+
+ const Vertex *clippedVertices = offTabPoly[0];
+ uint8 vertexParam1 = clippedVertices[numVertices - 1].colorIndex;
+ int16 currentVertexX = clippedVertices[numVertices - 1].x;
+ int16 currentVertexY = clippedVertices[numVertices - 1].y;
+
for (int32 nVertex = 0; nVertex < numVertices; nVertex++) {
const int16 oldVertexY = currentVertexY;
const int16 oldVertexX = currentVertexX;
const uint8 oldVertexParam = vertexParam1;
- vertexParam1 = vertices[nVertex].colorIndex;
+ vertexParam1 = clippedVertices[nVertex].colorIndex;
const uint8 vertexParam2 = vertexParam1;
- currentVertexX = vertices[nVertex].x;
- currentVertexY = vertices[nVertex].y;
+ currentVertexX = clippedVertices[nVertex].x;
+ currentVertexY = clippedVertices[nVertex].y;
// drawLine(oldVertexX,oldVertexY,currentVertexX,currentVertexY,255);
@@ -985,7 +1299,7 @@ void Renderer::renderPolygonsSimplified(int vtop, int32 vsize, uint16 color) con
}
void Renderer::renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom) {
- if (computePolygons(polygon.renderType, vertices, polygon.numVertices)) {
+ if (computePoly(polygon.renderType, vertices, polygon.numVertices)) {
const int32 vsize = vbottom - vtop + 1;
fillVertices(vtop, vsize, polygon.renderType, polygon.colorIndex);
}
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index ed9f65ae2dc..97f218b40b3 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -182,6 +182,8 @@ private:
* that is needed to render the primitive.
*/
uint8 _renderCoordinatesBuffer[10000]{0};
+ Vertex _clippedPolygonVertices1[128];
+ Vertex _clippedPolygonVertices2[128];
int32 _polyTabSize = 0;
int16 *_polyTab = nullptr;
@@ -205,7 +207,7 @@ private:
void renderPolygonsDither(int vtop, int32 vsize) const;
void renderPolygonsMarble(int vtop, int32 vsize, uint16 color) const;
void renderPolygonsSimplified(int vtop, int32 vsize, uint16 color) const;
- bool computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
+ bool computePoly(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
uint8 *preparePolygons(const Common::Array<BodyPolygon>& polygons, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
@@ -218,6 +220,11 @@ private:
void computeHolomapPolygon(int32 y1, int32 x1, int32 y2, int32 x2, int16 *polygonTabPtr);
void fillHolomapPolygons(const Vertex &vertex1, const Vertex &vertex2, const Vertex &texCoord1, const Vertex &texCoord2, int32 &top, int32 &bottom);
+ int16 leftClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices);
+ int16 rightClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices);
+ int16 topClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices);
+ int16 bottomClip(int16 polyRenderType, Vertex** offTabPoly, int32 numVertices);
+ int32 computePolyMinMax(int16 polyRenderType, Vertex **offTabPoly, int32 numVertices);
public:
Renderer(TwinEEngine *engine);
~Renderer();
More information about the Scummvm-git-logs
mailing list