// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #include <frantic/channels/channel_map.hpp> #include <frantic/channels/property_map.hpp> #include <frantic/graphics/boundbox3f.hpp> #include <frantic/particles/particle_file_metadata.hpp> namespace frantic { namespace particles { // This class represents a PRT file header, and is able to read or write it to an istream or ostream, respectively, on // disk. class prt_file_header { // This is the particle channel map of the file representation channels::channel_map m_particleChannelMap; boost::int64_t m_particleCount; bool m_allowNegativeCount; particle_file_metadata m_metadata; std::streampos m_particleCountPos; // Stores the stream position where the particle count must be written. std::streampos m_boundboxPos; // Stores the stream position where the boundbox value must be written. public: prt_file_header() { m_particleCount = -1; m_allowNegativeCount = false; } prt_file_header( const channels::channel_map& particleChannelMap ) : m_particleChannelMap( particleChannelMap ) { if( particleChannelMap.needs_scope_management() ) throw std::runtime_error( "prt_file_header() - The channel map particle layout requested includes non-raw data, " "such as a string. The particle layout must be raw numeric data." ); m_particleCount = -1; m_allowNegativeCount = false; } void set_allow_negative_count( bool allow ) { m_allowNegativeCount = allow; } /** * \return A property_map storing the general metadata from the prt file. */ const frantic::channels::property_map& get_general_metadata() const { return m_metadata.get_general_metadata(); } /** * Use this function to assign metadata that will be written by the next call to write_header(). * \param metadata The collection of names & values to write into the prt file. */ void set_general_metadata( const frantic::channels::property_map& metadata ); const frantic::channels::property_map* get_channel_metadata( const frantic::tstring& channelName ) const { return m_metadata.get_channel_metadata( channelName ); } void set_channel_metadata( const frantic::tstring& channelName, const frantic::channels::property_map& metadata ) { if( !m_particleChannelMap.has_channel( channelName ) ) throw std::invalid_argument( "prt_file_header.get_channel_metadata() Cannot add metadata to non-existing channel named \"" + frantic::strings::to_string( channelName ) + "\"" ); m_metadata.set_channel_metadata( channelName, metadata ); } const particle_file_metadata& get_all_metadata() const { return m_metadata; } void set_all_metadata( const particle_file_metadata& data ); ////////////////////// // Functions for dealing with the particle channel map ////////////////////// void set_channel_map( const channels::channel_map& particleChannelMap ) { if( particleChannelMap.needs_scope_management() ) throw std::runtime_error( "prt_file_header.set_channel_map() - The channel map particle layout requested " "includes non-raw data, such " "as a string. The particle layout must be raw numeric data." ); m_particleChannelMap = particleChannelMap; // We don't want to have any padding in the files we save // (i.e. if the particle uses 26 bytes, save 26 bytes and // not 28 bytes as it would be with 4 byte padding) m_particleChannelMap.remove_padding(); } const channels::channel_map& get_channel_map() const { return m_particleChannelMap; } ////////////////////// // Functions for dealing with header properties ////////////////////// boost::int64_t particle_count() const { return m_particleCount; } void set_particle_count( boost::int64_t particleCount ) { m_particleCount = particleCount; } ////////////////////// // Functions for dealing with file i/o of the header ////////////////////// // Function to read in the PRT header. The name parameter should be the filename for error messages. void read_header( std::istream& in, const frantic::tstring& streamName ); // Function to read in the PRT header. The name parameter should be the filename for error messages. void read_header( FILE* fin, const frantic::tstring& streamName ); // Function to write out the PRT header. The name parameter should be the filename for error messages. void write_header( std::ostream& out, const frantic::tstring& streamName ); // Function to write out the PRT header. The name parameter should be the filename for error messages. void write_header( FILE* out, const frantic::tstring& streamName ); // Function to rewrite the particle count once the whole PRT file is written. // The name parameter should be the filename for error messages. // NOTE: This function seeks in the stream, but doesn't return the seek position to where it was before. void rewrite_particle_count( std::ostream& out, const frantic::tstring& streamName, boost::int64_t particleCount ); // Function to rewrite the particle count once the whole PRT file is written. // The name parameter should be the filename for error messages. // NOTE: This function seeks in the stream, but doesn't return the seek position to where it was before. void rewrite_particle_count( FILE* out, const frantic::tstring& streamName, boost::int64_t particleCount ); /** * Seeks the stream back into the header section of the file and updates the bounding box. * \note This function seeks in the stream, but doesn't return the seek position to where it was before. * \param out The stream that just finished writing the PRT file. * \param streamName Provided for error messages * \param bounds The boundbox of the particles. */ void rewrite_particle_boundbox( std::ostream& out, const frantic::tstring& streamName, const frantic::graphics::boundbox3f& bounds ); /** * \overload This overload accepts a C style file pointer for file I/O */ void rewrite_particle_boundbox( FILE* out, const frantic::tstring& streamName, const frantic::graphics::boundbox3f& bounds ); }; } // namespace particles } // namespace frantic