Harmless math warning fixes. map->unordered_map in CNew3D::CacheModel. Avoid general aliasing problems (using bit_cast or the recommended/optimized-away memcpy).

This commit is contained in:
toxieainc 2022-08-19 21:34:22 +02:00 committed by trzy
parent 0eef09ba2b
commit 22ffb5cc19
12 changed files with 300 additions and 273 deletions

View file

@ -166,11 +166,15 @@
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
namespace Legacy3D { namespace Legacy3D {
// Microsoft doesn't provide isnan() and isinf() // Microsoft doesn't provide isnan() and isinf()
#ifdef _MSC_VER #ifdef _MSC_VER
#include <float.h> #include <cfloat>
#define ISNAN(x) (_isnan(x)) #define ISNAN(x) (_isnan(x))
#define ISINF(x) (!_finite(x)) #define ISINF(x) (!_finite(x))
#else #else
@ -847,9 +851,9 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri, bool wideScreen)
int vpHeight = (vpnode[0x14]>>18)&0x3FFF; // height (14.2) int vpHeight = (vpnode[0x14]>>18)&0x3FFF; // height (14.2)
// Field of view and clipping // Field of view and clipping
GLfloat vpTopAngle = (float) asin(*(float *)&vpnode[0x0E]); // FOV Y upper half-angle (radians) GLfloat vpTopAngle = asinf(uint_as_float(vpnode[0x0E])); // FOV Y upper half-angle (radians)
GLfloat vpBotAngle = (float) asin(*(float *)&vpnode[0x12]); // FOV Y lower half-angle GLfloat vpBotAngle = asinf(uint_as_float(vpnode[0x12])); // FOV Y lower half-angle
GLfloat fovYDegrees = (vpTopAngle+vpBotAngle)*(float)(180.0/3.14159265358979323846); GLfloat fovYDegrees = (vpTopAngle+vpBotAngle)*(float)(180.0/M_PI);
// 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)
@ -929,35 +933,35 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri, bool wideScreen)
UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF; UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF;
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
InitMatrixStack(matrixBase); InitMatrixStack(matrixBase);
// Safeguard: weird coordinate system matrices usually indicate scenes that will choke the renderer // Safeguard: weird coordinate system matrices usually indicate scenes that will choke the renderer
if (NULL != matrixBasePtr) if (NULL != matrixBasePtr)
{ {
float m21, m32, m13; float m21, m32, m13;
// Get the three elements that are usually set and see if their magnitudes are 1 // Get the three elements that are usually set and see if their magnitudes are 1
m21 = matrixBasePtr[6]; m21 = matrixBasePtr[6];
m32 = matrixBasePtr[10]; m32 = matrixBasePtr[10];
m13 = matrixBasePtr[5]; m13 = matrixBasePtr[5];
m21 *= m21; m21 *= m21;
m32 *= m32; m32 *= m32;
m13 *= m13; m13 *= m13;
if ((m21>1.05) || (m21<0.95)) if ((m21>1.05f) || (m21<0.95f))
return; return;
if ((m32>1.05) || (m32<0.95)) if ((m32>1.05f) || (m32<0.95f))
return; return;
if ((m13>1.05) || (m13<0.95)) if ((m13>1.05f) || (m13<0.95f))
return; return;
} }
// Render // Render
AppendDisplayList(&VROMCache, true, 0); // add a viewport display list node AppendDisplayList(&VROMCache, true, 0); // add a viewport display list node
AppendDisplayList(&PolyCache, true, 0); AppendDisplayList(&PolyCache, true, 0);
stackDepth = 0; stackDepth = 0;
listDepth = 0; listDepth = 0;
// Descend down the node link: Use recursive traversal // Descend down the node link: Use recursive traversal
DescendNodePtr(nodeAddr); DescendNodePtr(nodeAddr);
} }

View file

