Y texture offsets are just 5 bits. Texture coordinate wrap around happens in the same texture sheet, not into the next one. Fixes various texturing bugs in sega rally.

This commit is contained in:
Ian Curtis 2016-05-30 13:25:00 +00:00
parent d1f49675b1
commit 36074d9fd5
4 changed files with 34 additions and 9 deletions

View file

@ -6,7 +6,7 @@ NodeAttributes::NodeAttributes()
{ {
currentTexOffsetX = 0; currentTexOffsetX = 0;
currentTexOffsetY = 0; currentTexOffsetY = 0;
currentTexOffset = 0; page = 0;
} }
bool NodeAttributes::Push() bool NodeAttributes::Push()
@ -20,7 +20,7 @@ bool NodeAttributes::Push()
return false; return false;
} }
na.texOffset = currentTexOffset; na.page = page;
na.texOffsetX = currentTexOffsetX; na.texOffsetX = currentTexOffsetX;
na.texOffsetY = currentTexOffsetY; na.texOffsetY = currentTexOffsetY;
@ -35,7 +35,7 @@ bool NodeAttributes::Pop()
return false; // check for underflow return false; // check for underflow
} }
currentTexOffset = m_vecAttribs.back().texOffset; page = m_vecAttribs.back().page;
currentTexOffsetX = m_vecAttribs.back().texOffsetX; currentTexOffsetX = m_vecAttribs.back().texOffsetX;
currentTexOffsetY = m_vecAttribs.back().texOffsetY; currentTexOffsetY = m_vecAttribs.back().texOffsetY;
@ -51,7 +51,7 @@ bool NodeAttributes::StackLimit()
void NodeAttributes::Reset() void NodeAttributes::Reset()
{ {
currentTexOffset = 0; page = 0;
currentTexOffsetX = 0; currentTexOffsetX = 0;
currentTexOffsetY = 0; currentTexOffsetY = 0;
m_vecAttribs.clear(); m_vecAttribs.clear();

View file

@ -80,6 +80,7 @@ struct Model
// texture offsets for model // texture offsets for model
int textureOffsetX = 0; int textureOffsetX = 0;
int textureOffsetY = 0; int textureOffsetY = 0;
int page = 0;
//matrices //matrices
float modelMat[16]; float modelMat[16];
@ -112,7 +113,7 @@ public:
int currentTexOffsetX; int currentTexOffsetX;
int currentTexOffsetY; int currentTexOffsetY;
int currentTexOffset; // raw value int page;
private: private:
@ -120,7 +121,7 @@ private:
{ {
int texOffsetX; int texOffsetX;
int texOffsetY; int texOffsetY;
int texOffset; int page;
}; };
std::vector<NodeAttribs> m_vecAttribs; std::vector<NodeAttribs> m_vecAttribs;
}; };

View file

@ -128,7 +128,11 @@ void CNew3D::RenderScene(int priority, bool alpha)
} }
if (mesh.textured) { if (mesh.textured) {
auto tex1 = m_texSheet.BindTexture(m_textureRAM, mesh.format, mesh.mirrorU, mesh.mirrorV, mesh.x + m.textureOffsetX, mesh.y + m.textureOffsetY, mesh.width, mesh.height);
int x, y;
CalcTexOffset(m.textureOffsetX, m.textureOffsetY, m.page, mesh.x, mesh.y, x, y);
auto tex1 = m_texSheet.BindTexture(m_textureRAM, mesh.format, mesh.mirrorU, mesh.mirrorV, x, y, mesh.width, mesh.height);
if (tex1) { if (tex1) {
tex1->BindTexture(); tex1->BindTexture();
tex1->SetWrapMode(mesh.mirrorU, mesh.mirrorV); tex1->SetWrapMode(mesh.mirrorU, mesh.mirrorV);
@ -315,6 +319,7 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
// update texture offsets // update texture offsets
m->textureOffsetX = m_nodeAttribs.currentTexOffsetX; m->textureOffsetX = m_nodeAttribs.currentTexOffsetX;
m->textureOffsetY = m_nodeAttribs.currentTexOffsetY; m->textureOffsetY = m_nodeAttribs.currentTexOffsetY;
m->page = m_nodeAttribs.page;
if (!cached) { if (!cached) {
CacheModel(m, modelAddress); CacheModel(m, modelAddress);
@ -368,13 +373,13 @@ void CNew3D::DescendCullingNode(UINT32 addr)
if (!m_offset) // Step 1.5+ if (!m_offset) // Step 1.5+
{ {
tx = 32 * ((node[0x02] >> 7) & 0x3F); tx = 32 * ((node[0x02] >> 7) & 0x3F);
ty = 32 * (node[0x02] & 0x3F) + ((node[0x02] & 0x4000) ? 1024 : 0); // TODO: 5 or 6 bits for Y coord? ty = 32 * (node[0x02] & 0x1F);
// apply texture offsets, else retain current ones // apply texture offsets, else retain current ones
if ((node[0x02] & 0x8000)) { if ((node[0x02] & 0x8000)) {
m_nodeAttribs.currentTexOffsetX = tx; m_nodeAttribs.currentTexOffsetX = tx;
m_nodeAttribs.currentTexOffsetY = ty; m_nodeAttribs.currentTexOffsetY = ty;
m_nodeAttribs.currentTexOffset = node[0x02] & 0x7FFF; m_nodeAttribs.page = (node[0x02] & 0x4000) >> 14;
} }
} }
@ -1153,5 +1158,22 @@ bool CNew3D::IsVROMModel(UINT32 modelAddr)
return modelAddr >= 0x100000; return modelAddr >= 0x100000;
} }
void CNew3D::CalcTexOffset(int offX, int offY, int page, int x, int y, int& newX, int& newY)
{
newX = (x + offX) & 2047; // wrap around 2048, shouldn't be required
int oldPage = y / 1024;
y -= (oldPage * 1024); // remove page from tex y
// calc newY with wrap around, wraps around in the same sheet, not into another memory sheet
newY = (y + offY) & 1023;
// add page to Y
newY += ((oldPage + page) & 1) * 1024; // max page 0-1
}
} // New3D } // New3D

View file

@ -176,6 +176,8 @@ private:
bool IsDynamicModel(UINT32 *data); // check if the model has a colour palette bool IsDynamicModel(UINT32 *data); // check if the model has a colour palette
bool IsVROMModel(UINT32 modelAddr); bool IsVROMModel(UINT32 modelAddr);
void CalcTexOffset(int offX, int offY, int page, int x, int y, int& newX, int& newY);
/* /*
* Data * Data