From 16d7139e6aa16e4af1b54268dde7601e76fd4545 Mon Sep 17 00:00:00 2001 From: SNMetamorph <25657591+SNMetamorph@users.noreply.github.com> Date: Thu, 14 Sep 2023 23:50:31 +0400 Subject: [PATCH] server: novodex: refactored input/output streams --- server/novodex.cpp | 47 +++++---- server/physics/NxUserStream.cpp | 174 ++++++++++++++------------------ server/physics/NxUserStream.h | 37 +++---- 3 files changed, 127 insertions(+), 131 deletions(-) diff --git a/server/novodex.cpp b/server/novodex.cpp index 071d83f2..9ca4d9ed 100644 --- a/server/novodex.cpp +++ b/server/novodex.cpp @@ -327,8 +327,8 @@ PxConvexMesh *CPhysicNovodex :: ConvexMeshFromBmodel( entvars_t *pev, int modeli meshDesc.points.count = numVerts; meshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; - MemoryWriteBuffer buf; - bool status = m_pCooking->cookConvexMesh( meshDesc, buf ); + MemoryWriteBuffer outputBuffer; + bool status = m_pCooking->cookConvexMesh(meshDesc, outputBuffer); delete [] verts; if( !status ) @@ -337,7 +337,8 @@ PxConvexMesh *CPhysicNovodex :: ConvexMeshFromBmodel( entvars_t *pev, int modeli return NULL; } - pHull = m_pPhysics->createConvexMesh( MemoryReadBuffer( buf.data )); + MemoryReadBuffer inputBuffer(outputBuffer.getData(), outputBuffer.getSize()); + pHull = m_pPhysics->createConvexMesh(inputBuffer); if( !pHull ) ALERT( at_error, "failed to create convex mesh from %s\n", bmodel->name ); return pHull; @@ -422,8 +423,8 @@ PxTriangleMesh *CPhysicNovodex :: TriangleMeshFromBmodel( entvars_t *pev, int mo PX_ASSERT(res); #endif - MemoryWriteBuffer buf; - bool status = m_pCooking->cookTriangleMesh( meshDesc, buf ); + MemoryWriteBuffer outputBuffer; + bool status = m_pCooking->cookTriangleMesh(meshDesc, outputBuffer); delete [] indices; if( !status ) @@ -432,7 +433,8 @@ PxTriangleMesh *CPhysicNovodex :: TriangleMeshFromBmodel( entvars_t *pev, int mo return NULL; } - pMesh = m_pPhysics->createTriangleMesh( MemoryReadBuffer( buf.data )); + MemoryReadBuffer inputBuffer(outputBuffer.getData(), outputBuffer.getSize()); + pMesh = m_pPhysics->createTriangleMesh(inputBuffer); if( !pMesh ) ALERT( at_error, "failed to create triangle mesh from %s\n", bmodel->name ); @@ -513,7 +515,8 @@ PxConvexMesh *CPhysicNovodex :: ConvexMeshFromStudio( entvars_t *pev, int modeli if (CheckFileTimes(smodel->name, cacheFileName.string().c_str())) { // hull is never than studiomodel. Trying to load it - pHull = m_pPhysics->createConvexMesh( UserStream( cacheFileName.string().c_str(), true )); + UserStream cacheFileStream(cacheFileName.string().c_str(), true); + pHull = m_pPhysics->createConvexMesh(cacheFileStream); if( !pHull ) { @@ -659,7 +662,8 @@ PxConvexMesh *CPhysicNovodex :: ConvexMeshFromStudio( entvars_t *pev, int modeli meshDesc.points.stride = sizeof(Vector); meshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; - bool status = m_pCooking->cookConvexMesh( meshDesc, UserStream( cacheFileName.string().c_str(), false )); + UserStream outputFileStream(cacheFileName.string().c_str(), false); + bool status = m_pCooking->cookConvexMesh(meshDesc, outputFileStream); delete [] verts; delete [] m_verts; @@ -671,7 +675,8 @@ PxConvexMesh *CPhysicNovodex :: ConvexMeshFromStudio( entvars_t *pev, int modeli return NULL; } - pHull = m_pPhysics->createConvexMesh( UserStream( cacheFileName.string().c_str(), true )); + UserStream inputFileStream(cacheFileName.string().c_str(), true); + pHull = m_pPhysics->createConvexMesh(inputFileStream); if( !pHull ) ALERT( at_error, "failed to create convex mesh from %s\n", smodel->name ); return pHull; @@ -720,7 +725,8 @@ PxTriangleMesh *CPhysicNovodex::TriangleMeshFromStudio(entvars_t *pev, int model if (CheckFileTimes(smodel->name, cacheFilePath.string().c_str()) && !m_fWorldChanged) { // hull is never than studiomodel. Trying to load it - pMesh = m_pPhysics->createTriangleMesh(UserStream(cacheFilePath.string().c_str(), true)); + UserStream cacheFileStream(cacheFilePath.string().c_str(), true); + pMesh = m_pPhysics->createTriangleMesh(cacheFileStream); if (!pMesh) { @@ -907,7 +913,8 @@ PxTriangleMesh *CPhysicNovodex::TriangleMeshFromStudio(entvars_t *pev, int model PX_ASSERT(res); #endif - bool status = m_pCooking->cookTriangleMesh(meshDesc, UserStream(cacheFilePath.string().c_str(), false)); + UserStream outputFileStream(cacheFilePath.string().c_str(), false); + bool status = m_pCooking->cookTriangleMesh(meshDesc, outputFileStream); delete[] verts; delete[] indices; @@ -917,7 +924,8 @@ PxTriangleMesh *CPhysicNovodex::TriangleMeshFromStudio(entvars_t *pev, int model return NULL; } - pMesh = m_pPhysics->createTriangleMesh(UserStream(cacheFilePath.string().c_str(), true)); + UserStream inputFileStream(cacheFilePath.string().c_str(), true); + pMesh = m_pPhysics->createTriangleMesh(inputFileStream); if (!pMesh) ALERT(at_error, "failed to create triangle mesh from %s\n", smodel->name); return pMesh; @@ -1852,12 +1860,13 @@ int CPhysicNovodex :: FLoadTree( char *szMapName ) } // save off mapname - strcpy ( m_szMapName, szMapName ); + strcpy(m_szMapName, szMapName); char szHullFilename[MAX_PATH]; Q_snprintf( szHullFilename, sizeof( szHullFilename ), "cache/maps/%s.bin", szMapName ); - m_pSceneMesh = m_pPhysics->createTriangleMesh( UserStream( szHullFilename, true )); + UserStream cacheFileStream(szHullFilename, true); + m_pSceneMesh = m_pPhysics->createTriangleMesh(cacheFileStream); m_fWorldChanged = FALSE; return (m_pSceneMesh != NULL) ? TRUE : FALSE; @@ -2038,14 +2047,16 @@ int CPhysicNovodex :: BuildCollisionTree( char *szMapName ) char szHullFilename[MAX_PATH]; Q_snprintf( szHullFilename, sizeof( szHullFilename ), "cache/maps/%s.bin", szMapName ); - if( m_pCooking ) + if (m_pCooking) { - bool status = m_pCooking->cookTriangleMesh( levelDesc, UserStream( szHullFilename, false )); - } + UserStream outputFileStream(szHullFilename, false); + bool status = m_pCooking->cookTriangleMesh(levelDesc, outputFileStream); + } delete [] indices; - m_pSceneMesh = m_pPhysics->createTriangleMesh( UserStream( szHullFilename, true )); + UserStream inputFileStream(szHullFilename, true); + m_pSceneMesh = m_pPhysics->createTriangleMesh(inputFileStream); m_fWorldChanged = TRUE; return (m_pSceneMesh != NULL) ? TRUE : FALSE; diff --git a/server/physics/NxUserStream.cpp b/server/physics/NxUserStream.cpp index 92108e54..e52211ae 100644 --- a/server/physics/NxUserStream.cpp +++ b/server/physics/NxUserStream.cpp @@ -1,6 +1,7 @@ /* NxUserStream.cpp - this file is a part of Novodex physics engine implementation Copyright (C) 2012 Uncle Mike +Copyright (C) 2023 SNMetamorph This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,152 +18,122 @@ GNU General Public License for more details. #include "extdll.h" #include "util.h" -//#include "Pxf.h" #include "NxUserStream.h" -#include using namespace physx; -// user stream. constructor -UserStream :: UserStream( const char* filename, bool load ) : fp(NULL) +UserStream::UserStream(const char *filePath, bool precacheToMemory) { - load_file = load; + m_offset = 0; + m_fileCached = precacheToMemory; + m_fileHandle = nullptr; - if( load_file ) - { - int size; - - // load from pack or disk - buffer = LOAD_FILE( filename, &size ); - m_iLength = size; - m_iOffset = 0; + if (m_fileCached) { + fs::LoadFileToBuffer(filePath, m_dataBuffer); } else { - // make sure the directories have been made - char szFilePath[MAX_PATH]; - char szFullPath[MAX_PATH]; - - // make sure directories have been made - GET_GAME_DIR( szFilePath ); - - Q_snprintf( szFullPath, sizeof( szFullPath ), "%s/%s", szFilePath, filename ); - CreatePath( szFullPath ); // make sure what all folders are existing - - // write to disk - fp = fopen( szFullPath, "wb" ); - ASSERT( fp != NULL ); + m_fileHandle = fs::Open(filePath, "wb"); + ASSERT(m_fileHandle != nullptr); } } -UserStream :: ~UserStream() +UserStream::~UserStream() { - if( load_file ) - { - FREE_FILE( buffer ); - m_iOffset = m_iLength = 0; - buffer = NULL; - } - else + if (m_fileCached) { - if( fp ) fclose( fp ); - fp = NULL; + m_offset = 0; + m_dataBuffer.clear(); } -} - -void UserStream :: CreatePath( char *path ) -{ - char *ofs, save; - - for( ofs = path+1; *ofs; ofs++ ) + else { - if( *ofs == '/' || *ofs == '\\' ) - { - // create the directory - save = *ofs; - *ofs = 0; - _mkdir( path ); - *ofs = save; + if (m_fileHandle) { + fs::Close(m_fileHandle); } + m_fileHandle = nullptr; } } -// Loading API -uint32_t UserStream::read( void *outbuf, uint32_t size ) +uint32_t UserStream::read(void *outputBuf, uint32_t size) { - if( size == 0 ) + if (size == 0) { return 0; + } #ifdef _DEBUG // in case we failed to loading file - memset( outbuf, 0x00, size ); + memset(outputBuf, 0x00, size); #endif - if( !buffer || !outbuf ) + + size_t bufferLength = m_dataBuffer.size(); + if (!bufferLength || !outputBuf) return 0; // check for enough room - if( m_iOffset >= m_iLength ) + if (m_offset >= bufferLength) { + ALERT(at_warning, "UserStream::read: precached file buffer overrun\n"); return 0; // hit EOF + } - size_t read_size = 0; - - if( m_iOffset + size <= m_iLength ) + if (m_offset + size <= bufferLength) { - memcpy( outbuf, buffer + m_iOffset, size ); - (size_t)m_iOffset += size; - read_size = size; + memcpy(outputBuf, m_dataBuffer.data() + m_offset, size); + m_offset += size; + return size; } else { - size_t reduced_size = m_iLength - m_iOffset; - memcpy( outbuf, buffer + m_iOffset, reduced_size ); - (size_t)m_iOffset += reduced_size; - read_size = reduced_size; - ALERT( at_warning, "readBuffer: buffer is overrun\n" ); + ALERT(at_warning, "UserStream::read: precached file buffer overrun\n"); + size_t reducedSize = bufferLength - m_offset; + memcpy(outputBuf, m_dataBuffer.data() + m_offset, reducedSize); + m_offset += reducedSize; + return reducedSize; } - - return read_size; } -// Saving API -uint32_t UserStream::write( const void *buffer, uint32_t size ) +uint32_t UserStream::write(const void *inputBuf, uint32_t size) { - size_t w = fwrite( buffer, size, 1, fp ); - return w; + ASSERT(m_fileHandle != nullptr); + return fs::Write(const_cast(inputBuf), size, m_fileHandle); } -MemoryWriteBuffer::MemoryWriteBuffer() : currentSize(0), maxSize(0), data(NULL) +MemoryWriteBuffer::MemoryWriteBuffer() { + m_currentSize = 0; } MemoryWriteBuffer::~MemoryWriteBuffer() { - free( data ); + m_dataBuffer.clear(); } -uint32_t MemoryWriteBuffer::write( const void *buffer, uint32_t size ) +uint32_t MemoryWriteBuffer::write(const void *inputBuf, uint32_t size) { - PxU32 expectedSize = currentSize + size; - if( expectedSize > maxSize ) - { - maxSize = expectedSize + 4096; - - PxU8 *newData = (PxU8 *)malloc( maxSize ); - if( data ) - { - memcpy( newData, data, currentSize ); - free( data ); - } - data = newData; + const size_t growthSize = 4096; + size_t expectedSize = m_currentSize + size; + if (expectedSize > m_dataBuffer.size()) { + m_dataBuffer.resize(expectedSize + growthSize); } - - memcpy( data + currentSize, buffer, size ); - currentSize += size; + memcpy(m_dataBuffer.data() + m_currentSize, inputBuf, size); + m_currentSize += size; return size; } -MemoryReadBuffer::MemoryReadBuffer(const PxU8* data) : buffer(data) +size_t MemoryWriteBuffer::getSize() const +{ + return m_dataBuffer.size(); +} + +const uint8_t *MemoryWriteBuffer::getData() const { + return m_dataBuffer.data(); +} + +MemoryReadBuffer::MemoryReadBuffer(const uint8_t *data, size_t dataSize) +{ + m_dataSize = dataSize; + m_dataOffset = 0; + m_buffer = data; } MemoryReadBuffer::~MemoryReadBuffer() @@ -170,11 +141,22 @@ MemoryReadBuffer::~MemoryReadBuffer() // We don't own the data => no delete } -uint32_t MemoryReadBuffer::read(void *dest, uint32_t count) +uint32_t MemoryReadBuffer::read(void *outputBuf, uint32_t count) { - memcpy(dest, buffer, count); - buffer += count; - return count; + if (m_dataOffset >= m_dataSize) { + ALERT(at_warning, "MemoryReadBuffer::read: input buffer is overrun\n"); + return 0; + } + + size_t bytesToRead = count; + if (m_dataOffset + count > m_dataSize) { + ALERT(at_warning, "MemoryReadBuffer::read: input buffer is overrun\n"); + bytesToRead = m_dataSize - m_dataOffset; + } + + memcpy(outputBuf, m_buffer + m_dataOffset, bytesToRead); + m_dataOffset += bytesToRead; + return bytesToRead; } #endif // USE_PHYSICS_ENGINE diff --git a/server/physics/NxUserStream.h b/server/physics/NxUserStream.h index 58614bf0..8bcc3d60 100644 --- a/server/physics/NxUserStream.h +++ b/server/physics/NxUserStream.h @@ -1,6 +1,7 @@ /* NxUserStream.h - a Novodex physics engine implementation Copyright (C) 2012 Uncle Mike +Copyright (C) 2023 SNMetamorph This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,25 +19,23 @@ GNU General Public License for more details. #include "PxIO.h" #include "PxSimpleTypes.h" +#include "filesystem_utils.h" +#include class UserStream : public physx::PxInputStream, public physx::PxOutputStream { public: - UserStream( const char *filename, bool load ); + UserStream(const char *filename, bool precacheToMemory); virtual ~UserStream(); - virtual uint32_t read( void *outbuf, uint32_t size ); - virtual uint32_t write( const void *buffer, uint32_t size ); + virtual uint32_t read(void *outputBuf, uint32_t size); + virtual uint32_t write(const void *inputBuf, uint32_t size); private: - bool load_file; // state - FILE *fp; - byte *buffer; - size_t m_iOffset; - size_t m_iLength; - - // misc routines - void CreatePath( char *path ); + bool m_fileCached; + size_t m_offset; + std::vector m_dataBuffer; + fs::FileHandle m_fileHandle; }; class MemoryWriteBuffer : public physx::PxOutputStream @@ -45,23 +44,27 @@ class MemoryWriteBuffer : public physx::PxOutputStream MemoryWriteBuffer(); virtual ~MemoryWriteBuffer(); - virtual uint32_t write(const void *src, uint32_t count); + virtual uint32_t write(const void *inputBuf, uint32_t count); + const uint8_t *getData() const; + size_t getSize() const; - physx::PxU32 currentSize; - physx::PxU32 maxSize; - physx::PxU8 *data; +private: + size_t m_currentSize; + std::vector m_dataBuffer; }; class MemoryReadBuffer : public physx::PxInputStream { public: - MemoryReadBuffer(const physx::PxU8 *data); + MemoryReadBuffer(const uint8_t *data, size_t dataSize); virtual ~MemoryReadBuffer(); virtual uint32_t read(void *dest, uint32_t count); private: - mutable const physx::PxU8 *buffer; + size_t m_dataSize; + size_t m_dataOffset; + mutable const uint8_t *m_buffer; }; #endif // NX_USER_STREAM