@ -725,7 +725,7 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
// Specular shininess // Specular shininess
GLfloat specularCoefficient = (GLfloat) ((P->header[0]>>26) & 0x3F) * (1.0f/63.0f); GLfloat specularCoefficient = (GLfloat) ((P->header[0]>>26) & 0x3F) * (1.0f/63.0f);
int shinyBits = (P->header[6] >> 5) & 3; int shinyBits = (P->header[6] >> 5) & 3;
float shininess = std::pow(2.0f, 1.f + shinyBits); float shininess = std::exp2f(1 + shinyBits);
if (!(P->header[0]&0x80)) //|| (shininess == 0)) // bit 0x80 seems to enable specular lighting if (!(P->header[0]&0x80)) //|| (shininess == 0)) // bit 0x80 seems to enable specular lighting
{ {
specularCoefficient = 0.; // disable specularCoefficient = 0.; // disable
@ -1224,7 +1224,7 @@ bool CLegacy3D::CreateModelCache(ModelCache *Cache, unsigned vboMaxVerts,
{ {
// Last ditch attempt: try the local buffer size // Last ditch attempt: try the local buffer size
vboBytes = localBytes; vboBytes = localBytes;
glBufferData(GL_ARRAY_BUFFER, vboBytes, 0, isDynamic?GL_STREAM_DRAW:GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, vboBytes, nullptr, isDynamic?GL_STREAM_DRAW:GL_STATIC_DRAW);
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
return ErrorLog("OpenGL was unable to provide a %s vertex buffer.", isDynamic?"dynamic":"static"); return ErrorLog("OpenGL was unable to provide a %s vertex buffer.", isDynamic?"dynamic":"static");
} }

View file

@ -3,7 +3,7 @@
#include <utility> #include <utility>
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265359 #define M_PI 3.1415926535897932384626433832795
#endif #endif
namespace New3D { namespace New3D {
@ -17,10 +17,10 @@ void Mat4::LoadIdentity()
{ {
float *m = currentMatrix; float *m = currentMatrix;
m[0] = 1; m[4] = 0; m[8 ] = 0; m[12] = 0; m[0] = 1.f; m[4] = 0.f; m[8 ] = 0.f; m[12] = 0.f;
m[1] = 0; m[5] = 1; m[9 ] = 0; m[13] = 0; m[1] = 0.f; m[5] = 1.f; m[9 ] = 0.f; m[13] = 0.f;
m[2] = 0; m[6] = 0; m[10] = 1; m[14] = 0; m[2] = 0.f; m[6] = 0.f; m[10] = 1.f; m[14] = 0.f;
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1; m[3] = 0.f; m[7] = 0.f; m[11] = 0.f; m[15] = 1.f;
} }
void Mat4::MultiMatrices(const float a[16], const float b[16], float r[16]) void Mat4::MultiMatrices(const float a[16], const float b[16], float r[16])
@ -29,8 +29,7 @@ void Mat4::MultiMatrices(const float a[16], const float b[16], float r[16])
#define B(row,col) b[(col<<2)+row] #define B(row,col) b[(col<<2)+row]
#define P(row,col) r[(col<<2)+row] #define P(row,col) r[(col<<2)+row]
int i; for (int i = 0; i < 4; i++) {
for (i = 0; i < 4; i++) {
const float ai0 = A(i, 0), ai1 = A(i, 1), ai2 = A(i, 2), ai3 = A(i, 3); const float ai0 = A(i, 0), ai1 = A(i, 1), ai2 = A(i, 2), ai3 = A(i, 3);
P(i, 0) = ai0 * B(0, 0) + ai1 * B(1, 0) + ai2 * B(2, 0) + ai3 * B(3, 0); P(i, 0) = ai0 * B(0, 0) + ai1 * B(1, 0) + ai2 * B(2, 0) + ai3 * B(3, 0);
P(i, 1) = ai0 * B(0, 1) + ai1 * B(1, 1) + ai2 * B(2, 1) + ai3 * B(3, 1); P(i, 1) = ai0 * B(0, 1) + ai1 * B(1, 1) + ai2 * B(2, 1) + ai3 * B(3, 1);
@ -56,25 +55,25 @@ void Mat4::Translate(float x, float y, float z)
float m[16]; float m[16];
//========== //==========
m[0] = 1; m[0] = 1.f;
m[1] = 0; m[1] = 0.f;
m[2] = 0; m[2] = 0.f;
m[3] = 0; m[3] = 0.f;
m[4] = 0; m[4] = 0.f;
m[5] = 1; m[5] = 1.f;
m[6] = 0; m[6] = 0.f;
m[7] = 0; m[7] = 0.f;
m[8] = 0; m[8] = 0.f;
m[9] = 0; m[9] = 0.f;
m[10] = 1; m[10] = 1.f;
m[11] = 0; m[11] = 0.f;
m[12] = x; m[12] = x;
m[13] = y; m[13] = y;
m[14] = z; m[14] = z;
m[15] = 1; m[15] = 1.f;
Mat4::MultiMatrices(currentMatrix, m, currentMatrix); Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
} }
@ -86,155 +85,137 @@ void Mat4::Scale(float x, float y, float z)
//========== //==========
m[0] = x; m[0] = x;
m[1] = 0; m[1] = 0.f;
m[2] = 0; m[2] = 0.f;
m[3] = 0; m[3] = 0.f;
m[4] = 0; m[4] = 0.f;
m[5] = y; m[5] = y;
m[6] = 0; m[6] = 0.f;
m[7] = 0; m[7] = 0.f;
m[8] = 0; m[8] = 0.f;
m[9] = 0; m[9] = 0.f;
m[10] = z; m[10] = z;
m[11] = 0; m[11] = 0.f;
m[12] = 0; m[12] = 0.f;
m[13] = 0; m[13] = 0.f;
m[14] = 0; m[14] = 0.f;
m[15] = 1; m[15] = 1.f;
Mat4::MultiMatrices(currentMatrix, m, currentMatrix); Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
} }
void Mat4::Rotate(float angle, float x, float y, float z) void Mat4::Rotate(float angle, float x, float y, float z)
{ {
//===========
float c;
float s;
float m[16];
//===========
// normalise vector first // normalise vector first
{ {
//======== //========
float len; float inv_len;
//======== //========
len = std::sqrt(x * x + y * y + z * z); inv_len = 1.f/std::sqrt(x * x + y * y + z * z);
x /= len; x *= inv_len;
y /= len; y *= inv_len;
z /= len; z *= inv_len;
} }
c = std::cos(angle*3.14159265f / 180.0f); float c = std::cos(angle*(float)(M_PI / 180.0));
s = std::sin(angle*3.14159265f / 180.0f); float s = std::sin(angle*(float)(M_PI / 180.0));
m[0] = (x*x) * (1 - c) + c; float m[16];
m[1] = (y*x) * (1 - c) + (z*s); m[0] = (x*x) * (1.f - c) + c;
m[2] = (x*z) * (1 - c) - (y*s); m[1] = (y*x) * (1.f - c) + (z*s);
m[3] = 0; m[2] = (x*z) * (1.f - c) - (y*s);
m[3] = 0.f;
m[4] = (x*y) * (1 - c) - (z*s); m[4] = (x*y) * (1.f - c) - (z*s);
m[5] = (y*y) * (1 - c) + c; m[5] = (y*y) * (1.f - c) + c;
m[6] = (y*z) * (1 - c) + (x*s); m[6] = (y*z) * (1.f - c) + (x*s);
m[7] = 0; m[7] = 0.f;
m[8] = (x*z) * (1 - c) + (y*s); m[8] = (x*z) * (1.f - c) + (y*s);
m[9] = (y*z) * (1 - c) - (x*s); m[9] = (y*z) * (1.f - c) - (x*s);
m[10] = (z*z) * (1 - c) + c; m[10] = (z*z) * (1.f - c) + c;
m[11] = 0; m[11] = 0.f;
m[12] = 0; m[12] = 0.f;
m[13] = 0; m[13] = 0.f;
m[14] = 0; m[14] = 0.f;
m[15] = 1; m[15] = 1.f;
Mat4::MultiMatrices(currentMatrix, m, currentMatrix); Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
} }
void Mat4::Frustum(float left, float right, float bottom, float top, float nearVal, float farVal) void Mat4::Frustum(float left, float right, float bottom, float top, float nearVal, float farVal)
{ {
//===================== float x = (2.0F*nearVal) / (right - left);
float y = (2.0F*nearVal) / (top - bottom);
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(farVal + nearVal) / (farVal - nearVal);
float d = -(2.0F*farVal*nearVal) / (farVal - nearVal);
float m[16]; float m[16];
float x, y, a, b, c, d;
//=====================
x = (2.0F*nearVal) / (right - left);
y = (2.0F*nearVal) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farVal + nearVal) / (farVal - nearVal);
d = -(2.0F*farVal*nearVal) / (farVal - nearVal);
m[0] = x; m[0] = x;
m[1] = 0; m[1] = 0.f;
m[2] = 0; m[2] = 0.f;
m[3] = 0; m[3] = 0.f;
m[4] = 0; m[4] = 0.f;
m[5] = y; m[5] = y;
m[6] = 0; m[6] = 0.f;
m[7] = 0; m[7] = 0.f;
m[8] = a; m[8] = a;
m[9] = b; m[9] = b;
m[10] = c; m[10] = c;
m[11] = -1; m[11] = -1.f;
m[12] = 0; m[12] = 0.f;
m[13] = 0; m[13] = 0.f;
m[14] = d; m[14] = d;
m[15] = 0; m[15] = 0.f;
Mat4::MultiMatrices(currentMatrix, m, currentMatrix); Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
} }
void Mat4::Perspective(float fovy, float aspect, float zNear, float zFar) void Mat4::Perspective(float fovy, float aspect, float zNear, float zFar)
{ {
//========= float ymax = zNear * tanf(fovy * (float)(M_PI / 360.0));
float ymax; float xmax = ymax * aspect;
float xmax;
//=========
ymax = zNear * tanf(fovy * (float)M_PI / 360.0f);
xmax = ymax * aspect;
Frustum(-xmax, xmax, -ymax, ymax, zNear, zFar); Frustum(-xmax, xmax, -ymax, ymax, zNear, zFar);
} }
void Mat4::Ortho(float left, float right, float bottom, float top, float nearVal, float farVal) void Mat4::Ortho(float left, float right, float bottom, float top, float nearVal, float farVal)
{ {
//================ float tx = -(right + left) / (right - left);
float ty = -(top + bottom) / (top - bottom);
float tz = -(farVal + nearVal) / (farVal - nearVal);
float m[16]; float m[16];
float tx, ty, tz; m[0] = 2.f/(right-left);
//================ m[1] = 0.f;
m[2] = 0.f;
m[3] = 0.f;
tx = -(right + left) / (right - left); m[4] = 0.f;
ty = -(top + bottom) / (top - bottom); m[5] = 2.f/(top-bottom);
tz = -(farVal + nearVal) / (farVal - nearVal); m[6] = 0.f;
m[7] = 0.f;
m[0] = 2/(right-left); m[8] = 0.f;
m[1] = 0; m[9] = 0.f;
m[2] = 0; m[10] = -2.f/(farVal-nearVal);
m[3] = 0; m[11] = 0.f;
m[4] = 0;
m[5] = 2/(top-bottom);
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = -2/(farVal-nearVal);
m[11] = 0;
m[12] = tx; m[12] = tx;
m[13] = ty; m[13] = ty;
m[14] = tz; m[14] = tz;
m[15] = 1; m[15] = 1.f;
Mat4::MultiMatrices(currentMatrix, m, currentMatrix); Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
} }
@ -324,4 +305,4 @@ void Mat4::Release()
m_vMat4.clear(); m_vMat4.clear();
} }
}// New3D }// New3D

View file

