476 lines
17 KiB
C++
476 lines
17 KiB
C++
|
/*
|
||
|
Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
|
||
|
|
||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
of this software and associated documentation files (the "Software"), to deal
|
||
|
in the Software without restriction, including without limitation the rights
|
||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
copies of the Software, and to permit persons to whom the Software is
|
||
|
furnished to do so, subject to the following conditions:
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included in
|
||
|
all copies or substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "o3dgcTriangleFans.h"
|
||
|
#include "o3dgcArithmeticCodec.h"
|
||
|
|
||
|
//#define DEBUG_VERBOSE
|
||
|
|
||
|
namespace o3dgc
|
||
|
{
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
FILE* g_fileDebugTF = NULL;
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
|
||
|
O3DGCErrorCode SaveUIntData(const Vector<long> & data,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
bstream.WriteUInt32ASCII(0);
|
||
|
const unsigned long size = data.GetSize();
|
||
|
bstream.WriteUInt32ASCII(size);
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
bstream.WriteUIntASCII(data[i]);
|
||
|
}
|
||
|
bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode SaveIntData(const Vector<long> & data,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
bstream.WriteUInt32ASCII(0);
|
||
|
const unsigned long size = data.GetSize();
|
||
|
bstream.WriteUInt32ASCII(size);
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
bstream.WriteIntASCII(data[i]);
|
||
|
}
|
||
|
bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode SaveBinData(const Vector<long> & data,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
bstream.WriteUInt32ASCII(0);
|
||
|
const unsigned long size = data.GetSize();
|
||
|
long symbol;
|
||
|
bstream.WriteUInt32ASCII(size);
|
||
|
for(unsigned long i = 0; i < size; )
|
||
|
{
|
||
|
symbol = 0;
|
||
|
for(unsigned long h = 0; h < O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0 && i < size; ++h)
|
||
|
{
|
||
|
symbol += (data[i] << h);
|
||
|
++i;
|
||
|
}
|
||
|
bstream.WriteUCharASCII((unsigned char) symbol);
|
||
|
}
|
||
|
bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode CompressedTriangleFans::SaveUIntAC(const Vector<long> & data,
|
||
|
const unsigned long M,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
const unsigned int NMAX = data.GetSize() * 8 + 100;
|
||
|
const unsigned long size = data.GetSize();
|
||
|
long minValue = O3DGC_MAX_LONG;
|
||
|
bstream.WriteUInt32Bin(0);
|
||
|
bstream.WriteUInt32Bin(size);
|
||
|
if (size > 0)
|
||
|
{
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i, start %i\n", size, start);
|
||
|
fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
if (minValue > data[i])
|
||
|
{
|
||
|
minValue = data[i];
|
||
|
}
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
bstream.WriteUInt32Bin(minValue);
|
||
|
if ( m_sizeBufferAC < NMAX )
|
||
|
{
|
||
|
delete [] m_bufferAC;
|
||
|
m_sizeBufferAC = NMAX;
|
||
|
m_bufferAC = new unsigned char [m_sizeBufferAC];
|
||
|
}
|
||
|
Arithmetic_Codec ace;
|
||
|
ace.set_buffer(NMAX, m_bufferAC);
|
||
|
ace.start_encoder();
|
||
|
Adaptive_Data_Model mModelValues(M+1);
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
ace.encode(data[i]-minValue, mModelValues);
|
||
|
}
|
||
|
unsigned long encodedBytes = ace.stop_encoder();
|
||
|
for(unsigned long i = 0; i < encodedBytes; ++i)
|
||
|
{
|
||
|
bstream.WriteUChar8Bin(m_bufferAC[i]);
|
||
|
}
|
||
|
}
|
||
|
bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode CompressedTriangleFans::SaveBinAC(const Vector<long> & data,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
const unsigned int NMAX = data.GetSize() * 8 + 100;
|
||
|
const unsigned long size = data.GetSize();
|
||
|
bstream.WriteUInt32Bin(0);
|
||
|
bstream.WriteUInt32Bin(size);
|
||
|
if (size > 0)
|
||
|
{
|
||
|
if ( m_sizeBufferAC < NMAX )
|
||
|
{
|
||
|
delete [] m_bufferAC;
|
||
|
m_sizeBufferAC = NMAX;
|
||
|
m_bufferAC = new unsigned char [m_sizeBufferAC];
|
||
|
}
|
||
|
Arithmetic_Codec ace;
|
||
|
ace.set_buffer(NMAX, m_bufferAC);
|
||
|
ace.start_encoder();
|
||
|
Adaptive_Bit_Model bModel;
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i, start %i\n", size, start);
|
||
|
fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
ace.encode(data[i], bModel);
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
unsigned long encodedBytes = ace.stop_encoder();
|
||
|
for(unsigned long i = 0; i < encodedBytes; ++i)
|
||
|
{
|
||
|
bstream.WriteUChar8Bin(m_bufferAC[i]);
|
||
|
}
|
||
|
}
|
||
|
bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
|
||
|
O3DGCErrorCode CompressedTriangleFans::SaveIntACEGC(const Vector<long> & data,
|
||
|
const unsigned long M,
|
||
|
BinaryStream & bstream)
|
||
|
{
|
||
|
unsigned long start = bstream.GetSize();
|
||
|
const unsigned int NMAX = data.GetSize() * 8 + 100;
|
||
|
const unsigned long size = data.GetSize();
|
||
|
long minValue = 0;
|
||
|
bstream.WriteUInt32Bin(0);
|
||
|
bstream.WriteUInt32Bin(size);
|
||
|
if (size > 0)
|
||
|
{
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i, start %i\n", size, start);
|
||
|
fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
if (minValue > data[i])
|
||
|
{
|
||
|
minValue = data[i];
|
||
|
}
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
bstream.WriteUInt32Bin(minValue + O3DGC_MAX_LONG);
|
||
|
if ( m_sizeBufferAC < NMAX )
|
||
|
{
|
||
|
delete [] m_bufferAC;
|
||
|
m_sizeBufferAC = NMAX;
|
||
|
m_bufferAC = new unsigned char [m_sizeBufferAC];
|
||
|
}
|
||
|
Arithmetic_Codec ace;
|
||
|
ace.set_buffer(NMAX, m_bufferAC);
|
||
|
ace.start_encoder();
|
||
|
Adaptive_Data_Model mModelValues(M+2);
|
||
|
Static_Bit_Model bModel0;
|
||
|
Adaptive_Bit_Model bModel1;
|
||
|
unsigned long value;
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
value = data[i]-minValue;
|
||
|
if (value < M)
|
||
|
{
|
||
|
ace.encode(value, mModelValues);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ace.encode(M, mModelValues);
|
||
|
ace.ExpGolombEncode(value-M, 0, bModel0, bModel1);
|
||
|
}
|
||
|
}
|
||
|
unsigned long encodedBytes = ace.stop_encoder();
|
||
|
for(unsigned long i = 0; i < encodedBytes; ++i)
|
||
|
{
|
||
|
bstream.WriteUChar8Bin(m_bufferAC[i]);
|
||
|
}
|
||
|
}
|
||
|
bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode CompressedTriangleFans::Save(BinaryStream & bstream, bool encodeTrianglesOrder, O3DGCStreamType streamType)
|
||
|
{
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
g_fileDebugTF = fopen("SaveIntACEGC_new.txt", "w");
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
|
||
|
if (streamType == O3DGC_STREAM_TYPE_ASCII)
|
||
|
{
|
||
|
SaveUIntData(m_numTFANs , bstream);
|
||
|
SaveUIntData(m_degrees , bstream);
|
||
|
SaveUIntData(m_configs , bstream);
|
||
|
SaveBinData (m_operations, bstream);
|
||
|
SaveIntData (m_indices , bstream);
|
||
|
if (encodeTrianglesOrder)
|
||
|
{
|
||
|
SaveUIntData(m_trianglesOrder, bstream);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SaveIntACEGC(m_numTFANs , 4 , bstream);
|
||
|
SaveIntACEGC(m_degrees , 16, bstream);
|
||
|
SaveUIntAC (m_configs , 10, bstream);
|
||
|
SaveBinAC (m_operations, bstream);
|
||
|
SaveIntACEGC(m_indices , 8 , bstream);
|
||
|
if (encodeTrianglesOrder)
|
||
|
{
|
||
|
SaveIntACEGC(m_trianglesOrder , 16, bstream);
|
||
|
}
|
||
|
}
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
fclose(g_fileDebugTF);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadUIntData(Vector<long> & data,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
bstream.ReadUInt32ASCII(iterator);
|
||
|
const unsigned long size = bstream.ReadUInt32ASCII(iterator);
|
||
|
data.Allocate(size);
|
||
|
data.Clear();
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
data.PushBack(bstream.ReadUIntASCII(iterator));
|
||
|
}
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadIntData(Vector<long> & data,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
bstream.ReadUInt32ASCII(iterator);
|
||
|
const unsigned long size = bstream.ReadUInt32ASCII(iterator);
|
||
|
data.Allocate(size);
|
||
|
data.Clear();
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
data.PushBack(bstream.ReadIntASCII(iterator));
|
||
|
}
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadBinData(Vector<long> & data,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
bstream.ReadUInt32ASCII(iterator);
|
||
|
const unsigned long size = bstream.ReadUInt32ASCII(iterator);
|
||
|
long symbol;
|
||
|
data.Allocate(size * O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0);
|
||
|
data.Clear();
|
||
|
for(unsigned long i = 0; i < size;)
|
||
|
{
|
||
|
symbol = bstream.ReadUCharASCII(iterator);
|
||
|
for(unsigned long h = 0; h < O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0; ++h)
|
||
|
{
|
||
|
data.PushBack(symbol & 1);
|
||
|
symbol >>= 1;
|
||
|
++i;
|
||
|
}
|
||
|
}
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadUIntAC(Vector<long> & data,
|
||
|
const unsigned long M,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 12;
|
||
|
unsigned long size = bstream.ReadUInt32Bin(iterator);
|
||
|
if (size == 0)
|
||
|
{
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
long minValue = bstream.ReadUInt32Bin(iterator);
|
||
|
unsigned char * buffer = 0;
|
||
|
bstream.GetBuffer(iterator, buffer);
|
||
|
iterator += sizeSize;
|
||
|
data.Allocate(size);
|
||
|
Arithmetic_Codec acd;
|
||
|
acd.set_buffer(sizeSize, buffer);
|
||
|
acd.start_decoder();
|
||
|
Adaptive_Data_Model mModelValues(M+1);
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i\n", size);
|
||
|
fprintf(g_fileDebugTF, "size %i\n", size);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
data.PushBack(acd.decode(mModelValues)+minValue);
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadIntACEGC(Vector<long> & data,
|
||
|
const unsigned long M,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 12;
|
||
|
unsigned long size = bstream.ReadUInt32Bin(iterator);
|
||
|
if (size == 0)
|
||
|
{
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
long minValue = bstream.ReadUInt32Bin(iterator) - O3DGC_MAX_LONG;
|
||
|
unsigned char * buffer = 0;
|
||
|
bstream.GetBuffer(iterator, buffer);
|
||
|
iterator += sizeSize;
|
||
|
data.Allocate(size);
|
||
|
Arithmetic_Codec acd;
|
||
|
acd.set_buffer(sizeSize, buffer);
|
||
|
acd.start_decoder();
|
||
|
Adaptive_Data_Model mModelValues(M+2);
|
||
|
Static_Bit_Model bModel0;
|
||
|
Adaptive_Bit_Model bModel1;
|
||
|
unsigned long value;
|
||
|
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i\n", size);
|
||
|
fprintf(g_fileDebugTF, "size %i\n", size);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
value = acd.decode(mModelValues);
|
||
|
if ( value == M)
|
||
|
{
|
||
|
value += acd.ExpGolombDecode(0, bModel0, bModel1);
|
||
|
}
|
||
|
data.PushBack(value + minValue);
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
fflush(g_fileDebugTF);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode LoadBinAC(Vector<long> & data,
|
||
|
const BinaryStream & bstream,
|
||
|
unsigned long & iterator)
|
||
|
{
|
||
|
unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 8;
|
||
|
unsigned long size = bstream.ReadUInt32Bin(iterator);
|
||
|
if (size == 0)
|
||
|
{
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
unsigned char * buffer = 0;
|
||
|
bstream.GetBuffer(iterator, buffer);
|
||
|
iterator += sizeSize;
|
||
|
data.Allocate(size);
|
||
|
Arithmetic_Codec acd;
|
||
|
acd.set_buffer(sizeSize, buffer);
|
||
|
acd.start_decoder();
|
||
|
Adaptive_Bit_Model bModel;
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("-----------\nsize %i\n", size);
|
||
|
fprintf(g_fileDebugTF, "size %i\n", size);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
for(unsigned long i = 0; i < size; ++i)
|
||
|
{
|
||
|
data.PushBack(acd.decode(bModel));
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
printf("%i\t%i\n", i, data[i]);
|
||
|
fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
}
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
O3DGCErrorCode CompressedTriangleFans::Load(const BinaryStream & bstream,
|
||
|
unsigned long & iterator,
|
||
|
bool decodeTrianglesOrder,
|
||
|
O3DGCStreamType streamType)
|
||
|
{
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
g_fileDebugTF = fopen("Load_new.txt", "w");
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
if (streamType == O3DGC_STREAM_TYPE_ASCII)
|
||
|
{
|
||
|
LoadUIntData(m_numTFANs , bstream, iterator);
|
||
|
LoadUIntData(m_degrees , bstream, iterator);
|
||
|
LoadUIntData(m_configs , bstream, iterator);
|
||
|
LoadBinData (m_operations, bstream, iterator);
|
||
|
LoadIntData (m_indices , bstream, iterator);
|
||
|
if (decodeTrianglesOrder)
|
||
|
{
|
||
|
LoadUIntData(m_trianglesOrder , bstream, iterator);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadIntACEGC(m_numTFANs , 4 , bstream, iterator);
|
||
|
LoadIntACEGC(m_degrees , 16, bstream, iterator);
|
||
|
LoadUIntAC (m_configs , 10, bstream, iterator);
|
||
|
LoadBinAC (m_operations, bstream, iterator);
|
||
|
LoadIntACEGC(m_indices , 8 , bstream, iterator);
|
||
|
if (decodeTrianglesOrder)
|
||
|
{
|
||
|
LoadIntACEGC(m_trianglesOrder , 16, bstream, iterator);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG_VERBOSE
|
||
|
fclose(g_fileDebugTF);
|
||
|
#endif //DEBUG_VERBOSE
|
||
|
return O3DGC_OK;
|
||
|
}
|
||
|
}
|
||
|
|