diff --git a/Src/Graphics/Legacy3D/Legacy3D.cpp b/Src/Graphics/Legacy3D/Legacy3D.cpp index 3d32a8d..47a3282 100644 --- a/Src/Graphics/Legacy3D/Legacy3D.cpp +++ b/Src/Graphics/Legacy3D/Legacy3D.cpp @@ -161,6 +161,7 @@ #include "Supermodel.h" #include "Shaders3D.h" // fragment and vertex shaders #include "Graphics/Shader.h" +#include "Util/BitCast.h" #include #include @@ -851,8 +852,8 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri, bool wideScreen) int vpHeight = (vpnode[0x14]>>18)&0x3FFF; // height (14.2) // Field of view and clipping - GLfloat vpTopAngle = asinf(uint_as_float(vpnode[0x0E])); // FOV Y upper half-angle (radians) - GLfloat vpBotAngle = asinf(uint_as_float(vpnode[0x12])); // FOV Y lower half-angle + GLfloat vpTopAngle = asinf(Util::UintAsFloat(vpnode[0x0E])); // FOV Y upper half-angle (radians) + GLfloat vpBotAngle = asinf(Util::UintAsFloat(vpnode[0x12])); // FOV Y lower half-angle GLfloat fovYDegrees = (vpTopAngle+vpBotAngle)*(float)(180.0/M_PI); // TO-DO: investigate clipping planes diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index bb63366..b625326 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -7,6 +7,7 @@ #include #include #include "R3DFloat.h" +#include "Util/BitCast.h" #define MAX_RAM_VERTS 300000 #define MAX_ROM_VERTS 1500000 @@ -553,7 +554,7 @@ void CNew3D::DescendCullingNode(UINT32 addr) if (!m_offset) { // Step 1.5+ - float modelScale = uint_as_float(node[1]); + float modelScale = Util::UintAsFloat(node[1]); if (modelScale > std::numeric_limits::min()) { m_nodeAttribs.currentModelScale = modelScale; } @@ -573,9 +574,9 @@ void CNew3D::DescendCullingNode(UINT32 addr) // apply translation vector if (node[0x00] & 0x10) { - float x = uint_as_float(node[0x04 - m_offset]); - float y = uint_as_float(node[0x05 - m_offset]); - float z = uint_as_float(node[0x06 - m_offset]); + float x = Util::UintAsFloat(node[0x04 - m_offset]); + float y = Util::UintAsFloat(node[0x05 - m_offset]); + float z = Util::UintAsFloat(node[0x06 - m_offset]); m_modelMat.Translate(x, y, z); } // multiply matrix, if specified @@ -831,16 +832,16 @@ void CNew3D::RenderViewport(UINT32 addr) m_LODBlendTable = (LODBlendTable*)TranslateCullingAddress(vpnode[0x17] & 0xFFFFFF); /* - vp->angle_left = -atan2(*(float *)&vpnode[12], *(float *)&vpnode[13]); // These values work out as the normals for the clipping planes. - vp->angle_right = atan2(*(float *)&vpnode[16], -*(float *)&vpnode[17]); // Sometimes these values (dirt devils,lost world) are totally wrong - vp->angle_top = atan2(*(float *)&vpnode[14], *(float *)&vpnode[15]); // and don't work for the frustum values exactly. - vp->angle_bottom = -atan2(*(float *)&vpnode[18], -*(float *)&vpnode[19]); // Perhaps they are just used for culling and not rendering. + vp->angle_left = -atan2f(Util::UintAsFloat(vpnode[12]), Util::UintAsFloat(vpnode[13])); // These values work out as the normals for the clipping planes. + vp->angle_right = atan2f(Util::UintAsFloat(vpnode[16]), -Util::UintAsFloat(vpnode[17])); // Sometimes these values (dirt devils,lost world) are totally wrong + vp->angle_top = atan2f(Util::UintAsFloat(vpnode[14]), Util::UintAsFloat(vpnode[15])); // and don't work for the frustum values exactly. + vp->angle_bottom = -atan2f(Util::UintAsFloat(vpnode[18]), -Util::UintAsFloat(vpnode[19])); // Perhaps they are just used for culling and not rendering. */ - float cv = uint_as_float(vpnode[0x8]); // 1/(left-right) - float cw = uint_as_float(vpnode[0x9]); // 1/(top-bottom) - float io = uint_as_float(vpnode[0xa]); // top / bottom (ratio) - ish - float jo = uint_as_float(vpnode[0xb]); // left / right (ratio) + float cv = Util::UintAsFloat(vpnode[0x8]); // 1/(left-right) + float cw = Util::UintAsFloat(vpnode[0x9]); // 1/(top-bottom) + float io = Util::UintAsFloat(vpnode[0xa]); // top / bottom (ratio) - ish + float jo = Util::UintAsFloat(vpnode[0xb]); // left / right (ratio) vp->angle_left = (0.0f - jo) / cv; vp->angle_right = (1.0f - jo) / cv; @@ -854,10 +855,10 @@ void CNew3D::RenderViewport(UINT32 addr) 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) - vp->lightingParams[0] = uint_as_float(vpnode[0x05]); // sun X - vp->lightingParams[1] = -uint_as_float(vpnode[0x06]); // sun Y (- 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(uint_as_float(vpnode[0x07]), 1.0f)); // sun intensity (clamp to 0-1) + vp->lightingParams[0] = Util::UintAsFloat(vpnode[0x05]); // sun X + vp->lightingParams[1] = -Util::UintAsFloat(vpnode[0x06]); // sun Y (- to convert to ogl cordinate system) + vp->lightingParams[2] = -Util::UintAsFloat(vpnode[0x04]); // sun Z (- to convert to ogl cordinate system) + vp->lightingParams[3] = std::max(0.f, std::min(Util::UintAsFloat(vpnode[0x07]), 1.0f)); // sun intensity (clamp to 0-1) vp->lightingParams[4] = (float)((vpnode[0x24] >> 8) & 0xFF) * (float)(1.0 / 255.0); // ambient intensity vp->lightingParams[5] = 0.0f; // reserved @@ -868,13 +869,13 @@ void CNew3D::RenderViewport(UINT32 addr) // Spotlight int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index int spotFogColorIdx = (vpnode[0x20] >> 8) & 7; // spotlight on fog color index - 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) * (float)(1.0 / 8.0); // spotlight Y + 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) * (float)(1.0 / 8.0);// spotlight Y 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->spotRange[0] = 1.0f / uint_as_float(vpnode[0x21]); // spotlight start - vp->spotRange[1] = uint_as_float(vpnode[0x1F]); // spotlight extent + vp->spotRange[0] = 1.0f / Util::UintAsFloat(vpnode[0x21]); // spotlight start + vp->spotRange[1] = Util::UintAsFloat(vpnode[0x1F]); // spotlight extent vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color vp->spotColor[1] = color[spotColorIdx][1]; @@ -908,7 +909,7 @@ void CNew3D::RenderViewport(UINT32 addr) vp->fogParams[0] = (float)((vpnode[0x22] >> 16) & 0xFF) * (float)(1.0 / 255.0); // fog color R vp->fogParams[1] = (float)((vpnode[0x22] >> 8) & 0xFF) * (float)(1.0 / 255.0); // fog color G vp->fogParams[2] = (float)((vpnode[0x22] >> 0) & 0xFF) * (float)(1.0 / 255.0); // fog color B - vp->fogParams[3] = std::abs(uint_as_float(vpnode[0x23])); // fog density - ocean hunter uses negative values, but looks the same + vp->fogParams[3] = std::abs(Util::UintAsFloat(vpnode[0x23])); // fog density - ocean hunter uses negative values, but looks the same vp->fogParams[4] = (float)(INT16)(vpnode[0x25] & 0xFFFF)* (float)(1.0 / 255.0); // fog start // Avoid Infinite and NaN values for Star Wars Trilogy @@ -1065,6 +1066,9 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) void CNew3D::CacheModel(Model *m, const UINT32 *data) { + if (data == NULL) + return; + UINT16 texCoords[4][2]; PolyHeader ph; UINT64 lastHash = -1; @@ -1072,9 +1076,6 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) std::unordered_map sMap; - if (data == NULL) - return; - ph = data; int numTriangles = ph.NumTrianglesTotal(); @@ -1253,7 +1254,7 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) //sorted the data, now copy to main data structures - // we know how many meshes we have so reserve appropriate space + // we know how many meshes we have to reserve appropriate space m->meshes->reserve(sMap.size()); for (auto& it : sMap) { diff --git a/Src/Graphics/New3D/R3DFloat.cpp b/Src/Graphics/New3D/R3DFloat.cpp index 7a750b7..57b95b3 100644 --- a/Src/Graphics/New3D/R3DFloat.cpp +++ b/Src/Graphics/New3D/R3DFloat.cpp @@ -1,6 +1,6 @@ #include "Types.h" #include "R3DFloat.h" -#include "Util/GenericValue.h" +#include "Util/BitCast.h" float R3DFloat::GetFloat16(UINT16 f) { @@ -35,5 +35,5 @@ UINT32 R3DFloat::Convert16BitProFloat(UINT32 a1) float R3DFloat::ToFloat(UINT32 a1) { - return uint_as_float(a1); + return Util::UintAsFloat(a1); } diff --git a/Src/Util/BitCast.h b/Src/Util/BitCast.h new file mode 100644 index 0000000..20f158f --- /dev/null +++ b/Src/Util/BitCast.h @@ -0,0 +1,61 @@ +#ifndef INCLUDED_UTIL_BITCAST_H +#define INCLUDED_UTIL_BITCAST_H + +#include +#include + +namespace Util +{ +#if __cplusplus >= 202002L +#include +#define FloatAsInt(x) std::bit_cast(x) +#define IntAsFloat(x) std::bit_cast(x) +#define UintAsFloat(x) std::bit_cast(x) +#elif 1 +template +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::value, "destination type must be trivially copyable."); + static_assert(std::is_trivially_copyable::value, "source type must be trivially copyable"); + + Dest dest; + std::memcpy(&dest, &source, sizeof(dest)); + return dest; +} +#define FloatAsInt(x) bit_cast(x) +#define IntAsFloat(x) bit_cast(x) +#define UintAsFloat(x) bit_cast(x) +#else +inline int FloatAsInt(const float x) +{ + union { + float f; + int i; + } uc; + uc.f = x; + return uc.i; +} + +inline float IntAsFloat(const int i) +{ + union { + int i; + float f; + } iaf; + iaf.i = i; + return iaf.f; +} + +inline float UintAsFloat(const unsigned int i) +{ + union { + unsigned int u; + float f; + } iaf; + iaf.u = i; + return iaf.f; +} +#endif +} // Util + +#endif // INCLUDED_UTIL_BITCAST_H diff --git a/Src/Util/GenericValue.h b/Src/Util/GenericValue.h index e6a00b5..aa57e0d 100644 --- a/Src/Util/GenericValue.h +++ b/Src/Util/GenericValue.h @@ -20,57 +20,6 @@ #include #include -#if __cplusplus >= 202002L -#include -#define float_as_int(x) std::bit_cast(x) -#define int_as_float(x) std::bit_cast(x) -#define uint_as_float(x) std::bit_cast(x) -#elif 1 -template -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::value, "destination type must be trivially copyable."); - static_assert(std::is_trivially_copyable::value, "source type must be trivially copyable"); - - Dest dest; - std::memcpy(&dest, &source, sizeof(dest)); - return dest; -} -#define float_as_int(x) bit_cast(x) -#define int_as_float(x) bit_cast(x) -#define uint_as_float(x) bit_cast(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 detail diff --git a/VS2008/Supermodel.vcxproj b/VS2008/Supermodel.vcxproj index 9a7eaf4..0046347 100644 --- a/VS2008/Supermodel.vcxproj +++ b/VS2008/Supermodel.vcxproj @@ -1,4 +1,4 @@ - + @@ -545,6 +545,7 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config" + diff --git a/VS2008/Supermodel.vcxproj.filters b/VS2008/Supermodel.vcxproj.filters index 24798eb..a8b902b 100644 --- a/VS2008/Supermodel.vcxproj.filters +++ b/VS2008/Supermodel.vcxproj.filters @@ -847,6 +847,9 @@ Header Files\Graphics\New + + Header Files\Util +