mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-02-16 17:35:39 +00:00
Fixed compiler warnings, whitespace, and moved local variable declarations to site of assignment
This commit is contained in:
parent
ec7588e2cd
commit
3627213577
|
@ -146,9 +146,11 @@
|
||||||
* - Can some of the floating point flag attribs be replaced with ints?
|
* - Can some of the floating point flag attribs be replaced with ints?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include "Supermodel.h"
|
#include "Supermodel.h"
|
||||||
#include "Graphics/Legacy3D/Shaders3D.h" // fragment and vertex shaders
|
#include "Graphics/Legacy3D/Shaders3D.h" // fragment and vertex shaders
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace Legacy3D {
|
namespace Legacy3D {
|
||||||
|
|
||||||
|
@ -178,16 +180,14 @@ namespace Legacy3D {
|
||||||
#define NUM_DYNAMIC_MODELS 1024 // maximum number of unique dynamic models to cache
|
#define NUM_DYNAMIC_MODELS 1024 // maximum number of unique dynamic models to cache
|
||||||
#define NUM_DISPLAY_LIST_ITEMS 10000 // maximum number of model instances displayed per frame
|
#define NUM_DISPLAY_LIST_ITEMS 10000 // maximum number of model instances displayed per frame
|
||||||
|
|
||||||
// Scene traversal stack
|
|
||||||
#define STACK_SIZE 1024
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Texture Management
|
Texture Management
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
// Default mapping from Model3 texture format to texture sheet.
|
// Default mapping from Model3 texture format to texture sheet.
|
||||||
// Currently this is just a simple 1-to-1 mapping but if/when more formats get added, sheets will start to get reused.
|
// Currently this is just a simple 1-to-1 mapping but if/when more formats get
|
||||||
|
// added, sheets will start to get reused.
|
||||||
int CLegacy3D::defaultFmtToTexSheetNum[] = {
|
int CLegacy3D::defaultFmtToTexSheetNum[] = {
|
||||||
0, // Fmt 0 -> 0
|
0, // Fmt 0 -> 0
|
||||||
1, // 1 -> 1
|
1, // 1 -> 1
|
||||||
|
@ -201,10 +201,6 @@ int CLegacy3D::defaultFmtToTexSheetNum[] = {
|
||||||
|
|
||||||
void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int xi, yi, i;
|
|
||||||
UINT16 texel;
|
|
||||||
GLfloat c, a;
|
|
||||||
|
|
||||||
x &= 2047;
|
x &= 2047;
|
||||||
y &= 2047;
|
y &= 2047;
|
||||||
|
|
||||||
|
@ -226,14 +222,13 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
//printf("Decoding texture format %u: %u x %u @ (%u, %u) sheet %u\n", format, width, height, x, y, texNum);
|
//printf("Decoding texture format %u: %u x %u @ (%u, %u) sheet %u\n", format, width, height, x, y, texNum);
|
||||||
|
|
||||||
// Copy and decode
|
// Copy and decode
|
||||||
i = 0;
|
int i = 0;
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
default: // Unknown
|
default: // Unknown
|
||||||
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
textureBuffer[i++] = 0.0; // R
|
textureBuffer[i++] = 0.0; // R
|
||||||
textureBuffer[i++] = 0.0; // G
|
textureBuffer[i++] = 0.0; // G
|
||||||
|
@ -242,11 +237,10 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: // T1RGB5
|
case 0: // T1RGB5
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>10)&0x1F) * (1.0f/31.0f); // R
|
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>10)&0x1F) * (1.0f/31.0f); // R
|
||||||
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>5)&0x1F) * (1.0f/31.0f); // G
|
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>5)&0x1F) * (1.0f/31.0f); // G
|
||||||
|
@ -255,11 +249,10 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: // RGBA4
|
case 7: // RGBA4
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>12)&0xF) * (1.0f/15.0f); // R
|
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>12)&0xF) * (1.0f/15.0f); // R
|
||||||
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>8)&0xF) * (1.0f/15.0f); // G
|
textureBuffer[i++] = (GLfloat) ((textureRAM[yi*2048+xi]>>8)&0xF) * (1.0f/15.0f); // G
|
||||||
|
@ -268,14 +261,13 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: // 8-bit grayscale
|
case 5: // 8-bit grayscale
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
texel = textureRAM[yi*2048+xi];
|
UINT16 texel = textureRAM[yi*2048+xi];
|
||||||
c = (GLfloat) (texel&0xFF) * (1.0f/255.0f);
|
c = (GLfloat) (texel&0xFF) * (1.0f/255.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
|
@ -283,79 +275,71 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
textureBuffer[i++] = 1.0;
|
textureBuffer[i++] = 1.0;
|
||||||
*/
|
*/
|
||||||
// Interpret as 8-bit grayscale
|
// Interpret as 8-bit grayscale
|
||||||
texel = textureRAM[yi*2048+xi];
|
UINT16 texel = textureRAM[yi*2048+xi];
|
||||||
c = (GLfloat) texel * (1.0f/255.0f);
|
GLfloat c = texel * (1.0f/255.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = 1.0f;
|
textureBuffer[i++] = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: // 8-bit, L4A4
|
case 4: // 8-bit, L4A4
|
||||||
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
texel = textureRAM[yi*2048+xi];
|
UINT16 texel = textureRAM[yi*2048+xi];
|
||||||
//c = (GLfloat) (~texel&0x0F) * (1.0f/15.0f);
|
//GLfloat c = (~texel&0x0F) * (1.0f/15.0f);
|
||||||
//a = (GLfloat) ((texel>>4)&0xF) * (1.0f/15.0f);
|
//GLfloat a = ((texel>>4)&0xF) * (1.0f/15.0f);
|
||||||
c = (GLfloat) ((texel>>4)&0xF) * (1.0f/15.0f); // seems to work better in Lost World (raptor shadows)
|
GLfloat c = ((texel>>4)&0xF) * (1.0f/15.0f); // seems to work better in Lost World (raptor shadows)
|
||||||
a = (GLfloat) (texel&0xF) * (1.0f/15.0f);
|
GLfloat a = (texel&0xF) * (1.0f/15.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = a;
|
textureBuffer[i++] = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // 8-bit grayscale? (How does this differ from format 5? Alpha values?)
|
case 6: // 8-bit grayscale? (How does this differ from format 5? Alpha values?)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
texel = textureRAM[yi*2048+xi];
|
UINT16 texel = textureRAM[yi*2048+xi];
|
||||||
c = (GLfloat) ((texel>>4)&0xF) * (1.0f/15.0f);
|
GLfloat c = ((texel>>4)&0xF) * (1.0f/15.0f);
|
||||||
a = (GLfloat) (texel&0xF) * (1.0f/15.0f);
|
GLfloat a = (texel&0xF) * (1.0f/15.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = a;
|
textureBuffer[i++] = a;
|
||||||
*/
|
*/
|
||||||
texel = textureRAM[yi*2048+xi]&0xFF;
|
UINT16 texel = textureRAM[yi*2048+xi]&0xFF;
|
||||||
c = (GLfloat) texel * (1.0f/255.0f);
|
GLfloat c = texel * (1.0f/255.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = 1.0f;
|
textureBuffer[i++] = 1.0f;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // Unknown (all 16 bits appear present in Daytona 2, but only lower 8 bits in Le Mans 24)
|
case 2: // Unknown (all 16 bits appear present in Daytona 2, but only lower 8 bits in Le Mans 24)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
texel = textureRAM[yi*2048+xi];
|
UINT16 texel = textureRAM[yi*2048+xi];
|
||||||
a = (GLfloat) ((texel>>4)&0xF) * (1.0f/15.0f);
|
GLfloat a = ((texel>>4)&0xF) * (1.0f/15.0f);
|
||||||
c = (GLfloat) (texel&0xF) * (1.0f/15.0f);
|
GLfloat c = (texel&0xF) * (1.0f/15.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = a;
|
textureBuffer[i++] = a;
|
||||||
|
|
||||||
//printf("%04X\n", textureRAM[yi*2048+xi]);
|
//printf("%04X\n", textureRAM[yi*2048+xi]);
|
||||||
/*
|
/*
|
||||||
texel = textureRAM[yi*2048+xi]&0xFF;
|
UINT16 texel = textureRAM[yi*2048+xi]&0xFF;
|
||||||
c = (GLfloat) texel * (1.0f/255.0f);
|
GLfloat c = texel * (1.0f/255.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
|
@ -364,15 +348,14 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Interleaved A4L4 (high byte)
|
case 3: // Interleaved A4L4 (high byte)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
texel = textureRAM[yi*2048+xi]>>8;
|
UINT16 texel = textureRAM[yi*2048+xi]>>8;
|
||||||
c = (GLfloat) (texel&0xF) * (1.0f/15.0f);
|
GLfloat c = (texel&0xF) * (1.0f/15.0f);
|
||||||
a = (GLfloat) (texel>>4) * (1.0f/15.0f);
|
GLfloat a = (texel>>4) * (1.0f/15.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
|
@ -380,16 +363,15 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // Interleaved A4L4 (low byte)
|
case 1: // Interleaved A4L4 (low byte)
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (int yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
for (xi = x; xi < (x+width); xi++)
|
for (int xi = x; xi < (x+width); xi++)
|
||||||
{
|
{
|
||||||
// Interpret as A4L4
|
// Interpret as A4L4
|
||||||
texel = textureRAM[yi*2048+xi]&0xFF;
|
UINT16 texel = textureRAM[yi*2048+xi]&0xFF;
|
||||||
c = (GLfloat) (texel&0xF) * (1.0f/15.0f);
|
GLfloat c = (texel&0xF) * (1.0f/15.0f);
|
||||||
a = (GLfloat) (texel>>4) * (1.0f/15.0f);
|
GLfloat a = (texel>>4) * (1.0f/15.0f);
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
textureBuffer[i++] = c;
|
textureBuffer[i++] = c;
|
||||||
|
@ -414,10 +396,8 @@ void CLegacy3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
// Signals that new textures have been uploaded. Flushes model caches. Be careful not to exceed bounds!
|
// Signals that new textures have been uploaded. Flushes model caches. Be careful not to exceed bounds!
|
||||||
void CLegacy3D::UploadTextures(unsigned x, unsigned y, unsigned width, unsigned height)
|
void CLegacy3D::UploadTextures(unsigned x, unsigned y, unsigned width, unsigned height)
|
||||||
{
|
{
|
||||||
unsigned texSheet, xi, yi;
|
|
||||||
|
|
||||||
// Make everything red
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
// Make everything red
|
||||||
for (int i = 0; i < 512*512; )
|
for (int i = 0; i < 512*512; )
|
||||||
{
|
{
|
||||||
textureBuffer[i++] = 1.0f;
|
textureBuffer[i++] = 1.0f;
|
||||||
|
@ -428,11 +408,11 @@ void CLegacy3D::UploadTextures(unsigned x, unsigned y, unsigned width, unsigned
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update all texture sheets
|
// Update all texture sheets
|
||||||
for (texSheet = 0; texSheet < numTexSheets; texSheet++)
|
for (size_t texSheet = 0; texSheet < numTexSheets; texSheet++)
|
||||||
{
|
{
|
||||||
for (xi = x/32; xi < (x+width)/32; xi++)
|
for (size_t xi = x/32; xi < (x+width)/32; xi++)
|
||||||
{
|
{
|
||||||
for (yi = y/32; yi < (y+height)/32; yi++)
|
for (size_t yi = y/32; yi < (y+height)/32; yi++)
|
||||||
{
|
{
|
||||||
texSheets[texSheet].texFormat[yi][xi] = -1;
|
texSheets[texSheet].texFormat[yi][xi] = -1;
|
||||||
texSheets[texSheet].texWidth[yi][xi] = -1;
|
texSheets[texSheet].texWidth[yi][xi] = -1;
|
||||||
|
@ -494,7 +474,6 @@ void CLegacy3D::MultMatrix(UINT32 matrixOffset)
|
||||||
{
|
{
|
||||||
GLfloat m[4*4];
|
GLfloat m[4*4];
|
||||||
const float *src = &matrixBasePtr[matrixOffset*12];
|
const float *src = &matrixBasePtr[matrixOffset*12];
|
||||||
|
|
||||||
if (matrixBasePtr==NULL) // LA Machineguns
|
if (matrixBasePtr==NULL) // LA Machineguns
|
||||||
return;
|
return;
|
||||||
m[CMINDEX(0, 0)] = src[3];
|
m[CMINDEX(0, 0)] = src[3];
|
||||||
|
@ -513,7 +492,6 @@ void CLegacy3D::MultMatrix(UINT32 matrixOffset)
|
||||||
m[CMINDEX(3, 1)] = 0.0;
|
m[CMINDEX(3, 1)] = 0.0;
|
||||||
m[CMINDEX(3, 2)] = 0.0;
|
m[CMINDEX(3, 2)] = 0.0;
|
||||||
m[CMINDEX(3, 3)] = 1.0;
|
m[CMINDEX(3, 3)] = 1.0;
|
||||||
|
|
||||||
glMultMatrixf(m);
|
glMultMatrixf(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,26 +602,18 @@ static bool IsDynamicModel(const UINT32 *data)
|
||||||
*/
|
*/
|
||||||
bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
{
|
{
|
||||||
ModelCache *Cache;
|
|
||||||
const UINT32 *model;
|
|
||||||
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;
|
||||||
if (modelAddr == 0x200000) // Virtual On 2 (during boot-up, causes slow-down)
|
if (modelAddr == 0x200000) // Virtual On 2 (during boot-up, causes slow-down)
|
||||||
return OKAY;
|
return OKAY;
|
||||||
model = TranslateModelAddress(modelAddr);
|
const UINT32 *model = TranslateModelAddress(modelAddr);
|
||||||
|
|
||||||
// Determine whether model is in polygon RAM or VROM
|
// Determine whether model is in polygon RAM or VROM
|
||||||
if (IsVROMModel(modelAddr))
|
ModelCache *Cache = IsVROMModel(modelAddr) ? &VROMCache : &PolyCache;
|
||||||
Cache = &VROMCache;
|
|
||||||
else
|
|
||||||
Cache = &PolyCache;
|
|
||||||
|
|
||||||
// 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;
|
int lutIdx = modelAddr&0xFFFFFF;
|
||||||
ModelRef = LookUpModel(Cache, lutIdx, texOffset);
|
struct VBORef *ModelRef = LookUpModel(Cache, lutIdx, texOffset);
|
||||||
if (NULL == ModelRef && Cache == &VROMCache)
|
if (NULL == ModelRef && Cache == &VROMCache)
|
||||||
{
|
{
|
||||||
// If the model was a VROM model, it may be dynamic, so we need to try
|
// If the model was a VROM model, it may be dynamic, so we need to try
|
||||||
|
@ -691,12 +661,6 @@ bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
// Descends into a 10-word culling node
|
// Descends into a 10-word culling node
|
||||||
void CLegacy3D::DescendCullingNode(UINT32 addr)
|
void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
{
|
{
|
||||||
const UINT32 *node, *lodTable;
|
|
||||||
UINT32 matrixOffset, node1Ptr, node2Ptr;
|
|
||||||
float x, y, z, oldTexOffsetX, oldTexOffsetY;
|
|
||||||
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)
|
||||||
if (stackDepth>=(512+64)) // safety (prevent overflows -- OpenGL matrix stack will still overflow by this point)
|
if (stackDepth>=(512+64)) // safety (prevent overflows -- OpenGL matrix stack will still overflow by this point)
|
||||||
|
@ -705,7 +669,7 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = TranslateCullingAddress(addr);
|
const UINT32 *node = TranslateCullingAddress(addr);
|
||||||
if (NULL == node)
|
if (NULL == node)
|
||||||
{
|
{
|
||||||
--stackDepth;
|
--stackDepth;
|
||||||
|
@ -720,21 +684,21 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
// printf("%X -> %02X %04X\n", addr, node[0x00]&0xFF, node[0x02]&0xFFFF);
|
// printf("%X -> %02X %04X\n", addr, node[0x00]&0xFF, node[0x02]&0xFFFF);
|
||||||
|
|
||||||
// Extract known fields
|
// Extract known fields
|
||||||
node1Ptr = node[0x07-offset];
|
const UINT32 node1Ptr = node[0x07-offset];
|
||||||
node2Ptr = node[0x08-offset];
|
const UINT32 node2Ptr = node[0x08-offset];
|
||||||
matrixOffset = node[0x03-offset]&0xFFF;
|
const UINT32 matrixOffset = node[0x03-offset]&0xFFF;
|
||||||
x = *(float *) &node[0x04-offset];
|
const float x = *(float *) &node[0x04-offset];
|
||||||
y = *(float *) &node[0x05-offset];
|
const float y = *(float *) &node[0x05-offset];
|
||||||
z = *(float *) &node[0x06-offset];
|
const float z = *(float *) &node[0x06-offset];
|
||||||
|
|
||||||
// Texture offset?
|
// Texture offset?
|
||||||
oldTexOffsetX = texOffsetXY[0]; // save old offsets
|
const float oldTexOffsetX = texOffsetXY[0]; // save old offsets
|
||||||
oldTexOffsetY = texOffsetXY[1];
|
const float oldTexOffsetY = texOffsetXY[1];
|
||||||
oldTexOffset = texOffset;
|
const UINT16 oldTexOffset = texOffset;
|
||||||
if (!offset) // Step 1.5+
|
if (!offset) // Step 1.5+
|
||||||
{
|
{
|
||||||
tx = 32*((node[0x02]>>7)&0x3F);
|
int tx = 32*((node[0x02]>>7)&0x3F);
|
||||||
ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0); // TODO: 5 or 6 bits for Y coord?
|
int ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0); // TODO: 5 or 6 bits for Y coord?
|
||||||
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
|
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
|
||||||
{
|
{
|
||||||
texOffsetXY[0] = (GLfloat) tx;
|
texOffsetXY[0] = (GLfloat) tx;
|
||||||
|
@ -754,7 +718,7 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
// Descend down first link
|
// Descend down first link
|
||||||
if ((node[0x00]&0x08)) // 4-element LOD table
|
if ((node[0x00]&0x08)) // 4-element LOD table
|
||||||
{
|
{
|
||||||
lodTable = TranslateCullingAddress(node1Ptr);
|
const UINT32 *lodTable = TranslateCullingAddress(node1Ptr);
|
||||||
if (NULL != lodTable)
|
if (NULL != lodTable)
|
||||||
{
|
{
|
||||||
if ((node[0x03-offset]&0x20000000))
|
if ((node[0x03-offset]&0x20000000))
|
||||||
|
@ -781,41 +745,33 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
// 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.
|
||||||
void CLegacy3D::DescendPointerList(UINT32 addr)
|
void CLegacy3D::DescendPointerList(UINT32 addr)
|
||||||
{
|
{
|
||||||
const UINT32 *list;
|
|
||||||
UINT32 nodeAddr;
|
|
||||||
int listEnd;
|
|
||||||
|
|
||||||
if (listDepth > 2) // several Step 2.1 games require this safeguard
|
if (listDepth > 2) // several Step 2.1 games require this safeguard
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list = TranslateCullingAddress(addr);
|
const UINT32 *list = TranslateCullingAddress(addr);
|
||||||
if (NULL == list)
|
if (NULL == list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++listDepth;
|
++listDepth;
|
||||||
//printf("%08x LIST\n", addr);
|
|
||||||
// Traverse the list forward and print it out
|
// Traverse the list forward and print it out
|
||||||
listEnd = 0;
|
int listEnd = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
//printf(" %08x\n", list[listEnd]);
|
|
||||||
if ((list[listEnd] & 0x02000000)) // end of list (?)
|
if ((list[listEnd] & 0x02000000)) // end of list (?)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((list[listEnd] == 0) || (((list[listEnd])>>24) != 0))
|
if ((list[listEnd] == 0) || (((list[listEnd])>>24) != 0))
|
||||||
{
|
{
|
||||||
//printf("ATTENTION: Unknown list termination: %08X.\n", list[listEnd]);
|
//printf("ATTENTION: Unknown list termination: %08X.\n", list[listEnd]);
|
||||||
listEnd--; // back up to last valid list element
|
listEnd--; // back up to last valid list element
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
++listEnd;
|
++listEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the list backward and descend into each pointer
|
// Traverse the list backward and descend into each pointer
|
||||||
while (listEnd >= 0)
|
while (listEnd >= 0)
|
||||||
{
|
{
|
||||||
nodeAddr = list[listEnd]&0x00FFFFFF; // clear upper 8 bits to ensure this is processed as a culling node
|
UINT32 nodeAddr = list[listEnd]&0x00FFFFFF; // clear upper 8 bits to ensure this is processed as a culling node
|
||||||
if (!(list[listEnd]&0x01000000))//Fighting Vipers
|
if (!(list[listEnd]&0x01000000))//Fighting Vipers
|
||||||
{
|
{
|
||||||
if ((nodeAddr != 0) && (nodeAddr != 0x800800))
|
if ((nodeAddr != 0) && (nodeAddr != 0x800800))
|
||||||
|
@ -863,8 +819,7 @@ void CLegacy3D::DescendNodePtr(UINT32 nodeAddr)
|
||||||
// Draws viewports of the given priority
|
// Draws viewports of the given priority
|
||||||
void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
{
|
{
|
||||||
GLfloat color[8][3] = // RGB1 translation
|
static const GLfloat color[8][3] = {
|
||||||
{
|
|
||||||
{ 0.0, 0.0, 0.0 }, // off
|
{ 0.0, 0.0, 0.0 }, // off
|
||||||
{ 0.0, 0.0, 1.0 }, // blue
|
{ 0.0, 0.0, 1.0 }, // blue
|
||||||
{ 0.0, 1.0, 0.0 }, // green
|
{ 0.0, 1.0, 0.0 }, // green
|
||||||
|
@ -874,44 +829,35 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
{ 1.0, 1.0, 0.0 }, // yellow
|
{ 1.0, 1.0, 0.0 }, // yellow
|
||||||
{ 1.0, 1.0, 1.0 } // white
|
{ 1.0, 1.0, 1.0 } // white
|
||||||
};
|
};
|
||||||
const UINT32 *vpnode;
|
|
||||||
UINT32 nextAddr, nodeAddr, matrixBase;
|
|
||||||
int curPri;
|
|
||||||
int vpX, vpY, vpWidth, vpHeight;
|
|
||||||
int spotColorIdx;
|
|
||||||
GLfloat vpTopAngle, vpBotAngle, fovYDegrees;
|
|
||||||
GLfloat scrollFog, scrollAtt;
|
|
||||||
|
|
||||||
// Translate address and obtain pointer
|
// Translate address and obtain pointer
|
||||||
vpnode = TranslateCullingAddress(addr);
|
const UINT32 *vpnode = TranslateCullingAddress(addr);
|
||||||
if (NULL == vpnode)
|
if (NULL == vpnode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
curPri = (vpnode[0x00] >> 3) & 3; // viewport priority
|
|
||||||
nextAddr = vpnode[0x01] & 0xFFFFFF; // next viewport
|
|
||||||
nodeAddr = vpnode[0x02]; // scene database node pointer
|
|
||||||
|
|
||||||
// Recursively process next viewport
|
// Recursively process next viewport
|
||||||
if (vpnode[0x01] == 0) // memory probably hasn't been set up yet, abort
|
UINT32 nextAddr = vpnode[0x01]; // next viewport
|
||||||
|
UINT32 nodeAddr = vpnode[0x02]; // scene database node pointer
|
||||||
|
if (nextAddr == 0) // memory probably hasn't been set up yet, abort
|
||||||
return;
|
return;
|
||||||
if (vpnode[0x01] != 0x01000000)
|
if (nextAddr != 0x01000000)
|
||||||
RenderViewport(vpnode[0x01],pri);
|
RenderViewport(nextAddr, pri);
|
||||||
|
|
||||||
// If the priority doesn't match, do not process
|
// If the priority doesn't match, do not process
|
||||||
|
int curPri = (vpnode[0x00] >> 3) & 3; // viewport priority
|
||||||
if (curPri != pri)
|
if (curPri != pri)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Fetch viewport parameters (TO-DO: would rounding make a difference?)
|
// Fetch viewport parameters (TO-DO: would rounding make a difference?)
|
||||||
vpX = (vpnode[0x1A]&0xFFFF)>>4; // viewport X (12.4 fixed point)
|
int vpX = (vpnode[0x1A]&0xFFFF)>>4; // viewport X (12.4 fixed point)
|
||||||
vpY = (vpnode[0x1A]>>20)&0xFFF; // viewport Y (12.4)
|
int vpY = (vpnode[0x1A]>>20)&0xFFF; // viewport Y (12.4)
|
||||||
vpWidth = (vpnode[0x14]&0xFFFF)>>2; // width (14.2)
|
int vpWidth = (vpnode[0x14]&0xFFFF)>>2; // width (14.2)
|
||||||
vpHeight = (vpnode[0x14]>>18)&0x3FFF; // height (14.2)
|
int vpHeight = (vpnode[0x14]>>18)&0x3FFF; // height (14.2)
|
||||||
matrixBase = vpnode[0x16]&0xFFFFFF; // matrix base address
|
|
||||||
|
|
||||||
// Field of view and clipping
|
// Field of view and clipping
|
||||||
vpTopAngle = (float) asin(*(float *)&vpnode[0x0E]); // FOV Y upper half-angle (radians)
|
GLfloat vpTopAngle = (float) asin(*(float *)&vpnode[0x0E]); // FOV Y upper half-angle (radians)
|
||||||
vpBotAngle = (float) asin(*(float *)&vpnode[0x12]); // FOV Y lower half-angle
|
GLfloat vpBotAngle = (float) asin(*(float *)&vpnode[0x12]); // FOV Y lower half-angle
|
||||||
fovYDegrees = (vpTopAngle+vpBotAngle)*(float)(180.0/3.14159265358979323846);
|
GLfloat fovYDegrees = (vpTopAngle+vpBotAngle)*(float)(180.0/3.14159265358979323846);
|
||||||
// TO-DO: investigate clipping planes
|
// TO-DO: investigate clipping planes
|
||||||
|
|
||||||
// Set up viewport and projection (TO-DO: near and far clipping)
|
// Set up viewport and projection (TO-DO: near and far clipping)
|
||||||
|
@ -945,7 +891,7 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
lightingParams[5] = 0.0; // reserved
|
lightingParams[5] = 0.0; // reserved
|
||||||
|
|
||||||
// Spotlight
|
// Spotlight
|
||||||
spotColorIdx = (vpnode[0x20]>>11)&7; // spotlight color index
|
int spotColorIdx = (vpnode[0x20]>>11)&7; // spotlight color index
|
||||||
spotEllipse[0] = (float) ((vpnode[0x1E]>>3)&0x1FFF); // spotlight X position (fractional component?)
|
spotEllipse[0] = (float) ((vpnode[0x1E]>>3)&0x1FFF); // spotlight X position (fractional component?)
|
||||||
spotEllipse[1] = (float) ((vpnode[0x1D]>>3)&0x1FFF); // spotlight Y
|
spotEllipse[1] = (float) ((vpnode[0x1D]>>3)&0x1FFF); // spotlight Y
|
||||||
spotEllipse[2] = (float) ((vpnode[0x1E]>>16)&0xFFFF); // spotlight X size (16-bit? May have fractional component below bit 16)
|
spotEllipse[2] = (float) ((vpnode[0x1E]>>16)&0xFFFF); // spotlight X size (16-bit? May have fractional component below bit 16)
|
||||||
|
@ -979,8 +925,8 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
fogParams[3] = fogParams[4] = 0.0f;
|
fogParams[3] = fogParams[4] = 0.0f;
|
||||||
|
|
||||||
// Unknown light/fog parameters
|
// Unknown light/fog parameters
|
||||||
scrollFog = (float) (vpnode[0x20]&0xFF) * (1.0f/255.0f); // scroll fog
|
//GLfloat scrollFog = (float) (vpnode[0x20]&0xFF) * (1.0f/255.0f); // scroll fog
|
||||||
scrollAtt = (float) (vpnode[0x24]&0xFF) * (1.0f/255.0f); // scroll attenuation
|
//GLfloat scrollAtt = (float) (vpnode[0x24]&0xFF) * (1.0f/255.0f); // scroll attenuation
|
||||||
//printf("scrollFog = %g, scrollAtt = %g\n", scrollFog, scrollAtt);
|
//printf("scrollFog = %g, scrollAtt = %g\n", scrollFog, scrollAtt);
|
||||||
//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]);
|
||||||
|
|
||||||
|
@ -990,6 +936,7 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
texOffset = 0x0000;
|
texOffset = 0x0000;
|
||||||
|
|
||||||
// Set up coordinate system and base matrix
|
// Set up coordinate system and base matrix
|
||||||
|
UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF;
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
InitMatrixStack(matrixBase);
|
InitMatrixStack(matrixBase);
|
||||||
|
|
||||||
|
@ -1172,23 +1119,23 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
totalYRes = totalYResParam;
|
totalYRes = totalYResParam;
|
||||||
|
|
||||||
// Get ideal number of texture sheets required by default mapping from Model3 texture format to texture sheet
|
// Get ideal number of texture sheets required by default mapping from Model3 texture format to texture sheet
|
||||||
unsigned idealTexSheets = 0;
|
int idealTexSheets = 0;
|
||||||
for (unsigned fmt = 0; fmt < 8; fmt++)
|
for (size_t fmt = 0; fmt < 8; fmt++)
|
||||||
{
|
{
|
||||||
int sheetNum = defaultFmtToTexSheetNum[fmt];
|
int sheetNum = defaultFmtToTexSheetNum[fmt];
|
||||||
idealTexSheets = max<int>(idealTexSheets, sheetNum + 1);
|
idealTexSheets = std::max<int>(idealTexSheets, sheetNum + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get upper limit for number of texture maps to use from max number of texture units supported by video card
|
// Get upper limit for number of texture maps to use from max number of texture units supported by video card
|
||||||
GLint glMaxTexUnits;
|
GLint glMaxTexUnits;
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTexUnits);
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTexUnits);
|
||||||
unsigned maxTexMaps = max<int>(1, min<int>(g_Config.maxTexMaps, glMaxTexUnits));
|
int maxTexMaps = std::max<int>(1, std::min<int>(g_Config.maxTexMaps, glMaxTexUnits));
|
||||||
|
|
||||||
// Get upper limit for extent of texture maps to use from max texture size supported by video card
|
// Get upper limit for extent of texture maps to use from max texture size supported by video card
|
||||||
GLint maxTexSize;
|
GLint maxTexSize;
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
|
||||||
unsigned mapExtent = max<int>(1, min<unsigned>(g_Config.maxTexMapExtent, maxTexSize / 2048));
|
int mapExtent = std::max<int>(1, std::min<unsigned>(g_Config.maxTexMapExtent, maxTexSize / 2048));
|
||||||
unsigned mapSize = 2048 * mapExtent;
|
int mapSize = 2048 * mapExtent;
|
||||||
while (mapExtent > 1)
|
while (mapExtent > 1)
|
||||||
{
|
{
|
||||||
if ((mapExtent - 1) * (mapExtent - 1) < idealTexSheets)
|
if ((mapExtent - 1) * (mapExtent - 1) < idealTexSheets)
|
||||||
|
@ -1216,12 +1163,12 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
textureMapLoc = glGetUniformLocation(shaderProgram, "textureMap");
|
textureMapLoc = glGetUniformLocation(shaderProgram, "textureMap");
|
||||||
|
|
||||||
// If exists, bind to first texture unit
|
// If exists, bind to first texture unit
|
||||||
unsigned mapCount = 0;
|
int mapCount = 0;
|
||||||
if (textureMapLoc != -1)
|
if (textureMapLoc != -1)
|
||||||
glUniform1i(textureMapLoc, mapCount++);
|
glUniform1i(textureMapLoc, mapCount++);
|
||||||
|
|
||||||
// Try locating "textureMap[0-7]" uniforms in shader program
|
// Try locating "textureMap[0-7]" uniforms in shader program
|
||||||
for (unsigned mapNum = 0; mapNum < 8 && mapCount < maxTexMaps; mapNum++)
|
for (int mapNum = 0; mapNum < 8 && mapCount < maxTexMaps; mapNum++)
|
||||||
{
|
{
|
||||||
char uniformName[12];
|
char uniformName[12];
|
||||||
sprintf(uniformName, "textureMap%u", mapNum);
|
sprintf(uniformName, "textureMap%u", mapNum);
|
||||||
|
@ -1247,7 +1194,7 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
unsigned sheetsPerMap = mapExtent * mapExtent;
|
unsigned sheetsPerMap = mapExtent * mapExtent;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
numTexMaps = min<unsigned>(mapCount, 1 + (idealTexSheets - 1) / sheetsPerMap);
|
numTexMaps = std::min<unsigned>(mapCount, 1 + (idealTexSheets - 1) / sheetsPerMap);
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glGenTextures(numTexMaps, texMapIDs);
|
glGenTextures(numTexMaps, texMapIDs);
|
||||||
|
@ -1285,7 +1232,7 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
InfoLog("Created %u %ux%u-texel GL texture map(s).", numTexMaps, mapSize, mapSize);
|
InfoLog("Created %u %ux%u-texel GL texture map(s).", numTexMaps, mapSize, mapSize);
|
||||||
|
|
||||||
// Create texture sheet objects and assign them to texture maps
|
// Create texture sheet objects and assign them to texture maps
|
||||||
numTexSheets = min<unsigned>(numTexMaps * sheetsPerMap, idealTexSheets);
|
numTexSheets = std::min<unsigned>(numTexMaps * sheetsPerMap, idealTexSheets);
|
||||||
texSheets = new(std::nothrow) TexSheet[numTexSheets];
|
texSheets = new(std::nothrow) TexSheet[numTexSheets];
|
||||||
if (texSheets == NULL)
|
if (texSheets == NULL)
|
||||||
return ErrorLog("Unable to assign memory for %u texture sheet objects.", numTexSheets);
|
return ErrorLog("Unable to assign memory for %u texture sheet objects.", numTexSheets);
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
* -----------
|
* -----------
|
||||||
* - If vertex normals aren't offset from polygon normals, would that improve
|
* - If vertex normals aren't offset from polygon normals, would that improve
|
||||||
* specular lighting?
|
* specular lighting?
|
||||||
* - Check to see if vertices in LA Machineguns and Dirt Devils contain color
|
|
||||||
* values rather than normals.
|
|
||||||
* - More should be predecoded into the polygon structures, so that things like
|
* - More should be predecoded into the polygon structures, so that things like
|
||||||
* texture base coordinates are not re-decoded in two different places!
|
* texture base coordinates are not re-decoded in two different places!
|
||||||
*/
|
*/
|
||||||
|
@ -85,7 +83,7 @@ namespace Legacy3D {
|
||||||
// Macro to generate column-major (OpenGL) index from y,x subscripts
|
// Macro to generate column-major (OpenGL) index from y,x subscripts
|
||||||
#define CMINDEX(y,x) (x*4+y)
|
#define CMINDEX(y,x) (x*4+y)
|
||||||
|
|
||||||
static void CrossProd(GLfloat out[3], GLfloat a[3], GLfloat b[3])
|
static void CrossProd(GLfloat out[3], const GLfloat a[3], const GLfloat b[3])
|
||||||
{
|
{
|
||||||
out[0] = a[1]*b[2]-a[2]*b[1];
|
out[0] = a[1]*b[2]-a[2]*b[1];
|
||||||
out[1] = a[2]*b[0]-a[0]*b[2];
|
out[1] = a[2]*b[0]-a[0]*b[2];
|
||||||
|
@ -93,7 +91,7 @@ static void CrossProd(GLfloat out[3], GLfloat a[3], GLfloat b[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3x3 matrix used (upper-left of m[])
|
// 3x3 matrix used (upper-left of m[])
|
||||||
static void MultMat3Vec3(GLfloat out[3], GLfloat m[4*4], GLfloat v[3])
|
static void MultMat3Vec3(GLfloat out[3], const GLfloat m[4*4], const GLfloat v[3])
|
||||||
{
|
{
|
||||||
out[0] = m[CMINDEX(0,0)]*v[0]+m[CMINDEX(0,1)]*v[1]+m[CMINDEX(0,2)]*v[2];
|
out[0] = m[CMINDEX(0,0)]*v[0]+m[CMINDEX(0,1)]*v[1]+m[CMINDEX(0,2)]*v[2];
|
||||||
out[1] = m[CMINDEX(1,0)]*v[0]+m[CMINDEX(1,1)]*v[1]+m[CMINDEX(1,2)]*v[2];
|
out[1] = m[CMINDEX(1,0)]*v[0]+m[CMINDEX(1,1)]*v[1]+m[CMINDEX(1,2)]*v[2];
|
||||||
|
@ -124,6 +122,7 @@ static void InvertTransposeMat3(GLfloat out[4*4], GLfloat m[4*4])
|
||||||
out[CMINDEX(0,2)] = invDet*(a21*a10-a20*a11); out[CMINDEX(1,2)] = invDet*(-(a21*a00-a20*a01)); out[CMINDEX(2,2)] = invDet*(a11*a00-a10*a01);
|
out[CMINDEX(0,2)] = invDet*(a21*a10-a20*a11); out[CMINDEX(1,2)] = invDet*(-(a21*a00-a20*a01)); out[CMINDEX(2,2)] = invDet*(a11*a00-a10*a01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static void PrintMatrix(GLfloat m[4*4])
|
static void PrintMatrix(GLfloat m[4*4])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
|
@ -133,6 +132,7 @@ static void PrintMatrix(GLfloat m[4*4])
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -150,8 +150,6 @@ static void PrintMatrix(GLfloat m[4*4])
|
||||||
// Draws the display list
|
// Draws the display list
|
||||||
void CLegacy3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
void CLegacy3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
||||||
{
|
{
|
||||||
DisplayList *D;
|
|
||||||
|
|
||||||
// Bind and activate VBO (pointers activate currently bound VBO)
|
// Bind and activate VBO (pointers activate currently bound VBO)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
||||||
glVertexPointer(3, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_X*sizeof(GLfloat)));
|
glVertexPointer(3, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_X*sizeof(GLfloat)));
|
||||||
|
@ -179,7 +177,7 @@ void CLegacy3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw if there are items in the list
|
// Draw if there are items in the list
|
||||||
D = Cache->ListHead[state];
|
const DisplayList *D = Cache->ListHead[state];
|
||||||
while (D != NULL)
|
while (D != NULL)
|
||||||
{
|
{
|
||||||
if (D->isViewport)
|
if (D->isViewport)
|
||||||
|
@ -202,12 +200,11 @@ void CLegacy3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GLint frontFace;
|
|
||||||
|
|
||||||
if (D->Data.Model.frontFace == -GL_CW) // no backface culling (all normals have lost their Z component)
|
if (D->Data.Model.frontFace == -GL_CW) // no backface culling (all normals have lost their Z component)
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
else // use appropriate winding convention
|
else // use appropriate winding convention
|
||||||
{
|
{
|
||||||
|
GLint frontFace;
|
||||||
glGetIntegerv(GL_FRONT_FACE, &frontFace);
|
glGetIntegerv(GL_FRONT_FACE, &frontFace);
|
||||||
if (frontFace != D->Data.Model.frontFace)
|
if (frontFace != D->Data.Model.frontFace)
|
||||||
glFrontFace(D->Data.Model.frontFace);
|
glFrontFace(D->Data.Model.frontFace);
|
||||||
|
@ -228,14 +225,13 @@ void CLegacy3D::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 CLegacy3D::AppendDisplayList(ModelCache *Cache, bool isViewport, const struct VBORef *Model)
|
bool CLegacy3D::AppendDisplayList(ModelCache *Cache, bool isViewport, const struct VBORef *Model)
|
||||||
{
|
{
|
||||||
int lm, i;
|
|
||||||
|
|
||||||
if ((Cache->listSize+2) > Cache->maxListSize) // a model may have 2 states (viewports are added to both display lists)
|
if ((Cache->listSize+2) > Cache->maxListSize) // a model may have 2 states (viewports are added to both display lists)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
//return ErrorLog("Display list is full.");
|
//return ErrorLog("Display list is full.");
|
||||||
|
|
||||||
// Insert states into the display list
|
// Insert states into the display list
|
||||||
for (i = 0; i < 2; i++)
|
size_t lm = 0;
|
||||||
|
for (size_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (isViewport)
|
if (isViewport)
|
||||||
{
|
{
|
||||||
|
@ -299,9 +295,9 @@ bool CLegacy3D::AppendDisplayList(ModelCache *Cache, bool isViewport, const stru
|
||||||
* This is described further in InsertPolygon(), where the vertices
|
* This is described further in InsertPolygon(), where the vertices
|
||||||
* are ordered in clockwise fashion.
|
* are ordered in clockwise fashion.
|
||||||
*/
|
*/
|
||||||
GLfloat x[3] = { 1.0f, 0.0f, 0.0f };
|
static const GLfloat x[3] = { 1.0f, 0.0f, 0.0f };
|
||||||
GLfloat y[3] = { 0.0f, 1.0f, 0.0f };
|
static const GLfloat y[3] = { 0.0f, 1.0f, 0.0f };
|
||||||
GLfloat z[3] = { 0.0f, 0.0f, -1.0f*matrixBasePtr[0x5] };
|
const GLfloat z[3] = { 0.0f, 0.0f, -1.0f*matrixBasePtr[0x5] };
|
||||||
GLfloat m[4*4];
|
GLfloat m[4*4];
|
||||||
GLfloat xT[3], yT[3], zT[3], pT[3];
|
GLfloat xT[3], yT[3], zT[3], pT[3];
|
||||||
|
|
||||||
|
@ -344,7 +340,7 @@ bool CLegacy3D::AppendDisplayList(ModelCache *Cache, bool isViewport, const stru
|
||||||
void CLegacy3D::ClearDisplayList(ModelCache *Cache)
|
void CLegacy3D::ClearDisplayList(ModelCache *Cache)
|
||||||
{
|
{
|
||||||
Cache->listSize = 0;
|
Cache->listSize = 0;
|
||||||
for (int i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
Cache->ListHead[i] = NULL;
|
Cache->ListHead[i] = NULL;
|
||||||
Cache->ListTail[i] = NULL;
|
Cache->ListTail[i] = NULL;
|
||||||
|
@ -364,21 +360,15 @@ void CLegacy3D::ClearDisplayList(ModelCache *Cache)
|
||||||
// Inserts a vertex into the local vertex buffer, incrementing both the local and VBO pointers. The normal is scaled by normFlip.
|
// Inserts a vertex into the local vertex buffer, incrementing both the local and VBO pointers. The normal is scaled by normFlip.
|
||||||
void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P, float normFlip)
|
void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P, float normFlip)
|
||||||
{
|
{
|
||||||
GLfloat r, g, b;
|
|
||||||
GLfloat translucence, fogIntensity, texWidth, texHeight, texBaseX, texBaseY, contourProcessing;
|
|
||||||
unsigned baseIdx, texFormat, texEnable, lightEnable, modulate, colorIdx;
|
|
||||||
TexSheet *texSheet;
|
|
||||||
int s, texPage, shininess;
|
|
||||||
|
|
||||||
// Texture selection
|
// Texture selection
|
||||||
texEnable = P->header[6]&0x04000000;
|
unsigned texEnable = P->header[6]&0x04000000;
|
||||||
texFormat = (P->header[6]>>7)&7;
|
unsigned texFormat = (P->header[6]>>7)&7;
|
||||||
texWidth = (GLfloat) (32<<((P->header[3]>>3)&7));
|
GLfloat texWidth = (GLfloat) (32<<((P->header[3]>>3)&7));
|
||||||
texHeight = (GLfloat) (32<<((P->header[3]>>0)&7));
|
GLfloat texHeight = (GLfloat) (32<<((P->header[3]>>0)&7));
|
||||||
texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
int texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
||||||
texSheet = fmtToTexSheet[texFormat]; // get X&Y offset of texture sheet within texture map
|
TexSheet *texSheet = fmtToTexSheet[texFormat]; // get X&Y offset of texture sheet within texture map
|
||||||
texBaseX = (GLfloat) (texSheet->xOffset + (((32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1))) + (int)texOffsetXY[0])&2047));
|
GLfloat texBaseX = (GLfloat) (texSheet->xOffset + (((32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1))) + (int)texOffsetXY[0])&2047));
|
||||||
texBaseY = (GLfloat) (texSheet->yOffset + (((32*(P->header[5]&0x1F)+texPage) + (int)texOffsetXY[1])&2047));
|
GLfloat texBaseY = (GLfloat) (texSheet->yOffset + (((32*(P->header[5]&0x1F)+texPage) + (int)texOffsetXY[1])&2047));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lighting and Color Modulation:
|
* Lighting and Color Modulation:
|
||||||
|
@ -419,25 +409,30 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
||||||
* correct, but cones are too dark. Need to investigate further.
|
* correct, but cones are too dark. Need to investigate further.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lightEnable = !(P->header[6]&0x00010000);
|
unsigned lightEnable = !(P->header[6]&0x00010000);
|
||||||
modulate = !(P->header[4]&0x80); // makes traffic lights blink in Daytona and works best in Sega Rally 2
|
unsigned modulate = !(P->header[4]&0x80); // makes traffic lights blink in Daytona and works best in Sega Rally 2
|
||||||
//modulate = P->header[3]&0x80; // seems to work better overall (TODO: are header[3]&0x80 and header[4]&0x80 ever both set?)
|
//unsigned modulate = P->header[3]&0x80; // seems to work better overall (TODO: are header[3]&0x80 and header[4]&0x80 ever both set?)
|
||||||
|
|
||||||
// Material color
|
// Material color
|
||||||
|
GLfloat r = 1.0;
|
||||||
|
GLfloat g = 1.0;
|
||||||
|
GLfloat b = 1.0;
|
||||||
if ((P->header[1]&2) == 0)
|
if ((P->header[1]&2) == 0)
|
||||||
{
|
{
|
||||||
colorIdx = ((P->header[4]>>20)&0x7FF) - 0; // works for Scud
|
size_t base = 0x400;
|
||||||
colorIdx = ((P->header[4]>>8)&0x7FF) - 0; // works for Daytona2 lights
|
//size_t colorIdx = ((P->header[4]>>20)&0x7FF) - 0; // works for Scud
|
||||||
unsigned base = 0x400;
|
size_t colorIdx = ((P->header[4]>>8)&0x7FF) - 0; // works for Daytona2 lights and Scud
|
||||||
b = (GLfloat) (polyRAM[base+colorIdx]&0xFF) * (1.0f/255.0f);
|
b = (GLfloat) (polyRAM[base+colorIdx]&0xFF) * (1.0f/255.0f);
|
||||||
g = (GLfloat) ((polyRAM[base+colorIdx]>>8)&0xFF) * (1.0f/255.0f);
|
g = (GLfloat) ((polyRAM[base+colorIdx]>>8)&0xFF) * (1.0f/255.0f);
|
||||||
r = (GLfloat) ((polyRAM[base+colorIdx]>>16)&0xFF) * (1.0f/255.0f);
|
r = (GLfloat) ((polyRAM[base+colorIdx]>>16)&0xFF) * (1.0f/255.0f);
|
||||||
//modulate=true;
|
//modulate=true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
else if ((P->header[6] & 0x02000000))
|
else if ((P->header[6] & 0x02000000))
|
||||||
{
|
{
|
||||||
r = g = b = (GLfloat) ((P->header[6]>>26)&0x1f) * (1.0f/31.0f);
|
r = g = b = (GLfloat) ((P->header[6]>>26)&0x1f) * (1.0f/31.0f);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Colors are 8-bit (almost certainly true, see Star Wars)
|
// Colors are 8-bit (almost certainly true, see Star Wars)
|
||||||
|
@ -453,9 +448,9 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
||||||
if (!modulate)
|
if (!modulate)
|
||||||
r = g = b = 1.0f;
|
r = g = b = 1.0f;
|
||||||
}
|
}
|
||||||
if ((P->header[6] & 0x02000000)) { lightEnable=false;r=b=0;g=1.0;texEnable=false;modulate=false;}
|
|
||||||
// Specular shininess
|
// Specular shininess
|
||||||
shininess = (P->header[0]>>26)&0x3F;
|
int shininess = (P->header[0]>>26)&0x3F;
|
||||||
//shininess = (P->header[0]>>28)&0xF;
|
//shininess = (P->header[0]>>28)&0xF;
|
||||||
//if (shininess)
|
//if (shininess)
|
||||||
// printf("%X\n", shininess);
|
// printf("%X\n", shininess);
|
||||||
|
@ -489,12 +484,12 @@ if ((P->header[6] & 0x02000000)) { lightEnable=false;r=b=0;g=1.0;texEnable=false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Determine whether polygon is translucent
|
// Determine whether polygon is translucent
|
||||||
translucence = (GLfloat) ((P->header[6]>>18)&0x1F) * (1.0f/31.0f);
|
GLfloat translucence = (GLfloat) ((P->header[6]>>18)&0x1F) * (1.0f/31.0f);
|
||||||
if ((P->header[6]&0x00800000)) // if set, polygon is opaque
|
if ((P->header[6]&0x00800000)) // if set, polygon is opaque
|
||||||
translucence = 1.0f;
|
translucence = 1.0f;
|
||||||
|
|
||||||
// Fog intensity (for luminous polygons)
|
// Fog intensity (for luminous polygons)
|
||||||
fogIntensity = (GLfloat) ((P->header[6]>>11)&0x1F) * (1.0f/31.0f);
|
GLfloat fogIntensity = (GLfloat) ((P->header[6]>>11)&0x1F) * (1.0f/31.0f);
|
||||||
if (!(P->header[6]&0x00010000)) // if not luminous, always use full fog intensity
|
if (!(P->header[6]&0x00010000)) // if not luminous, always use full fog intensity
|
||||||
fogIntensity = 1.0f;
|
fogIntensity = 1.0f;
|
||||||
|
|
||||||
|
@ -506,16 +501,15 @@ if ((P->header[6] & 0x02000000)) { lightEnable=false;r=b=0;g=1.0;texEnable=false
|
||||||
* alpha blended texture formats as well in order to discard fully
|
* alpha blended texture formats as well in order to discard fully
|
||||||
* transparent pixels.
|
* transparent pixels.
|
||||||
*/
|
*/
|
||||||
|
GLfloat contourProcessing = -1.0f;
|
||||||
if ((P->header[6]&0x80000000) || (texFormat==7) || // contour processing enabled or RGBA4 texture
|
if ((P->header[6]&0x80000000) || (texFormat==7) || // contour processing enabled or RGBA4 texture
|
||||||
((texFormat==1) && (P->header[6]&2)) || // A4L4 interleaved (these formats are not being interpreted correctly, see Scud Race clock tower)
|
((texFormat==1) && (P->header[6]&2)) || // A4L4 interleaved (these formats are not being interpreted correctly, see Scud Race clock tower)
|
||||||
((texFormat==3) && (P->header[6]&4))) // A4L4 interleaved
|
((texFormat==3) && (P->header[6]&4))) // A4L4 interleaved
|
||||||
contourProcessing = 1.0f;
|
contourProcessing = 1.0f;
|
||||||
else
|
|
||||||
contourProcessing = -1.0f;
|
|
||||||
|
|
||||||
// Store to local vertex buffer
|
// Store to local vertex buffer
|
||||||
s = P->state;
|
size_t s = P->state;
|
||||||
baseIdx = Cache->curVertIdx[s]*VBO_VERTEX_SIZE;
|
size_t baseIdx = Cache->curVertIdx[s]*VBO_VERTEX_SIZE;
|
||||||
|
|
||||||
Cache->verts[s][baseIdx + VBO_VERTEX_OFFSET_X] = V->x;
|
Cache->verts[s][baseIdx + VBO_VERTEX_OFFSET_X] = V->x;
|
||||||
Cache->verts[s][baseIdx + VBO_VERTEX_OFFSET_Y] = V->y;
|
Cache->verts[s][baseIdx + VBO_VERTEX_OFFSET_Y] = V->y;
|
||||||
|
@ -551,10 +545,6 @@ if ((P->header[6] & 0x02000000)) { lightEnable=false;r=b=0;g=1.0;texEnable=false
|
||||||
|
|
||||||
bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
{
|
{
|
||||||
GLfloat n[3], v1[3], v2[3], normZFlip;
|
|
||||||
int i;
|
|
||||||
bool doubleSided;
|
|
||||||
|
|
||||||
// Bounds testing: up to 12 triangles will be inserted (worst case: double sided quad is 6 triangles)
|
// Bounds testing: up to 12 triangles will be inserted (worst case: double sided quad is 6 triangles)
|
||||||
if ((Cache->curVertIdx[P->state]+6*2) >= Cache->maxVertIdx)
|
if ((Cache->curVertIdx[P->state]+6*2) >= Cache->maxVertIdx)
|
||||||
return ErrorLocalVertexOverflow(); // local buffers are not expected to overflow
|
return ErrorLocalVertexOverflow(); // local buffers are not expected to overflow
|
||||||
|
@ -562,7 +552,7 @@ bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
return FAIL; // this just indicates we may need to re-cache
|
return FAIL; // this just indicates we may need to re-cache
|
||||||
|
|
||||||
// Is the polygon double sided?
|
// Is the polygon double sided?
|
||||||
doubleSided = (P->header[1]&0x10) ? true : false;
|
bool doubleSided = (P->header[1]&0x10) ? true : false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine polygon winding by taking cross product of vectors formed from
|
* Determine polygon winding by taking cross product of vectors formed from
|
||||||
|
@ -581,6 +571,9 @@ bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
* to do with using the correct Z convention to identify a vector pointing
|
* to do with using the correct Z convention to identify a vector pointing
|
||||||
* toward or away from the screen.
|
* toward or away from the screen.
|
||||||
*/
|
*/
|
||||||
|
GLfloat v1[3];
|
||||||
|
GLfloat v2[3];
|
||||||
|
GLfloat n[3];
|
||||||
v1[0] = P->Vert[0].x-P->Vert[1].x;
|
v1[0] = P->Vert[0].x-P->Vert[1].x;
|
||||||
v1[1] = P->Vert[0].y-P->Vert[1].y;
|
v1[1] = P->Vert[0].y-P->Vert[1].y;
|
||||||
v1[2] = P->Vert[0].z-P->Vert[1].z;
|
v1[2] = P->Vert[0].z-P->Vert[1].z;
|
||||||
|
@ -589,19 +582,19 @@ bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
v2[2] = P->Vert[2].z-P->Vert[1].z;
|
v2[2] = P->Vert[2].z-P->Vert[1].z;
|
||||||
CrossProd(n,v1,v2);
|
CrossProd(n,v1,v2);
|
||||||
|
|
||||||
normZFlip = -1.0f*matrixBasePtr[0x5]; // coordinate system m13 component
|
GLfloat normZFlip = -1.0f*matrixBasePtr[0x5]; // coordinate system m13 component
|
||||||
|
|
||||||
if (normZFlip*(n[0]*P->n[0]+n[1]*P->n[1]+n[2]*P->n[2]) >= 0.0) // clockwise winding confirmed
|
if (normZFlip*(n[0]*P->n[0]+n[1]*P->n[1]+n[2]*P->n[2]) >= 0.0) // clockwise winding confirmed
|
||||||
{
|
{
|
||||||
// Store the first triangle
|
// Store the first triangle
|
||||||
for (i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
InsertVertex(Cache, &(P->Vert[i]), P, 1.0f);
|
InsertVertex(Cache, &(P->Vert[i]), P, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doubleSided) // store backside as counter-clockwise
|
if (doubleSided) // store backside as counter-clockwise
|
||||||
{
|
{
|
||||||
for (i = 2; i >=0; i--)
|
for (int i = 2; i >=0; i--)
|
||||||
{
|
{
|
||||||
InsertVertex(Cache, &(P->Vert[i]), P, -1.0f);
|
InsertVertex(Cache, &(P->Vert[i]), P, -1.0f);
|
||||||
}
|
}
|
||||||
|
@ -624,14 +617,14 @@ bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
}
|
}
|
||||||
else // counterclockwise winding, reverse it
|
else // counterclockwise winding, reverse it
|
||||||
{
|
{
|
||||||
for (i = 2; i >=0; i--)
|
for (int i = 2; i >=0; i--)
|
||||||
{
|
{
|
||||||
InsertVertex(Cache, &(P->Vert[i]), P, 1.0f);
|
InsertVertex(Cache, &(P->Vert[i]), P, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doubleSided) // store backside as clockwise
|
if (doubleSided) // store backside as clockwise
|
||||||
{
|
{
|
||||||
for (i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
InsertVertex(Cache, &(P->Vert[i]), P, -1.0f);
|
InsertVertex(Cache, &(P->Vert[i]), P, -1.0f);
|
||||||
}
|
}
|
||||||
|
@ -658,9 +651,7 @@ bool CLegacy3D::InsertPolygon(ModelCache *Cache, const Poly *P)
|
||||||
// Begins caching a new model by resetting to the start of the local vertex buffer
|
// Begins caching a new model by resetting to the start of the local vertex buffer
|
||||||
struct VBORef *CLegacy3D::BeginModel(ModelCache *Cache)
|
struct VBORef *CLegacy3D::BeginModel(ModelCache *Cache)
|
||||||
{
|
{
|
||||||
struct VBORef *Model;
|
size_t m = Cache->numModels;
|
||||||
|
|
||||||
unsigned m = Cache->numModels;
|
|
||||||
|
|
||||||
// Determine whether we've exceeded the model cache limits (caller will have to recache)
|
// Determine whether we've exceeded the model cache limits (caller will have to recache)
|
||||||
if (m >= Cache->maxModels)
|
if (m >= Cache->maxModels)
|
||||||
|
@ -669,10 +660,10 @@ struct VBORef *CLegacy3D::BeginModel(ModelCache *Cache)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model = &(Cache->Models[m]);
|
struct VBORef *Model = &(Cache->Models[m]);
|
||||||
|
|
||||||
// Reset to the beginning of the local vertex buffer
|
// Reset to the beginning of the local vertex buffer
|
||||||
for (int i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
Cache->curVertIdx[i] = 0;
|
Cache->curVertIdx[i] = 0;
|
||||||
|
|
||||||
// Clear the VBO reference to 0 and clear texture references
|
// Clear the VBO reference to 0 and clear texture references
|
||||||
|
@ -691,7 +682,7 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
||||||
int m = Cache->numModels++;
|
int m = Cache->numModels++;
|
||||||
|
|
||||||
// Record the number of vertices, completing the VBORef
|
// Record the number of vertices, completing the VBORef
|
||||||
for (int i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
Model->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
|
||||||
|
@ -730,10 +721,6 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
||||||
|
|
||||||
struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOffset, const UINT32 *data)
|
struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOffset, const UINT32 *data)
|
||||||
{
|
{
|
||||||
Vertex Prev[4]; // previous vertices
|
|
||||||
int numPolys = 0;
|
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
// Sega Rally 2 bad models
|
// Sega Rally 2 bad models
|
||||||
//if (lutIdx == 0x27a1 || lutIdx == 0x21e0)
|
//if (lutIdx == 0x27a1 || lutIdx == 0x21e0)
|
||||||
// return FAIL;
|
// return FAIL;
|
||||||
|
@ -747,17 +734,13 @@ struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOf
|
||||||
return NULL; // too many models!
|
return NULL; // too many models!
|
||||||
|
|
||||||
// Cache all polygons
|
// Cache all polygons
|
||||||
|
Vertex Prev[4]; // previous vertices
|
||||||
|
int numPolys = 0;
|
||||||
|
bool done = false;
|
||||||
while (!done)
|
while (!done)
|
||||||
{
|
{
|
||||||
Poly P; // current polygon
|
|
||||||
GLfloat mag;
|
|
||||||
GLfloat uvScale;
|
|
||||||
int texEnable, texFormat, texWidth, texHeight, texPage, texBaseX, texBaseY;
|
|
||||||
unsigned i, j, vmask;
|
|
||||||
UINT32 ix, iy, iz, it;
|
|
||||||
bool validPoly;
|
|
||||||
|
|
||||||
// Set current header pointer (header is 7 words)
|
// Set current header pointer (header is 7 words)
|
||||||
|
Poly P; // current polygon
|
||||||
P.header = data;
|
P.header = data;
|
||||||
data += 7; // data will now point to first vertex
|
data += 7; // data will now point to first vertex
|
||||||
if (P.header[6]==0)// || P.header[0]==0)
|
if (P.header[6]==0)// || P.header[0]==0)
|
||||||
|
@ -767,44 +750,21 @@ struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOf
|
||||||
// vertices (very large values or 0). Ignoring polygons with these bits set
|
// vertices (very large values or 0). Ignoring polygons with these bits set
|
||||||
// seems to fix the problem. Perhaps these polygons exist for alignment
|
// seems to fix the problem. Perhaps these polygons exist for alignment
|
||||||
// purposes or are another type of entity altogether?
|
// purposes or are another type of entity altogether?
|
||||||
validPoly = (P.header[0] & 0x300) != 0x300;
|
bool validPoly = (P.header[0] & 0x300) != 0x300;
|
||||||
// if (!validPoly)
|
|
||||||
|
|
||||||
{
|
|
||||||
//printf("Invalid poly:\n");
|
|
||||||
//for (int i = 0; i < 7; i++)
|
|
||||||
// printf(" %d: %08x\n", i, P.header[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain basic polygon parameters
|
// Obtain basic polygon parameters
|
||||||
done = P.header[1]&4; // last polygon?
|
done = P.header[1]&4; // last polygon?
|
||||||
P.numVerts = (P.header[0]&0x40)?4:3;
|
P.numVerts = (P.header[0]&0x40)?4:3;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if ((P.header[0] & 0xf) && numPolys == 0)
|
|
||||||
{
|
|
||||||
validPoly=false;
|
|
||||||
printf("LNK=%x num=%d\n", P.header[0] & 0xf, P.numVerts);
|
|
||||||
}
|
|
||||||
if (lutIdx==0x8c0955)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 7; i++)
|
|
||||||
printf("%d %d: %08x\n", numPolys, i, P.header[i]);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Texture data
|
// Texture data
|
||||||
texEnable = P.header[6]&0x04000000;
|
int texEnable = P.header[6]&0x04000000;
|
||||||
texFormat = (P.header[6]>>7)&7;
|
int texFormat = (P.header[6]>>7)&7;
|
||||||
texWidth = (32<<((P.header[3]>>3)&7));
|
int texWidth = (32<<((P.header[3]>>3)&7));
|
||||||
texHeight = (32<<((P.header[3]>>0)&7));
|
int texHeight = (32<<((P.header[3]>>0)&7));
|
||||||
texPage = (P.header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
|
int 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))) + (int)texOffsetXY[0];
|
int texBaseX = ((32*(((P.header[4]&0x1F)<<1)|((P.header[5]>>7)&1))) + (int)texOffsetXY[0]) & 2047;
|
||||||
texBaseY = (32*(P.header[5]&0x1F)+texPage) + (int)texOffsetXY[1];
|
int texBaseY = ((32*(P.header[5]&0x1F)+texPage) + (int)texOffsetXY[1]) & 2047;
|
||||||
texBaseX &= 2047;
|
GLfloat uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f);
|
||||||
texBaseY &= 2047;
|
|
||||||
uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f);
|
|
||||||
|
|
||||||
// Determine whether this is an alpha polygon (TODO: when testing textures, test if texturing enabled? Might not matter)
|
// Determine whether this is an alpha polygon (TODO: when testing textures, test if texturing enabled? Might not matter)
|
||||||
if (((P.header[6]&0x00800000)==0) || // translucent polygon
|
if (((P.header[6]&0x00800000)==0) || // translucent polygon
|
||||||
|
@ -844,10 +804,9 @@ if (lutIdx==0x8c0955)
|
||||||
P.n[2] = (GLfloat) (((INT32)P.header[3])>>8) * (1.0f/4194304.0f);
|
P.n[2] = (GLfloat) (((INT32)P.header[3])>>8) * (1.0f/4194304.0f);
|
||||||
|
|
||||||
// Fetch reused vertices according to bitfield, then new verts
|
// Fetch reused vertices according to bitfield, then new verts
|
||||||
i = 0;
|
size_t j = 0;
|
||||||
j = 0;
|
size_t vmask = 1;
|
||||||
vmask = 1;
|
for (size_t i = 0; i < 4; i++) // up to 4 reused vertices
|
||||||
for (i = 0; i < 4; i++) // up to 4 reused vertices
|
|
||||||
{
|
{
|
||||||
if ((P.header[0x00]&vmask))
|
if ((P.header[0x00]&vmask))
|
||||||
{
|
{
|
||||||
|
@ -860,10 +819,10 @@ if (lutIdx==0x8c0955)
|
||||||
for (; j < P.numVerts; j++) // remaining vertices are new and defined here
|
for (; j < P.numVerts; j++) // remaining vertices are new and defined here
|
||||||
{
|
{
|
||||||
// Fetch vertices
|
// Fetch vertices
|
||||||
ix = data[0];
|
UINT32 ix = data[0];
|
||||||
iy = data[1];
|
UINT32 iy = data[1];
|
||||||
iz = data[2];
|
UINT32 iz = data[2];
|
||||||
it = data[3];
|
UINT32 it = data[3];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Check for bad vertices (Sega Rally 2)
|
// Check for bad vertices (Sega Rally 2)
|
||||||
|
@ -886,7 +845,7 @@ if (lutIdx==0x8c0955)
|
||||||
data += 4;
|
data += 4;
|
||||||
|
|
||||||
// Normalize the vertex normal
|
// Normalize the vertex normal
|
||||||
mag = sqrt(P.Vert[j].n[0]*P.Vert[j].n[0]+P.Vert[j].n[1]*P.Vert[j].n[1]+P.Vert[j].n[2]*P.Vert[j].n[2]);
|
GLfloat mag = sqrt(P.Vert[j].n[0]*P.Vert[j].n[0]+P.Vert[j].n[1]*P.Vert[j].n[1]+P.Vert[j].n[2]*P.Vert[j].n[2]);
|
||||||
P.Vert[j].n[0] /= mag;
|
P.Vert[j].n[0] /= mag;
|
||||||
P.Vert[j].n[1] /= mag;
|
P.Vert[j].n[1] /= mag;
|
||||||
P.Vert[j].n[2] /= mag;
|
P.Vert[j].n[2] /= mag;
|
||||||
|
@ -895,7 +854,7 @@ if (lutIdx==0x8c0955)
|
||||||
if (validPoly)
|
if (validPoly)
|
||||||
{
|
{
|
||||||
// Copy current vertices into previous vertex array
|
// Copy current vertices into previous vertex array
|
||||||
for (i = 0; i < 4; i++)
|
for (size_t i = 0; i < 4; i++)
|
||||||
Prev[i] = P.Vert[i];
|
Prev[i] = P.Vert[i];
|
||||||
|
|
||||||
// Copy this polygon into the model buffer
|
// Copy this polygon into the model buffer
|
||||||
|
@ -941,9 +900,9 @@ struct VBORef *CLegacy3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texO
|
||||||
void CLegacy3D::ClearModelCache(ModelCache *Cache)
|
void CLegacy3D::ClearModelCache(ModelCache *Cache)
|
||||||
{
|
{
|
||||||
Cache->vboCurOffset = 0;
|
Cache->vboCurOffset = 0;
|
||||||
for (int i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
Cache->curVertIdx[i] = 0;
|
Cache->curVertIdx[i] = 0;
|
||||||
for (int i = 0; i < Cache->numModels; i++)
|
for (size_t i = 0; i < Cache->numModels; i++)
|
||||||
Cache->lut[Cache->Models[i].lutIdx] = -1;
|
Cache->lut[Cache->Models[i].lutIdx] = -1;
|
||||||
|
|
||||||
Cache->numModels = 0;
|
Cache->numModels = 0;
|
||||||
|
@ -954,10 +913,6 @@ bool CLegacy3D::CreateModelCache(ModelCache *Cache, unsigned vboMaxVerts,
|
||||||
unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries,
|
unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries,
|
||||||
unsigned displayListSize, bool isDynamic)
|
unsigned displayListSize, bool isDynamic)
|
||||||
{
|
{
|
||||||
unsigned i;
|
|
||||||
int vboBytes, localBytes;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
Cache->dynamic = isDynamic;
|
Cache->dynamic = isDynamic;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -972,11 +927,11 @@ bool CLegacy3D::CreateModelCache(ModelCache *Cache, unsigned vboMaxVerts,
|
||||||
glGenBuffers(1, &(Cache->vboID));
|
glGenBuffers(1, &(Cache->vboID));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
|
||||||
|
|
||||||
vboBytes = vboMaxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat);
|
size_t vboBytes = vboMaxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat);
|
||||||
localBytes = localMaxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat);
|
size_t localBytes = localMaxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat);
|
||||||
|
|
||||||
// Try allocating until size is
|
// Try allocating until size is
|
||||||
success = false;
|
bool success = false;
|
||||||
while (vboBytes >= localBytes)
|
while (vboBytes >= localBytes)
|
||||||
{
|
{
|
||||||
glBufferData(GL_ARRAY_BUFFER, vboBytes, 0, isDynamic?GL_STREAM_DRAW:GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vboBytes, 0, isDynamic?GL_STREAM_DRAW:GL_STATIC_DRAW);
|
||||||
|
@ -1006,7 +961,7 @@ bool CLegacy3D::CreateModelCache(ModelCache *Cache, unsigned vboMaxVerts,
|
||||||
Cache->vboCurOffset = 0;
|
Cache->vboCurOffset = 0;
|
||||||
|
|
||||||
// Attempt to allocate space for local VBO
|
// Attempt to allocate space for local VBO
|
||||||
for (i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
Cache->verts[i] = new(std::nothrow) GLfloat[localMaxVerts*VBO_VERTEX_SIZE];
|
Cache->verts[i] = new(std::nothrow) GLfloat[localMaxVerts*VBO_VERTEX_SIZE];
|
||||||
Cache->curVertIdx[i] = 0;
|
Cache->curVertIdx[i] = 0;
|
||||||
|
@ -1035,7 +990,7 @@ bool CLegacy3D::CreateModelCache(ModelCache *Cache, unsigned vboMaxVerts,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear LUT (MUST be done here because ClearModelCache() won't do it for dynamic models)
|
// Clear LUT (MUST be done here because ClearModelCache() won't do it for dynamic models)
|
||||||
for (i = 0; i < numLUTEntries; i++)
|
for (size_t i = 0; i < numLUTEntries; i++)
|
||||||
Cache->lut[i] = -1;
|
Cache->lut[i] = -1;
|
||||||
|
|
||||||
// All good!
|
// All good!
|
||||||
|
@ -1046,7 +1001,7 @@ void CLegacy3D::DestroyModelCache(ModelCache *Cache)
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &(Cache->vboID));
|
glDeleteBuffers(1, &(Cache->vboID));
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (Cache->verts[i] != NULL)
|
if (Cache->verts[i] != NULL)
|
||||||
delete [] Cache->verts[i];
|
delete [] Cache->verts[i];
|
||||||
|
|
|
@ -206,7 +206,7 @@ bool CTextureRefs::UpdateHashCapacity(unsigned capacity)
|
||||||
m_hashEntries = new(std::nothrow) HashEntry*[capacity];
|
m_hashEntries = new(std::nothrow) HashEntry*[capacity];
|
||||||
if (!m_hashEntries)
|
if (!m_hashEntries)
|
||||||
return false;
|
return false;
|
||||||
memset(m_hashEntries, NULL, capacity * sizeof(HashEntry*));
|
memset(m_hashEntries, 0, capacity * sizeof(HashEntry*));
|
||||||
if (oldEntries)
|
if (oldEntries)
|
||||||
{
|
{
|
||||||
// Redistribute entries into new entries array
|
// Redistribute entries into new entries array
|
||||||
|
|
Loading…
Reference in a new issue