@ -1,20 +1,21 @@
#include "New3D.h" #include "New3D.h"
#include "Texture.h" #include "Texture.h"
#include "Vec.h" #include "Vec.h"
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <string.h> #include <cstring>
#include <unordered_map>
#include "R3DFloat.h" #include "R3DFloat.h"
#define MAX_RAM_VERTS 300000 #define MAX_RAM_VERTS 300000
#define MAX_ROM_VERTS 1500000 #define MAX_ROM_VERTS 1500000
#define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (1.0F/255.0f)) #define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (float)(1.0/255.0))
namespace New3D { namespace New3D {
CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName) CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName)
: m_r3dShader(config), : m_r3dShader(config),
m_r3dScrollFog(config), m_r3dScrollFog(config),
m_gameName(gameName) m_gameName(gameName)
@ -26,7 +27,7 @@ CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName)
m_textureRAM = nullptr; m_textureRAM = nullptr;
m_sunClamp = true; m_sunClamp = true;
m_shadeIsSigned = true; m_shadeIsSigned = true;
m_numPolyVerts = 3; m_numPolyVerts = 3;
m_primType = GL_TRIANGLES; m_primType = GL_TRIANGLES;
if (config["QuadRendering"].ValueAs<bool>()) { if (config["QuadRendering"].ValueAs<bool>()) {
@ -72,8 +73,8 @@ void CNew3D::SetStepping(int stepping)
bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam) bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam)
{ {
// Resolution and offset within physical display area // Resolution and offset within physical display area
m_xRatio = xRes / 496.0f; m_xRatio = xRes * (float)(1.0 / 496.0);
m_yRatio = yRes / 384.0f; m_yRatio = yRes * (float)(1.0 / 384.0);
m_xOffs = xOffset; m_xOffs = xOffset;
m_yOffs = yOffset; m_yOffs = yOffset;
m_xRes = xRes; m_xRes = xRes;
@ -129,7 +130,7 @@ void CNew3D::DrawScrollFog()
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for (auto &n : m_nodes) { for (auto &n : m_nodes) {
if (n.viewport.priority == i) { if (n.viewport.priority == i) {
if (n.viewport.scrollFog) { if (n.viewport.scrollFog != 0.f) {
rgba[0] = n.viewport.fogParams[0]; rgba[0] = n.viewport.fogParams[0];
rgba[1] = n.viewport.fogParams[1]; rgba[1] = n.viewport.fogParams[1];
rgba[2] = n.viewport.fogParams[2]; rgba[2] = n.viewport.fogParams[2];
@ -149,7 +150,7 @@ CheckScroll:
if (n.viewport.priority == i) { if (n.viewport.priority == i) {
//if we have a fog density value //if we have a fog density value
if (n.viewport.fogParams[3]) { if (n.viewport.fogParams[3] != 0.f) {
if (rgba[0] == n.viewport.fogParams[0] && if (rgba[0] == n.viewport.fogParams[0] &&
rgba[1] == n.viewport.fogParams[1] && rgba[1] == n.viewport.fogParams[1] &&
@ -246,7 +247,7 @@ bool CNew3D::SkipLayer(int layer)
{ {
for (const auto &n : m_nodes) { for (const auto &n : m_nodes) {
if (n.viewport.priority == layer) { if (n.viewport.priority == layer) {
if (n.models.size()) { if (!n.models.empty()) {
return false; return false;
} }
} }
@ -283,7 +284,7 @@ void CNew3D::SetRenderStates()
glDisable (GL_BLEND); glDisable (GL_BLEND);
glStencilFunc (GL_EQUAL, 0, 0xFF); // basically stencil test passes if the value is zero glStencilFunc (GL_EQUAL, 0, 0xFF); // basically stencil test passes if the value is zero
glStencilOp (GL_KEEP, GL_INCR, GL_INCR); // if the stencil test passes, we incriment the value glStencilOp (GL_KEEP, GL_INCR, GL_INCR); // if the stencil test passes, we increment the value
glStencilMask (0xFF); glStencilMask (0xFF);
} }
@ -318,7 +319,7 @@ void CNew3D::RenderFrame(void)
} }
// release any resources from last frame // release any resources from last frame
m_polyBufferRam.clear(); // clear dyanmic model memory buffer m_polyBufferRam.clear(); // clear dynamic model memory buffer
m_nodes.clear(); // memory will grow during the object life time, that's fine, no need to shrink to fit m_nodes.clear(); // memory will grow during the object life time, that's fine, no need to shrink to fit
m_modelMat.Release(); // would hope we wouldn't need this but no harm in checking m_modelMat.Release(); // would hope we wouldn't need this but no harm in checking
m_nodeAttribs.Reset(); m_nodeAttribs.Reset();
@ -329,7 +330,7 @@ void CNew3D::RenderFrame(void)
m_vbo.Bind(true); m_vbo.Bind(true);
m_vbo.BufferSubData(MAX_ROM_VERTS*sizeof(FVertex), m_polyBufferRam.size()*sizeof(FVertex), m_polyBufferRam.data()); // upload all the dynamic data to GPU in one go m_vbo.BufferSubData(MAX_ROM_VERTS*sizeof(FVertex), m_polyBufferRam.size()*sizeof(FVertex), m_polyBufferRam.data()); // upload all the dynamic data to GPU in one go
if (m_polyBufferRom.size()) { if (!m_polyBufferRom.empty()) {
// sync rom memory with vbo // sync rom memory with vbo
int romBytes = (int)m_polyBufferRom.size() * sizeof(FVertex); int romBytes = (int)m_polyBufferRom.size() * sizeof(FVertex);
@ -355,10 +356,6 @@ void CNew3D::RenderFrame(void)
for (int pri = 0; pri <= 3; pri++) { for (int pri = 0; pri <= 3; pri++) {
//==============
bool hasOverlay;
//==============
if (SkipLayer(pri)) continue; if (SkipLayer(pri)) continue;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -367,12 +364,12 @@ void CNew3D::RenderFrame(void)
m_r3dFrameBuffers.SetFBO(Layer::colour); m_r3dFrameBuffers.SetFBO(Layer::colour);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
SetRenderStates(); SetRenderStates();
m_r3dShader.DiscardAlpha(true); // discard all translucent pixels in opaque pass m_r3dShader.DiscardAlpha(true); // discard all translucent pixels in opaque pass
m_r3dFrameBuffers.SetFBO(Layer::colour); m_r3dFrameBuffers.SetFBO(Layer::colour);
hasOverlay = RenderScene(pri, renderOverlay, Layer::colour); bool hasOverlay = RenderScene(pri, renderOverlay, Layer::colour);
if (!renderOverlay && ProcessLos(pri)) { if (!renderOverlay && ProcessLos(pri)) {
ProcessLos(pri); ProcessLos(pri);
@ -514,8 +511,8 @@ void CNew3D::DescendCullingNode(UINT32 addr)
UINT16 uCullRadius; UINT16 uCullRadius;
float fCullRadius; float fCullRadius;
UINT16 uBlendRadius; UINT16 uBlendRadius;
float fBlendRadius; //float fBlendRadius;
UINT8 lodTablePointer; //UINT8 lodTablePointer;
NodeType nodeType; NodeType nodeType;
if (m_nodeAttribs.StackLimit()) { if (m_nodeAttribs.StackLimit()) {
@ -533,7 +530,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
child1Ptr = node[0x07 - m_offset] & 0x7FFFFFF; // mask colour table bits child1Ptr = node[0x07 - m_offset] & 0x7FFFFFF; // mask colour table bits
sibling2Ptr = node[0x08 - m_offset] & 0x1FFFFFF; // mask colour table bits sibling2Ptr = node[0x08 - m_offset] & 0x1FFFFFF; // mask colour table bits
matrixOffset = node[0x03 - m_offset] & 0xFFF; matrixOffset = node[0x03 - m_offset] & 0xFFF;
lodTablePointer = (node[0x03 - m_offset] >> 12) & 0x7F; //lodTablePointer = (node[0x03 - m_offset] >> 12) & 0x7F;
// check our node type // check our node type
if (nodeType == NodeType::viewport) { if (nodeType == NodeType::viewport) {
@ -556,7 +553,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
if (!m_offset) { // Step 1.5+ if (!m_offset) { // Step 1.5+
float modelScale = *(float *)&node[1]; float modelScale = uint_as_float(node[1]);
if (modelScale > std::numeric_limits<float>::min()) { if (modelScale > std::numeric_limits<float>::min()) {
m_nodeAttribs.currentModelScale = modelScale; m_nodeAttribs.currentModelScale = modelScale;
} }
@ -576,9 +573,9 @@ void CNew3D::DescendCullingNode(UINT32 addr)
// apply translation vector // apply translation vector
if (node[0x00] & 0x10) { if (node[0x00] & 0x10) {
float x = *(float *)&node[0x04 - m_offset]; float x = uint_as_float(node[0x04 - m_offset]);
float y = *(float *)&node[0x05 - m_offset]; float y = uint_as_float(node[0x05 - m_offset]);
float z = *(float *)&node[0x06 - m_offset]; float z = uint_as_float(node[0x06 - m_offset]);
m_modelMat.Translate(x, y, z); m_modelMat.Translate(x, y, z);
} }
// multiply matrix, if specified // multiply matrix, if specified
@ -590,7 +587,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
fCullRadius = R3DFloat::GetFloat16(uCullRadius); fCullRadius = R3DFloat::GetFloat16(uCullRadius);
uBlendRadius = node[9 - m_offset] >> 16; uBlendRadius = node[9 - m_offset] >> 16;
fBlendRadius = R3DFloat::GetFloat16(uBlendRadius); //fBlendRadius = R3DFloat::GetFloat16(uBlendRadius);
if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) { if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) {
@ -788,14 +785,14 @@ void CNew3D::RenderViewport(UINT32 addr)
{ {
static const GLfloat color[8][3] = static const GLfloat color[8][3] =
{ // RGB1 color translation { // RGB1 color translation
{ 0.0, 0.0, 0.0 }, // off { 0.0f, 0.0f, 0.0f }, // off
{ 0.0, 0.0, 1.0 }, // blue { 0.0f, 0.0f, 1.0f }, // blue
{ 0.0, 1.0, 0.0 }, // green { 0.0f, 1.0f, 0.0f }, // green
{ 0.0, 1.0, 1.0 }, // cyan { 0.0f, 1.0f, 1.0f }, // cyan
{ 1.0, 0.0, 0.0 }, // red { 1.0f, 0.0f, 0.0f }, // red
{ 1.0, 0.0, 1.0 }, // purple { 1.0f, 0.0f, 1.0f }, // purple
{ 1.0, 1.0, 0.0 }, // yellow { 1.0f, 1.0f, 0.0f }, // yellow
{ 1.0, 1.0, 1.0 } // white { 1.0f, 1.0f, 1.0f } // white
}; };
if ((addr & 0x00FFFFFF) == 0) { if ((addr & 0x00FFFFFF) == 0) {
@ -824,10 +821,10 @@ void CNew3D::RenderViewport(UINT32 addr)
m_currentPriority = vp->priority; m_currentPriority = vp->priority;
// Fetch viewport parameters (TO-DO: would rounding make a difference?) // Fetch viewport parameters (TO-DO: would rounding make a difference?)
vp->vpX = (int)(((vpnode[0x1A] & 0xFFFF) / 16.0f) + 0.5f); // viewport X (12.4 fixed point) vp->vpX = (int)(((vpnode[0x1A] & 0xFFFF) * (float)(1.0 / 16.0)) + 0.5f); // viewport X (12.4 fixed point)
vp->vpY = (int)(((vpnode[0x1A] >> 16) / 16.0f) + 0.5f); // viewport Y (12.4) vp->vpY = (int)(((vpnode[0x1A] >> 16) * (float)(1.0 / 16.0)) + 0.5f); // viewport Y (12.4)
vp->vpWidth = (int)(((vpnode[0x14] & 0xFFFF) / 4.0f) + 0.5f); // width (14.2) vp->vpWidth = (int)(((vpnode[0x14] & 0xFFFF) * (float)(1.0 / 4.0)) + 0.5f); // width (14.2)
vp->vpHeight = (int)(((vpnode[0x14] >> 16) / 4.0f) + 0.5f); // height (14.2) vp->vpHeight = (int)(((vpnode[0x14] >> 16) * (float)(1.0 / 4.0)) + 0.5f); // height (14.2)
uint32_t matrixBase = vpnode[0x16] & 0xFFFFFF; // matrix base address uint32_t matrixBase = vpnode[0x16] & 0xFFFFFF; // matrix base address
@ -840,29 +837,29 @@ void CNew3D::RenderViewport(UINT32 addr)
vp->angle_bottom = -atan2(*(float *)&vpnode[18], -*(float *)&vpnode[19]); // Perhaps they are just used for culling and not rendering. vp->angle_bottom = -atan2(*(float *)&vpnode[18], -*(float *)&vpnode[19]); // Perhaps they are just used for culling and not rendering.
*/ */
float cv = *(float *)&vpnode[0x8]; // 1/(left-right) float cv = uint_as_float(vpnode[0x8]); // 1/(left-right)
float cw = *(float *)&vpnode[0x9]; // 1/(top-bottom) float cw = uint_as_float(vpnode[0x9]); // 1/(top-bottom)
float io = *(float *)&vpnode[0xa]; // top / bottom (ratio) - ish float io = uint_as_float(vpnode[0xa]); // top / bottom (ratio) - ish
float jo = *(float *)&vpnode[0xb]; // left / right (ratio) float jo = uint_as_float(vpnode[0xb]); // left / right (ratio)
vp->angle_left = (1.0f / cv) * (0.0f - jo); vp->angle_left = (0.0f - jo) / cv;
vp->angle_right = (1.0f / cv) * (1.0f - jo); vp->angle_right = (1.0f - jo) / cv;
vp->angle_bottom = (1.0f / cw) * -(1.0f - io); vp->angle_bottom = -(1.0f - io)/ cw;
vp->angle_top = (1.0f / cw) * -(0.0f - io); vp->angle_top = -(0.0f - io)/ cw;
// calculate the frustum shape, near/far pair are dummy values // calculate the frustum shape, near/far pair are dummy values
CalcViewport(vp, 1, 1000); CalcViewport(vp, 1.f, 1000.f);
// calculate frustum planes // calculate frustum planes
CalcFrustumPlanes(m_planes, vp->projectionMatrix); // we need to calc a 'projection matrix' to get the correct frustum planes for clipping CalcFrustumPlanes(m_planes, vp->projectionMatrix); // we need to calc a 'projection matrix' to get the correct frustum planes for clipping
// Lighting (note that sun vector points toward sun -- away from vertex) // Lighting (note that sun vector points toward sun -- away from vertex)
vp->lightingParams[0] = *(float *)&vpnode[0x05]; // sun X vp->lightingParams[0] = uint_as_float(vpnode[0x05]); // sun X
vp->lightingParams[1] = -*(float *)&vpnode[0x06]; // sun Y (- to convert to ogl cordinate system) vp->lightingParams[1] = -uint_as_float(vpnode[0x06]); // sun Y (- to convert to ogl cordinate system)
vp->lightingParams[2] = -*(float *)&vpnode[0x04]; // sun Z (- to convert to ogl cordinate system) vp->lightingParams[2] = -uint_as_float(vpnode[0x04]); // sun Z (- to convert to ogl cordinate system)
vp->lightingParams[3] = std::max(0.f, std::min(*(float *)&vpnode[0x07], 1.0f)); // sun intensity (clamp to 0-1) vp->lightingParams[3] = std::max(0.f, std::min(uint_as_float(vpnode[0x07]), 1.0f)); // sun intensity (clamp to 0-1)
vp->lightingParams[4] = (float)((vpnode[0x24] >> 8) & 0xFF) * (1.0f / 255.0f); // ambient intensity vp->lightingParams[4] = (float)((vpnode[0x24] >> 8) & 0xFF) * (float)(1.0 / 255.0); // ambient intensity
vp->lightingParams[5] = 0.0; // reserved vp->lightingParams[5] = 0.0f; // reserved
vp->sunClamp = m_sunClamp; vp->sunClamp = m_sunClamp;
vp->intensityClamp = (m_step == 0x10); // just step 1.0 ? vp->intensityClamp = (m_step == 0x10); // just step 1.0 ?
@ -871,13 +868,13 @@ void CNew3D::RenderViewport(UINT32 addr)
// Spotlight // Spotlight
int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index
int spotFogColorIdx = (vpnode[0x20] >> 8) & 7; // spotlight on fog color index int spotFogColorIdx = (vpnode[0x20] >> 8) & 7; // spotlight on fog color index
vp->spotEllipse[0] = (float)(INT16)(vpnode[0x1E] & 0xFFFF) / 8.0f; // spotlight X position (13.3 fixed point) vp->spotEllipse[0] = (float)(INT16)(vpnode[0x1E] & 0xFFFF) * (float)(1.0 / 8.0); // spotlight X position (13.3 fixed point)
vp->spotEllipse[1] = (float)(INT16)(vpnode[0x1D] & 0xFFFF) / 8.0f; // spotlight Y vp->spotEllipse[1] = (float)(INT16)(vpnode[0x1D] & 0xFFFF) * (float)(1.0 / 8.0); // spotlight Y
vp->spotEllipse[2] = (float)((vpnode[0x1E] >> 16) & 0xFFFF); // spotlight X size (16-bit) vp->spotEllipse[2] = (float)((vpnode[0x1E] >> 16) & 0xFFFF); // spotlight X size (16-bit)
vp->spotEllipse[3] = (float)((vpnode[0x1D] >> 16) & 0xFFFF); // spotlight Y size vp->spotEllipse[3] = (float)((vpnode[0x1D] >> 16) & 0xFFFF); // spotlight Y size
vp->spotRange[0] = 1.0f / (*(float *)&vpnode[0x21]); // spotlight start vp->spotRange[0] = 1.0f / uint_as_float(vpnode[0x21]); // spotlight start
vp->spotRange[1] = *(float *)&vpnode[0x1F]; // spotlight extent vp->spotRange[1] = uint_as_float(vpnode[0x1F]); // spotlight extent
vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color
vp->spotColor[1] = color[spotColorIdx][1]; vp->spotColor[1] = color[spotColorIdx][1];
@ -898,8 +895,8 @@ void CNew3D::RenderViewport(UINT32 addr)
vp->spotEllipse[3] = std::roundf(2047.0f / vp->spotEllipse[3]); vp->spotEllipse[3] = std::roundf(2047.0f / vp->spotEllipse[3]);
// Scale the spotlight to the OpenGL viewport // Scale the spotlight to the OpenGL viewport
vp->spotEllipse[0] = vp->spotEllipse[0] * m_xRatio + m_xOffs; vp->spotEllipse[0] = vp->spotEllipse[0] * m_xRatio + (float)m_xOffs;
vp->spotEllipse[1] = vp->spotEllipse[1] * m_yRatio + m_yOffs; vp->spotEllipse[1] = vp->spotEllipse[1] * m_yRatio + (float)m_yOffs;
vp->spotEllipse[2] *= m_xRatio; vp->spotEllipse[2] *= m_xRatio;
vp->spotEllipse[3] *= m_yRatio; vp->spotEllipse[3] *= m_yRatio;
@ -908,22 +905,22 @@ void CNew3D::RenderViewport(UINT32 addr)
vp->losPosY = (int)(((vpnode[0x1c] >> 16) / 16.0f) + 0.5f); // y position 0 starts from the top vp->losPosY = (int)(((vpnode[0x1c] >> 16) / 16.0f) + 0.5f); // y position 0 starts from the top
// Fog // Fog
vp->fogParams[0] = (float)((vpnode[0x22] >> 16) & 0xFF) * (1.0f / 255.0f); // fog color R vp->fogParams[0] = (float)((vpnode[0x22] >> 16) & 0xFF) * (float)(1.0 / 255.0); // fog color R
vp->fogParams[1] = (float)((vpnode[0x22] >> 8) & 0xFF) * (1.0f / 255.0f); // fog color G vp->fogParams[1] = (float)((vpnode[0x22] >> 8) & 0xFF) * (float)(1.0 / 255.0); // fog color G
vp->fogParams[2] = (float)((vpnode[0x22] >> 0) & 0xFF) * (1.0f / 255.0f); // fog color B vp->fogParams[2] = (float)((vpnode[0x22] >> 0) & 0xFF) * (float)(1.0 / 255.0); // fog color B
vp->fogParams[3] = std::abs(*(float *)&vpnode[0x23]); // fog density - ocean hunter uses negative values, but looks the same vp->fogParams[3] = std::abs(uint_as_float(vpnode[0x23])); // fog density - ocean hunter uses negative values, but looks the same
vp->fogParams[4] = (float)(INT16)(vpnode[0x25] & 0xFFFF)*(1.0f / 255.0f); // fog start vp->fogParams[4] = (float)(INT16)(vpnode[0x25] & 0xFFFF)* (float)(1.0 / 255.0); // fog start
// Avoid Infinite and NaN values for Star Wars Trilogy // Avoid Infinite and NaN values for Star Wars Trilogy
if (std::isinf(vp->fogParams[3]) || std::isnan(vp->fogParams[3])) { if (std::isinf(vp->fogParams[3]) || std::isnan(vp->fogParams[3])) {
for (int i = 0; i < 7; i++) vp->fogParams[i] = 0.0f; for (int i = 0; i < 7; i++) vp->fogParams[i] = 0.0f;
} }
vp->fogParams[5] = (float)((vpnode[0x24] >> 16) & 0xFF) * (1.0f / 255.0f); // fog attenuation vp->fogParams[5] = (float)((vpnode[0x24] >> 16) & 0xFF) * (float)(1.0 / 255.0); // fog attenuation
vp->fogParams[6] = (float)((vpnode[0x25] >> 16) & 0xFF) * (1.0f / 255.0f); // fog ambient vp->fogParams[6] = (float)((vpnode[0x25] >> 16) & 0xFF) * (float)(1.0 / 255.0); // fog ambient
vp->scrollFog = (float)(vpnode[0x20] & 0xFF) * (1.0f / 255.0f); // scroll fog vp->scrollFog = (float)(vpnode[0x20] & 0xFF) * (float)(1.0 / 255.0); // scroll fog
vp->scrollAtt = (float)(vpnode[0x24] & 0xFF) * (1.0f / 255.0f); // scroll attenuation vp->scrollAtt = (float)(vpnode[0x24] & 0xFF) * (float)(1.0 / 255.0); // scroll attenuation
// Clear texture offsets before proceeding // Clear texture offsets before proceeding
m_nodeAttribs.Reset(); m_nodeAttribs.Reset();
@ -947,7 +944,7 @@ void CNew3D::RenderViewport(UINT32 addr)
void CNew3D::CopyVertexData(const R3DPoly& r3dPoly, std::vector<FVertex>& vertexArray) void CNew3D::CopyVertexData(const R3DPoly& r3dPoly, std::vector<FVertex>& vertexArray)
{ {
// both lemans 24 and dirt devils are rendering some totally transparent polys as the first object in each viewport // both lemans 24 and dirt devils are rendering some totally transparent polys as the first object in each viewport
// in dirt devils it's parallel to the camera so is completel invisible, but breaks our depth calculation // in dirt devils it's parallel to the camera so is completely invisible, but breaks our depth calculation
// in lemans 24 its a sort of diamond shape, but never leaves a hole in the transparent geometry so must be being skipped by the h/w // in lemans 24 its a sort of diamond shape, but never leaves a hole in the transparent geometry so must be being skipped by the h/w
if (r3dPoly.faceColour[3] == 0) { if (r3dPoly.faceColour[3] == 0) {
return; return;
@ -1058,7 +1055,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph)
if (currentMesh->microTexture) { if (currentMesh->microTexture) {
float microTexScale[] = { 2, 4, 16, 256 }; static const float microTexScale[] = { 2.f, 4.f, 16.f, 256.f };
currentMesh->microTextureID = ph.MicroTextureID(); currentMesh->microTextureID = ph.MicroTextureID();
currentMesh->microTextureScale = microTexScale[ph.MicroTextureMinLOD()]; currentMesh->microTextureScale = microTexScale[ph.MicroTextureMinLOD()];
@ -1073,7 +1070,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
UINT64 lastHash = -1; UINT64 lastHash = -1;
SortingMesh* currentMesh = nullptr; SortingMesh* currentMesh = nullptr;
std::map<UINT64, SortingMesh> sMap; std::unordered_map<UINT64, SortingMesh> sMap;
if (data == NULL) if (data == NULL)
return; return;
@ -1086,7 +1083,6 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
R3DPoly p; // current polygon R3DPoly p; // current polygon
float uvScale; float uvScale;
int i, j;
if (ph.header[6] == 0) { if (ph.header[6] == 0) {
break; break;
@ -1099,9 +1095,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
if (sMap.count(hash) == 0) { if (sMap.count(hash) == 0) {
sMap[hash] = SortingMesh(); currentMesh = &sMap.insert({hash, SortingMesh()}).first->second;
currentMesh = &sMap[hash];
//make space for our vertices //make space for our vertices
currentMesh->verts.reserve(numTriangles * 3); currentMesh->verts.reserve(numTriangles * 3);
@ -1109,8 +1103,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
//set mesh values //set mesh values
SetMeshValues(currentMesh, ph); SetMeshValues(currentMesh, ph);
} }
else
currentMesh = &sMap[hash]; currentMesh = &sMap[hash];
} }
// Obtain basic polygon parameters // Obtain basic polygon parameters
@ -1120,9 +1114,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
ph.FaceNormal(p.faceNormal); ph.FaceNormal(p.faceNormal);
// Fetch reused vertices according to bitfield, then new verts // Fetch reused vertices according to bitfield, then new verts
i = 0; int j = 0;
j = 0; for (int i = 0; i < 4; i++) // up to 4 reused vertices
for (i = 0; i < 4; i++) // up to 4 reused vertices
{ {
if (ph.SharedVertex(i)) if (ph.SharedVertex(i))
{ {
@ -1165,7 +1158,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
} }
// if we have flat shading, we can't re-use normals from shared vertices // if we have flat shading, we can't re-use normals from shared vertices
for (i = 0; i < p.number && !ph.SmoothShading(); i++) { for (int i = 0; i < p.number && !ph.SmoothShading(); i++) {
p.v[i].normal[0] = p.faceNormal[0]; p.v[i].normal[0] = p.faceNormal[0];
p.v[i].normal[1] = p.faceNormal[1]; p.v[i].normal[1] = p.faceNormal[1];
p.v[i].normal[2] = p.faceNormal[2]; p.v[i].normal[2] = p.faceNormal[2];
@ -1202,7 +1195,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
//========== //==========
if (!m_shadeIsSigned) { if (!m_shadeIsSigned) {
shade = (ix & 0xFF) / 255.f; shade = (ix & 0xFF) * (float)(1.0 / 255.0);
} }
else { else {
shade = BYTE_TO_FLOAT((INT8)(ix & 0xFF)); shade = BYTE_TO_FLOAT((INT8)(ix & 0xFF));
@ -1237,8 +1230,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
// flip normals // flip normals
V3::inverse(tempP.faceNormal); V3::inverse(tempP.faceNormal);
for (int i = 0; i < tempP.number; i++) { for (int i2 = 0; i2 < tempP.number; i2++) {
V3::inverse(tempP.v[i].normal); V3::inverse(tempP.v[i2].normal);
} }
CopyVertexData(tempP, currentMesh->verts); CopyVertexData(tempP, currentMesh->verts);
@ -1250,7 +1243,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
} }
// Copy current vertices into previous vertex array // Copy current vertices into previous vertex array
for (i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
m_prev[i] = p.v[i]; m_prev[i] = p.v[i];
m_prevTexCoords[i][0] = texCoords[i][0]; m_prevTexCoords[i][0] = texCoords[i][0];
m_prevTexCoords[i][1] = texCoords[i][1]; m_prevTexCoords[i][1] = texCoords[i][1];
@ -1365,10 +1358,10 @@ void CNew3D::CalcFrustumPlanes(Plane p[5], const float* matrix)
p[3].Normalise(); p[3].Normalise();
// Front Plane // Front Plane
p[4].a = 0; p[4].a = 0.f;
p[4].b = 0; p[4].b = 0.f;
p[4].c = -1; p[4].c = -1.f;
p[4].d =0; p[4].d = 0.f;
} }
void CNew3D::CalcBox(float distance, BBox& box) void CNew3D::CalcBox(float distance, BBox& box)
@ -1377,49 +1370,49 @@ void CNew3D::CalcBox(float distance, BBox& box)
box.points[0][0] = -distance; box.points[0][0] = -distance;
box.points[0][1] = -distance; box.points[0][1] = -distance;
box.points[0][2] = distance; box.points[0][2] = distance;
box.points[0][3] = 1; box.points[0][3] = 1.f;
//bottom left back //bottom left back
box.points[1][0] = -distance; box.points[1][0] = -distance;
box.points[1][1] = -distance; box.points[1][1] = -distance;
box.points[1][2] = -distance; box.points[1][2] = -distance;
box.points[1][3] = 1; box.points[1][3] = 1.f;
//bottom right back //bottom right back
box.points[2][0] = distance; box.points[2][0] = distance;
box.points[2][1] = -distance; box.points[2][1] = -distance;
box.points[2][2] = -distance; box.points[2][2] = -distance;
box.points[2][3] = 1; box.points[2][3] = 1.f;
//bottom right front //bottom right front
box.points[3][0] = distance; box.points[3][0] = distance;
box.points[3][1] = -distance; box.points[3][1] = -distance;
box.points[3][2] = distance; box.points[3][2] = distance;
box.points[3][3] = 1; box.points[3][3] = 1.f;
//top left front //top left front
box.points[4][0] = -distance; box.points[4][0] = -distance;
box.points[4][1] = distance; box.points[4][1] = distance;
box.points[4][2] = distance; box.points[4][2] = distance;
box.points[4][3] = 1; box.points[4][3] = 1.f;
//top left back //top left back
box.points[5][0] = -distance; box.points[5][0] = -distance;
box.points[5][1] = distance; box.points[5][1] = distance;
box.points[5][2] = -distance; box.points[5][2] = -distance;
box.points[5][3] = 1; box.points[5][3] = 1.f;
//top right back //top right back
box.points[6][0] = distance; box.points[6][0] = distance;
box.points[6][1] = distance; box.points[6][1] = distance;
box.points[6][2] = -distance; box.points[6][2] = -distance;
box.points[6][3] = 1; box.points[6][3] = 1.f;
//top right front //top right front
box.points[7][0] = distance; box.points[7][0] = distance;
box.points[7][1] = distance; box.points[7][1] = distance;
box.points[7][2] = distance; box.points[7][2] = distance;
box.points[7][3] = 1; box.points[7][3] = 1.f;
} }
void CNew3D::MultVec(const float matrix[16], const float in[4], float out[4]) void CNew3D::MultVec(const float matrix[16], const float in[4], float out[4])
@ -1444,7 +1437,7 @@ void CNew3D::TransformBox(const float *m, BBox& box)
} }
} }
Clip CNew3D::ClipBox(BBox& box, Plane planes[5]) Clip CNew3D::ClipBox(const BBox& box, Plane planes[5])
{ {
int count = 0; int count = 0;
@ -1453,7 +1446,7 @@ Clip CNew3D::ClipBox(BBox& box, Plane planes[5])
int temp = 0; int temp = 0;
for (int j = 0; j < 5; j++) { for (int j = 0; j < 5; j++) {
if (planes[j].DistanceToPoint(box.points[i]) >= 0) { if (planes[j].DistanceToPoint(box.points[i]) >= 0.f) {
temp++; temp++;
} }
} }
@ -1472,7 +1465,7 @@ Clip CNew3D::ClipBox(BBox& box, Plane planes[5])
int temp = 0; int temp = 0;
for (int j = 0; j < 8; j++) { for (int j = 0; j < 8; j++) {
if (planes[i].DistanceToPoint(box.points[j]) >= 0) { if (planes[i].DistanceToPoint(box.points[j]) >= 0.f) {
temp++; temp++;
} }
} }
@ -1490,7 +1483,7 @@ Clip CNew3D::ClipBox(BBox& box, Plane planes[5])
void CNew3D::CalcBoxExtents(const BBox& box) void CNew3D::CalcBoxExtents(const BBox& box)
{ {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (box.points[i][2] < 0) { if (box.points[i][2] < 0.f) {
m_nfPairs[m_currentPriority].zNear = std::max(box.points[i][2], m_nfPairs[m_currentPriority].zNear); m_nfPairs[m_currentPriority].zNear = std::max(box.points[i][2], m_nfPairs[m_currentPriority].zNear);
m_nfPairs[m_currentPriority].zFar = std::min(box.points[i][2], m_nfPairs[m_currentPriority].zFar); m_nfPairs[m_currentPriority].zFar = std::min(box.points[i][2], m_nfPairs[m_currentPriority].zFar);
} }
@ -1512,13 +1505,11 @@ void CNew3D::ClipPolygon(ClipPoly& clipPoly, Plane planes[5])
//================= //=================
bool currentIn; bool currentIn;
bool nextIn;
float currentDot; float currentDot;
float nextDot;
//================= //=================
currentDot = planes[i].DotProduct(in->list[0].pos); currentDot = planes[i].DotProduct(in->list[0].pos);
currentIn = (currentDot + planes[i].d) >= 0; currentIn = (currentDot + planes[i].d) >= 0.f;
out->count = 0; out->count = 0;
for (int j = 0; j < in->count; j++) { for (int j = 0; j < in->count; j++) {
@ -1533,16 +1524,16 @@ void CNew3D::ClipPolygon(ClipPoly& clipPoly, Plane planes[5])
nextIndex = 0; nextIndex = 0;
} }
nextDot = planes[i].DotProduct(in->list[nextIndex].pos); float nextDot = planes[i].DotProduct(in->list[nextIndex].pos);
nextIn = (nextDot + planes[i].d) >= 0; bool nextIn = (nextDot + planes[i].d) >= 0.f;
// we have an intersection // we have an intersection
if (currentIn != nextIn) { if (currentIn != nextIn) {
float u = (currentDot + planes[i].d) / (currentDot - nextDot); float u = (currentDot + planes[i].d) / (currentDot - nextDot);
float* p1 = in->list[j].pos; const float* p1 = in->list[j].pos;
float* p2 = in->list[nextIndex].pos; const float* p2 = in->list[nextIndex].pos;
out->list[out->count].pos[0] = p1[0] + ((p2[0] - p1[0]) * u); out->list[out->count].pos[0] = p1[0] + ((p2[0] - p1[0]) * u);
out->list[out->count].pos[1] = p1[1] + ((p2[1] - p1[1]) * u); out->list[out->count].pos[1] = p1[1] + ((p2[1] - p1[1]) * u);
@ -1590,7 +1581,7 @@ void CNew3D::ClipModel(const Model *m)
ClipPolygon(clipPoly, m_planes); ClipPolygon(clipPoly, m_planes);
for (int j = 0; j < clipPoly.count; j++) { for (int j = 0; j < clipPoly.count; j++) {
if (clipPoly.list[j].pos[2] < 0) { if (clipPoly.list[j].pos[2] < 0.f) {
m_nfPairs[m_currentPriority].zNear = std::max(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zNear); m_nfPairs[m_currentPriority].zNear = std::max(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zNear);
m_nfPairs[m_currentPriority].zFar = std::min(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zFar); m_nfPairs[m_currentPriority].zFar = std::min(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zFar);
} }
@ -1601,12 +1592,12 @@ void CNew3D::ClipModel(const Model *m)
void CNew3D::CalcViewport(Viewport* vp, float near, float far) void CNew3D::CalcViewport(Viewport* vp, float near, float far)
{ {
if (far > 1e30) { if (far > 1e30f) {
far = near * 1000000; // fix for ocean hunter which passes some FLT_MAX for a few matrices. HW must have some safe guard for these far = near * 1000000.f; // fix for ocean hunter which passes some FLT_MAX for a few matrices. HW must have some safe guard for these
} }
if (near < far / 1000000) { if (near < far / 1000000.f) {
near = far / 1000000; // if we get really close to zero somehow, we will have almost no depth precision near = far / 1000000.f; // if we get really close to zero somehow, we will have almost no depth precision
} }
float l = near * vp->angle_left; // we need to calc the shape of the projection frustum for culling float l = near * vp->angle_left; // we need to calc the shape of the projection frustum for culling
@ -1646,18 +1637,18 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far)
float correction = windowAR / viewableAreaAR; float correction = windowAR / viewableAreaAR;
vp->x = 0; vp->x = 0;
vp->y = m_yOffs + (int)((384 - (vp->vpY + vp->vpHeight))*m_yRatio); vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
vp->width = m_totalXRes; vp->width = m_totalXRes;
vp->height = (int)(vp->vpHeight*m_yRatio); vp->height = (int)((float)vp->vpHeight*m_yRatio);
vp->projectionMatrix.Frustum(l*correction, r*correction, b, t, near, far); vp->projectionMatrix.Frustum(l*correction, r*correction, b, t, near, far);
} }
else { else {
vp->x = m_xOffs + (int)(vp->vpX*m_xRatio); vp->x = m_xOffs + (int)((float)vp->vpX*m_xRatio);
vp->y = m_yOffs + (int)((384 - (vp->vpY + vp->vpHeight))*m_yRatio); vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
vp->width = (int)(vp->vpWidth*m_xRatio); vp->width = (int)((float)vp->vpWidth*m_xRatio);
vp->height = (int)(vp->vpHeight*m_yRatio); vp->height = (int)((float)vp->vpHeight*m_yRatio);
vp->projectionMatrix.Frustum(l, r, b, t, near, far); vp->projectionMatrix.Frustum(l, r, b, t, near, far);
} }

View file

@ -183,7 +183,7 @@ public:
* Parameters: * Parameters:
* config Run-time configuration. * config Run-time configuration.
*/ */
CNew3D(const Util::Config::Node &config, std::string gameName); CNew3D(const Util::Config::Node &config, const std::string& gameName);
~CNew3D(void); ~CNew3D(void);
private: private:
@ -305,7 +305,7 @@ private:
void CalcBox (float distance, BBox& box); void CalcBox (float distance, BBox& box);
void TransformBox (const float *m, BBox& box); void TransformBox (const float *m, BBox& box);
void MultVec (const float matrix[16], const float in[4], float out[4]); void MultVec (const float matrix[16], const float in[4], float out[4]);
Clip ClipBox (BBox& box, Plane planes[5]); Clip ClipBox (const BBox& box, Plane planes[5]);
void ClipModel (const Model *m); void ClipModel (const Model *m);
void ClipPolygon (ClipPoly& clipPoly, Plane planes[5]); void ClipPolygon (ClipPoly& clipPoly, Plane planes[5]);
void CalcBoxExtents (const BBox& box); void CalcBoxExtents (const BBox& box);

View file

@ -8,11 +8,11 @@ struct Plane
float a, b, c, d; float a, b, c, d;
void Normalise() { void Normalise() {
float temp = std::sqrt((a * a) + (b * b) + (c * c)); float temp = 1.f/std::sqrt((a * a) + (b * b) + (c * c));
a /= temp; a *= temp;
b /= temp; b *= temp;
c /= temp; c *= temp;
d /= temp; d *= temp;
} }
float DistanceToPoint(const float v[3]) { float DistanceToPoint(const float v[3]) {
@ -24,4 +24,4 @@ struct Plane
} }
}; };
#endif #endif

View file

@ -1,5 +1,6 @@
#include "Types.h" #include "Types.h"
#include "R3DFloat.h" #include "R3DFloat.h"
#include "Util\GenericValue.h"
float R3DFloat::GetFloat16(UINT16 f) float R3DFloat::GetFloat16(UINT16 f)
{ {
@ -13,17 +14,16 @@ float R3DFloat::GetFloat32(UINT32 f)
UINT32 R3DFloat::ConvertProFloat(UINT32 a1) UINT32 R3DFloat::ConvertProFloat(UINT32 a1)
{ {
int exponent = (a1 & 0x7E000000) >> 25; UINT32 exponent = (a1 & 0x7E000000) >> 25;
if (exponent <= 31) { // positive if (exponent <= 31) { // positive
exponent += 127; exponent += 127;
} }
else { // negative exponent else { // negative exponent
exponent -= 64; exponent += 127 - 64;
exponent += 127;
} }
int mantissa = (a1 & 0x1FFFFFF) >> 2; UINT32 mantissa = (a1 & 0x1FFFFFF) >> 2;
return (a1 & 0x80000000) | (exponent << 23) | mantissa; return (a1 & 0x80000000) | (exponent << 23) | mantissa;
} }
@ -35,5 +35,5 @@ UINT32 R3DFloat::Convert16BitProFloat(UINT32 a1)
float R3DFloat::ToFloat(UINT32 a1) float R3DFloat::ToFloat(UINT32 a1)
{ {
return *(float*)(&a1); return uint_as_float(a1);
} }

View file

@ -3,8 +3,8 @@
namespace R3DFloat namespace R3DFloat
{ {
static const UINT16 Pro16BitMax = 0x7fff; constexpr UINT16 Pro16BitMax = 0x7fff;
static const float Pro16BitFltMin = 1e-7f; // float min in IEEE constexpr float Pro16BitFltMin = 1e-7f; // float min in IEEE
float GetFloat16(UINT16 f); float GetFloat16(UINT16 f);
float GetFloat32(UINT32 f); float GetFloat32(UINT32 f);
@ -14,4 +14,4 @@ namespace R3DFloat
float ToFloat(UINT32 a1); // integer float to actual IEEE 754 float float ToFloat(UINT32 a1); // integer float to actual IEEE 754 float
} }
#endif #endif

View file

@ -37,7 +37,7 @@ private:
texCoords[1] = t; texCoords[1] = t;
verts[0] = x; verts[0] = x;
verts[1] = y; verts[1] = y;
verts[2] = 0; // z = 0 verts[2] = 0.f; // z = 0
} }
float texCoords[2]; float texCoords[2];
@ -73,4 +73,4 @@ private:
} }
#endif #endif

View file

@ -602,7 +602,7 @@ void SCSP_StopSlot(_SLOT *slot,int keyoff)
//DebugLog("KEYOFF2 %d",slot->slot); //DebugLog("KEYOFF2 %d",slot->slot);
} }
#define log2(n) (log((float) n)/log((float) 2)) //#define log2(n) (log((float) n)/log((float) 2))
bool SCSP_Init(const Util::Config::Node &config, int n) bool SCSP_Init(const Util::Config::Node &config, int n)
{ {
@ -641,7 +641,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
{ {
double fcent=(double) 1200.0*log2((double)(((double) 1024.0+(double)i)/(double)1024.0)); double fcent=(double) 1200.0*log2((double)(((double) 1024.0+(double)i)/(double)1024.0));
//float fcent=1.0+(float) i/1024.0; //float fcent=1.0+(float) i/1024.0;
fcent=(double) 44100.0*pow(2.0,fcent/1200.0); fcent=(double) 44100.0*exp2(fcent/1200.0);
FNS_Table[i]=(UINT32)((float) (1<<SHIFT) *fcent); FNS_Table[i]=(UINT32)((float) (1<<SHIFT) *fcent);
//FNS_Table[i]=(i>>(10-SHIFT))|(1<<SHIFT); //FNS_Table[i]=(i>>(10-SHIFT))|(1<<SHIFT);
@ -655,7 +655,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
#ifdef RB_VOLUME #ifdef RB_VOLUME
// Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB // Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
volume[i] = 65536.0*pow(2.0, (-0.375 / 6.0)*i); volume[i] = 65536.0*exp2((-0.375 / 6.0)*i);
for (i = 256; i < 256 * 4; i++) for (i = 256; i < 256 * 4; i++)
volume[i] = 0; volume[i] = 0;

View file

@ -42,10 +42,10 @@ struct _LFO
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v))) #define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
//Convert DB to multiply amplitude //Convert DB to multiply amplitude
#define DB(v) LFIX(pow(10.0,v/20.0)) #define DB(v) LFIX(pow(10.0,(v)*(1.0/20.0)))
//Convert cents to step increment //Convert cents to step increment
#define CENTS(v) LFIX(pow(2.0,v/1200.0)) #define CENTS(v) LFIX(exp2((v)*(1.0/1200.0)))
static int PLFO_TRI[256], PLFO_SQR[256], PLFO_SAW[256], PLFO_NOI[256]; static int PLFO_TRI[256], PLFO_SQR[256], PLFO_SAW[256], PLFO_NOI[256];
static int ALFO_TRI[256], ALFO_SQR[256], ALFO_SAW[256], ALFO_NOI[256]; static int ALFO_TRI[256], ALFO_SQR[256], ALFO_SAW[256], ALFO_NOI[256];
@ -115,12 +115,12 @@ void LFO_Init(void)
float limit = PSCALE[s]; float limit = PSCALE[s];
for (i = -128; i < 128; ++i) for (i = -128; i < 128; ++i)
{ {
PSCALES[s][i + 128] = CENTS(((limit*(float)i) / 128.0)); PSCALES[s][i + 128] = CENTS(((limit*(double)i) / 128.0));
} }
limit = -ASCALE[s]; limit = -ASCALE[s];
for (i = 0; i < 256; ++i) for (i = 0; i < 256; ++i)
{ {
ASCALES[s][i] = DB(((limit*(float)i) / 256.0)); ASCALES[s][i] = DB(((limit*(double)i) / 256.0));
} }
} }
} }

View file

@ -20,6 +20,57 @@
#include <memory> #include <memory>
#include <cctype> #include <cctype>
#if __cplusplus >= 202002L
#include <bit>
#define float_as_int(x) std::bit_cast<int>(x)
#define int_as_float(x) std::bit_cast<float>(x)
#define uint_as_float(x) std::bit_cast<float>(x)
#elif 1
template <class Dest, class Source>
inline Dest bit_cast(Source const& source) {
static_assert(sizeof(Dest) == sizeof(Source), "size of destination and source objects must be equal");
static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable.");
static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable");
Dest dest;
std::memcpy(&dest, &source, sizeof(dest));
return dest;
}
#define float_as_int(x) bit_cast<int,float>(x)
#define int_as_float(x) bit_cast<float,int>(x)
#define uint_as_float(x) bit_cast<float,unsigned int>(x)
#else
inline int float_as_int(const float x)
{
union {
float f;
int i;
} uc;
uc.f = x;
return uc.i;
}
inline float int_as_float(const int i)
{
union {
int i;
float f;
} iaf;
iaf.i = i;
return iaf.f;
}
inline float uint_as_float(const unsigned int i)
{
union {
unsigned int u;
float f;
} iaf;
iaf.u = i;
return iaf.f;
}
#endif
namespace Util namespace Util
{ {
namespace detail namespace detail