Commit 84c6199e authored by Christopher Tenter's avatar Christopher Tenter
Browse files

Add support for loading splat binaries ver 3

parent cc4e5ffe
include (plugin)
openflipper_plugin (TYPES SPLATCLOUD)
openflipper_plugin (DIRS Snappy
TYPES SPLATCLOUD)
......@@ -62,6 +62,8 @@
#include "FilePTS.hh"
#include "Snappy/snappy.h"
#if QT_VERSION >= 0x050000
#include <QtWidgets>
#else
......@@ -102,9 +104,82 @@ FilePTSPlugin::FilePTSPlugin() :
saveMakeDefaultButton_( 0 )
{ }
//----------------------------------------------------------------
void FilePTSPlugin::initializePlugin()
{
QString info =
"This plugin is based on the Snappy compression library by google<br> "
"<br> "
"The following license applies to their code: <br> "
"Copyright 2005 Google Inc.All Rights Reserved. <br>"
" <br>"
"Redistribution and use in source and binary forms, with or without <br>"
"modification, are permitted provided that the following conditions are <br>"
"met : <br>"
" <br>"
" *Redistributions of source code must retain the above copyright <br>"
"notice, this list of conditions and the following disclaimer. <br>"
" * Redistributions in binary form must reproduce the above <br>"
"copyright notice, this list of conditions and the following disclaimer <br>"
"in the documentation and / or other materials provided with the <br>"
"distribution. <br>"
" * Neither the name of Google Inc.nor the names of its <br>"
"contributors may be used to endorse or promote products derived from <br>"
"this software without specific prior written permission. <br>"
" <br>"
"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS <br>"
"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT <br>"
"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR <br>"
"A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT <br>"
"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, <br>"
"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT <br>"
"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, <br>"
"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY <br>"
"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT <br>"
"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE <br>"
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
emit addAboutInfo(info, "FilePTS");
}
//----------------------------------------------------------------
namespace SplatDataFileFormat
{
// Standard Property Types (File Format)
enum STDPropTypes
{
FLOAT = 0,
FLOATVEC2 = 1,
FLOATVEC3 = 2,
DOUBLE = 3,
DOUBLEVEC2 = 4,
DOUBLEVEC3 = 5,
INT32 = 6,
INT32VEC2 = 7,
INT32VEC3 = 8,
INT16 = 9,
INT16VEC2 = 10,
INT16VEC3 = 11,
INT8 = 12,
INT8VEC2 = 13,
INT8VEC3 = 14,
UINT32 = 15,
UINT32VEC2 = 16,
UINT32VEC3 = 17,
UINT16 = 18,
UINT16VEC2 = 19,
UINT16VEC3 = 20,
UINT8 = 21,
UINT8VEC2 = 22,
UINT8VEC3 = 23,
INT32ARRAY = 24,
FLOATVEC2ARRAY = 25,
FLOATVEC3ARRAY = 26,
};
}
bool FilePTSPlugin::readBinaryFile( const char *_filename, SplatCloud &_splatCloud ) /*const*/
{
......@@ -156,7 +231,7 @@ bool FilePTSPlugin::readBinaryFile( const char *_filename, SplatCloud &_splatClo
fread( &fileType, sizeof(int), 1, file );
// check file type
if( fileType != 1 && fileType != 2 )
if( fileType != 1 && fileType != 2 && fileType != 3 )
{
emit log( LOGERR, tr("Bad filetype (%1) in input file \"%2\".\n").arg( QString::number( fileType ), _filename ) );
fclose( file );
......@@ -170,91 +245,174 @@ bool FilePTSPlugin::readBinaryFile( const char *_filename, SplatCloud &_splatClo
// set number of splats
_splatCloud.resizeSplats( numSplats );
// read positions
if (fileType < 3)
{
unsigned int i;
for( i=0; i<numSplats; ++i )
// read positions
{
float pos[3];
fread( pos, sizeof(float), 3, file );
unsigned int i;
for (i = 0; i < numSplats; ++i)
{
float pos[3];
fread(pos, sizeof(float), 3, file);
SplatCloud::Position position;
position[0] = pos[0];
position[1] = pos[1];
position[2] = pos[2];
SplatCloud::Position position;
position[0] = pos[0];
position[1] = pos[1];
position[2] = pos[2];
_splatCloud.positions( i ) = position;
_splatCloud.positions(i) = position;
}
}
}
// read normals
if( loadNormals )
{
unsigned int i;
for( i=0; i<numSplats; ++i )
// read normals
if (loadNormals)
{
float nrm[3];
fread( nrm, sizeof(float), 3, file );
unsigned int i;
for (i = 0; i < numSplats; ++i)
{
float nrm[3];
fread(nrm, sizeof(float), 3, file);
SplatCloud::Normal normal;
normal[0] = nrm[0];
normal[1] = nrm[1];
normal[2] = nrm[2];
SplatCloud::Normal normal;
normal[0] = nrm[0];
normal[1] = nrm[1];
normal[2] = nrm[2];
_splatCloud.normals( i ) = normal;
_splatCloud.normals(i) = normal;
}
}
}
// read pointsizes
if( loadPointsizes )
{
unsigned int i;
for( i=0; i<numSplats; ++i )
// read pointsizes
if (loadPointsizes)
{
float ps = 0.0f;
fread( &ps, sizeof(float), 1, file );
unsigned int i;
for (i = 0; i < numSplats; ++i)
{
float ps = 0.0f;
fread(&ps, sizeof(float), 1, file);
SplatCloud::Pointsize pointsize;
pointsize = ps;
SplatCloud::Pointsize pointsize;
pointsize = ps;
_splatCloud.pointsizes( i ) = pointsize;
_splatCloud.pointsizes(i) = pointsize;
}
}
}
// read colors
if( loadColors )
{
unsigned int i;
for( i=0; i<numSplats; ++i )
// read colors
if (loadColors)
{
unsigned int col = 0;
fread( &col, sizeof(unsigned int), 1, file );
unsigned int i;
for (i = 0; i < numSplats; ++i)
{
unsigned int col = 0;
fread(&col, sizeof(unsigned int), 1, file);
SplatCloud::Color color; // ignore colorrange
color[0] = (unsigned char) ((col >> 16) & 0xFF);
color[1] = (unsigned char) ((col >> 8) & 0xFF);
color[2] = (unsigned char) ((col ) & 0xFF);
SplatCloud::Color color; // ignore colorrange
color[0] = (unsigned char)((col >> 16) & 0xFF);
color[1] = (unsigned char)((col >> 8) & 0xFF);
color[2] = (unsigned char)((col) & 0xFF);
_splatCloud.colors( i ) = color;
_splatCloud.colors(i) = color;
}
}
}
// read indices
if( loadIndices )
// read indices
if (loadIndices)
{
unsigned int i;
for (i = 0; i < numSplats; ++i)
{
int idx = -1;
fread(&idx, sizeof(idx), 1, file);
SplatCloud::Index index;
index = idx;
_splatCloud.indices(i) = index;
}
}
}
else if (fileType == 3)
{
unsigned int i;
for( i=0; i<numSplats; ++i )
// file contains named property containers
int numProperties = 0;
fread(&numProperties, sizeof(int), 1, file);
for (int propID = 0; propID < numProperties; ++propID)
{
int idx = -1;
fread( &idx, sizeof(idx), 1, file );
// read property chunk
SplatCloud::Index index;
index = idx;
// property name
int propNameLen = 0;
fread(&propNameLen, sizeof(int), 1, file);
std::string propName(propNameLen, 0);
if (propNameLen > 0)
fread(&propName[0], 1, propNameLen, file);
// property data type
int dataType = 0;
fread(&dataType, sizeof(int), 1, file);
// size of compressed data chunk
quint64 compressedSize = 0;
fread(&compressedSize, sizeof(quint64), 1, file);
size_t compressedSizeT = static_cast<size_t>(compressedSize);
_splatCloud.indices( i ) = index;
if (compressedSize)
{
// read data
if (dataType == SplatDataFileFormat::FLOATVEC3)
{
if (propName == "Points")
readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.positions(0)));
else if (propName == "Normals" && loadNormals)
readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.normals(0)));
else
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
else if (dataType == SplatDataFileFormat::FLOAT)
{
if (propName == "Radii" && loadPointsizes)
readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.pointsizes(0)));
else
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
else if (dataType == SplatDataFileFormat::UINT16)
{
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
else if (dataType == SplatDataFileFormat::UINT32)
{
if (propName == "Colors" && loadColors)
{
std::vector<ACG::Vec4uc> fileColors(numSplats);
readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&fileColors[0]));
for (uint i = 0; i < numSplats; ++i)
{
for (int k = 0; k < 3; ++k)
_splatCloud.colors(i)[k] = fileColors[i][k];
}
}
else
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
else if (dataType == SplatDataFileFormat::INT32)
{
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
else
{
emit log(LOGWARN, tr("Unknown Property type. \"%1\".\n").arg(_filename));
fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
}
}
}
}
// check for errors
if( ferror( file ) )
{
......@@ -737,6 +895,16 @@ bool FilePTSPlugin::writeTextFile( const char *_filename, const SplatCloudNode *
//----------------------------------------------------------------
bool FilePTSPlugin::readCompressedBinaryChunk(FILE* _file, size_t _compressedSize, char* _dst)
{
std::vector<char> compressedData(_compressedSize);
fread(&compressedData[0], 1, _compressedSize, _file);
return snappy::RawUncompress(&compressedData[0], _compressedSize, _dst);
}
//----------------------------------------------------------------
int FilePTSPlugin::loadObject( QString _filename )
{
// set default options
......@@ -816,7 +984,7 @@ int FilePTSPlugin::loadObject( QString _filename )
}
// something went wrong, so delete objects
unsigned int i, num = objectIDs.size();
size_t i, num = objectIDs.size();
for( i=0; i<num; ++i )
emit deleteObject( objectIDs[ i ] );
}
......
......@@ -77,6 +77,7 @@ class QPushButton;
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <OpenFlipper/BasePlugin/ScriptInterface.hh>
#include <OpenFlipper/BasePlugin/RPCInterface.hh>
#include <OpenFlipper/BasePlugin/AboutInfoInterface.hh>
#include <OpenFlipper/common/Types.hh>
......@@ -86,15 +87,16 @@ class QPushButton;
//== CLASS DEFINITION ============================================
class FilePTSPlugin : public QObject, BaseInterface, FileInterface, LoadSaveInterface, LoggingInterface, ScriptInterface, RPCInterface
class FilePTSPlugin : public QObject, BaseInterface, FileInterface, LoadSaveInterface, LoggingInterface, ScriptInterface, RPCInterface, AboutInfoInterface
{
Q_OBJECT
Q_INTERFACES( FileInterface )
Q_INTERFACES( LoadSaveInterface )
Q_INTERFACES( LoggingInterface )
Q_INTERFACES( BaseInterface )
Q_INTERFACES( ScriptInterface )
Q_INTERFACES( RPCInterface )
Q_INTERFACES( FileInterface )
Q_INTERFACES( LoadSaveInterface )
Q_INTERFACES( LoggingInterface )
Q_INTERFACES( BaseInterface )
Q_INTERFACES( ScriptInterface )
Q_INTERFACES( RPCInterface )
Q_INTERFACES( AboutInfoInterface )
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.OpenFlipper.Plugins.Plugin-FilePTS")
#endif
......@@ -112,9 +114,13 @@ signals:
void log( QString _message );
void log( Logtype _type, QString _message );
//-- AboutInfoInterface --
void addAboutInfo(QString _text, QString _tabName);
private slots:
// -- Base Interface --
void initializePlugin();
void noguiSupported() { }
public:
......@@ -155,6 +161,10 @@ private:
bool writeBinaryFile( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/;
bool writeTextFile ( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/;
// read and decompress a binary chunk from file stream (snappy compression)
bool readCompressedBinaryChunk( FILE* _file, size_t _compressedSize, char* _dst );
// widgets
QWidget *loadOptions_;
QWidget *saveOptions_;
......
// Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
//
// 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 Google Inc. 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 AND CONTRIBUTORS
// "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.
#include "snappy.h"
#include "snappy-c.h"
extern "C" {
snappy_status snappy_compress(const char* input,
size_t input_length,
char* compressed,
size_t *compressed_length) {
if (*compressed_length < snappy_max_compressed_length(input_length)) {
return SNAPPY_BUFFER_TOO_SMALL;
}
snappy::RawCompress(input, input_length, compressed, compressed_length);
return SNAPPY_OK;
}
snappy_status snappy_uncompress(const char* compressed,
size_t compressed_length,
char* uncompressed,
size_t* uncompressed_length) {
size_t real_uncompressed_length;
if (!snappy::GetUncompressedLength(compressed,
compressed_length,
&real_uncompressed_length)) {
return SNAPPY_INVALID_INPUT;
}
if (*uncompressed_length < real_uncompressed_length) {
return SNAPPY_BUFFER_TOO_SMALL;
}
if (!snappy::RawUncompress(compressed, compressed_length, uncompressed)) {
return SNAPPY_INVALID_INPUT;
}
*uncompressed_length = real_uncompressed_length;
return SNAPPY_OK;
}
size_t snappy_max_compressed_length(size_t source_length) {
return snappy::MaxCompressedLength(source_length);
}
snappy_status snappy_uncompressed_length(const char *compressed,
size_t compressed_length,
size_t *result) {
if (snappy::GetUncompressedLength(compressed,
compressed_length,
result)) {
return SNAPPY_OK;
} else {
return SNAPPY_INVALID_INPUT;
}
}
snappy_status snappy_validate_compressed_buffer(const char *compressed,
size_t compressed_length) {
if (snappy::IsValidCompressedBuffer(compressed, compressed_length)) {
return SNAPPY_OK;
} else {
return SNAPPY_INVALID_INPUT;
}
}
} // extern "C"
/*
* Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
*
* 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 Google Inc. 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 AND CONTRIBUTORS
* "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.
*
* Plain C interface (a wrapper around the C++ implementation).
*/
#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_
#define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
/*
* Return values; see the documentation for each function to know
* what each can return.
*/
typedef enum {
SNAPPY_OK = 0,
SNAPPY_INVALID_INPUT = 1,
SNAPPY_BUFFER_TOO_SMALL = 2
} snappy_status;
/*
* Takes the data stored in "input[0..input_length-1]" and stores
* it in the array pointed to by "compressed".
*
* <compressed_length> signals the space available in "compressed".
* If it is not at least equal to "snappy_max_compressed_length(input_length)",
* SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression,
* <compressed_length> contains the true length of the compressed output,
* and SNAPPY_OK is returned.
*
* Example:
* size_t output_length = snappy_max_compressed_length(input_length);
* char* output = (char*)malloc(output_length);
* if (snappy_compress(input, input_length, output, &output_length)
* == SNAPPY_OK) {
* ... Process(output, output_length) ...
* }
* free(output);
*/
snappy_status snappy_compress(const char* input,
size_t input_length,
char* compressed,
size_t* compressed_length);
/*
* Given data in "compressed[0..compressed_length-1]" generated by
* calling the snappy_compress routine, this routine stores
* the uncompressed data to
* uncompressed[0..uncompressed_length-1].
* Returns failure (a value not equal to SNAPPY_OK) if the message
* is corrupted and could not be decrypted.
*
* <uncompressed_length> signals the space available in "uncompressed".
* If it is not at least equal to the value returned by
* snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL
* is returned. After successful decompression, <uncompressed_length>
* contains the true length of the decompressed output.
*
* Example:
* size_t output_length;
* if (snappy_uncompressed_length(input, input_length, &output_length)
* != SNAPPY_OK) {
* ... fail ...
* }
* char* output = (char*)malloc(output_length);
* if (snappy_uncompress(input, input_length, output, &output_length)
* == SNAPPY_OK) {
* ... Process(output, output_length) ...
* }
* free(output);
*/
snappy_status snappy_uncompress(const char* compressed,
size_t compressed_length,
char* uncompressed,
size_t* uncompressed_length);
/*
* Returns the maximal size of the compressed representation of
* input data that is "source_length" bytes in length.
*/
size_t snappy_max_compressed_length(size_t source_length);