mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
- Texture offsets: models are now decoded for each individual texture offset state and texture coordinates are adjusted while generating the vertex data.
- Model LUT now capable of differentiating between texture offset states (linked list of different texture offsets for each model address). - Removed texOffset uniform attribute from vertex shader -- no longer needed.
This commit is contained in:
parent
c5c518390a
commit
a033058deb
|
@ -23,6 +23,11 @@
|
||||||
* Models.cpp
|
* Models.cpp
|
||||||
*
|
*
|
||||||
* Model parsing, caching, and drawing.
|
* Model parsing, caching, and drawing.
|
||||||
|
*
|
||||||
|
* TO-DO List:
|
||||||
|
* -----------
|
||||||
|
* - More should be predecoded into the polygon structures, so that things like
|
||||||
|
* texture base coordinates are not re-decoded in two different places!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -132,7 +137,6 @@ void CRender3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, D->Data.Model.modelViewMatrix);
|
glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, D->Data.Model.modelViewMatrix);
|
||||||
glUniform2fv(texOffsetLoc, 1, D->Data.Model.texOffset);
|
|
||||||
glDrawArrays(GL_TRIANGLES, D->Data.Model.index, D->Data.Model.numVerts);
|
glDrawArrays(GL_TRIANGLES, D->Data.Model.index, D->Data.Model.numVerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +145,7 @@ void CRender3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends an instance of a model or viewport to the display list, copying over the required state information
|
// Appends an instance of a model or viewport to the display list, copying over the required state information
|
||||||
BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelNum)
|
BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, const struct VBORef *Model)
|
||||||
{
|
{
|
||||||
int lm, i;
|
int lm, i;
|
||||||
|
|
||||||
|
@ -173,21 +177,17 @@ BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelN
|
||||||
// Copy projection matrix
|
// Copy projection matrix
|
||||||
glGetFloatv(GL_PROJECTION_MATRIX, Cache->List[lm].Data.Viewport.projectionMatrix);
|
glGetFloatv(GL_PROJECTION_MATRIX, Cache->List[lm].Data.Viewport.projectionMatrix);
|
||||||
}
|
}
|
||||||
else if (Cache->Models[modelNum].numVerts[i] > 0) // vertices exist for this state
|
else if (Model->numVerts[i] > 0) // vertices exist for this state
|
||||||
{
|
{
|
||||||
// Get index for new display list item and advance to next one
|
// Get index for new display list item and advance to next one
|
||||||
lm = Cache->listSize++;
|
lm = Cache->listSize++;
|
||||||
|
|
||||||
// Point to VBO for current model and state
|
// Point to VBO for current model and state
|
||||||
Cache->List[lm].Data.Model.index = Cache->Models[modelNum].index[i];
|
Cache->List[lm].Data.Model.index = Model->index[i];
|
||||||
Cache->List[lm].Data.Model.numVerts = Cache->Models[modelNum].numVerts[i];
|
Cache->List[lm].Data.Model.numVerts = Model->numVerts[i];
|
||||||
|
|
||||||
// Copy modelview matrix
|
// Copy modelview matrix
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, Cache->List[lm].Data.Model.modelViewMatrix);
|
glGetFloatv(GL_MODELVIEW_MATRIX, Cache->List[lm].Data.Model.modelViewMatrix);
|
||||||
|
|
||||||
// Texture offset
|
|
||||||
Cache->List[lm].Data.Model.texOffset[0] = texOffset[0];
|
|
||||||
Cache->List[lm].Data.Model.texOffset[1] = texOffset[1];
|
|
||||||
}
|
}
|
||||||
else // nothing to do, continue loop
|
else // nothing to do, continue loop
|
||||||
continue;
|
continue;
|
||||||
|
@ -252,8 +252,8 @@ void CRender3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
||||||
texWidth = (GLfloat) (32<<((P->header[3]>>3)&7));
|
texWidth = (GLfloat) (32<<((P->header[3]>>3)&7));
|
||||||
texHeight = (GLfloat) (32<<((P->header[3]>>0)&7));
|
texHeight = (GLfloat) (32<<((P->header[3]>>0)&7));
|
||||||
texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
||||||
texBaseX = (GLfloat) (32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1)));
|
texBaseX = (GLfloat) (32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1))) + texOffsetXY[0];
|
||||||
texBaseY = (GLfloat) (32*(P->header[5]&0x1F)+texPage);
|
texBaseY = (GLfloat) (32*(P->header[5]&0x1F)+texPage) + texOffsetXY[1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lighting and Color Modulation:
|
* Lighting and Color Modulation:
|
||||||
|
@ -494,43 +494,55 @@ BOOL CRender3D::BeginModel(ModelCache *Cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT
|
// Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT
|
||||||
void CRender3D::EndModel(ModelCache *Cache, int lutIdx)
|
struct VBORef *CRender3D::EndModel(ModelCache *Cache, int lutIdx, UINT16 texOffset)
|
||||||
{
|
{
|
||||||
int m;
|
struct VBORef *Model;
|
||||||
|
int m;
|
||||||
|
|
||||||
m = Cache->numModels++;
|
m = Cache->numModels++;
|
||||||
|
Model = &(Cache->Models[m]);
|
||||||
|
|
||||||
// Record the number of vertices, completing the VBORef
|
// Record the number of vertices, completing the VBORef
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
Cache->Models[m].numVerts[i] = Cache->curVertIdx[i];
|
Model->numVerts[i] = Cache->curVertIdx[i];
|
||||||
|
|
||||||
// First alpha polygon immediately follows the normal polygons
|
// First alpha polygon immediately follows the normal polygons
|
||||||
Cache->Models[m].index[POLY_STATE_ALPHA] = Cache->Models[m].index[POLY_STATE_NORMAL]+Cache->Models[m].numVerts[POLY_STATE_NORMAL];
|
Model->index[POLY_STATE_ALPHA] = Model->index[POLY_STATE_NORMAL] + Model->numVerts[POLY_STATE_NORMAL];
|
||||||
|
|
||||||
// Upload from local vertex buffer to real VBO
|
// Upload from local vertex buffer to real VBO
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
||||||
if (Cache->Models[m].numVerts[POLY_STATE_NORMAL] > 0)
|
if (Model->numVerts[POLY_STATE_NORMAL] > 0)
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, Cache->Models[m].index[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_NORMAL]);
|
glBufferSubData(GL_ARRAY_BUFFER, Model->index[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_NORMAL]);
|
||||||
if (Cache->Models[m].numVerts[POLY_STATE_ALPHA] > 0)
|
if (Model->numVerts[POLY_STATE_ALPHA] > 0)
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, Cache->Models[m].index[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_ALPHA]);
|
glBufferSubData(GL_ARRAY_BUFFER, Model->index[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_ALPHA]);
|
||||||
|
|
||||||
// Update the LUT
|
|
||||||
Cache->lut[lutIdx] = m;
|
|
||||||
|
|
||||||
// Record LUT index in the model VBORef
|
// Record LUT index in the model VBORef
|
||||||
Cache->Models[m].lutIdx = lutIdx;
|
Model->lutIdx = lutIdx;
|
||||||
|
|
||||||
|
// Texture offset of this model state
|
||||||
|
Model->texOffset = texOffset;
|
||||||
|
|
||||||
|
// Update the LUT and link up to any existing model that already exists here
|
||||||
|
if (Cache->lut[lutIdx] >= 0) // another texture offset state already cached
|
||||||
|
Model->nextTexOffset = &(Cache->Models[Cache->lut[lutIdx]]);
|
||||||
|
Cache->lut[lutIdx] = m;
|
||||||
|
|
||||||
|
// Return a pointer to the cached model's VBO reference
|
||||||
|
return Model;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CacheModel():
|
* CacheModel():
|
||||||
*
|
*
|
||||||
* Decodes and caches a complete model. Returns FAIL if any sort of overflow in
|
* Decodes and caches a complete model. Returns NULL if any sort of overflow in
|
||||||
* the cache occurred. In this case, the model cache should be cleared before
|
* the cache occurred. In this case, the model cache should be cleared before
|
||||||
* being used again because an incomplete model will be stored, wasting vertex
|
* being used again because an incomplete model will be stored, wasting vertex
|
||||||
* buffer space.
|
* buffer space.
|
||||||
|
*
|
||||||
|
* A pointer to the VBO reference for the cached model is returned when
|
||||||
|
* successful.
|
||||||
*/
|
*/
|
||||||
|
struct VBORef *CRender3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOffset, const UINT32 *data)
|
||||||
BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
|
|
||||||
{
|
{
|
||||||
Vertex Prev[4]; // previous vertices
|
Vertex Prev[4]; // previous vertices
|
||||||
int numPolys = 0;
|
int numPolys = 0;
|
||||||
|
@ -541,11 +553,11 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
|
||||||
// return FAIL;
|
// return FAIL;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return FAIL;
|
return NULL;
|
||||||
|
|
||||||
// Start constructing a new model
|
// Start constructing a new model
|
||||||
if (FAIL == BeginModel(Cache))
|
if (FAIL == BeginModel(Cache))
|
||||||
return FAIL; // too many models!
|
return NULL; // too many models!
|
||||||
|
|
||||||
// Cache all polygons
|
// Cache all polygons
|
||||||
while (!done)
|
while (!done)
|
||||||
|
@ -572,8 +584,10 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
|
||||||
texWidth = (32<<((P.header[3]>>3)&7));
|
texWidth = (32<<((P.header[3]>>3)&7));
|
||||||
texHeight = (32<<((P.header[3]>>0)&7));
|
texHeight = (32<<((P.header[3]>>0)&7));
|
||||||
texPage = (P.header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
texPage = (P.header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
||||||
texBaseX = (32*(((P.header[4]&0x1F)<<1)|((P.header[5]>>7)&1)));
|
texBaseX = (32*(((P.header[4]&0x1F)<<1)|((P.header[5]>>7)&1))) + (int)texOffsetXY[0];
|
||||||
texBaseY = (32*(P.header[5]&0x1F)+texPage);
|
texBaseY = (32*(P.header[5]&0x1F)+texPage) + (int)texOffsetXY[1];
|
||||||
|
texBaseX &= 2047;
|
||||||
|
texBaseY &= 2047;
|
||||||
uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f);
|
uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f);
|
||||||
|
|
||||||
// Determine whether this is an alpha polygon
|
// Determine whether this is an alpha polygon
|
||||||
|
@ -599,7 +613,7 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the texture
|
// Decode the texture
|
||||||
DecodeTexture(texFormat, texBaseX+(int)texOffset[0], texBaseY+(int)texOffset[1], texWidth, texHeight);
|
DecodeTexture(texFormat, texBaseX, texBaseY, texWidth, texHeight);
|
||||||
|
|
||||||
// Polygon normal is in upper 24 bits: sign + 1.22 fixed point
|
// Polygon normal is in upper 24 bits: sign + 1.22 fixed point
|
||||||
P.n[0] = (GLfloat) (((INT32)P.header[1])>>8) * (1.0f/4194304.0f);
|
P.n[0] = (GLfloat) (((INT32)P.header[1])>>8) * (1.0f/4194304.0f);
|
||||||
|
@ -661,16 +675,13 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
|
||||||
|
|
||||||
// Copy this polygon into the model buffer
|
// Copy this polygon into the model buffer
|
||||||
if (OKAY != InsertPolygon(Cache,&P))
|
if (OKAY != InsertPolygon(Cache,&P))
|
||||||
return FAIL;
|
return NULL;
|
||||||
|
|
||||||
++numPolys;
|
++numPolys;
|
||||||
}
|
}
|
||||||
StopDecoding:
|
|
||||||
|
|
||||||
// Finish model and enter it into the LUT
|
// Finish model and enter it into the LUT
|
||||||
EndModel(Cache,lutIdx);
|
return EndModel(Cache,lutIdx,texOffset);
|
||||||
|
|
||||||
return OKAY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -678,12 +689,26 @@ StopDecoding:
|
||||||
Cache Management
|
Cache Management
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
// Use this to determine if a model needs to be cached (returns TRUE if so)
|
/*
|
||||||
BOOL CRender3D::NeedToCache(ModelCache *Cache, int lutIdx)
|
* Look up a model. Use this to determine if a model needs to be cached
|
||||||
|
* (returns NULL if so).
|
||||||
|
*/
|
||||||
|
struct VBORef *CRender3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texOffset)
|
||||||
{
|
{
|
||||||
//if (Cache->dynamic) // never permanently store models in dynamic caches
|
int m = Cache->lut[lutIdx];
|
||||||
// return TRUE;
|
|
||||||
return (Cache->lut[lutIdx]<0) ? TRUE : FALSE;
|
// Has any state associated with this model LUT index been cached at all?
|
||||||
|
if (m < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Has the specified texture offset been cached?
|
||||||
|
for (struct VBORef *Model = &(Cache->Models[m]); Model != NULL; Model = Model->nextTexOffset)
|
||||||
|
{
|
||||||
|
if (Model->texOffset == texOffset)
|
||||||
|
return Model;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // no match found, we must cache this new model state
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard all models in the cache and the display list
|
// Discard all models in the cache and the display list
|
||||||
|
|
|
@ -188,8 +188,8 @@ void CRender3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
UINT16 texel;
|
UINT16 texel;
|
||||||
GLfloat c, a;
|
GLfloat c, a;
|
||||||
|
|
||||||
x %= 2048;
|
x &= 2047;
|
||||||
y %= 2048;
|
y &= 2047;
|
||||||
|
|
||||||
if ((x+width)>2048 || (y+height)>2048)
|
if ((x+width)>2048 || (y+height)>2048)
|
||||||
return;
|
return;
|
||||||
|
@ -198,7 +198,7 @@ void CRender3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
//ErrorLog("Encountered a texture that is too large (%d,%d,%d,%d)", x, y, width, height);
|
//ErrorLog("Encountered a texture that is too large (%d,%d,%d,%d)", x, y, width, height);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if ALL texture tiles have been properly decoded
|
// Check to see if ALL texture tiles have been properly decoded
|
||||||
if ((textureFormat[y/32][x/32]==format) && (textureWidth[y/32][x/32]>=width) && (textureHeight[y/32][x/32]>=height))
|
if ((textureFormat[y/32][x/32]==format) && (textureWidth[y/32][x/32]>=width) && (textureHeight[y/32][x/32]>=height))
|
||||||
return;
|
return;
|
||||||
|
@ -616,12 +616,16 @@ void CRender3D::ClearStack(void)
|
||||||
* buffer overflows and display list overflows will be detected. An attempt is
|
* buffer overflows and display list overflows will be detected. An attempt is
|
||||||
* made to salvage the situation if this occurs, so if DrawModel() returns
|
* made to salvage the situation if this occurs, so if DrawModel() returns
|
||||||
* FAIL, it is a serious matter and rendering should be aborted for the frame.
|
* FAIL, it is a serious matter and rendering should be aborted for the frame.
|
||||||
|
*
|
||||||
|
* The current texture offset state, texOffset, is also used. Models are cached
|
||||||
|
* for each unique texOffset.
|
||||||
*/
|
*/
|
||||||
BOOL CRender3D::DrawModel(UINT32 modelAddr)
|
BOOL CRender3D::DrawModel(UINT32 modelAddr)
|
||||||
{
|
{
|
||||||
ModelCache *Cache;
|
ModelCache *Cache;
|
||||||
const UINT32 *model;
|
const UINT32 *model;
|
||||||
int lutIdx;
|
int lutIdx;
|
||||||
|
struct VBORef *ModelRef;
|
||||||
|
|
||||||
//if (modelAddr==0x7FFF00) // Fighting Vipers (this is not polygon data!)
|
//if (modelAddr==0x7FFF00) // Fighting Vipers (this is not polygon data!)
|
||||||
// return;
|
// return;
|
||||||
|
@ -637,10 +641,12 @@ BOOL CRender3D::DrawModel(UINT32 modelAddr)
|
||||||
|
|
||||||
// Look up the model in the LUT and cache it if necessary
|
// Look up the model in the LUT and cache it if necessary
|
||||||
lutIdx = modelAddr&0xFFFFFF;
|
lutIdx = modelAddr&0xFFFFFF;
|
||||||
if (NeedToCache(Cache, lutIdx))
|
ModelRef = LookUpModel(Cache, lutIdx, texOffset);
|
||||||
|
if (NULL == ModelRef)
|
||||||
{
|
{
|
||||||
// Attempt to cache the model
|
// Attempt to cache the model
|
||||||
if (CacheModel(Cache, lutIdx, model) != OKAY)
|
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
||||||
|
if (NULL == ModelRef)
|
||||||
{
|
{
|
||||||
// Model could not be cached. Render what we have so far and try again.
|
// Model could not be cached. Render what we have so far and try again.
|
||||||
DrawDisplayList(&VROMCache, POLY_STATE_NORMAL);
|
DrawDisplayList(&VROMCache, POLY_STATE_NORMAL);
|
||||||
|
@ -651,13 +657,14 @@ BOOL CRender3D::DrawModel(UINT32 modelAddr)
|
||||||
ClearModelCache(&PolyCache);
|
ClearModelCache(&PolyCache);
|
||||||
|
|
||||||
// Try caching again...
|
// Try caching again...
|
||||||
if (CacheModel(Cache, lutIdx, model) != OKAY)
|
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
||||||
|
if (NULL == ModelRef)
|
||||||
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
|
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to display list
|
// Add to display list
|
||||||
return AppendDisplayList(Cache, FALSE, Cache->lut[lutIdx]);
|
return AppendDisplayList(Cache, FALSE, ModelRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Descends into a 10-word culling node
|
// Descends into a 10-word culling node
|
||||||
|
@ -667,6 +674,7 @@ void CRender3D::DescendCullingNode(UINT32 addr)
|
||||||
UINT32 matrixOffset, node1Ptr, node2Ptr;
|
UINT32 matrixOffset, node1Ptr, node2Ptr;
|
||||||
float x, y, z, oldTexOffsetX, oldTexOffsetY;
|
float x, y, z, oldTexOffsetX, oldTexOffsetY;
|
||||||
int tx, ty;
|
int tx, ty;
|
||||||
|
UINT16 oldTexOffset;
|
||||||
|
|
||||||
++stackDepth;
|
++stackDepth;
|
||||||
// Stack depth of 64 is too small for Star Wars Trilogy (Hoth)
|
// Stack depth of 64 is too small for Star Wars Trilogy (Hoth)
|
||||||
|
@ -696,15 +704,20 @@ void CRender3D::DescendCullingNode(UINT32 addr)
|
||||||
z = *(float *) &node[0x06-offset];
|
z = *(float *) &node[0x06-offset];
|
||||||
|
|
||||||
// Texture offset?
|
// Texture offset?
|
||||||
oldTexOffsetX = texOffset[0]; // save old offsets
|
oldTexOffsetX = texOffsetXY[0]; // save old offsets
|
||||||
oldTexOffsetY = texOffset[1];
|
oldTexOffsetY = texOffsetXY[1];
|
||||||
tx = 32*((node[0x02]>>7)&0x3F);
|
oldTexOffset = texOffset;
|
||||||
ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0);
|
if (!offset) // Step 1.5+
|
||||||
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
|
|
||||||
{
|
{
|
||||||
texOffset[0] = (GLfloat) tx;
|
tx = 32*((node[0x02]>>7)&0x3F);
|
||||||
texOffset[1] = (GLfloat) ty;
|
ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0); // TODO: 5 or 6 bits for Y coord?
|
||||||
//printf("Tex Offset: %d, %d (%08X %08X)\n", tx, ty, node[0x02], node[0x00]);
|
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
|
||||||
|
{
|
||||||
|
texOffsetXY[0] = (GLfloat) tx;
|
||||||
|
texOffsetXY[1] = (GLfloat) ty;
|
||||||
|
texOffset = node[0x02]&0x7FFF;
|
||||||
|
//printf("Tex Offset: %d, %d (%08X %08X)\n", tx, ty, node[0x02], node1Ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply matrix and translation
|
// Apply matrix and translation
|
||||||
|
@ -735,8 +748,9 @@ void CRender3D::DescendCullingNode(UINT32 addr)
|
||||||
--stackDepth;
|
--stackDepth;
|
||||||
|
|
||||||
// Restore old texture offsets
|
// Restore old texture offsets
|
||||||
texOffset[0] = oldTexOffsetX;
|
texOffsetXY[0] = oldTexOffsetX;
|
||||||
texOffset[1] = oldTexOffsetY;
|
texOffsetXY[1] = oldTexOffsetY;
|
||||||
|
texOffset = oldTexOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A list of pointers. MAME assumes that these may only point to culling nodes.
|
// A list of pointers. MAME assumes that these may only point to culling nodes.
|
||||||
|
@ -1119,8 +1133,9 @@ void CRender3D::RenderViewport(UINT32 addr, int pri)
|
||||||
//printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]);
|
//printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]);
|
||||||
|
|
||||||
// Clear texture offsets before proceeding
|
// Clear texture offsets before proceeding
|
||||||
texOffset[0] = 0.0;
|
texOffsetXY[0] = 0.0;
|
||||||
texOffset[1] = 0.0;
|
texOffsetXY[1] = 0.0;
|
||||||
|
texOffset = 0x0000;
|
||||||
|
|
||||||
// Set up coordinate system and base matrix
|
// Set up coordinate system and base matrix
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
@ -1329,7 +1344,6 @@ BOOL CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
spotEllipseLoc = glGetUniformLocation(shaderProgram, "spotEllipse");
|
spotEllipseLoc = glGetUniformLocation(shaderProgram, "spotEllipse");
|
||||||
spotRangeLoc = glGetUniformLocation(shaderProgram, "spotRange");
|
spotRangeLoc = glGetUniformLocation(shaderProgram, "spotRange");
|
||||||
spotColorLoc = glGetUniformLocation(shaderProgram, "spotColor");
|
spotColorLoc = glGetUniformLocation(shaderProgram, "spotColor");
|
||||||
texOffsetLoc = glGetUniformLocation(shaderProgram, "texOffset");
|
|
||||||
|
|
||||||
// Get locations of custom vertex attributes
|
// Get locations of custom vertex attributes
|
||||||
subTextureLoc = glGetAttribLocation(shaderProgram,"subTexture");
|
subTextureLoc = glGetAttribLocation(shaderProgram,"subTexture");
|
||||||
|
|
|
@ -60,12 +60,20 @@ struct Poly
|
||||||
const UINT32 *header; // pointer to Real3D 7-word polygon header
|
const UINT32 *header; // pointer to Real3D 7-word polygon header
|
||||||
};
|
};
|
||||||
|
|
||||||
// References to model polygons stored in a VBO
|
/*
|
||||||
|
* VBORef:
|
||||||
|
*
|
||||||
|
* Reference to model polygons stored in a VBO. Each reference has two sets of
|
||||||
|
* vertices: normal and alpha. Copies of the model with different texture
|
||||||
|
* offsets applied are searchable via the linked list of texture offset states.
|
||||||
|
*/
|
||||||
struct VBORef
|
struct VBORef
|
||||||
{
|
{
|
||||||
unsigned index[2]; // index of model polygons in VBO
|
unsigned index[2]; // index of model polygons in VBO
|
||||||
unsigned numVerts[2]; // number of vertices
|
unsigned numVerts[2];// number of vertices
|
||||||
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
|
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
|
||||||
|
struct VBORef *nextTexOffset; // linked list of models with different texture offset states
|
||||||
|
UINT16 texOffset; // texture offset data for this model
|
||||||
};
|
};
|
||||||
|
|
||||||
// Display list items: model instances and viewport settings
|
// Display list items: model instances and viewport settings
|
||||||
|
@ -92,7 +100,6 @@ struct DisplayList
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
GLfloat modelViewMatrix[4*4]; // model-view matrix
|
GLfloat modelViewMatrix[4*4]; // model-view matrix
|
||||||
GLfloat texOffset[2]; // texture offset (X, Y)
|
|
||||||
unsigned index; // index in VBO
|
unsigned index; // index in VBO
|
||||||
unsigned numVerts; // number of vertices
|
unsigned numVerts; // number of vertices
|
||||||
} Model;
|
} Model;
|
||||||
|
@ -281,18 +288,18 @@ private:
|
||||||
const UINT32 *TranslateModelAddress(UINT32 addr);
|
const UINT32 *TranslateModelAddress(UINT32 addr);
|
||||||
|
|
||||||
// Model caching and display list management
|
// Model caching and display list management
|
||||||
void DrawDisplayList(ModelCache *Cache, POLY_STATE state);
|
void DrawDisplayList(ModelCache *Cache, POLY_STATE state);
|
||||||
BOOL AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelNum);
|
BOOL AppendDisplayList(ModelCache *Cache, BOOL isViewport, const struct VBORef *Model);
|
||||||
void ClearDisplayList(ModelCache *Cache);
|
void ClearDisplayList(ModelCache *Cache);
|
||||||
BOOL InsertPolygon(ModelCache *cache, const Poly *p);
|
BOOL InsertPolygon(ModelCache *cache, const Poly *p);
|
||||||
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
|
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
|
||||||
BOOL BeginModel(ModelCache *cache);
|
BOOL BeginModel(ModelCache *cache);
|
||||||
void EndModel(ModelCache *cache, int lutIdx);
|
struct VBORef *EndModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
|
||||||
BOOL CacheModel(ModelCache *cache, int lutIdx, const UINT32 *data);
|
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 texOffset, const UINT32 *data);
|
||||||
BOOL NeedToCache(ModelCache *cache, int lutIdx);
|
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
|
||||||
void ClearModelCache(ModelCache *cache);
|
void ClearModelCache(ModelCache *cache);
|
||||||
BOOL CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, BOOL isDynamic);
|
BOOL CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, BOOL isDynamic);
|
||||||
void DestroyModelCache(ModelCache *cache);
|
void DestroyModelCache(ModelCache *cache);
|
||||||
|
|
||||||
// Texture management
|
// Texture management
|
||||||
void DecodeTexture(int format, int x, int y, int width, int height);
|
void DecodeTexture(int format, int x, int y, int width, int height);
|
||||||
|
@ -359,7 +366,8 @@ private:
|
||||||
int stackDepth; // for debugging and error handling purposes
|
int stackDepth; // for debugging and error handling purposes
|
||||||
|
|
||||||
// Texture offset (during scene graph processing)
|
// Texture offset (during scene graph processing)
|
||||||
GLfloat texOffset[2]; // X, Y
|
GLfloat texOffsetXY[2]; // decoded X, Y offsets
|
||||||
|
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
||||||
|
|
||||||
// Resolution scaling factors (to support resolutions higher than 496x384) and offsets
|
// Resolution scaling factors (to support resolutions higher than 496x384) and offsets
|
||||||
GLfloat xRatio, yRatio;
|
GLfloat xRatio, yRatio;
|
||||||
|
@ -379,7 +387,6 @@ private:
|
||||||
GLuint spotEllipseLoc; // uniform
|
GLuint spotEllipseLoc; // uniform
|
||||||
GLuint spotRangeLoc; // uniform
|
GLuint spotRangeLoc; // uniform
|
||||||
GLuint spotColorLoc; // uniform
|
GLuint spotColorLoc; // uniform
|
||||||
GLuint texOffsetLoc; // uniform
|
|
||||||
GLuint subTextureLoc; // attribute
|
GLuint subTextureLoc; // attribute
|
||||||
GLuint texParamsLoc; // attribute
|
GLuint texParamsLoc; // attribute
|
||||||
GLuint texFormatLoc; // attribute
|
GLuint texFormatLoc; // attribute
|
||||||
|
|
|
@ -34,7 +34,7 @@ uniform vec3 lighting[2]; // lighting state (lighting[0] = sun direction, light
|
||||||
uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height)
|
uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height)
|
||||||
uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit
|
uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit
|
||||||
uniform vec3 spotColor; // spotlight RGB color
|
uniform vec3 spotColor; // spotlight RGB color
|
||||||
uniform vec2 texOffset; // offset (within 2048x2048 texture sheet) to apply to texture base coordinates
|
//uniform vec2 texOffset; // offset (within 2048x2048 texture sheet) to apply to texture base coordinates
|
||||||
|
|
||||||
// Custom vertex attributes
|
// Custom vertex attributes
|
||||||
attribute vec4 subTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)
|
attribute vec4 subTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)
|
||||||
|
@ -139,7 +139,7 @@ void main(void)
|
||||||
// Pass remaining parameters to fragment shader
|
// Pass remaining parameters to fragment shader
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
fsSubTexture = subTexture;
|
fsSubTexture = subTexture;
|
||||||
fsSubTexture.xy += texOffset; // apply texture offset
|
//fsSubTexture.xy += texOffset; // apply texture offset
|
||||||
fsTexParams = texParams;
|
fsTexParams = texParams;
|
||||||
fsTransLevel = transLevel;
|
fsTransLevel = transLevel;
|
||||||
fsTexFormat = texFormat;
|
fsTexFormat = texFormat;
|
||||||
|
|
Loading…
Reference in a new issue