Files
XCEngine/engine/third_party/physx/source/common/src/CmSerialize.cpp

417 lines
10 KiB
C++

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxIntrinsics.h"
#include "foundation/PxUtilities.h"
#include "CmSerialize.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxAlloca.h"
#include "foundation/PxFPU.h"
using namespace physx;
using namespace Cm;
void physx::readChunk(PxI8& a, PxI8& b, PxI8& c, PxI8& d, PxInputStream& stream)
{
stream.read(&a, sizeof(PxI8));
stream.read(&b, sizeof(PxI8));
stream.read(&c, sizeof(PxI8));
stream.read(&d, sizeof(PxI8));
}
///////////////////////////////////////////////////////////////////////////////
PxU16 physx::readWord(bool mismatch, PxInputStream& stream)
{
PxU16 d;
stream.read(&d, sizeof(PxU16));
if(mismatch)
flip(d);
return d;
}
PxU32 physx::readDword(bool mismatch, PxInputStream& stream)
{
PxU32 d;
stream.read(&d, sizeof(PxU32));
if(mismatch)
flip(d);
return d;
}
PxF32 physx::readFloat(bool mismatch, PxInputStream& stream)
{
union
{
PxU32 d;
PxF32 f;
} u;
stream.read(&u.d, sizeof(PxU32));
if(mismatch)
flip(u.d);
return u.f;
}
///////////////////////////////////////////////////////////////////////////////
void physx::writeWord(PxU16 value, bool mismatch, PxOutputStream& stream)
{
if(mismatch)
flip(value);
stream.write(&value, sizeof(PxU16));
}
void physx::writeDword(PxU32 value, bool mismatch, PxOutputStream& stream)
{
if(mismatch)
flip(value);
stream.write(&value, sizeof(PxU32));
}
void physx::writeFloat(PxF32 value, bool mismatch, PxOutputStream& stream)
{
if(mismatch)
flip(value);
stream.write(&value, sizeof(PxF32));
}
///////////////////////////////////////////////////////////////////////////////
bool physx::readFloatBuffer(PxF32* dest, PxU32 nbFloats, bool mismatch, PxInputStream& stream)
{
stream.read(dest, sizeof(PxF32)*nbFloats);
if(mismatch)
{
for(PxU32 i=0;i<nbFloats;i++)
flip(dest[i]);
}
return true;
}
void physx::writeFloatBuffer(const PxF32* src, PxU32 nb, bool mismatch, PxOutputStream& stream)
{
if(mismatch)
{
while(nb--)
{
PxF32 f = *src++;
flip(f);
stream.write(&f, sizeof(PxF32));
}
}
else
stream.write(src, sizeof(PxF32) * nb);
}
void physx::writeWordBuffer(const PxU16* src, PxU32 nb, bool mismatch, PxOutputStream& stream)
{
if(mismatch)
{
while(nb--)
{
PxU16 w = *src++;
flip(w);
stream.write(&w, sizeof(PxU16));
}
}
else
stream.write(src, sizeof(PxU16) * nb);
}
void physx::readWordBuffer(PxU16* dest, PxU32 nb, bool mismatch, PxInputStream& stream)
{
stream.read(dest, sizeof(PxU16)*nb);
if(mismatch)
{
for(PxU32 i=0;i<nb;i++)
{
flip(dest[i]);
}
}
}
void physx::writeWordBuffer(const PxI16* src, PxU32 nb, bool mismatch, PxOutputStream& stream)
{
if (mismatch)
{
while (nb--)
{
PxI16 w = *src++;
flip(w);
stream.write(&w, sizeof(PxI16));
}
}
else
stream.write(src, sizeof(PxI16) * nb);
}
void physx::readByteBuffer(PxU8* dest, PxU32 nb, PxInputStream& stream)
{
stream.read(dest, sizeof(PxU8) * nb);
}
void physx::writeByteBuffer(const PxU8* src, PxU32 nb, PxOutputStream& stream)
{
stream.write(src, sizeof(PxU8) * nb);
}
void physx::readWordBuffer(PxI16* dest, PxU32 nb, bool mismatch, PxInputStream& stream)
{
stream.read(dest, sizeof(PxI16)*nb);
if (mismatch)
{
for (PxU32 i = 0; i < nb; i++)
{
flip(dest[i]);
}
}
}
///////////////////////////////////////////////////////////////////////////////
bool physx::writeHeader(PxI8 a, PxI8 b, PxI8 c, PxI8 d, PxU32 version, bool mismatch, PxOutputStream& stream)
{
// Store endianness
PxI8 streamFlags = PxLittleEndian();
if(mismatch)
streamFlags^=1;
// Export header
writeChunk('N', 'X', 'S', streamFlags, stream); // "Novodex stream" identifier
writeChunk(a, b, c, d, stream); // Chunk identifier
writeDword(version, mismatch, stream);
return true;
}
bool Cm::WriteHeader(PxU8 a, PxU8 b, PxU8 c, PxU8 d, PxU32 version, bool mismatch, PxOutputStream& stream)
{
// Store endianness
PxU8 streamFlags = PxU8(PxLittleEndian());
if(mismatch)
streamFlags^=1;
// Export header
writeChunk('I', 'C', 'E', PxI8(streamFlags), stream); // ICE identifier
writeChunk(PxI8(a), PxI8(b), PxI8(c), PxI8(d), stream); // Chunk identifier
writeDword(version, mismatch, stream);
return true;
}
bool physx::readHeader(PxI8 a_, PxI8 b_, PxI8 c_, PxI8 d_, PxU32& version, bool& mismatch, PxInputStream& stream)
{
// Import header
PxI8 a, b, c, d;
readChunk(a, b, c, d, stream);
if(a!='N' || b!='X' || c!='S')
return false;
const PxI8 fileLittleEndian = d&1;
mismatch = fileLittleEndian!=PxLittleEndian();
readChunk(a, b, c, d, stream);
if(a!=a_ || b!=b_ || c!=c_ || d!=d_)
return false;
version = readDword(mismatch, stream);
return true;
}
bool Cm::ReadHeader(PxU8 a_, PxU8 b_, PxU8 c_, PxU8 d_, PxU32& version, bool& mismatch, PxInputStream& stream)
{
// Import header
PxI8 a, b, c, d;
readChunk(a, b, c, d, stream);
if(a!='I' || b!='C' || c!='E')
return false;
const PxU8 FileLittleEndian = PxU8(d&1);
mismatch = FileLittleEndian!=PxLittleEndian();
readChunk(a, b, c, d, stream);
if(a!=a_ || b!=b_ || c!=c_ || d!=d_)
return false;
version = readDword(mismatch, stream);
return true;
}
///////////////////////////////////////////////////////////////////////////////
PxU32 physx::computeMaxIndex(const PxU32* indices, PxU32 nbIndices)
{
PxU32 maxIndex=0;
while(nbIndices--)
{
PxU32 currentIndex = *indices++;
if(currentIndex>maxIndex)
maxIndex = currentIndex;
}
return maxIndex;
}
PxU16 physx::computeMaxIndex(const PxU16* indices, PxU32 nbIndices)
{
PxU16 maxIndex=0;
while(nbIndices--)
{
PxU16 currentIndex = *indices++;
if(currentIndex>maxIndex)
maxIndex = currentIndex;
}
return maxIndex;
}
void physx::storeIndices(PxU32 maxIndex, PxU32 nbIndices, const PxU32* indices, PxOutputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
for(PxU32 i=0;i<nbIndices;i++)
{
PxU8 data = PxU8(indices[i]);
stream.write(&data, sizeof(PxU8));
}
}
else if(maxIndex<=0xffff)
{
for(PxU32 i=0;i<nbIndices;i++)
writeWord(PxTo16(indices[i]), platformMismatch, stream);
}
else
{
writeIntBuffer(indices, nbIndices, platformMismatch, stream);
}
}
void physx::readIndices(PxU32 maxIndex, PxU32 nbIndices, PxU32* indices, PxInputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
PxU8 data;
for(PxU32 i=0;i<nbIndices;i++)
{
stream.read(&data, sizeof(PxU8));
indices[i] = data;
}
}
else if(maxIndex<=0xffff)
{
for(PxU32 i=0;i<nbIndices;i++)
indices[i] = readWord(platformMismatch, stream);
}
else
{
readIntBuffer(indices, nbIndices, platformMismatch, stream);
}
}
///////////////////////////////////////////////////////////////////////////////
void Cm::StoreIndices(PxU32 maxIndex, PxU32 nbIndices, const PxU32* indices, PxOutputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
for(PxU32 i=0;i<nbIndices;i++)
{
PxU8 data = PxU8(indices[i]);
stream.write(&data, sizeof(PxU8));
}
}
else if(maxIndex<=0xffff)
{
for(PxU32 i=0;i<nbIndices;i++)
writeWord(PxTo16(indices[i]), platformMismatch, stream);
}
else
{
// WriteDwordBuffer(indices, nbIndices, platformMismatch, stream);
for(PxU32 i=0;i<nbIndices;i++)
writeDword(indices[i], platformMismatch, stream);
}
}
void Cm::ReadIndices(PxU32 maxIndex, PxU32 nbIndices, PxU32* indices, PxInputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
PxU8* tmp = reinterpret_cast<PxU8*>(PxAlloca(nbIndices*sizeof(PxU8)));
stream.read(tmp, nbIndices*sizeof(PxU8));
for(PxU32 i=0;i<nbIndices;i++)
indices[i] = tmp[i];
// for(PxU32 i=0;i<nbIndices;i++)
// indices[i] = stream.ReadByte();
}
else if(maxIndex<=0xffff)
{
PxU16* tmp = reinterpret_cast<PxU16*>(PxAlloca(nbIndices*sizeof(PxU16)));
readWordBuffer(tmp, nbIndices, platformMismatch, stream);
for(PxU32 i=0;i<nbIndices;i++)
indices[i] = tmp[i];
// for(PxU32 i=0;i<nbIndices;i++)
// indices[i] = ReadWord(platformMismatch, stream);
}
else
{
ReadDwordBuffer(indices, nbIndices, platformMismatch, stream);
}
}
void Cm::StoreIndices(PxU16 maxIndex, PxU32 nbIndices, const PxU16* indices, PxOutputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
for(PxU32 i=0;i<nbIndices;i++)
{
PxU8 data = PxU8(indices[i]);
stream.write(&data, sizeof(PxU8));
}
}
else
{
for(PxU32 i=0;i<nbIndices;i++)
writeWord(indices[i], platformMismatch, stream);
}
}
void Cm::ReadIndices(PxU16 maxIndex, PxU32 nbIndices, PxU16* indices, PxInputStream& stream, bool platformMismatch)
{
if(maxIndex<=0xff)
{
PxU8* tmp = reinterpret_cast<PxU8*>(PxAlloca(nbIndices*sizeof(PxU8)));
stream.read(tmp, nbIndices*sizeof(PxU8));
for(PxU32 i=0;i<nbIndices;i++)
indices[i] = tmp[i];
}
else
{
readWordBuffer(indices, nbIndices, platformMismatch, stream);
}
}