// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #include <frantic/graphics/boundbox3f.hpp> #include <frantic/strings/tstring.hpp> #include <tinyxml2.h> #include <boost/filesystem/path.hpp> #include <boost/rational.hpp> #include <map> namespace frantic { namespace geometry { class xmesh_metadata { public: enum transform_type_t { transform_type_none, transform_type_point, transform_type_vector, transform_type_normal, transform_type_invalid }; enum length_unit_t { length_unit_unitless, length_unit_inches, length_unit_feet, length_unit_miles, length_unit_millimeters, length_unit_centimeters, length_unit_meters, length_unit_kilometers, length_unit_invalid }; private: bool hasLengthUnit; double lengthUnitScale; length_unit_t lengthUnit; bool hasFramesPerSecond; boost::rational<boost::int64_t> framesPerSecond; bool hasBoundbox; frantic::graphics::boundbox3f boundbox; typedef std::map<frantic::tstring, frantic::tstring> user_data_collection_t; user_data_collection_t userData; // typedef std::map<std::string,mesh_channel_metadata> channel_metadata_collection_t; // channel_metadata_collection_t meshChannelMetadata; typedef std::map<frantic::tstring, transform_type_t> channel_transform_type_collection_t; channel_transform_type_collection_t channelTransformType; // TODO: this shouldn't be a friend friend void insert_channel_transform_type_tags( const xmesh_metadata&, tinyxml2::XMLHandle, const std::string&, bool ); public: xmesh_metadata(); /** * Remove all defined metadata. */ void clear( void ); // Frames per second /** * Remove the frames per second metadata. */ void clear_frames_per_second(); /** * Set the frames per second. * * The frames per second is defined as a rational numerator/denominator * because that allows us to express frame rates such as NTSC exactly * (30000/1001). * * @param numerator the numerator part of the frames per second. * @param denominator the denominator part of the frames per second. */ void set_frames_per_second( boost::int64_t numerator, boost::int64_t denominator = 1 ); /** * Set the frames per second. * * @param framesPerSecond the frames per second. */ void set_frames_per_second( const boost::rational<boost::int64_t>& framesPerSecond ); /** * Return true if the frames per second is defined, and false otherwise. * * @return true if the frames per second is defined, and false otherwise. */ bool has_frames_per_second() const; /** * Return the frames per second. If has_frames_per_second() is false, * then this value is undefined. * * @return the frames per second. */ boost::rational<boost::int64_t> get_frames_per_second() const; // Boundbox /** * Remove the boundbox metadata. */ void clear_boundbox(); /** * Set the boundbox. * * @param boundbox the boundbox value. */ void set_boundbox( const frantic::graphics::boundbox3f& boundbox ); /** * Return true if the boundbox is defined, and false otherwise. * * @return true if the boundbox is defined, and false otherwise. */ bool has_boundbox() const; /** * Return the boundbox. If has_boundbox() is false, then this value is * undefined. * * @return the boundbox. */ frantic::graphics::boundbox3f get_boundbox() const; // Length unit /** * Remove the length unit metadata. */ void clear_length_unit(); /** * Set the length unit. The length unit comprises a unit and a multiplier. * For example, a unit or 10 cm corresponds to lengthUnitScale 10 and * lengthUnit length_unit_centimeters. * * @param lengthUnitScale the multiple of lengthUnit. * @param lengthUnit the length unit. */ void set_length_unit( double lengthUnitScale, length_unit_t lengthUnit ); /** * Return true if the length unit is defined, and false otherwise. * * @return true if the length unit is defined, and false otherwise. */ bool has_length_unit() const; /** * Return the length unit multiplier. * * @return the length unit multiplier. */ double get_length_unit_scale() const; /** * Return the length unit. * * @return the length unit. */ length_unit_t get_length_unit() const; // Channel transform types /** * Remove the transform type metadata for all channels. */ void clear_channel_transform_type(); /** * Set the transform type for the specified channel. * * @param channelName the channel name to specify a transform type for. * @param transformType the transform type for the specified channel. */ void set_channel_transform_type( const frantic::tstring& channelName, transform_type_t transformType ); /** * Return the transform type for the specified channel. Defaults to * transform_type_none. * * @param channelName the channel name to find. * @return the transform_type_t of the specified channel. */ transform_type_t get_channel_transform_type( const frantic::tstring& channelName ) const; // User data /** * Remove all user data. */ void clear_user_data(); /** * Set the user data for the specified key to the specified value. If the key already * exists, its old value is overwritten. * * @param key the key for the user data. * @param value the value for the user data. */ void set_user_data( const frantic::tstring& key, const frantic::tstring& value ); /** * Remove the user data with the specified key. * * @param key the key for the user data to remove. */ void erase_user_data( const frantic::tstring& key ); /** * Return true if user data with the specified key exists, and false otherwise. * * @param key the user data key to find. * @return true if user data with the specified key exists, and false otherwise. */ bool has_user_data( const frantic::tstring& key ) const; /** * Set the out vector to a list of the defined user data keys. * * @param[out] out a vector to populate with a list of the defined user data keys. */ void get_user_data_keys( std::vector<frantic::tstring>& out ) const; /** * Return the user data value for the specified key. Throws an exception if * there is no user data for the specified key. * * @param key the key to find. * @return the value associated with the key. */ frantic::tstring get_user_data( const frantic::tstring& key ) const; }; /** * Populate the metadata using values found in the XML document. * * @param doc the XML document to read. * @param[out] outMetadata the metadata to populate. */ void read_xmesh_metadata( tinyxml2::XMLDocument& doc, xmesh_metadata& outMetadata ); /** * Populate the metadata using values found in the XML document. * * @param path the XML file to read. * @param[out] outMetadata the metadata to populate. */ void read_xmesh_metadata( const boost::filesystem::path& path, xmesh_metadata& outMetadata ); /** * Append metadata to the specified XML document. * This is intended for internal use by classes such as xmesh_sequence_saver * and xmesh_writer. * You should normally call this after the document is already populated with * xmesh channels and files, etc. * * @param[out] outDocument append metadata onto this document. * @param metadata the metadata to append. * @param standalone if true, create a standalone XML file without any * real xmesh data. This should normally be false. */ void write_xmesh_metadata( tinyxml2::XMLDocument& outDocument, const xmesh_metadata& metadata, bool standalone = false ); /** * Create a standalone XML metadata file without any real xmesh data. * This is intended for internal use. * * @param path the XML filename to create. * @param metadata the metadata to write. */ void write_xmesh_metadata( const boost::filesystem::path& path, const xmesh_metadata& metadata ); /** * Converts a meters scale to an appropriate length unit. * The length unit comprises a unit and a multiplier. * For example, a unit of 10 cm corresponds to lengthUnitScale 10 and * lengthUnit length_unit_centimeters. * * @param metersScale the unit size in meters. * @return a pair containing < the multiple of lengthUnit, the length unit > */ std::pair<double, xmesh_metadata::length_unit_t> get_xmesh_length_unit_from_meters( double metersScale ); /** * Converts an xmesh length unit to meters */ double get_meters_from_xmesh_length_unit( double, frantic::geometry::xmesh_metadata::length_unit_t ); } // namespace geometry } // namespace frantic