Files
filament/third_party/meshoptimizer/gltf/gltfpack.h
2022-10-17 09:57:58 -07:00

400 lines
12 KiB
C++

/**
* gltfpack - version 0.18
*
* Copyright (C) 2016-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://github.com/zeux/meshoptimizer
*
* This application is distributed under the MIT License. See notice at the end of this file.
*/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "../extern/cgltf.h"
#include <assert.h>
#include <string>
#include <vector>
struct Attr
{
float f[4];
};
struct Stream
{
cgltf_attribute_type type;
int index;
int target; // 0 = base mesh, 1+ = morph target
std::vector<Attr> data;
};
struct Transform
{
float data[16];
};
struct Mesh
{
int scene;
std::vector<cgltf_node*> nodes;
std::vector<Transform> instances;
cgltf_material* material;
cgltf_skin* skin;
cgltf_primitive_type type;
std::vector<Stream> streams;
std::vector<unsigned int> indices;
size_t targets;
std::vector<float> target_weights;
std::vector<const char*> target_names;
std::vector<cgltf_material_mapping> variants;
};
struct Track
{
cgltf_node* node;
cgltf_animation_path_type path;
bool constant;
bool dummy;
size_t components; // 1 unless path is cgltf_animation_path_type_weights
cgltf_interpolation_type interpolation;
std::vector<float> time; // empty for resampled or constant animations
std::vector<Attr> data;
};
struct Animation
{
const char* name;
float start;
int frames;
std::vector<Track> tracks;
};
enum TextureKind
{
TextureKind_Generic,
TextureKind_Color,
TextureKind_Normal,
TextureKind_Attrib,
TextureKind__Count
};
enum TextureMode
{
TextureMode_Raw,
TextureMode_ETC1S,
TextureMode_UASTC,
};
struct Settings
{
int pos_bits;
int tex_bits;
int nrm_bits;
int col_bits;
bool pos_normalized;
bool pos_float;
int trn_bits;
int rot_bits;
int scl_bits;
int anim_freq;
bool anim_const;
bool keep_nodes;
bool keep_materials;
bool keep_extras;
bool mesh_merge;
bool mesh_instancing;
float simplify_threshold;
bool simplify_aggressive;
float simplify_debug;
int meshlet_debug;
bool texture_ktx2;
bool texture_embed;
bool texture_pow2;
bool texture_flipy;
float texture_scale;
int texture_limit;
TextureMode texture_mode[TextureKind__Count];
int texture_quality[TextureKind__Count];
int texture_jobs;
bool quantize;
bool compress;
bool compressmore;
bool fallback;
int verbose;
};
struct QuantizationPosition
{
float offset[3];
float scale;
int bits;
bool normalized;
};
struct QuantizationTexture
{
float offset[2];
float scale[2];
int bits;
bool normalized;
};
struct StreamFormat
{
enum Filter
{
Filter_None = 0,
Filter_Oct = 1,
Filter_Quat = 2,
Filter_Exp = 3,
};
cgltf_type type;
cgltf_component_type component_type;
bool normalized;
size_t stride;
Filter filter;
};
struct NodeInfo
{
int scene;
bool keep;
bool animated;
unsigned int animated_paths;
int remap;
std::vector<size_t> mesh_nodes;
bool has_mesh;
size_t mesh_index;
cgltf_skin* mesh_skin;
};
struct MaterialInfo
{
bool keep;
bool usesTextureTransform;
bool needsTangents;
unsigned int textureSetMask;
int remap;
};
struct ImageInfo
{
TextureKind kind;
bool normal_map;
bool srgb;
int channels;
};
struct ExtensionInfo
{
const char* name;
bool used;
bool required;
};
struct BufferView
{
enum Kind
{
Kind_Vertex,
Kind_Index,
Kind_Skin,
Kind_Time,
Kind_Keyframe,
Kind_Instance,
Kind_Image,
Kind_Count
};
enum Compression
{
Compression_None = -1,
Compression_Attribute,
Compression_Index,
Compression_IndexSequence,
};
Kind kind;
StreamFormat::Filter filter;
Compression compression;
size_t stride;
int variant;
std::string data;
size_t bytes;
};
struct TempFile
{
std::string path;
int fd;
TempFile();
TempFile(const char* suffix);
~TempFile();
void create(const char* suffix);
};
std::string getFullPath(const char* path, const char* base_path);
std::string getFileName(const char* path);
std::string getExtension(const char* path);
bool readFile(const char* path, std::string& data);
bool writeFile(const char* path, const std::string& data);
cgltf_data* parseObj(const char* path, std::vector<Mesh>& meshes, const char** error);
cgltf_data* parseGltf(const char* path, std::vector<Mesh>& meshes, std::vector<Animation>& animations, const char** error);
void processAnimation(Animation& animation, const Settings& settings);
void processMesh(Mesh& mesh, const Settings& settings);
void debugSimplify(const Mesh& mesh, Mesh& kinds, Mesh& loops, float ratio);
void debugMeshlets(const Mesh& mesh, Mesh& meshlets, Mesh& bounds, int max_vertices, bool scan);
bool compareMeshTargets(const Mesh& lhs, const Mesh& rhs);
bool compareMeshVariants(const Mesh& lhs, const Mesh& rhs);
bool compareMeshNodes(const Mesh& lhs, const Mesh& rhs);
void mergeMeshInstances(Mesh& mesh);
void mergeMeshes(std::vector<Mesh>& meshes, const Settings& settings);
void filterEmptyMeshes(std::vector<Mesh>& meshes);
void filterStreams(Mesh& mesh, const MaterialInfo& mi);
void mergeMeshMaterials(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settings);
void markNeededMaterials(cgltf_data* data, std::vector<MaterialInfo>& materials, const std::vector<Mesh>& meshes, const Settings& settings);
bool hasValidTransform(const cgltf_texture_view& view);
void analyzeMaterials(cgltf_data* data, std::vector<MaterialInfo>& materials, std::vector<ImageInfo>& images);
void optimizeMaterials(cgltf_data* data, const char* input_path, std::vector<ImageInfo>& images);
bool readImage(const cgltf_image& image, const char* input_path, std::string& data, std::string& mime_type);
bool hasAlpha(const std::string& data, const char* mime_type);
bool getDimensions(const std::string& data, const char* mime_type, int& width, int& height);
void adjustDimensions(int& width, int& height, const Settings& settings);
const char* mimeExtension(const char* mime_type);
#ifdef WITH_BASISU
void encodeImages(std::string* encoded, const cgltf_data* data, const std::vector<ImageInfo>& images, const char* input_path, const Settings& settings);
#endif
void markScenes(cgltf_data* data, std::vector<NodeInfo>& nodes);
void markAnimated(cgltf_data* data, std::vector<NodeInfo>& nodes, const std::vector<Animation>& animations);
void markNeededNodes(cgltf_data* data, std::vector<NodeInfo>& nodes, const std::vector<Mesh>& meshes, const std::vector<Animation>& animations, const Settings& settings);
void remapNodes(cgltf_data* data, std::vector<NodeInfo>& nodes, size_t& node_offset);
void decomposeTransform(float translation[3], float rotation[4], float scale[3], const float* transform);
QuantizationPosition prepareQuantizationPosition(const std::vector<Mesh>& meshes, const Settings& settings);
void prepareQuantizationTexture(cgltf_data* data, std::vector<QuantizationTexture>& result, std::vector<size_t>& indices, const std::vector<Mesh>& meshes, const Settings& settings);
void getPositionBounds(float min[3], float max[3], const Stream& stream, const QuantizationPosition& qp, const Settings& settings);
StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const QuantizationPosition& qp, const QuantizationTexture& qt, const Settings& settings);
StreamFormat writeIndexStream(std::string& bin, const std::vector<unsigned int>& stream);
StreamFormat writeTimeStream(std::string& bin, const std::vector<float>& data);
StreamFormat writeKeyframeStream(std::string& bin, cgltf_animation_path_type type, const std::vector<Attr>& data, const Settings& settings);
void compressVertexStream(std::string& bin, const std::string& data, size_t count, size_t stride);
void compressIndexStream(std::string& bin, const std::string& data, size_t count, size_t stride);
void compressIndexSequence(std::string& bin, const std::string& data, size_t count, size_t stride);
size_t getBufferView(std::vector<BufferView>& views, BufferView::Kind kind, StreamFormat::Filter filter, BufferView::Compression compression, size_t stride, int variant = 0);
void comma(std::string& s);
void append(std::string& s, size_t v);
void append(std::string& s, float v);
void append(std::string& s, const char* v);
void append(std::string& s, const std::string& v);
void appendJson(std::string& s, const char* data);
const char* attributeType(cgltf_attribute_type type);
const char* animationPath(cgltf_animation_path_type type);
void writeMaterial(std::string& json, const cgltf_data* data, const cgltf_material& material, const QuantizationPosition* qp, const QuantizationTexture* qt);
void writeBufferView(std::string& json, BufferView::Kind kind, StreamFormat::Filter filter, size_t count, size_t stride, size_t bin_offset, size_t bin_size, BufferView::Compression compression, size_t compressed_offset, size_t compressed_size);
void writeSampler(std::string& json, const cgltf_sampler& sampler);
void writeImage(std::string& json, std::vector<BufferView>& views, const cgltf_image& image, const ImageInfo& info, size_t index, const char* input_path, const Settings& settings);
void writeEncodedImage(std::string& json, std::vector<BufferView>& views, const cgltf_image& image, const std::string& encoded, const ImageInfo& info, const char* output_path, const Settings& settings);
void writeTexture(std::string& json, const cgltf_texture& texture, const ImageInfo* info, cgltf_data* data, const Settings& settings);
void writeMeshAttributes(std::string& json, std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const Mesh& mesh, int target, const QuantizationPosition& qp, const QuantizationTexture& qt, const Settings& settings);
size_t writeMeshIndices(std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const Mesh& mesh, const Settings& settings);
size_t writeJointBindMatrices(std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const cgltf_skin& skin, const QuantizationPosition& qp, const Settings& settings);
size_t writeInstances(std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const std::vector<Transform>& transforms, const QuantizationPosition& qp, const Settings& settings);
void writeMeshNode(std::string& json, size_t mesh_offset, cgltf_node* node, cgltf_skin* skin, cgltf_data* data, const QuantizationPosition* qp);
void writeMeshNodeInstanced(std::string& json, size_t mesh_offset, size_t accr_offset);
void writeSkin(std::string& json, const cgltf_skin& skin, size_t matrix_accr, const std::vector<NodeInfo>& nodes, cgltf_data* data);
void writeNode(std::string& json, const cgltf_node& node, const std::vector<NodeInfo>& nodes, cgltf_data* data);
void writeAnimation(std::string& json, std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const Animation& animation, size_t i, cgltf_data* data, const std::vector<NodeInfo>& nodes, const Settings& settings);
void writeCamera(std::string& json, const cgltf_camera& camera);
void writeLight(std::string& json, const cgltf_light& light);
void writeArray(std::string& json, const char* name, const std::string& contents);
void writeExtensions(std::string& json, const ExtensionInfo* extensions, size_t count);
void writeExtras(std::string& json, const cgltf_extras& extras);
void writeScene(std::string& json, const cgltf_scene& scene, const std::string& roots);
/**
* Copyright (c) 2016-2022 Arseny Kapoulkine
*
* 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.
*/