godot/thirdparty/ufbx/ufbx.c

#ifndef UFBX_UFBX_C_INCLUDED
#define UFBX_UFBX_C_INCLUDED

#if defined(UFBX_HEADER_PATH)
	#include UFBX_HEADER_PATH
#else
	#include "ufbx.h"
#endif

// -- User configuration

// User configuration:
//   UFBX_REGRESSION           Enable regression mode for development
//   UFBX_UBSAN                Explicitly enable undefined behavior sanitizer workarounds
//   UFBX_NO_UNALIGNED_LOADS   Do not use unaligned loads even when they are supported
//   UFBX_USE_UNALIGNED_LOADS  Forcibly use unaligned loads on unknown platforms
//   UFBX_USE_SSE              Explicitly enable SSE2 support (for x86)
//   UFBX_HAS_FTELLO           Allow ufbx to use `ftello()` to measure file size
//   UFBX_WASM_32BIT           Optimize WASM for 32-bit architectures
//   UFBX_TRACE                Log calls of `ufbxi_check()` for tracing execution
//   UFBX_LITTLE_ENDIAN=0/1    Explicitly define little/big endian architecture
//   UFBX_PATH_SEPARATOR=''    Specify default platform path separator

// Mostly internal for debugging:
//   UFBX_STATIC_ANALYSIS      Enable static analysis augmentation
//   UFBX_DEBUG_BINARY_SEARCH  Force using binary search for debugging
//   UFBX_EXTENSIVE_THREADING  Use threads for small inputs

#if defined(UFBX_CONFIG_SOURCE)
	#include UFBX_CONFIG_SOURCE
#endif

// -- Configuration

#define UFBXI_MAX_NON_ARRAY_VALUES
#define UFBXI_MAX_NODE_DEPTH
#define UFBXI_MAX_XML_DEPTH
#define UFBXI_MAX_SKIP_SIZE
#define UFBXI_MAP_MAX_SCAN
#define UFBXI_KD_FAST_DEPTH
#define UFBXI_HUGE_MAX_SCAN
#define UFBXI_MIN_FILE_FORMAT_LOOKAHEAD
#define UFBXI_FACE_GROUP_HASH_BITS
#define UFBXI_MIN_THREADED_DEFLATE_BYTES
#define UFBXI_MIN_THREADED_ASCII_VALUES
#define UFBXI_GEOMETRY_CACHE_BUFFER_SIZE

#ifndef UFBXI_MAX_NURBS_ORDER
#define UFBXI_MAX_NURBS_ORDER
#endif

// By default enough to have squares be non-denormal
#ifndef UFBX_EPSILON
#define UFBX_EPSILON
#endif

// -- Feature exclusion

#if !defined(UFBX_MINIMAL)
	#if !defined(UFBX_NO_SUBDIVISION)
		#define UFBXI_FEATURE_SUBDIVISION
	#endif
	#if !defined(UFBX_NO_TESSELLATION)
		#define UFBXI_FEATURE_TESSELLATION
	#endif
	#if !defined(UFBX_NO_GEOMETRY_CACHE)
		#define UFBXI_FEATURE_GEOMETRY_CACHE
	#endif
	#if !defined(UFBX_NO_SCENE_EVALUATION)
		#define UFBXI_FEATURE_SCENE_EVALUATION
	#endif
	#if !defined(UFBX_NO_SKINNING_EVALUATION)
		#define UFBXI_FEATURE_SKINNING_EVALUATION
	#endif
	#if !defined(UFBX_NO_ANIMATION_BAKING)
		#define UFBXI_FEATURE_ANIMATION_BAKING
	#endif
	#if !defined(UFBX_NO_TRIANGULATION)
		#define UFBXI_FEATURE_TRIANGULATION
	#endif
	#if !defined(UFBX_NO_INDEX_GENERATION)
		#define UFBXI_FEATURE_INDEX_GENERATION
	#endif
	#if !defined(UFBX_NO_FORMAT_OBJ)
		#define UFBXI_FEATURE_FORMAT_OBJ
	#endif
#endif

#if defined(UFBX_DEV)
	#if !defined(UFBX_NO_ERROR_STACK)
		#define UFBXI_FEATURE_ERROR_STACK
	#endif
#endif

#if !defined(UFBXI_FEATURE_SUBDIVISION) && defined(UFBX_ENABLE_SUBDIVISION)
	#define UFBXI_FEATURE_SUBDIVISION
#endif
#if !defined(UFBXI_FEATURE_TESSELLATION) && defined(UFBX_ENABLE_TESSELLATION)
	#define UFBXI_FEATURE_TESSELLATION
#endif
#if !defined(UFBXI_FEATURE_GEOMETRY_CACHE) && defined(UFBX_ENABLE_GEOMETRY_CACHE)
	#define UFBXI_FEATURE_GEOMETRY_CACHE
#endif
#if !defined(UFBXI_FEATURE_SCENE_EVALUATION) && defined(UFBX_ENABLE_SCENE_EVALUATION)
	#define UFBXI_FEATURE_SCENE_EVALUATION
#endif
#if !defined(UFBXI_FEATURE_SKINNING_EVALUATION) && defined(UFBX_ENABLE_SKINNING_EVALUATION)
	#define UFBXI_FEATURE_SKINNING_EVALUATION
#endif
#if !defined(UFBXI_FEATURE_ANIMATION_BAKING) && defined(UFBX_ENABLE_ANIMATION_BAKING)
	#define UFBXI_FEATURE_ANIMATION_BAKING
#endif
#if !defined(UFBXI_FEATURE_TRIANGULATION) && defined(UFBX_ENABLE_TRIANGULATION)
	#define UFBXI_FEATURE_TRIANGULATION
#endif
#if !defined(UFBXI_FEATURE_INDEX_GENERATION) && defined(UFBX_ENABLE_INDEX_GENERATION)
	#define UFBXI_FEATURE_INDEX_GENERATION
#endif
#if !defined(UFBXI_FEATURE_FORMAT_OBJ) && defined(UFBX_ENABLE_FORMAT_OBJ)
	#define UFBXI_FEATURE_FORMAT_OBJ
#endif
#if !defined(UFBXI_FEATURE_ERROR_STACK) && defined(UFBX_ENABLE_ERROR_STACK)
	#define UFBXI_FEATURE_ERROR_STACK
#endif

#if !defined(UFBXI_FEATURE_SUBDIVISION)
	#define UFBXI_FEATURE_SUBDIVISION
#endif
#if !defined(UFBXI_FEATURE_TESSELLATION)
	#define UFBXI_FEATURE_TESSELLATION
#endif
#if !defined(UFBXI_FEATURE_GEOMETRY_CACHE)
	#define UFBXI_FEATURE_GEOMETRY_CACHE
#endif
#if !defined(UFBXI_FEATURE_SCENE_EVALUATION)
	#define UFBXI_FEATURE_SCENE_EVALUATION
#endif
#if !defined(UFBXI_FEATURE_SKINNING_EVALUATION)
	#define UFBXI_FEATURE_SKINNING_EVALUATION
#endif
#if !defined(UFBXI_FEATURE_ANIMATION_BAKING)
	#define UFBXI_FEATURE_ANIMATION_BAKING
#endif
#if !defined(UFBXI_FEATURE_TRIANGULATION)
	#define UFBXI_FEATURE_TRIANGULATION
#endif
#if !defined(UFBXI_FEATURE_INDEX_GENERATION)
	#define UFBXI_FEATURE_INDEX_GENERATION
#endif
#if !defined(UFBXI_FEATURE_FORMAT_OBJ)
	#define UFBXI_FEATURE_FORMAT_OBJ
#endif
#if !defined(UFBXI_FEATURE_ERROR_STACK)
	#define UFBXI_FEATURE_ERROR_STACK
#endif

// Derived features

#if UFBXI_FEATURE_GEOMETRY_CACHE
	#define UFBXI_FEATURE_XML
#else
	#define UFBXI_FEATURE_XML
#endif

#if UFBXI_FEATURE_TRIANGULATION
	#define UFBXI_FEATURE_KD
#else
	#define UFBXI_FEATURE_KD
#endif

#if !UFBXI_FEATURE_SUBDIVISION || !UFBXI_FEATURE_TESSELLATION || !UFBXI_FEATURE_GEOMETRY_CACHE || !UFBXI_FEATURE_SCENE_EVALUATION || !UFBXI_FEATURE_SKINNING_EVALUATION || !UFBXI_FEATURE_ANIMATION_BAKING || !UFBXI_FEATURE_TRIANGULATION || !UFBXI_FEATURE_INDEX_GENERATION || !UFBXI_FEATURE_XML || !UFBXI_FEATURE_KD || !UFBXI_FEATURE_FORMAT_OBJ
	#define UFBXI_PARTIAL_FEATURES
#endif

// -- Headers

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <locale.h>
#include <float.h>

#if !defined(UFBX_NO_MATH_H)
	#include <math.h>
	#define UFBX_INFINITY
	#define UFBX_NAN
#endif

#if !defined(UFBX_MATH_PREFIX)
	#define UFBX_MATH_PREFIX
#endif

#define ufbxi_math_cat2(a, b)
#define ufbxi_math_cat(a, b)
#define ufbxi_math_fn(name)

#if !defined(UFBX_NO_MATH_DEFINES)
	#define ufbx_sqrt
	#define ufbx_fabs
	#define ufbx_pow
	#define ufbx_sin
	#define ufbx_cos
	#define ufbx_tan
	#define ufbx_asin
	#define ufbx_acos
	#define ufbx_atan
	#define ufbx_atan2
	#define ufbx_copysign
	#define ufbx_fmin
	#define ufbx_fmax
	#define ufbx_nextafter
	#define ufbx_rint
	#define ufbx_ceil
	#define ufbx_isnan
#endif

#if defined(UFBX_NO_MATH_H) && !defined(UFBX_NO_MATH_DECLARATIONS)
	double ufbx_sqrt(double x);
	double ufbx_sin(double x);
	double ufbx_cos(double x);
	double ufbx_tan(double x);
	double ufbx_asin(double x);
	double ufbx_acos(double x);
	double ufbx_atan(double x);
	double ufbx_atan2(double y, double x);
	double ufbx_pow(double x, double y);
	double ufbx_fmin(double a, double b);
	double ufbx_fmax(double a, double b);
	double ufbx_fabs(double x);
	double ufbx_copysign(double x, double y);
	double ufbx_nextafter(double x, double y);
	double ufbx_rint(double x);
	double ufbx_ceil(double x);
	int ufbx_isnan(double x);
#endif

#if !defined(UFBX_INFINITY)
	#define UFBX_INFINITY
#endif
#if !defined(UFBX_NAN)
	#define UFBX_NAN
#endif

// -- Platform

#if defined(_MSC_VER)
	#define UFBXI_MSC_VER
#else
	#define UFBXI_MSC_VER
#endif

#if defined(__GNUC__)
	#define UFBXI_GNUC
#else
	#define UFBXI_GNUC
#endif

#if !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
	#define ufbxi_noinline
	#define ufbxi_forceinline
	#define ufbxi_restrict
	#if defined(_Check_return_)
		#define ufbxi_nodiscard
	#else
		#define ufbxi_nodiscard
	#endif
	#define ufbxi_unused
	#define ufbxi_unlikely
#elif !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__))
	#define ufbxi_noinline
	#define ufbxi_forceinline
	#define ufbxi_restrict
	#define ufbxi_nodiscard
	#define ufbxi_unused
	#define ufbxi_unlikely(cond)
#else
	#define ufbxi_noinline
	#define ufbxi_forceinline
	#define ufbxi_nodiscard
	#define ufbxi_restrict
	#define ufbxi_unused
	#define ufbxi_unlikely
#endif

#if !defined(UFBX_STANDARD_C) && defined(__clang__)
	#define ufbxi_nounroll
#elif !defined(UFBX_STANDARD_C) && UFBXI_GNUC >= 8
	#define ufbxi_nounroll
#elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
	#define ufbxi_nounroll
#else
	#define ufbxi_nounroll
#endif

#if defined(__GNUC__) && !defined(__clang__)
	#define ufbxi_ignore
#else
	#define ufbxi_ignore(cond)
#endif

#if defined(_MSC_VER)
	#pragma warning(push)
	#pragma warning(disable: 4061) // enumerator 'ENUM' in switch of enum 'enum' is not explicitly handled by a case label
	#pragma warning(disable: 4200) // nonstandard extension used: zero-sized array in struct/union
	#pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
	#pragma warning(disable: 4210) // nonstandard extension used: function given file scope
	#pragma warning(disable: 4127) // conditional expression is constant
	#pragma warning(disable: 4706) // assignment within conditional expression
	#pragma warning(disable: 4789) // buffer 'type_and_name' of size 8 bytes will be overrun; 16 bytes will be written starting at offset 0
	#pragma warning(disable: 4820) // type': 'N' bytes padding added after data member 'member'
	#if defined(UFBX_STANDARD_C)
		#pragma warning(disable: 4996) // 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.
	#endif
	#if defined(UFBXI_PARTIAL_FEATURES)
		#pragma warning(disable: 4100) // 'name': unreferenced formal parameter
		#pragma warning(disable: 4505) // 'func': unreferenced function with internal linkage has been removed
	#endif
#endif

#if defined(__clang__)
	#pragma clang diagnostic push
	#pragma clang diagnostic ignored "-Wmissing-field-initializers"
	#pragma clang diagnostic ignored "-Wmissing-braces"
	#pragma clang diagnostic ignored "-Wdouble-promotion"
	#pragma clang diagnostic ignored "-Wpedantic"
	#pragma clang diagnostic ignored "-Wcast-qual"
	#pragma clang diagnostic ignored "-Wcast-align"
	#pragma clang diagnostic ignored "-Wcovered-switch-default"
	#pragma clang diagnostic ignored "-Wpadded"
	#pragma clang diagnostic ignored "-Wswitch-enum"
	#pragma clang diagnostic ignored "-Wfloat-equal"
	#pragma clang diagnostic ignored "-Wformat-nonliteral"
	#if __has_warning("-Watomic-implicit-seq-cst")
		#pragma clang diagnostic ignored "-Watomic-implicit-seq-cst"
	#endif
	#if defined(UFBX_STANDARD_C)
		#pragma clang diagnostic ignored "-Wunused-function"
	#endif
	#if defined(UFBXI_PARTIAL_FEATURES)
		#pragma clang diagnostic ignored "-Wunused-function"
		#pragma clang diagnostic ignored "-Wunused-parameter"
	#endif
	#if defined(__cplusplus)
		#pragma clang diagnostic ignored "-Wold-style-cast"
		#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
	#else
		#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
		#pragma clang diagnostic ignored "-Wbad-function-cast"
	#endif
#endif

#if defined(__GNUC__)
	#pragma GCC diagnostic push
	#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
	#pragma GCC diagnostic ignored "-Wmissing-braces"
	#pragma GCC diagnostic ignored "-Wdouble-promotion"
	#pragma GCC diagnostic ignored "-Wpedantic"
	#pragma GCC diagnostic ignored "-Wcast-qual"
	#pragma GCC diagnostic ignored "-Wcast-align"
	#pragma GCC diagnostic ignored "-Wpadded"
	#pragma GCC diagnostic ignored "-Wswitch-enum"
	#pragma GCC diagnostic ignored "-Wfloat-equal"
	#pragma GCC diagnostic ignored "-Wformat-nonliteral"
	#pragma GCC diagnostic ignored "-Wlong-long"
	#if defined(UFBX_STANDARD_C)
		#pragma GCC diagnostic ignored "-Wunused-function"
	#endif
	#if defined(UFBXI_PARTIAL_FEATURES)
		#pragma GCC diagnostic ignored "-Wunused-function"
		#pragma GCC diagnostic ignored "-Wunused-parameter"
	#endif
	#if defined(__cplusplus)
		#pragma GCC diagnostic ignored "-Wold-style-cast"
		#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
	#else
		#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
		#pragma GCC diagnostic ignored "-Wbad-function-cast"
		#if __GNUC__ >= 5
			#pragma GCC diagnostic ignored "-Wc90-c99-compat"
			#pragma GCC diagnostic ignored "-Wc99-c11-compat"
		#endif
	#endif
#endif

#if !defined(ufbx_static_assert)
	#if defined(__cplusplus) && __cplusplus >= 201103
		#define ufbx_static_assert
	#else
		#define ufbx_static_assert(desc, cond)
	#endif
#endif

#if defined(__has_feature)
	#if __has_feature(undefined_behavior_sanitizer) && !defined(UFBX_UBSAN)
		#define UFBX_UBSAN
	#endif
#endif

#if defined(__SANITIZE_UNDEFINED__)  && !defined(UFBX_UBSAN)
	#define UFBX_UBSAN
#endif

// Don't use unaligned loads with UB-sanitizer
#if defined(UFBX_UBSAN) && !defined(UFBX_NO_UNALIGNED_LOADS)
	#define UFBX_NO_UNALIGNED_LOADS
#endif

#if defined(__clang_analyzer__) && !defined(UFBX_STATIC_ANALYSIS)
	#define UFBX_STATIC_ANALYSIS
#endif

#if defined(UFBX_STATIC_ANALYSIS)
	bool ufbxi_analysis_opaque;
	#define ufbxi_maybe_null
#else
	#define ufbxi_maybe_null(ptr)
#endif

#if !defined(ufbxi_trace)
	#if defined(UFBX_TRACE)
		#define ufbxi_trace
	#else
		#define ufbxi_trace(desc)
	#endif
#endif

#ifndef UFBX_PATH_SEPARATOR
	#if defined(_WIN32)
		#define UFBX_PATH_SEPARATOR
	#else
		#define UFBX_PATH_SEPARATOR
	#endif
#endif

#if !defined(UFBX_STANDARD_C) && defined(_POSIX_C_SOURCE)
	#if _POSIX_C_SOURCE >= 200112l
		#ifndef UFBX_HAS_FTELLO
			#define UFBX_HAS_FTELLO
		#endif
	#endif
#endif

#if !defined(UFBX_STANDARD_C) && (defined(_MSC_VER) && defined(_M_X64)) || ((defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__)) || defined(UFBX_USE_SSE)
	#define UFBXI_HAS_SSE
	#include <xmmintrin.h>
	#include <emmintrin.h>
#else
	#define UFBXI_HAS_SSE
#endif

#if !defined(UFBX_LITTLE_ENDIAN)
	#if !defined(UFBX_STANDARD_C) && (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) || defined(__wasm__) || defined(__EMSCRIPTEN__))
		#define UFBX_LITTLE_ENDIAN
	#else
		#define UFBX_LITTLE_ENDIAN
	#endif
#endif

// Unaligned little-endian load functions
// On platforms that support unaligned access natively (x86, x64, ARM64) just use normal loads,
// with unaligned attributes, otherwise do manual byte-wise load.

#define ufbxi_read_u8(ptr)

// Detect support for `__attribute__((aligned(1)))`
#if !defined(UFBX_STANDARD_C) && (defined(__clang__) && defined(__APPLE__))
	// Apple overrides Clang versioning, 5.0 here maps to 3.3
	#if __clang_major__ >= 5
		#define UFBXI_HAS_ATTRIBUTE_ALIGNED
	#endif
#elif !defined(UFBX_STANDARD_C) && defined(__clang__)
	#if (__clang_major__ >= 4) || (__clang_major__ == 3 && __clang_minor__ >= 3)
		#define UFBXI_HAS_ATTRIBUTE_ALIGNED
	#endif
#elif !defined(UFBX_STANDARD_C) && defined(__GNUC__)
	#if __GNUC__ >= 5
		#define UFBXI_HAS_ATTRIBUTE_ALIGNED
	#endif
#endif

#if defined(UFBXI_HAS_ATTRIBUTE_ALIGNED)
	#define UFBXI_HAS_UNALIGNED
	#define ufbxi_unaligned
	ufbxi_unaligned_u16;
	ufbxi_unaligned_u32;
	ufbxi_unaligned_u64;
	ufbxi_unaligned_f32;
	ufbxi_unaligned_f64;
#elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
	#define UFBXI_HAS_UNALIGNED
	#if defined(_M_IX86)
		// MSVC seems to assume all pointers are unaligned for x86
		#define ufbxi_unaligned
	#else
		#define ufbxi_unaligned
	#endif
	typedef uint16_t ufbxi_unaligned_u16;
	typedef uint32_t ufbxi_unaligned_u32;
	typedef uint64_t ufbxi_unaligned_u64;
	typedef float ufbxi_unaligned_f32;
	typedef double ufbxi_unaligned_f64;
#endif

#if (defined(UFBXI_HAS_UNALIGNED) && UFBX_LITTLE_ENDIAN && !defined(UFBX_NO_UNALIGNED_LOADS)) || defined(UFBX_USE_UNALIGNED_LOADS)
	#define ufbxi_read_u16(ptr)
	#define ufbxi_read_u32(ptr)
	#define ufbxi_read_u64(ptr)
	#define ufbxi_read_f32(ptr)
	#define ufbxi_read_f64(ptr)
#else
	static ufbxi_forceinline uint16_t ufbxi_read_u16(const void *ptr) {
		const char *p = (const char*)ptr;
		return (uint16_t)(
			(unsigned)(uint8_t)p[0] << 0u |
			(unsigned)(uint8_t)p[1] << 8u );
	}
	static ufbxi_forceinline uint32_t ufbxi_read_u32(const void *ptr) {
		const char *p = (const char*)ptr;
		return (uint32_t)(
			(unsigned)(uint8_t)p[0] <<  0u |
			(unsigned)(uint8_t)p[1] <<  8u |
			(unsigned)(uint8_t)p[2] << 16u |
			(unsigned)(uint8_t)p[3] << 24u );
	}
	static ufbxi_forceinline uint64_t ufbxi_read_u64(const void *ptr) {
		const char *p = (const char*)ptr;
		return (uint64_t)(
			(uint64_t)(uint8_t)p[0] <<  0u |
			(uint64_t)(uint8_t)p[1] <<  8u |
			(uint64_t)(uint8_t)p[2] << 16u |
			(uint64_t)(uint8_t)p[3] << 24u |
			(uint64_t)(uint8_t)p[4] << 32u |
			(uint64_t)(uint8_t)p[5] << 40u |
			(uint64_t)(uint8_t)p[6] << 48u |
			(uint64_t)(uint8_t)p[7] << 56u );
	}
	static ufbxi_forceinline float ufbxi_read_f32(const void *ptr) {
		uint32_t u = ufbxi_read_u32(ptr);
		float f;
		memcpy(&f, &u, 4);
		return f;
	}
	static ufbxi_forceinline double ufbxi_read_f64(const void *ptr) {
		uint64_t u = ufbxi_read_u64(ptr);
		double f;
		memcpy(&f, &u, 8);
		return f;
	}
#endif

#define ufbxi_read_i8(ptr)
#define ufbxi_read_i16(ptr)
#define ufbxi_read_i32(ptr)
#define ufbxi_read_i64(ptr)

ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();

// -- Version

#define UFBX_SOURCE_VERSION
ufbx_abi_data_def const uint32_t ufbx_source_version =;

ufbx_static_assert();

// -- Fast copy

#if UFBXI_HAS_SSE
	#define ufbxi_copy_16_bytes(dst, src)
#elif defined(UFBXI_HAS_UNALIGNED)
	#define ufbxi_copy_16_bytes
#else
	#define ufbxi_copy_16_bytes
#endif


// -- Large fast integer

#if !defined(UFBX_STANDARD_C) && (defined(__wasm__) || defined(__EMSCRIPTEN__)) && !defined(UFBX_WASM_32BIT)
	typedef uint64_t ufbxi_fast_uint;
#else
	ufbxi_fast_uint;
#endif

// -- Wrapping right shift

#if !defined(UFBX_STANDARD_C) && defined(_MSC_VER) && defined(_M_X64)
	#define ufbxi_wrap_shr64
#else
	#define ufbxi_wrap_shr64(a, b)
#endif

// -- Atomic counter

#define UFBXI_THREAD_SAFE

#if defined(__cplusplus)
	#define ufbxi_extern_c
#else
	#define ufbxi_extern_c
#endif

#if !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
	ufbxi_atomic_counter;
	#define ufbxi_atomic_counter_init(ptr)
	#define ufbxi_atomic_counter_free(ptr)
	#define ufbxi_atomic_counter_inc(ptr)
	#define ufbxi_atomic_counter_dec(ptr)
	#define ufbxi_atomic_counter_load(ptr)
#elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
	#if defined(_M_X64) || defined(_M_ARM64)
		ufbxi_extern_c __int64 _InterlockedIncrement64(__int64 volatile * lpAddend);
		ufbxi_extern_c __int64 _InterlockedDecrement64(__int64 volatile * lpAddend);
		ufbxi_extern_c __int64 _InterlockedExchangeAdd64(__int64 volatile * lpAddend, __int64 Value);
		typedef volatile __int64 ufbxi_atomic_counter;
		#define ufbxi_atomic_counter_init
		#define ufbxi_atomic_counter_free
		#define ufbxi_atomic_counter_inc
		#define ufbxi_atomic_counter_dec
		#define ufbxi_atomic_counter_load
	#else
		ufbxi_extern_c long __cdecl _InterlockedIncrement(long volatile * lpAddend);
		ufbxi_extern_c long __cdecl _InterlockedDecrement(long volatile * lpAddend);
		ufbxi_extern_c long __cdecl _InterlockedExchangeAdd(long volatile * lpAddend, long Value);
		typedef volatile long ufbxi_atomic_counter;
		#define ufbxi_atomic_counter_init
		#define ufbxi_atomic_counter_free
		#define ufbxi_atomic_counter_inc
		#define ufbxi_atomic_counter_dec
		#define ufbxi_atomic_counter_load
	#endif
#elif !defined(UFBX_STANDARD_C) && defined(__TINYC__)
	#if defined(__x86_64__) || defined(_AMD64_)
		static size_t ufbxi_tcc_atomic_add(volatile size_t *dst, size_t value) {
			__asm__ __volatile__("lock; xaddq %0, %1;" : "+r" (value), "=m" (*dst) : "m" (dst));
			return value;
		}
	#elif defined(__i386__) || defined(_X86_)
		static size_t ufbxi_tcc_atomic_add(volatile size_t *dst, size_t value) {
			__asm__ __volatile__("lock; xaddl %0, %1;" : "+r" (value), "=m" (*dst) : "m" (dst));
			return value;
		}
	#else
		#error Unexpected TCC architecture
	#endif
	typedef volatile size_t ufbxi_atomic_counter;
	#define ufbxi_atomic_counter_init
	#define ufbxi_atomic_counter_free
	#define ufbxi_atomic_counter_inc
	#define ufbxi_atomic_counter_dec
	#define ufbxi_atomic_counter_load
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
	#include <new>
	#include <atomic>
	typedef struct { alignas(std::atomic_size_t) char data[sizeof(std::atomic_size_t)]; } ufbxi_atomic_counter;
	#define ufbxi_atomic_counter_init
	#define ufbxi_atomic_counter_free
	#define ufbxi_atomic_counter_inc
	#define ufbxi_atomic_counter_dec
	#define ufbxi_atomic_counter_load
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)
	#include <stdatomic.h>
	typedef volatile atomic_size_t ufbxi_atomic_counter;
	#define ufbxi_atomic_counter_init
	#define ufbxi_atomic_counter_free
	#define ufbxi_atomic_counter_inc
	#define ufbxi_atomic_counter_dec
	#define ufbxi_atomic_counter_load
#else
	typedef volatile size_t ufbxi_atomic_counter;
	#define ufbxi_atomic_counter_init
	#define ufbxi_atomic_counter_free
	#define ufbxi_atomic_counter_inc
	#define ufbxi_atomic_counter_dec
	#define ufbxi_atomic_counter_load
	#undef UFBXI_THREAD_SAFE
	#define UFBXI_THREAD_SAFE
#endif

// -- Bit manipulation

#if !defined(UFBX_STANDARD_C) && defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
	ufbxi_extern_c unsigned char _BitScanReverse(unsigned long * _Index, unsigned long _Mask);
	ufbxi_extern_c unsigned char _BitScanReverse64(unsigned long * _Index, unsigned __int64 _Mask);
	static ufbxi_forceinline ufbxi_unused uint32_t ufbxi_lzcnt64(uint64_t v) {
		unsigned long index;
		#if defined(_M_X64)
			_BitScanReverse64(&index, (unsigned __int64)v);
		#else
			uint32_t hi = (uint32_t)(v >> 32u);
			uint32_t hi_nonzero = hi != 0 ? 1 : 0;
			uint32_t part = hi_nonzero ? hi : (uint32_t)v;
			_BitScanReverse(&index, (unsigned long)part);
			index += hi_nonzero * 32u;
		#endif
		return 63 - (uint32_t)index;
	}
#elif !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__))
	#define ufbxi_lzcnt64(v)
#else
	// DeBrujin table lookup
	static const uint8_t ufbxi_lzcnt_table[] = {
		63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2, 9, 5, 28, 11, 13, 21, 42,
		19, 25, 31, 34, 40, 46, 52, 59, 1, 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41,
		53, 18, 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0,
	};
	static ufbxi_noinline ufbxi_unused uint32_t ufbxi_lzcnt64(uint64_t v) {
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v |= v >> 32;
		return ufbxi_lzcnt_table[(v * UINT64_C(0x03f79d71b4cb0a89)) >> 58];
	}
#endif

// -- Debug

#if defined(UFBX_DEBUG_BINARY_SEARCH) || defined(UFBX_REGRESSION)
	#define ufbxi_clamp_linear_threshold
#else
	#define ufbxi_clamp_linear_threshold(v)
#endif

#if defined(UFBX_REGRESSION)
	#undef UFBXI_MAX_SKIP_SIZE
	#define UFBXI_MAX_SKIP_SIZE

	#undef UFBXI_MAP_MAX_SCAN
	#define UFBXI_MAP_MAX_SCAN

	#undef UFBXI_KD_FAST_DEPTH
	#define UFBXI_KD_FAST_DEPTH

	#undef UFBXI_FACE_GROUP_HASH_BITS
	#define UFBXI_FACE_GROUP_HASH_BITS
#endif

#if defined(UFBX_REGRESSION) || defined(UFBX_EXTENSIVE_THREADING)
	#undef UFBXI_MIN_THREADED_DEFLATE_BYTES
	#define UFBXI_MIN_THREADED_DEFLATE_BYTES

	#undef UFBXI_MIN_THREADED_ASCII_VALUES
	#define UFBXI_MIN_THREADED_ASCII_VALUES
#endif

#if defined(UFBX_REGRESSION)
	#define ufbxi_regression_assert
#else
	#define ufbxi_regression_assert(cond)
#endif

#if defined(UFBX_REGRESSION) || defined(UFBX_DEV)
	#define ufbxi_dev_assert
#else
	#define ufbxi_dev_assert(cond)
#endif

#define ufbxi_unreachable(reason)

#if defined(UFBX_REGRESSION)
	#define UFBXI_IS_REGRESSION
#else
	#define UFBXI_IS_REGRESSION
#endif

#if defined(_MSC_VER)
	#define ufbxi_thread_local
#elif defined(__GNUC__) || defined(__clang__)
	#define ufbxi_thread_local
#elif UFBXI_HAS_CPP11
	#define ufbxi_thread_local
#elif UFBX_STDC >= 201112L
	#define ufbxi_thread_local
#endif

#if defined(UFBXI_ANALYSIS_RECURSIVE)
	#define ufbxi_recursive_function
	#define ufbxi_recursive_function_void
#elif UFBXI_IS_REGRESSION && defined(ufbxi_thread_local)
	#define ufbxi_recursive_function
	#define ufbxi_recursive_function_void
#else
	#define ufbxi_recursive_function(m_ret, m_name, m_args, m_max_depth, m_params)
	#define ufbxi_recursive_function_void(m_name, m_args, m_max_depth, m_params)
#endif

// -- Utility

#if defined(UFBX_UBSAN)
	static void ufbxi_assert_zero(size_t offset) { ufbx_assert(offset == 0); }
	#define ufbxi_add_ptr
	#define ufbxi_sub_ptr
#else
	#define ufbxi_add_ptr(ptr, offset)
	#define ufbxi_sub_ptr(ptr, offset)
#endif

#define ufbxi_arraycount(arr)
#define ufbxi_for(m_type, m_name, m_begin, m_num)
#define ufbxi_for_ptr(m_type, m_name, m_begin, m_num)

// WARNING: Evaluates `m_list` twice!
#define ufbxi_for_list(m_type, m_name, m_list)
#define ufbxi_for_ptr_list(m_type, m_name, m_list)

#define ufbxi_string_literal(str)

static ufbxi_forceinline uint32_t ufbxi_min32(uint32_t a, uint32_t b) {}
static ufbxi_forceinline uint32_t ufbxi_max32(uint32_t a, uint32_t b) {}
static ufbxi_forceinline uint64_t ufbxi_min64(uint64_t a, uint64_t b) {}
static ufbxi_forceinline uint64_t ufbxi_max64(uint64_t a, uint64_t b) {}
static ufbxi_forceinline size_t ufbxi_min_sz(size_t a, size_t b) {}
static ufbxi_forceinline size_t ufbxi_max_sz(size_t a, size_t b) {}
static ufbxi_forceinline ufbx_real ufbxi_min_real(ufbx_real a, ufbx_real b) {}
static ufbxi_forceinline ufbx_real ufbxi_max_real(ufbx_real a, ufbx_real b) {}

static ufbxi_forceinline int32_t ufbxi_f64_to_i32(double value)
{}

static ufbxi_forceinline int64_t ufbxi_f64_to_i64(double value)
{}

#if defined(UFBX_REGRESSION)
	static size_t ufbxi_to_size(ptrdiff_t delta) {
		ufbx_assert(delta >= 0);
		return (size_t)delta;
	}
#else
	#define ufbxi_to_size(delta)
#endif

// Stable sort array `m_type m_data[m_size]` using the predicate `m_cmp_lambda(a, b)`
// `m_linear_size` is a hint for how large blocks handle initially do with insertion sort
// `m_tmp` must be a memory buffer with at least the same size and alignment as `m_data`
#define ufbxi_macro_stable_sort(m_type, m_linear_size, m_data, m_tmp, m_size, m_cmp_lambda)

#define ufbxi_macro_lower_bound_eq(m_type, m_linear_size, m_result_ptr, m_data, m_begin, m_size, m_cmp_lambda, m_eq_lambda)

#define ufbxi_macro_upper_bound_eq(m_type, m_linear_size, m_result_ptr, m_data, m_begin, m_size, m_eq_lambda)

ufbxi_less_fn;

static ufbxi_noinline void ufbxi_stable_sort(size_t stride, size_t linear_size, void *in_data, void *in_tmp, size_t size, ufbxi_less_fn *less_fn, void *less_user)
{}

static ufbxi_forceinline void ufbxi_swap(void *a, void *b, size_t size)
{}

static ufbxi_noinline void ufbxi_unstable_sort(void *in_data, size_t size, size_t stride, ufbxi_less_fn *less_fn, void *less_user)
{}

// -- Float parsing
//
// Custom float parsing that handles floats up to (-)ddddddddddddddddddd.ddddddddddddddddddd
// If larger or scientific notation is used then it defers to `strtod()`.
// For the algorithm we need 128-bit division that is either provided by hardware on x64 or
// a custom implementation below.

#if !defined(UFBX_STANDARD_C) && UFBXI_MSC_VER >= 1920 && defined(_M_X64) && !defined(__clang__)
	ufbxi_extern_c extern unsigned __int64 __cdecl _udiv128(unsigned __int64  highdividend,
		unsigned __int64 lowdividend, unsigned __int64 divisor, unsigned __int64 *remainder);
	#define ufbxi_div128
#elif !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(_M_X64))
	static ufbxi_forceinline uint64_t ufbxi_div128(uint64_t a_hi, uint64_t a_lo, uint64_t b, uint64_t *p_rem) {}
#else
	static ufbxi_forceinline uint64_t ufbxi_div128(uint64_t a_hi, uint64_t a_lo, uint64_t b, uint64_t *p_rem) {
		// Divide `(a_hi << 64 | a_lo)` by `b`, returns quotinent and stores reminder in `p_rem`.
		// Based on TAOCP 2.4 multi-word division single algorithm digit step.
		//
		// Notation:
		//   b is the base (2^32) in this case
		//   aN is the Nth digit (base b) of a from the least significant digit
		//   { x y z } is a multi-digit number b^2*x + b*y + z
		//   ie. for a 64-bit number a = { a1 a0 } = b*a1 + a0
		//
		// We do the division in two steps by dividing three digits in each iteration:
		//
		//   q1, r = { a3 a2 a1 } / { b1 b0 }
		//   q0, r = { r1 r0 a0 } / { b1 b0 }
		//
		// In each step we want to compute the expression:
		//
		//   q, r = { u2 u1 u0 } / { v1 v0 }
		//
		// However we cannot rely on being able to do `u96 / u64` division we estimate
		// the result by considering only the leading digits:
		//
		//   q^ = { u2 u1 } / v1                                       [A]
		//   r^ = { u2 u1 } % v1 = { u2 u1 } - v1 * q^                 [B]
		//
		// As long as `v1 >= b/2` the estimate `q^` is at most two larger than the actual `q`
		// (proof in TAOCP 2.4) so we can compute the correction amount `c`:
		//
		//   q <= q^ <= q + 2
		//   q = q^ - c                                                [C]
		//
		// We can compute the final remainder (that must be non-negative) as follows:
		//
		//   r = { u2 u1 u0 } - v*q
		//   r = { u2 u1 u0 } - v*(q^ - c)
		//   r = { u2 u1 u0 } - v*q^ + v*c
		//   r = { u2 u1 u0 } - { v1 v0 } * q^ + v*c
		//   r = b^2*u2 + b*u1 + u0 - b*v1*q^ - v0*q^ + v*c
		//   r = b*(b*u2 + u1 - v1*q^) + u0 - v0*q^ + v*c
		//   r = b*({ u2 u1 } - v1*q^) + u0 - v0*q^ + v*c
		//   r = b*r^ + u0 - v0*q^ + v*c
		//   r = { r^ u0 } - v0*q^ + v*c                               [D]
		//
		// As we know `0 <= c <= 2` we can first check if `r < 0` requiring `c >= 1`:
		//
		//   { r^ u0 } - v0*q^ < 0
		//   { r^ u0 } < v0*q^                                         [E]
		//
		// If we know that `r < 0` we can check if `r < -v` requiring `c = 2`:
		//
		//   { r^ u0 } - v0*q^ < -v
		//   v0*q^ - { r^ u0 } > v                                     [F]
		//

		// First we need to make sure `v1 >= b/2`, we can do this by multiplying the whole
		// expression by `2^shift` so that the high bit of `v` is set.
		uint32_t shift = ufbxi_lzcnt64(b);
		a_hi = (a_hi << shift) | (shift ? a_lo >> (64 - shift) : 0);
		a_lo <<= shift;
		b <<= shift;

		uint64_t v = b;
		uint32_t v1 = (uint32_t)(v >> 32);
		uint32_t v0 = (uint32_t)(v);
		uint64_t q1, q0, r;

		// q1, r = { a3 a2 a1 } / { b1 b0 }
		{
			uint64_t u2_u1 = a_hi;
			uint32_t u0 = (uint32_t)(a_lo >> 32u);

			uint64_t qh = u2_u1 / v1;            // q^ = { u2 u1 } / v1          [A]
			uint64_t rh = u2_u1 % v1;            // r^ = { u2 u1 } % v1          [B]
			uint64_t rh_u0 = rh << 32u | u0;     // { r^ u0 }
			uint64_t v0qh = v0 * qh;             // v0*q^
			uint32_t c = rh_u0 < v0qh ? 1 : 0;   // { r^ u0 } < v0*q^            [E]
			c += c & (v0qh - rh_u0 > v ? 1 : 0); // v0*q^ - { r^ u0 } > v        [F]
			q1 = qh - c;                         // q1 = q^ - c                  [C]
			r = rh_u0 - v0qh + v*c;              // r = { r^ u0 } - v0*q^ + v*c  [D]
		}

		// q0, r = { r1 r0 a0 } / { b1 b0 }
		{
			uint64_t u2_u1 = r;
			uint32_t u0 = (uint32_t)a_lo;

			uint64_t qh = u2_u1 / v1;            // q^ = { u2 u1 } / v1          [A]
			uint64_t rh = u2_u1 % v1;            // r^ = { u2 u1 } % v1          [B]
			uint64_t rh_u0 = rh << 32u | u0;     // { r^ u0 }
			uint64_t v0qh = v0 * qh;             // v0*q^
			uint32_t c = rh_u0 < v0qh ? 1 : 0;   // { r^ u0 } < v0*q^            [E]
			c += c & (v0qh - rh_u0 > v ? 1 : 0); // v0*q^ - { r^ u0 } > v        [F]
			q0 = qh - c;                         // q0 = q^ - c                  [C]
			r = rh_u0 - v0qh + v*c;              // r = { r^ u0 } - v0*q^ + v*c  [D]
		}

		// Un-normalize the remainder and return the quotinent
		*p_rem = r >> shift;
		return q1 << 32u | q0;
	}
#endif

ufbxi_parse_double_flag;

static const uint64_t ufbxi_pow5_tab[] =;
static const int8_t ufbxi_pow2_tab[] =;
static const double ufbxi_pow10_tab_f64[] =;

static ufbxi_noinline uint32_t ufbxi_parse_double_init_flags()
{}

static ufbxi_noinline double ufbxi_parse_double_slow(const char *str, char **end)
{}

static ufbxi_noinline double ufbxi_parse_double(const char *str, size_t max_length, char **end, uint32_t flags)
{}

static ufbxi_forceinline int64_t ufbxi_parse_int64(const char *str, char **end)
{}

// -- DEFLATE implementation

#if !defined(ufbx_inflate)

// Lookup data: [0:5] extra bits [5:8] flags [16:32] base value
// Generated by `misc/deflate_lut.py`
static const uint32_t ufbxi_deflate_length_lut[] =;
static const uint32_t ufbxi_deflate_dist_lut[] =;

static const uint8_t ufbxi_deflate_code_length_permutation[] =;

#define UFBXI_INFLATE_FAST_MIN_IN
#define UFBXI_INFLATE_FAST_MIN_OUT

#define UFBXI_HUFF_MAX_BITS
#define UFBXI_HUFF_MAX_VALUE
#define UFBXI_HUFF_FAST_BITS
#define UFBXI_HUFF_FAST_SIZE
#define UFBXI_HUFF_FAST_MASK
#define UFBXI_HUFF_MAX_LONG_BITS
#define UFBXI_HUFF_MAX_LONG_SYMS

#define UFBXI_HUFF_CODELEN_FAST_BITS
#define UFBXI_HUFF_CODELEN_FAST_MASK

#define UFBXI_HUFF_MAX_EXTRA_SYMS

ufbxi_bit_stream;

// Packed symbol information:
//
//   [0:5]   total_bits    // [fast=1] Number of bits in the symbol _including_ extra bits
//   [0:5]   extra_mask    // [fast=0] Mask of extra bits to use
//   [5]     end           // 1 if end/invalid symbol, always 0 if `fast` (*1)
//   [6]     match         // 1 if the symbol is a match length, always 0 in non `lit_length` trees (always 0 if `end`)
//   [7]     fast          // 1 if the symbol can be determined from the table bits and `end=0`
//   [8:16]  lit_byte      // [lit_length]                     Literal byte
//   [8:16]  len_index     // [lit_length, match=1]            Match length index
//   [8:16]  dist_index    // [dist]                           Match distance index
//   [8:16]  code_length   // [code_length]                    Dynamic Huffman code length code
//   [8:16]  long_offset   // [fast_sym, fast=0, extra_mask>0] Base offset (halved) to `long_sym[]`
//   [8:16]  code_prefix   // [fast_sym, fast=0, extra_mask=0] First 8-bits of the code (reverse of the lookup)
//
// (*1) Not allowing `end` if `fast` serves a dual purpose: It allows us to omit a check for the end symbol in the
// fast path and allows using the symbol as a 64-bit shift amount (x64/ARM64/WASM have native modulo 64 shifts).
//
// Valid bit patterns, all other patterns are forbidden (`sorted_to_sym[]` contains same patterns as `long_sym[]`):
//
//   tree                    b e m f v
//
//   lit_length.fast_sym[]   N 0 0 1 L  // Short N bit code (no extra allowed) for literal byte L
//   lit_length.fast_sym[]   N 0 1 1 I  // Short N bit code (huff+extra bits) for length index I
//   lit_length.fast_sym[]   M 0 0 0 X  // Long code at `lit_length.long_sym[X*2 + ((bits>>FAST_BITS) & M)]`
//   lit_length.fast_sym[]   0 0 0 0 R  // Extra long code with prefix R, use `lit_length.sorted_to_sym[]` to resolve (*1)
//   lit_length.fast_sym[]   N 1 0 0 0  // Short N bit code for end-of-block (256) symbol
//   lit_length.fast_sym[]   0 1 0 0 1  // Invalid lit_length code
//
//   lit_length.long_sym[]   N 0 0 0 L  // Long N bit code (no extra allowed) for literal byte L
//   lit_length.long_sym[]   N 0 1 0 I  // Long N bit code (huff+extra bits) for length index I
//   lit_length.long_sym[]   N 1 0 0 0  // Long N bit code for end-of-block (256) symbol
//   lit_length.long_sym[]   0 1 0 0 1  // Invalid lit_length code
//
//   dist.fast_sym[]         N 0 0 1 L  // Short N bit code (huff+extra bits) for distance index I
//   dist.fast_sym[]         M 0 0 0 X  // Long code at `dist.long_sym[X*2 + ((bits>>FAST_BITS) & M)]`
//   dist.fast_sym[]         0 0 0 0 R  // Extra long code with prefix R, use `dist.sorted_to_sym[]` to resolve (*1)
//   dist.fast_sym[]         N 1 0 0 1  // Unused symbol 30-31 or invalid distance code
//
//   dist.long_sym[]         N 0 0 0 I  // Long N bit code (huff+extra bits) for distance index I
//   dist.long_sym[]         N 1 0 0 1  // Unused symbol 30-31 or invalid distance code
//
//   code_length.fast_sym[]  N 0 0 1 B  // Short N bit code (huff only, extra handled explicitly) for symbol bit count B
//   code_length.fast_sym[]  M 0 0 0 X  // Long code at `dist.long_sym[X*2 + ((bits>>FAST_BITS) & M)]`
//   code_length.fast_sym[]  0 0 0 0 R  // Extra long code with prefix R, use `code_length.sorted_to_sym[]` to resolve (*1)
//
//   code_length.long_sym[]  N 0 0 0 B  // Long N bit code (huff only, extra handled explicitly) for symbol bit count B
//
// (*1) Never necessary if `fast_bits >= 10` due to `long_sym[]` covering all possible codes,
//
ufbxi_huff_sym;

#define ufbxi_huff_sym_total_bits(sym)
#define ufbxi_huff_sym_long_mask(sym)
#define ufbxi_huff_sym_long_offset(sym)
#define ufbxi_huff_sym_value(sym)

enum {};

#define UFBXI_HUFF_ERROR_SYM
#define UFBXI_HUFF_UNINITIALIZED_SYM

ufbxi_huff_tree;

ufbxi_trees;

ufbxi_inflate_retain_imp;

ufbx_static_assert();

ufbxi_deflate_context;

static ufbxi_forceinline uint32_t
ufbxi_bit_reverse(uint32_t mask, uint32_t num_bits)
{}

static ufbxi_noinline const char *
ufbxi_bit_chunk_refill(ufbxi_bit_stream *s, const char *ptr)
{}

static ufbxi_noinline void ufbxi_bit_stream_init(ufbxi_bit_stream *s, const ufbx_inflate_input *input)
{}

static ufbxi_noinline const char *
ufbxi_bit_yield(ufbxi_bit_stream *s, const char *ptr)
{}

static ufbxi_forceinline void
ufbxi_bit_refill(uint64_t *p_bits, size_t *p_left, const char **p_data, ufbxi_bit_stream *s)
{}

// See `ufbxi_bit_refill()`
#define ufbxi_macro_bit_refill_fast(m_bits, m_left, m_data, m_refill_bits)

static ufbxi_noinline int
ufbxi_bit_copy_bytes(void *dst, ufbxi_bit_stream *s, size_t len)
{}

// 0: Success
// -1: Overfull
// -2: Underfull
static ufbxi_noinline ptrdiff_t
ufbxi_huff_build_imp(ufbxi_huff_tree *tree, uint8_t *sym_bits, uint32_t sym_count, const uint32_t *sym_extra, uint32_t sym_extra_offset, uint32_t fast_bits, uint32_t *bits_counts)
{}

// 0: Success
// -1: Overfull
// -2: Underfull
static ufbxi_noinline ptrdiff_t
ufbxi_huff_build(ufbxi_huff_tree *tree, uint8_t *sym_bits, uint32_t sym_count, const uint32_t *sym_extra, uint32_t sym_extra_offset, uint32_t fast_bits)
{}

static ufbxi_forceinline ufbxi_huff_sym
ufbxi_huff_decode_bits(const ufbxi_huff_tree *tree, uint64_t bits, uint32_t fast_bits, uint32_t fast_mask)
{}

static ufbxi_noinline void ufbxi_init_static_huff(ufbxi_trees *trees, const ufbx_inflate_input *input)
{}

// 0: Success
// -1: Huffman Overfull
// -2: Huffman Underfull
// -3: Code 16 repeat overflow
// -4: Code 17 repeat overflow
// -5: Code 18 repeat overflow
// -6: Bad length code
// -7: Cancelled
static ufbxi_noinline ptrdiff_t ufbxi_init_dynamic_huff_tree(ufbxi_deflate_context *dc, const ufbxi_huff_tree *huff_code_length, ufbxi_huff_tree *tree,
	uint32_t num_symbols, const uint32_t *sym_extra, uint32_t sym_extra_offset, uint32_t fast_bits)
{}

static ufbxi_noinline ptrdiff_t
ufbxi_init_dynamic_huff(ufbxi_deflate_context *dc, ufbxi_trees *trees)
{}

static ufbxi_noinline uint32_t ufbxi_adler32(const void *data, size_t size)
{}

static ufbxi_noinline int
ufbxi_inflate_block_slow(ufbxi_deflate_context *dc, ufbxi_trees *trees, size_t max_symbols)
{}

ufbx_static_assert(); // `fast lit, fast len, slow dist` in 56 bits
ufbx_static_assert(); // Largest code fits in a single long lookup

// Optimized version of `ufbxi_inflate_block_slow()`.
// Has a lot of assumptions (see asserts) and does not call _any_ (even forceinlined) functions.
static ufbxi_noinline int
ufbxi_inflate_block_fast(ufbxi_deflate_context *dc, ufbxi_trees *trees)
{}

static void ufbxi_inflate_init_retain(ufbx_inflate_retain *retain)
{}

// TODO: Error codes should have a quick test if the destination buffer overflowed
// Returns actual number of decompressed bytes or negative error:
// -1: Bad compression method (ZLIB header)
// -2: Requires dictionary (ZLIB header)
// -3: Bad FCHECK (ZLIB header)
// -4: Bad NLEN (Uncompressed LEN != ~NLEN)
// -5: Uncompressed source overflow
// -6: Uncompressed destination overflow
// -7: Bad block type
// -8: Truncated checksum (deprecated, reported as -9)
// -9: Checksum mismatch
// -10: Literal destination overflow
// -11: Bad distance code or distance of (30..31)
// -12: Match out of bounds
// -13: Bad lit/length code
// -14: Codelen Huffman Overfull
// -15: Codelen Huffman Underfull
// -16 - -21: Litlen Huffman: Overfull / Underfull / Repeat 16/17/18 overflow / Bad length code
// -22 - -27: Distance Huffman: Overfull / Underfull / Repeat 16/17/18 overflow / Bad length code
// -28: Cancelled
// -29: Invalid ufbx_inflate_input.internal_fast_bits value
ufbxi_extern_c ptrdiff_t ufbx_inflate(void *dst, size_t dst_size, const ufbx_inflate_input *input, ufbx_inflate_retain *retain)
{}

#endif // !defined(ufbx_inflate)

// -- Errors

static const char ufbxi_empty_char[1] =;

static ufbxi_noinline int ufbxi_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list args)
{}

static ufbxi_noinline int ufbxi_snprintf(char *buf, size_t buf_size, const char *fmt, ...)
{}

static ufbxi_noinline void ufbxi_panicf_imp(ufbx_panic *panic, const char *fmt, ...)
{}

#define ufbxi_panicf(panic, cond, ...)

// Prefix the error condition with $Description\0 for a human readable description
#define ufbxi_error_msg(cond, msg)

static ufbxi_noinline int ufbxi_fail_imp_err(ufbx_error *err, const char *cond, const char *func, uint32_t line)
{}

ufbxi_nodiscard static ufbxi_noinline size_t ufbxi_utf8_valid_length(const char *str, size_t length)
{}

static ufbxi_noinline void ufbxi_clean_string_utf8(char *str, size_t length)
{}

static ufbxi_noinline void ufbxi_set_err_info(ufbx_error *err, const char *data, size_t length)
{}

static ufbxi_noinline void ufbxi_fmt_err_info(ufbx_error *err, const char *fmt, ...)
{}

static ufbxi_noinline void ufbxi_clear_error(ufbx_error *err)
{}

#if UFBXI_FEATURE_ERROR_STACK
	#define ufbxi_function
	#define ufbxi_line
	#define ufbxi_cond_str
#else
	#define ufbxi_function
	#define ufbxi_line
	#define ufbxi_cond_str(cond)
#endif

#define ufbxi_check_err(err, cond)
#define ufbxi_check_return_err(err, cond, ret)
#define ufbxi_fail_err(err, desc)

#define ufbxi_check_err_msg(err, cond, msg)
#define ufbxi_check_return_err_msg(err, cond, ret, msg)
#define ufbxi_fail_err_msg(err, desc, msg)
#define ufbxi_report_err_msg(err, desc, msg)

static ufbxi_noinline void ufbxi_fix_error_type(ufbx_error *error, const char *default_desc)
{}

// -- Allocator

// Returned for zero size allocations, place in the constant data
// to catch writes to bad allocations.
#if defined(UFBX_REGRESSION)
static const char ufbxi_zero_size_buffer[4096] = { 0 };
#else
static const char ufbxi_zero_size_buffer[64] =;
#endif

static ufbxi_forceinline size_t ufbxi_align_to_mask(size_t value, size_t align_mask)
{}

static ufbxi_forceinline size_t ufbxi_size_align_mask(size_t size)
{}

ufbxi_allocator;

static ufbxi_forceinline bool ufbxi_does_overflow(size_t total, size_t a, size_t b)
{}

static ufbxi_noinline void *ufbxi_alloc_size(ufbxi_allocator *ator, size_t size, size_t n)
{}

static void ufbxi_free_size(ufbxi_allocator *ator, size_t size, void *ptr, size_t n);
static ufbxi_noinline void *ufbxi_realloc_size(ufbxi_allocator *ator, size_t size, void *old_ptr, size_t old_n, size_t n)
{}

static ufbxi_noinline void ufbxi_free_size(ufbxi_allocator *ator, size_t size, void *ptr, size_t n)
{}

ufbxi_noinline ufbxi_nodiscard static bool ufbxi_grow_array_size(ufbxi_allocator *ator, size_t size, void *p_ptr, size_t *p_cap, size_t n)
{}

static ufbxi_noinline void ufbxi_free_ator(ufbxi_allocator *ator)
{}

#define ufbxi_alloc(ator, type, n)
#define ufbxi_alloc_zero(ator, type, n)
#define ufbxi_realloc(ator, type, old_ptr, old_n, n)
#define ufbxi_realloc_zero(ator, type, old_ptr, old_n, n)
#define ufbxi_free(ator, type, ptr, n)

#define ufbxi_grow_array(ator, p_ptr, p_cap, n)

#define UFBXI_SCENE_IMP_MAGIC
#define UFBXI_MESH_IMP_MAGIC
#define UFBXI_LINE_CURVE_IMP_MAGIC
#define UFBXI_CACHE_IMP_MAGIC
#define UFBXI_ANIM_IMP_MAGIC
#define UFBXI_BAKED_ANIM_IMP_MAGIC
#define UFBXI_REFCOUNT_IMP_MAGIC
#define UFBXI_BUF_CHUNK_IMP_MAGIC

// -- Memory buffer
//
// General purpose memory buffer that can be used either as a chunked linear memory
// allocator or a non-contiguous stack. You can convert the contents of `ufbxi_buf`
// to a contiguous range of memory by calling `ufbxi_make_array[_all]()`

ufbxi_buf_padding;
ufbxi_buf_chunk;

struct ufbxi_buf_padding {};

struct ufbxi_buf_chunk {};

ufbx_static_assert();

ufbxi_buf;

ufbxi_buf_state;

static ufbxi_noinline void *ufbxi_push_size_new_block(ufbxi_buf *b, size_t size)
{}

static ufbxi_noinline void *ufbxi_push_size(ufbxi_buf *b, size_t size, size_t n)
{}

static ufbxi_forceinline void *ufbxi_push_size_fast(ufbxi_buf *b, size_t size, size_t n)
{}

static ufbxi_noinline void *ufbxi_push_size_zero(ufbxi_buf *b, size_t size, size_t n)
{}

ufbxi_nodiscard static ufbxi_noinline void *ufbxi_push_size_copy(ufbxi_buf *b, size_t size, size_t n, const void *data)
{}

ufbxi_nodiscard static ufbxi_forceinline void *ufbxi_push_size_copy_fast(ufbxi_buf *b, size_t size, size_t n, const void *data)
{}

static ufbxi_noinline void ufbxi_buf_free_unused(ufbxi_buf *b)
{}

static ufbxi_noinline void ufbxi_pop_size(ufbxi_buf *b, size_t size, size_t n, void *dst, bool peek)
{}

static ufbxi_noinline void *ufbxi_push_pop_size(ufbxi_buf *dst, ufbxi_buf *src, size_t size, size_t n)
{}

static ufbxi_noinline void *ufbxi_push_peek_size(ufbxi_buf *dst, ufbxi_buf *src, size_t size, size_t n)
{}

static ufbxi_noinline void ufbxi_buf_free(ufbxi_buf *buf)
{}

static ufbxi_noinline void ufbxi_buf_clear(ufbxi_buf *buf)
{}

#define ufbxi_push(b, type, n)
#define ufbxi_push_zero(b, type, n)
#define ufbxi_push_copy(b, type, n, data)
#define ufbxi_push_copy_fast(b, type, n, data)
#define ufbxi_push_fast(b, type, n)
#define ufbxi_pop(b, type, n, dst)
#define ufbxi_peek(b, type, n, dst)
#define ufbxi_push_pop(dst, src, type, n)
#define ufbxi_push_peek(dst, src, type, n)

// -- Hash map
//
// The actual element comparison is left to the user of `ufbxi_map`, see usage below.
//
// NOTES:
//   ufbxi_map_insert() does not support duplicate values, use find first if duplicates are possible!
//   Inserting duplicate elements fails with an assertion if `UFBX_REGRESSION` is enabled.

ufbxi_aa_node;

ufbxi_cmp_fn;

struct ufbxi_aa_node {};

ufbxi_map;

static ufbxi_noinline void ufbxi_map_init(ufbxi_map *map, ufbxi_allocator *ator, ufbxi_cmp_fn *cmp_fn, void *cmp_user)
{}

static ufbxi_noinline void ufbxi_map_free(ufbxi_map *map)
{}

// Recursion limit: log2(2^64 / sizeof(ufbxi_aa_node))
static ufbxi_noinline ufbxi_aa_node *ufbxi_aa_tree_insert(ufbxi_map *map, ufbxi_aa_node *node, const void *value, uint32_t index, size_t item_size)
	ufbxi_recursive_function(ufbxi_aa_node *, ufbxi_aa_tree_insert, (map, node, value, index, item_size), 59,
		(ufbxi_map *map, ufbxi_aa_node *node, const void *value, uint32_t index, size_t item_size))
{}

static ufbxi_noinline void *ufbxi_aa_tree_find(ufbxi_map *map, const void *value, size_t item_size)
{}

static ufbxi_noinline bool ufbxi_map_grow_size_imp(ufbxi_map *map, size_t item_size, size_t min_size)
{}

static ufbxi_forceinline bool ufbxi_map_grow_size(ufbxi_map *map, size_t size, size_t min_size)
{}

static ufbxi_noinline void *ufbxi_map_find_size(ufbxi_map *map, size_t size, uint32_t hash, const void *value)
{}

static ufbxi_noinline void *ufbxi_map_insert_size(ufbxi_map *map, size_t size, uint32_t hash, const void *value)
{}

#define ufbxi_map_grow(map, type, min_size)
#define ufbxi_map_find(map, type, hash, value)
#define ufbxi_map_insert(map, type, hash, value)

static int ufbxi_map_cmp_uint64(void *user, const void *va, const void *vb)
{}

static int ufbxi_map_cmp_const_char_ptr(void *user, const void *va, const void *vb)
{}

static int ufbxi_map_cmp_uintptr(void *user, const void *va, const void *vb)
{}

// -- Hash functions

static ufbxi_noinline uint32_t ufbxi_hash_string(const char *str, size_t length)
{}

// NOTE: _Must_ match `ufbxi_hash_string()`
static ufbxi_noinline uint32_t ufbxi_hash_string_check_ascii(const char *str, size_t length, bool *p_non_ascii)
{}

static ufbxi_forceinline uint32_t ufbxi_hash32(uint32_t x)
{}

static ufbxi_forceinline uint32_t ufbxi_hash64(uint64_t x)
{}

static ufbxi_forceinline uint32_t ufbxi_hash_uptr(uintptr_t ptr)
{}

#define ufbxi_hash_ptr(ptr)

// -- Warnings

ufbxi_warnings;

ufbxi_nodiscard static ufbxi_noinline int ufbxi_vwarnf_imp(ufbxi_warnings *ws, ufbx_warning_type type, uint32_t element_id, const char *fmt, va_list args)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_warnf_imp(ufbxi_warnings *ws, ufbx_warning_type type, uint32_t element_id, const char *fmt, ...)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_pop_warnings(ufbxi_warnings *ws, ufbx_warning_list *warnings, bool *p_has_warning)
{}

// -- String pool

// All strings found in FBX files are interned for deduplication and fast
// comparison. Our fixed internal strings (`ufbxi_String`) are considered the
// canonical pointers for said strings so we can compare them by address.

ufbxi_string_pool;

ufbxi_sanitized_string;

static ufbxi_forceinline bool ufbxi_str_equal(ufbx_string a, ufbx_string b)
{}

static ufbxi_forceinline bool ufbxi_str_less(ufbx_string a, ufbx_string b)
{}

static ufbxi_forceinline int ufbxi_str_cmp(ufbx_string a, ufbx_string b)
{}

static ufbxi_forceinline ufbx_string ufbxi_str_c(const char *str)
{}

static ufbxi_noinline uint32_t ufbxi_get_concat_key(const ufbx_string *parts, size_t num_parts)
{}

static ufbxi_noinline int ufbxi_concat_str_cmp(const ufbx_string *ref, const ufbx_string *parts, size_t num_parts)
{}

static ufbxi_forceinline bool ufbxi_starts_with(ufbx_string str, ufbx_string prefix)
{}

static ufbxi_forceinline bool ufbxi_ends_with(ufbx_string str, ufbx_string suffix)
{}

static ufbxi_noinline bool ufbxi_remove_prefix_len(ufbx_string *str, const char *prefix, size_t prefix_len)
{}

static ufbxi_noinline bool ufbxi_remove_suffix_len(ufbx_string *str, const char *suffix, size_t suffix_len)
{}

static ufbxi_forceinline bool ufbxi_remove_prefix_str(ufbx_string *str, ufbx_string prefix)
{}

static ufbxi_forceinline bool ufbxi_remove_suffix_c(ufbx_string *str, const char *suffix)
{}

static int ufbxi_map_cmp_string(void *user, const void *va, const void *vb)
{}

static ufbxi_forceinline ufbx_string ufbxi_safe_string(const char *data, size_t length)
{}

static void ufbxi_string_pool_temp_free(ufbxi_string_pool *pool)
{}

ufbxi_nodiscard static size_t ufbxi_add_replacement_char(ufbxi_string_pool *pool, char *dst, char c)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_sanitize_string(ufbxi_string_pool *pool, ufbxi_sanitized_string *sanitized, const char *str, size_t length, size_t valid_length, bool push_both)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_sanitized_string(ufbxi_string_pool *pool, ufbxi_sanitized_string *sanitized, const char *str, size_t length, uint32_t hash, bool raw)
{}

ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_push_string_imp(ufbxi_string_pool *pool, const char *str, size_t length, size_t *p_out_length, bool copy, bool raw)
{}

ufbxi_nodiscard static ufbxi_forceinline const char *ufbxi_push_string(ufbxi_string_pool *pool, const char *str, size_t length, size_t *p_out_length, bool raw)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_push_string_place(ufbxi_string_pool *pool, const char **p_str, size_t *p_length, bool raw)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_string_place_str(ufbxi_string_pool *pool, ufbx_string *p_str, bool raw)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_string_place_blob(ufbxi_string_pool *pool, ufbx_blob *p_blob, bool raw)
{}

// -- String constants
//
// All strings in FBX files are pooled so by having canonical string constant
// addresses we can compare strings to these constants by comparing pointers.
// Keep the list alphabetically sorted!

static const char ufbxi_AllSame[] =;
static const char ufbxi_Alphas[] =;
static const char ufbxi_AmbientColor[] =;
static const char ufbxi_AnimationCurveNode[] =;
static const char ufbxi_AnimationCurve[] =;
static const char ufbxi_AnimationLayer[] =;
static const char ufbxi_AnimationStack[] =;
static const char ufbxi_ApertureFormat[] =;
static const char ufbxi_ApertureMode[] =;
static const char ufbxi_AreaLightShape[] =;
static const char ufbxi_AspectH[] =;
static const char ufbxi_AspectHeight[] =;
static const char ufbxi_AspectRatioMode[] =;
static const char ufbxi_AspectW[] =;
static const char ufbxi_AspectWidth[] =;
static const char ufbxi_Audio[] =;
static const char ufbxi_AudioLayer[] =;
static const char ufbxi_BaseLayer[] =;
static const char ufbxi_BinaryData[] =;
static const char ufbxi_BindPose[] =;
static const char ufbxi_BindingTable[] =;
static const char ufbxi_Binormals[] =;
static const char ufbxi_BinormalsIndex[] =;
static const char ufbxi_BinormalsW[] =;
static const char ufbxi_BlendMode[] =;
static const char ufbxi_BlendModes[] =;
static const char ufbxi_BlendShapeChannel[] =;
static const char ufbxi_BlendShape[] =;
static const char ufbxi_BlendWeights[] =;
static const char ufbxi_BoundaryRule[] =;
static const char ufbxi_Boundary[] =;
static const char ufbxi_ByEdge[] =;
static const char ufbxi_ByPolygonVertex[] =;
static const char ufbxi_ByPolygon[] =;
static const char ufbxi_ByVertex[] =;
static const char ufbxi_ByVertice[] =;
static const char ufbxi_Cache[] =;
static const char ufbxi_CameraProjectionType[] =;
static const char ufbxi_CameraStereo[] =;
static const char ufbxi_CameraSwitcher[] =;
static const char ufbxi_Camera[] =;
static const char ufbxi_CastLight[] =;
static const char ufbxi_CastShadows[] =;
static const char ufbxi_Channel[] =;
static const char ufbxi_Character[] =;
static const char ufbxi_Children[] =;
static const char ufbxi_Cluster[] =;
static const char ufbxi_CollectionExclusive[] =;
static const char ufbxi_Collection[] =;
static const char ufbxi_ColorIndex[] =;
static const char ufbxi_Color[] =;
static const char ufbxi_Colors[] =;
static const char ufbxi_Cone_angle[] =;
static const char ufbxi_ConeAngle[] =;
static const char ufbxi_Connections[] =;
static const char ufbxi_Constraint[] =;
static const char ufbxi_Content[] =;
static const char ufbxi_CoordAxisSign[] =;
static const char ufbxi_CoordAxis[] =;
static const char ufbxi_Count[] =;
static const char ufbxi_Creator[] =;
static const char ufbxi_CurrentTextureBlendMode[] =;
static const char ufbxi_CurrentTimeMarker[] =;
static const char ufbxi_CustomFrameRate[] =;
static const char ufbxi_DecayType[] =;
static const char ufbxi_DefaultCamera[] =;
static const char ufbxi_Default[] =;
static const char ufbxi_Definitions[] =;
static const char ufbxi_DeformPercent[] =;
static const char ufbxi_Deformer[] =;
static const char ufbxi_DiffuseColor[] =;
static const char ufbxi_Dimension[] =;
static const char ufbxi_Dimensions[] =;
static const char ufbxi_DisplayLayer[] =;
static const char ufbxi_Document[] =;
static const char ufbxi_Documents[] =;
static const char ufbxi_EdgeCrease[] =;
static const char ufbxi_EdgeIndexArray[] =;
static const char ufbxi_Edges[] =;
static const char ufbxi_EmissiveColor[] =;
static const char ufbxi_Entry[] =;
static const char ufbxi_FBXHeaderExtension[] =;
static const char ufbxi_FBXVersion[] =;
static const char ufbxi_FKEffector[] =;
static const char ufbxi_FarPlane[] =;
static const char ufbxi_FbxPropertyEntry[] =;
static const char ufbxi_FbxSemanticEntry[] =;
static const char ufbxi_FieldOfViewX[] =;
static const char ufbxi_FieldOfViewY[] =;
static const char ufbxi_FieldOfView[] =;
static const char ufbxi_FileName[] =;
static const char ufbxi_Filename[] =;
static const char ufbxi_FilmHeight[] =;
static const char ufbxi_FilmSqueezeRatio[] =;
static const char ufbxi_FilmWidth[] =;
static const char ufbxi_FlipNormals[] =;
static const char ufbxi_FocalLength[] =;
static const char ufbxi_Form[] =;
static const char ufbxi_Freeze[] =;
static const char ufbxi_FrontAxisSign[] =;
static const char ufbxi_FrontAxis[] =;
static const char ufbxi_FullWeights[] =;
static const char ufbxi_GateFit[] =;
static const char ufbxi_GeometricRotation[] =;
static const char ufbxi_GeometricScaling[] =;
static const char ufbxi_GeometricTranslation[] =;
static const char ufbxi_GeometryUVInfo[] =;
static const char ufbxi_Geometry[] =;
static const char ufbxi_GlobalSettings[] =;
static const char ufbxi_Hole[] =;
static const char ufbxi_HotSpot[] =;
static const char ufbxi_IKEffector[] =;
static const char ufbxi_ImageData[] =;
static const char ufbxi_Implementation[] =;
static const char ufbxi_Indexes[] =;
static const char ufbxi_InheritType[] =;
static const char ufbxi_InnerAngle[] =;
static const char ufbxi_Intensity[] =;
static const char ufbxi_IsTheNodeInSet[] =;
static const char ufbxi_KeyAttrDataFloat[] =;
static const char ufbxi_KeyAttrFlags[] =;
static const char ufbxi_KeyAttrRefCount[] =;
static const char ufbxi_KeyCount[] =;
static const char ufbxi_KeyTime[] =;
static const char ufbxi_KeyValueFloat[] =;
static const char ufbxi_Key[] =;
static const char ufbxi_KnotVectorU[] =;
static const char ufbxi_KnotVectorV[] =;
static const char ufbxi_KnotVector[] =;
static const char ufbxi_LayerElementBinormal[] =;
static const char ufbxi_LayerElementColor[] =;
static const char ufbxi_LayerElementEdgeCrease[] =;
static const char ufbxi_LayerElementHole[] =;
static const char ufbxi_LayerElementMaterial[] =;
static const char ufbxi_LayerElementNormal[] =;
static const char ufbxi_LayerElementPolygonGroup[] =;
static const char ufbxi_LayerElementSmoothing[] =;
static const char ufbxi_LayerElementTangent[] =;
static const char ufbxi_LayerElementUV[] =;
static const char ufbxi_LayerElementVertexCrease[] =;
static const char ufbxi_LayerElementVisibility[] =;
static const char ufbxi_LayerElement[] =;
static const char ufbxi_Layer[] =;
static const char ufbxi_LayeredTexture[] =;
static const char ufbxi_Lcl_Rotation[] =;
static const char ufbxi_Lcl_Scaling[] =;
static const char ufbxi_Lcl_Translation[] =;
static const char ufbxi_LeftCamera[] =;
static const char ufbxi_LightType[] =;
static const char ufbxi_Light[] =;
static const char ufbxi_LimbLength[] =;
static const char ufbxi_LimbNode[] =;
static const char ufbxi_Limb[] =;
static const char ufbxi_Line[] =;
static const char ufbxi_Link[] =;
static const char ufbxi_LocalStart[] =;
static const char ufbxi_LocalStop[] =;
static const char ufbxi_LocalTime[] =;
static const char ufbxi_LodGroup[] =;
static const char ufbxi_MappingInformationType[] =;
static const char ufbxi_Marker[] =;
static const char ufbxi_MaterialAssignation[] =;
static const char ufbxi_Material[] =;
static const char ufbxi_Materials[] =;
static const char ufbxi_Matrix[] =;
static const char ufbxi_Media[] =;
static const char ufbxi_Mesh[] =;
static const char ufbxi_Model[] =;
static const char ufbxi_Name[] =;
static const char ufbxi_NearPlane[] =;
static const char ufbxi_NodeAttributeName[] =;
static const char ufbxi_NodeAttribute[] =;
static const char ufbxi_Node[] =;
static const char ufbxi_Normals[] =;
static const char ufbxi_NormalsIndex[] =;
static const char ufbxi_NormalsW[] =;
static const char ufbxi_Null[] =;
static const char ufbxi_NurbsCurve[] =;
static const char ufbxi_NurbsSurfaceOrder[] =;
static const char ufbxi_NurbsSurface[] =;
static const char ufbxi_Nurbs[] =;
static const char ufbxi_OO[] =;
static const char ufbxi_OP[] =;
static const char ufbxi_ObjectMetaData[] =;
static const char ufbxi_ObjectType[] =;
static const char ufbxi_Objects[] =;
static const char ufbxi_Order[] =;
static const char ufbxi_OriginalUnitScaleFactor[] =;
static const char ufbxi_OriginalUpAxis[] =;
static const char ufbxi_OriginalUpAxisSign[] =;
static const char ufbxi_OrthoZoom[] =;
static const char ufbxi_OuterAngle[] =;
static const char ufbxi_PO[] =;
static const char ufbxi_PP[] =;
static const char ufbxi_PointsIndex[] =;
static const char ufbxi_Points[] =;
static const char ufbxi_PolygonGroup[] =;
static const char ufbxi_PolygonIndexArray[] =;
static const char ufbxi_PolygonVertexIndex[] =;
static const char ufbxi_PoseNode[] =;
static const char ufbxi_Pose[] =;
static const char ufbxi_PostRotation[] =;
static const char ufbxi_PreRotation[] =;
static const char ufbxi_PreviewDivisionLevels[] =;
static const char ufbxi_Properties60[] =;
static const char ufbxi_Properties70[] =;
static const char ufbxi_PropertyTemplate[] =;
static const char ufbxi_R[] =;
static const char ufbxi_ReferenceStart[] =;
static const char ufbxi_ReferenceStop[] =;
static const char ufbxi_ReferenceTime[] =;
static const char ufbxi_RelativeFileName[] =;
static const char ufbxi_RelativeFilename[] =;
static const char ufbxi_RenderDivisionLevels[] =;
static const char ufbxi_RightCamera[] =;
static const char ufbxi_RootNode[] =;
static const char ufbxi_Root[] =;
static const char ufbxi_RotationAccumulationMode[] =;
static const char ufbxi_RotationOffset[] =;
static const char ufbxi_RotationOrder[] =;
static const char ufbxi_RotationPivot[] =;
static const char ufbxi_Rotation[] =;
static const char ufbxi_S[] =;
static const char ufbxi_ScaleAccumulationMode[] =;
static const char ufbxi_ScalingOffset[] =;
static const char ufbxi_ScalingPivot[] =;
static const char ufbxi_Scaling[] =;
static const char ufbxi_SceneInfo[] =;
static const char ufbxi_SelectionNode[] =;
static const char ufbxi_SelectionSet[] =;
static const char ufbxi_ShadingModel[] =;
static const char ufbxi_Shape[] =;
static const char ufbxi_Shininess[] =;
static const char ufbxi_Show[] =;
static const char ufbxi_Size[] =;
static const char ufbxi_Skin[] =;
static const char ufbxi_SkinningType[] =;
static const char ufbxi_Smoothing[] =;
static const char ufbxi_Smoothness[] =;
static const char ufbxi_SnapOnFrameMode[] =;
static const char ufbxi_SpecularColor[] =;
static const char ufbxi_Step[] =;
static const char ufbxi_SubDeformer[] =;
static const char ufbxi_T[] =;
static const char ufbxi_Take[] =;
static const char ufbxi_Takes[] =;
static const char ufbxi_Tangents[] =;
static const char ufbxi_TangentsIndex[] =;
static const char ufbxi_TangentsW[] =;
static const char ufbxi_Texture[] =;
static const char ufbxi_Texture_alpha[] =;
static const char ufbxi_TextureId[] =;
static const char ufbxi_TextureRotationPivot[] =;
static const char ufbxi_TextureScalingPivot[] =;
static const char ufbxi_TextureUV[] =;
static const char ufbxi_TextureUVVerticeIndex[] =;
static const char ufbxi_Thumbnail[] =;
static const char ufbxi_TimeMarker[] =;
static const char ufbxi_TimeMode[] =;
static const char ufbxi_TimeProtocol[] =;
static const char ufbxi_TimeSpanStart[] =;
static const char ufbxi_TimeSpanStop[] =;
static const char ufbxi_TransformLink[] =;
static const char ufbxi_Transform[] =;
static const char ufbxi_Translation[] =;
static const char ufbxi_TrimNurbsSurface[] =;
static const char ufbxi_Type[] =;
static const char ufbxi_TypedIndex[] =;
static const char ufbxi_UVIndex[] =;
static const char ufbxi_UVSet[] =;
static const char ufbxi_UVSwap[] =;
static const char ufbxi_UV[] =;
static const char ufbxi_UnitScaleFactor[] =;
static const char ufbxi_UpAxisSign[] =;
static const char ufbxi_UpAxis[] =;
static const char ufbxi_Version5[] =;
static const char ufbxi_VertexCacheDeformer[] =;
static const char ufbxi_VertexCrease[] =;
static const char ufbxi_VertexCreaseIndex[] =;
static const char ufbxi_VertexIndexArray[] =;
static const char ufbxi_Vertices[] =;
static const char ufbxi_Video[] =;
static const char ufbxi_Visibility[] =;
static const char ufbxi_Weight[] =;
static const char ufbxi_Weights[] =;
static const char ufbxi_WrapModeU[] =;
static const char ufbxi_WrapModeV[] =;
static const char ufbxi_X[] =;
static const char ufbxi_Y[] =;
static const char ufbxi_Z[] =;
static const char ufbxi_d_X[] =;
static const char ufbxi_d_Y[] =;
static const char ufbxi_d_Z[] =;

static const ufbx_string ufbxi_strings[] =;

static const ufbx_vec3 ufbxi_one_vec3 =;

#define UFBXI_PI
#define UFBXI_DPI
#define UFBXI_DEG_TO_RAD
#define UFBXI_RAD_TO_DEG
#define UFBXI_DEG_TO_RAD_DOUBLE
#define UFBXI_RAD_TO_DEG_DOUBLE
#define UFBXI_MM_TO_INCH

ufbx_inline ufbx_vec3 ufbxi_add3(ufbx_vec3 a, ufbx_vec3 b) {}

ufbx_inline ufbx_vec3 ufbxi_sub3(ufbx_vec3 a, ufbx_vec3 b) {}

ufbx_inline ufbx_vec3 ufbxi_mul3(ufbx_vec3 a, ufbx_real b) {}

ufbx_inline ufbx_vec3 ufbxi_lerp3(ufbx_vec3 a, ufbx_vec3 b, ufbx_real t) {}

ufbx_inline ufbx_real ufbxi_dot3(ufbx_vec3 a, ufbx_vec3 b) {}

ufbx_inline ufbx_real ufbxi_length3(ufbx_vec3 v)
{}

ufbx_inline ufbx_real ufbxi_min3(ufbx_vec3 v)
{}

ufbx_inline ufbx_vec3 ufbxi_cross3(ufbx_vec3 a, ufbx_vec3 b) {}

ufbx_inline ufbx_vec3 ufbxi_normalize3(ufbx_vec3 a) {}

ufbx_inline ufbx_real ufbxi_distsq2(ufbx_vec2 a, ufbx_vec2 b) {}

static ufbxi_noinline ufbx_vec3 ufbxi_slow_normalize3(const ufbx_vec3 *a) {}

static ufbxi_noinline ufbx_vec3 ufbxi_slow_normalized_cross3(const ufbx_vec3 *a, const ufbx_vec3 *b) {}

// -- Threading

ufbxi_task;
ufbxi_thread;
ufbxi_thread_pool;

ufbxi_task_fn;

struct ufbxi_task {};

ufbxi_task_imp;

ufbxi_task_group;

struct ufbxi_thread_pool {};

static void ufbxi_thread_pool_execute(ufbxi_thread_pool *pool, uint32_t index)
{}

ufbxi_noinline static void ufbxi_thread_pool_update_finished(ufbxi_thread_pool *pool, uint32_t max_index)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_thread_pool_wait_imp(ufbxi_thread_pool *pool, uint32_t group, bool can_fail)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_thread_pool_wait_group(ufbxi_thread_pool *pool)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_thread_pool_wait_all(ufbxi_thread_pool *pool)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_thread_pool_init(ufbxi_thread_pool *pool, ufbx_error *error, ufbxi_allocator *ator, const ufbx_thread_opts *opts)
{}

ufbxi_noinline static void ufbxi_thread_pool_free(ufbxi_thread_pool *pool)
{}

ufbxi_nodiscard ufbxi_noinline static uint32_t ufbxi_thread_pool_available_tasks(ufbxi_thread_pool *pool)
{}

ufbxi_noinline static void ufbxi_thread_pool_flush_group(ufbxi_thread_pool *pool)
{}

ufbxi_nodiscard ufbxi_noinline static ufbxi_task *ufbxi_thread_pool_create_task(ufbxi_thread_pool *pool, ufbxi_task_fn *fn)
{}

static void ufbxi_thread_pool_run_task(ufbxi_thread_pool *pool, ufbxi_task *task)
{}

// -- Type definitions

ufbxi_node;

ufbxi_value_type;

ufbxi_value;

ufbxi_value_array;

struct ufbxi_node {};

ufbxi_refcount;

struct ufbxi_refcount {};

static ufbxi_noinline void ufbxi_init_ref(ufbxi_refcount *refcount, uint32_t magic, ufbxi_refcount *parent);
static ufbxi_noinline void ufbxi_retain_ref(ufbxi_refcount *refcount);

#define ufbxi_get_imp(type, ptr)

ufbxi_scene_imp;

ufbx_static_assert();

ufbxi_mesh_imp;

ufbx_static_assert();

ufbxi_ascii_token;

ufbxi_ascii;

ufbxi_template;

ufbxi_fbx_id_entry;

ufbxi_fbx_attr_entry;

// Temporary connection before we resolve the element pointers
ufbxi_tmp_connection;

ufbxi_element_info;

ufbxi_tmp_bone_pose;

ufbxi_tmp_mesh_texture;

ufbxi_mesh_extra;

ufbxi_tmp_material_texture;

ufbxi_texture_extra;

ufbxi_obj_attrib;

#define UFBXI_OBJ_NUM_ATTRIBS
#define UFBXI_OBJ_NUM_ATTRIBS_EXT

ufbxi_obj_index_range;

ufbxi_obj_mesh;

ufbxi_obj_group_entry;

ufbxi_obj_fast_indices;

// Temporary pointer to a `ufbx_anim_stack` by name used to patch start/stop
// time from "Takes" if necessary.
ufbxi_tmp_anim_stack;

ufbxi_file_content;

ufbxi_obj_context;

ufbxi_context;

static ufbxi_noinline int ufbxi_fail_imp(ufbxi_context *uc, const char *cond, const char *func, uint32_t line)
{}

#define ufbxi_check(cond)
#define ufbxi_check_return(cond, ret)
#define ufbxi_fail(desc)
#define ufbxi_fail_return(desc, ret)

#define ufbxi_check_msg(cond, msg)
#define ufbxi_check_return_msg(cond, ret, msg)
#define ufbxi_fail_msg(desc, msg)

#define ufbxi_warnf(type, ...)
#define ufbxi_warnf_tag(type, element_id, ...)

// -- Progress

static ufbxi_forceinline uint64_t ufbxi_get_read_offset(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_report_progress(ufbxi_context *uc)
{}

// TODO: Remove `ufbxi_unused` when it's not needed anymore
ufbxi_unused ufbxi_nodiscard static ufbxi_forceinline int ufbxi_progress(ufbxi_context *uc, size_t work_units)
{}

// -- IO

static ufbxi_noinline const char *ufbxi_refill(ufbxi_context *uc, size_t size, bool require_size)
{}

static ufbxi_forceinline void ufbxi_pause_progress(ufbxi_context *uc)
{}

static ufbxi_noinline int ufbxi_resume_progress(ufbxi_context *uc)
{}

static ufbxi_noinline const char *ufbxi_yield(ufbxi_context *uc, size_t size)
{}

static ufbxi_forceinline const char *ufbxi_peek_bytes(ufbxi_context *uc, size_t size)
{}

static ufbxi_forceinline const char *ufbxi_read_bytes(ufbxi_context *uc, size_t size)
{}

static ufbxi_forceinline void ufbxi_consume_bytes(ufbxi_context *uc, size_t size)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_skip_bytes(ufbxi_context *uc, uint64_t size)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_to(ufbxi_context *uc, void *dst, size_t size)
{}

// -- File IO

static ufbxi_noinline void ufbxi_init_ator(ufbx_error *error, ufbxi_allocator *ator, const ufbx_allocator_opts *opts, const char *name)
{}

static ufbxi_noinline FILE *ufbxi_fopen(const char *path, size_t path_len, ufbxi_allocator *tmp_ator)
{}

static uint64_t ufbxi_ftell(FILE *file)
{}

static size_t ufbxi_file_read(void *user, void *data, size_t max_size)
{}

static bool ufbxi_file_skip(void *user, size_t size)
{}

static void ufbxi_file_close(void *user)
{}

ufbxi_memory_stream;

static size_t ufbxi_memory_read(void *user, void *data, size_t max_size)
{}

static bool ufbxi_memory_skip(void *user, size_t size)
{}

static void ufbxi_memory_close(void *user)
{}

// -- XML

#if UFBXI_FEATURE_XML

typedef struct ufbxi_xml_tag ufbxi_xml_tag;
typedef struct ufbxi_xml_attrib ufbxi_xml_attrib;
typedef struct ufbxi_xml_document ufbxi_xml_document;

struct ufbxi_xml_attrib {
	ufbx_string name;
	ufbx_string value;
};

struct ufbxi_xml_tag {
	ufbx_string name;
	ufbx_string text;

	ufbxi_xml_attrib *attribs;
	size_t num_attribs;

	ufbxi_xml_tag *children;
	size_t num_children;
};

struct ufbxi_xml_document {
	ufbxi_xml_tag *root;
	ufbxi_buf buf;
};

typedef struct {
	ufbx_error error;

	ufbxi_allocator *ator;

	ufbxi_buf tmp_stack;
	ufbxi_buf result;

	ufbxi_xml_document *doc;

	ufbx_read_fn *read_fn;
	void *read_user;

	char *tok;
	size_t tok_cap;
	size_t tok_len;

	const char *pos, *pos_end;
	char data[4096];

	bool io_error;
} ufbxi_xml_context;

enum {
	UFBXI_XML_CTYPE_WHITESPACE = 0x1,
	UFBXI_XML_CTYPE_SINGLE_QUOTE = 0x2,
	UFBXI_XML_CTYPE_DOUBLE_QUOTE = 0x4,
	UFBXI_XML_CTYPE_NAME_END = 0x8,
	UFBXI_XML_CTYPE_TAG_START = 0x10,
	UFBXI_XML_CTYPE_END_OF_FILE = 0x20,
};

// Generated by `misc/gen_xml_ctype.py`
static const uint8_t ufbxi_xml_ctype[256] = {
	32,0,0,0,0,0,0,0,0,9,9,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	9,0,12,0,0,0,0,10,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,16,8,8,8,
};

static ufbxi_noinline void ufbxi_xml_refill(ufbxi_xml_context *xc)
{
	size_t num = xc->read_fn(xc->read_user, xc->data, sizeof(xc->data));
	if (num == SIZE_MAX || num < sizeof(xc->data)) xc->io_error = true;
	if (num < sizeof(xc->data)) {
		xc->data[num++] = '\0';
	}
	xc->pos = xc->data;
	xc->pos_end = xc->data + num;
}

static ufbxi_forceinline void ufbxi_xml_advance(ufbxi_xml_context *xc)
{
	if (++xc->pos == xc->pos_end) ufbxi_xml_refill(xc);
}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_xml_push_token_char(ufbxi_xml_context *xc, char c)
{
	if (xc->tok_len == xc->tok_cap || UFBXI_IS_REGRESSION) {
		ufbxi_check_err(&xc->error, ufbxi_grow_array(xc->ator, &xc->tok, &xc->tok_cap, xc->tok_len + 1));
	}
	xc->tok[xc->tok_len++] = c;
	return 1;
}

static ufbxi_noinline int ufbxi_xml_accept(ufbxi_xml_context *xc, char ch)
{
	if (*xc->pos == ch) {
		ufbxi_xml_advance(xc);
		return 1;
	} else {
		return 0;
	}
}

static ufbxi_noinline void ufbxi_xml_skip_while(ufbxi_xml_context *xc, uint32_t ctypes)
{
	while (ufbxi_xml_ctype[(uint8_t)*xc->pos] & ctypes) {
		ufbxi_xml_advance(xc);
	}
}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_xml_skip_until_string(ufbxi_xml_context *xc, ufbx_string *dst, const char *suffix)
{
	xc->tok_len = 0;
	size_t match_len = 0, ix = 0, suffix_len = strlen(suffix);
	char buf[16] = { 0 };
	size_t wrap_mask = sizeof(buf) - 1;
	ufbx_assert(suffix_len < sizeof(buf));
	for (;;) {
		char c = *xc->pos;
		ufbxi_check_err_msg(&xc->error, c != 0, "Truncated file");
		ufbxi_xml_advance(xc);
		if (ix >= suffix_len) {
			ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, buf[(ix - suffix_len) & wrap_mask]));
		}

		buf[ix++ & wrap_mask] = c;
		for (match_len = 0; match_len < suffix_len; match_len++) {
			if (buf[(ix - suffix_len + match_len) & wrap_mask] != suffix[match_len]) {
				break;
			}
		}
		if (match_len == suffix_len) break;
	}

	ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));
	if (dst) {
		dst->length = xc->tok_len - 1;
		dst->data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
		ufbxi_check_err(&xc->error, dst->data);
	}

	return 1;
}

static ufbxi_noinline int ufbxi_xml_read_until(ufbxi_xml_context *xc, ufbx_string *dst, uint32_t ctypes)
{
	xc->tok_len = 0;
	for (;;) {
		char c = *xc->pos;

		if (c == '&') {
			size_t entity_begin = xc->tok_len;
			for (;;) {
				ufbxi_xml_advance(xc);
				c = *xc->pos;
				ufbxi_check_err(&xc->error, c != '\0');
				if (c == ';') break;
				ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, c));
			}
			ufbxi_xml_advance(xc);
			ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));

			char *entity = xc->tok + entity_begin;
			xc->tok_len = entity_begin;

			if (entity[0] == '#') {
				unsigned long code = 0;
				if (entity[1] == 'x') {
					code = strtoul(entity + 2, NULL, 16);
				} else {
					code = strtoul(entity + 1, NULL, 10);
				}

				char bytes[5] = { 0 };
				if (code < 0x80) {
					bytes[0] = (char)code;
				} else if (code < 0x800) {
					bytes[0] = (char)(0xc0 | (code>>6));
					bytes[1] = (char)(0x80 | (code & 0x3f));
				} else if (code < 0x10000) {
					bytes[0] = (char)(0xe0 | (code>>12));
					bytes[1] = (char)(0x80 | ((code>>6) & 0x3f));
					bytes[2] = (char)(0x80 | (code & 0x3f));
				} else {
					bytes[0] = (char)(0xf0 | (code>>18));
					bytes[1] = (char)(0x80 | ((code>>12) & 0x3f));
					bytes[2] = (char)(0x80 | ((code>>6) & 0x3f));
					bytes[3] = (char)(0x80 | (code & 0x3f));
				}
				for (char *b = bytes; *b; b++) {
					ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, *b));
				}
			} else {
				char ch = '\0';
				if (!strcmp(entity, "lt")) ch = '<';
				else if (!strcmp(entity, "quot")) ch = '"';
				else if (!strcmp(entity, "amp")) ch = '&';
				else if (!strcmp(entity, "apos")) ch = '\'';
				else if (!strcmp(entity, "gt")) ch = '>';
				if (ch) {
					ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, ch));
				}
			}
		} else {
			if ((ufbxi_xml_ctype[(uint8_t)c] & ctypes) != 0) break;
			ufbxi_check_err_msg(&xc->error, c != 0, "Truncated file");
			ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, c));
			ufbxi_xml_advance(xc);
		}
	}

	ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));
	if (dst) {
		dst->length = xc->tok_len - 1;
		dst->data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
		ufbxi_check_err(&xc->error, dst->data);
	}

	return 1;
}

// Recursion limited by check at the start
static ufbxi_noinline int ufbxi_xml_parse_tag(ufbxi_xml_context *xc, size_t depth, bool *p_closing, const char *opening)
	ufbxi_recursive_function(int, ufbxi_xml_parse_tag, (xc, depth, p_closing, opening), UFBXI_MAX_XML_DEPTH + 1,
		(ufbxi_xml_context *xc, size_t depth, bool *p_closing, const char *opening))
{
	ufbxi_check_err(&xc->error, depth < UFBXI_MAX_XML_DEPTH);

	if (!ufbxi_xml_accept(xc, '<')) {
		if (*xc->pos == '\0') {
			*p_closing = true;
		} else {
			ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, NULL, UFBXI_XML_CTYPE_TAG_START | UFBXI_XML_CTYPE_END_OF_FILE));
			bool has_text = false;
			for (size_t i = 0; i < xc->tok_len; i++) {
				if ((ufbxi_xml_ctype[(uint8_t)xc->tok[i]] & UFBXI_XML_CTYPE_WHITESPACE) == 0) {
					has_text = true;
					break;
				}
			}

			if (has_text) {
				ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
				ufbxi_check_err(&xc->error, tag);
				tag->name.data = ufbxi_empty_char;

				tag->text.length = xc->tok_len - 1;
				tag->text.data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
				ufbxi_check_err(&xc->error, tag->text.data);
			}
		}
		return 1;
	}

	if (ufbxi_xml_accept(xc, '/')) {
		ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, NULL, UFBXI_XML_CTYPE_NAME_END));
		ufbxi_check_err(&xc->error, opening && !strcmp(xc->tok, opening));
		ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
		if (!ufbxi_xml_accept(xc, '>')) return 0;
		*p_closing = true;
		return 1;
	} else if (ufbxi_xml_accept(xc, '!')) {
		if (ufbxi_xml_accept(xc, '[')) {
			for (const char *ch = "CDATA["; *ch; ch++) {
				if (!ufbxi_xml_accept(xc, *ch)) return 0;
			}

			ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
			ufbxi_check_err(&xc->error, tag);
			ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, &tag->text, "]]>"));
			tag->name.data = ufbxi_empty_char;

		} else if (ufbxi_xml_accept(xc, '-')) {
			if (!ufbxi_xml_accept(xc, '-')) return 0;
			ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, "-->"));
		} else {
			// TODO: !DOCTYPE
			ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, ">"));
		}
		return 1;
	} else if (ufbxi_xml_accept(xc, '?')) {
		ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, "?>"));
		return 1;
	}

	ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
	ufbxi_check_err(&xc->error, tag);
	ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &tag->name, UFBXI_XML_CTYPE_NAME_END));
	tag->text.data = ufbxi_empty_char;

	bool has_children = false;

	size_t num_attribs = 0;
	for (;;) {
		ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
		if (ufbxi_xml_accept(xc, '/')) {
			if (!ufbxi_xml_accept(xc, '>')) return 0;
			break;
		} else if (ufbxi_xml_accept(xc, '>')) {
			has_children = true;
			break;
		} else {
			ufbxi_xml_attrib *attrib = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_attrib, 1);
			ufbxi_check_err(&xc->error, attrib);
			ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &attrib->name, UFBXI_XML_CTYPE_NAME_END));
			ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
			if (!ufbxi_xml_accept(xc, '=')) return 0;
			ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
			uint32_t quote_ctype = 0;
			if (ufbxi_xml_accept(xc, '"')) {
				quote_ctype = UFBXI_XML_CTYPE_DOUBLE_QUOTE;
			} else if (ufbxi_xml_accept(xc, '\'')) {
				quote_ctype = UFBXI_XML_CTYPE_SINGLE_QUOTE;
			} else {
				ufbxi_fail_err(&xc->error, "Bad attrib value");
			}
			ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &attrib->value, quote_ctype));
			ufbxi_xml_advance(xc);
			num_attribs++;
		}
	}

	tag->num_attribs = num_attribs;
	tag->attribs = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_attrib, num_attribs);
	ufbxi_check_err(&xc->error, tag->attribs);

	if (has_children) {
		size_t children_begin = xc->tmp_stack.num_items;
		for (;;) {
			bool closing = false;
			ufbxi_check_err(&xc->error, ufbxi_xml_parse_tag(xc, depth + 1, &closing, tag->name.data));
			if (closing) break;
		}

		tag->num_children = xc->tmp_stack.num_items - children_begin;
		tag->children = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_tag, tag->num_children);
		ufbxi_check_err(&xc->error, tag->children);
	}

	return 1;
}

static ufbxi_noinline int ufbxi_xml_parse_root(ufbxi_xml_context *xc)
{
	ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->result, ufbxi_xml_tag, 1);
	ufbxi_check_err(&xc->error, tag);
	tag->name.data = ufbxi_empty_char;
	tag->text.data = ufbxi_empty_char;

	for (;;) {
		bool closing = false;
		ufbxi_check_err(&xc->error, ufbxi_xml_parse_tag(xc, 0, &closing, NULL));
		if (closing) break;
	}

	tag->num_children = xc->tmp_stack.num_items;
	tag->children = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_tag, tag->num_children);
	ufbxi_check_err(&xc->error, tag->children);

	xc->doc = ufbxi_push(&xc->result, ufbxi_xml_document, 1);
	ufbxi_check_err(&xc->error, xc->doc);

	xc->doc->root = tag;
	xc->doc->buf = xc->result;

	return 1;
}

typedef struct {
	ufbxi_allocator *ator;
	ufbx_read_fn *read_fn;
	void *read_user;
	const char *prefix;
	size_t prefix_length;
} ufbxi_xml_load_opts;

static ufbxi_noinline ufbxi_xml_document *ufbxi_load_xml(ufbxi_xml_load_opts *opts, ufbx_error *error)
{
	ufbxi_xml_context xc = { UFBX_ERROR_NONE };
	xc.ator = opts->ator;
	xc.read_fn = opts->read_fn;
	xc.read_user = opts->read_user;

	xc.tmp_stack.ator = xc.ator;
	xc.result.ator = xc.ator;

	xc.result.unordered = true;

	if (opts->prefix_length > 0) {
		xc.pos = opts->prefix;
		xc.pos_end = opts->prefix + opts->prefix_length;
	} else {
		ufbxi_xml_refill(&xc);
	}

	int ok = ufbxi_xml_parse_root(&xc);

	ufbxi_buf_free(&xc.tmp_stack);
	ufbxi_free(xc.ator, char, xc.tok, xc.tok_cap);

	if (ok) {
		return xc.doc;
	} else {
		ufbxi_buf_free(&xc.result);
		if (error) {
			*error = xc.error;
		}

		return NULL;
	}
}

static ufbxi_noinline void ufbxi_free_xml(ufbxi_xml_document *doc)
{
	ufbxi_buf buf = doc->buf;
	ufbxi_buf_free(&buf);
}

static ufbxi_noinline ufbxi_xml_tag *ufbxi_xml_find_child(ufbxi_xml_tag *tag, const char *name)
{
	ufbxi_for(ufbxi_xml_tag, child, tag->children, tag->num_children) {
		if (!strcmp(child->name.data, name)) {
			return child;
		}
	}
	return NULL;
}

static ufbxi_noinline ufbxi_xml_attrib *ufbxi_xml_find_attrib(ufbxi_xml_tag *tag, const char *name)
{
	ufbxi_for(ufbxi_xml_attrib, attrib, tag->attribs, tag->num_attribs) {
		if (!strcmp(attrib->name.data, name)) {
			return attrib;
		}
	}
	return NULL;
}

#endif

// -- FBX value type information

static char ufbxi_normalize_array_type(char type, char bool_type) {}

static ufbxi_noinline size_t ufbxi_array_type_size(char type)
{}

// -- Node operations

static ufbxi_noinline ufbxi_node *ufbxi_find_child(ufbxi_node *node, const char *name)
{}

// Retrieve values from nodes with type codes:
// Any: '_' (ignore)
// NUMBER: 'I' int32_t 'L' int64_t 'F' float 'D' double 'R' ufbxi_real 'B' bool 'Z' size_t
// STRING: 'S' ufbx_string 'C' const char* (checked) 's' ufbx_string 'c' const char * (unchecked) 'b' ufbx_blob

ufbxi_nodiscard ufbxi_forceinline static int ufbxi_get_val_at(ufbxi_node *node, size_t ix, char fmt, void *v)
{}

ufbxi_nodiscard ufbxi_noinline static ufbxi_value_array *ufbxi_get_array(ufbxi_node *node, char fmt)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val1(ufbxi_node *node, const char *fmt, void *v0)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val2(ufbxi_node *node, const char *fmt, void *v0, void *v1)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val3(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val4(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2, void *v3)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val5(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2, void *v3, void *v4)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_find_val1(ufbxi_node *node, const char *name, const char *fmt, void *v0)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_find_val2(ufbxi_node *node, const char *name, const char *fmt, void *v0, void *v1)
{}

ufbxi_nodiscard static ufbxi_noinline ufbxi_value_array *ufbxi_find_array(ufbxi_node *node, const char *name, char fmt)
{}

static ufbxi_node *ufbxi_find_child_strcmp(ufbxi_node *node, const char *name)
{}

// -- Element extra data allocation

ufbxi_nodiscard static ufbxi_noinline void *ufbxi_push_element_extra_size(ufbxi_context *uc, uint32_t id, size_t size)
{}

static ufbxi_noinline void *ufbxi_get_element_extra(ufbxi_context *uc, uint32_t id)
{}

#define ufbxi_push_element_extra(uc, id, type)

// -- Parsing state machine
//
// When reading the file we maintain a coarse representation of the structure so
// that we can resolve array info (type, included in result, etc). Using this info
// we can often read/decompress the contents directly into the right memory area.

ufbxi_parse_state;

ufbxi_array_flags;

ufbxi_array_info;

static ufbxi_noinline ufbxi_parse_state ufbxi_update_parse_state(ufbxi_parse_state parent, const char *name)
{}

static bool ufbxi_is_array_node(ufbxi_context *uc, ufbxi_parse_state parent, const char *name, ufbxi_array_info *info)
{}

static ufbxi_noinline bool ufbxi_is_raw_string(ufbxi_context *uc, ufbxi_parse_state parent, const char *name, size_t index)
{}

// -- Binary parsing

ufbxi_nodiscard static ufbxi_noinline char *ufbxi_swap_endian(ufbxi_context *uc, const void *src, size_t count, size_t elem_size)
{}

// Swap the endianness of an array typed with a lowercase letter
ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_swap_endian_array(ufbxi_context *uc, const void *src, size_t count, char type)
{}

// Swap the endianness of a single value (shallow, swaps string/array header words)
ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_swap_endian_value(ufbxi_context *uc, const void *src, char type)
{}

// Read and convert a post-7000 FBX data array into a different format. `src_type` may be equal to `dst_type`
// if the platform is not binary compatible with the FBX data representation.
ufbxi_nodiscard static ufbxi_noinline int ufbxi_binary_convert_array(ufbxi_context *maybe_uc, char src_type, char dst_type, const void *src, void *dst, size_t size)
{}

// Read pre-7000 separate properties as an array.
ufbxi_nodiscard static ufbxi_noinline int ufbxi_binary_parse_multivalue_array(ufbxi_context *uc, char dst_type, void *dst, size_t size, ufbxi_buf *tmp_buf)
{}

ufbxi_nodiscard ufbxi_noinline static void *ufbxi_push_array_data(ufbxi_context *uc, const ufbxi_array_info *info, size_t size, ufbxi_buf *tmp_buf)
{}

ufbxi_noinline static void ufbxi_postprocess_bool_array(char *data, size_t size)
{}

ufbxi_deflate_task;

static bool ufbxi_deflate_task_fn(ufbxi_task *task)
{}

// Recursion limited by check at the start
ufbxi_nodiscard ufbxi_noinline static int ufbxi_binary_parse_node(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive)
	ufbxi_recursive_function(int, ufbxi_binary_parse_node, (uc, depth, parent_state, p_end, tmp_buf, recursive), UFBXI_MAX_NODE_DEPTH + 1,
		(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive))
{}

#define UFBXI_BINARY_MAGIC_SIZE
#define UFBXI_BINARY_HEADER_SIZE
static const char ufbxi_binary_magic[] =;

// -- ASCII parsing

#define UFBXI_ASCII_END
#define UFBXI_ASCII_NAME
#define UFBXI_ASCII_BARE_WORD
#define UFBXI_ASCII_INT
#define UFBXI_ASCII_FLOAT
#define UFBXI_ASCII_STRING

static ufbxi_noinline char ufbxi_ascii_refill(ufbxi_context *uc)
{}

static ufbxi_noinline char ufbxi_ascii_yield(ufbxi_context *uc)
{}

static ufbxi_forceinline char ufbxi_ascii_peek(ufbxi_context *uc)
{}

static ufbxi_forceinline char ufbxi_ascii_next(ufbxi_context *uc)
{}

static ufbxi_noinline uint32_t ufbxi_ascii_parse_version(ufbxi_context *uc)
{}

static const uint32_t ufbxi_space_mask = ;

ufbx_static_assert();

static ufbxi_forceinline bool ufbxi_is_space(char c)
{}

static ufbxi_noinline char ufbxi_ascii_skip_whitespace(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_ascii_push_token_char(ufbxi_context *uc, ufbxi_ascii_token *token, char c)
{}

ufbxi_nodiscard static ufbxi_forceinline int ufbxi_ascii_push_token_string(ufbxi_context *uc, ufbxi_ascii_token *token, const char *data, size_t length)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_skip_until(ufbxi_context *uc, char dst)
{}

ufbxi_ascii_span;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_store_array(ufbxi_context *uc, ufbxi_buf *tmp_buf)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_try_ignore_string(ufbxi_context *uc, ufbxi_ascii_token *token)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_next_token(ufbxi_context *uc, ufbxi_ascii_token *token)
{}

ufbxi_nodiscard static int ufbxi_ascii_accept(ufbxi_context *uc, char type)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_ascii_read_int_array(ufbxi_context *uc, char type, size_t *p_num_read)
{}

ufbxi_ascii_array_task;

ufbxi_noinline static const char *ufbxi_ascii_array_task_parse_floats(ufbxi_ascii_array_task *t, const char *src, const char *src_end, uint32_t parse_flags)
{}

ufbxi_noinline static const char *ufbxi_ascii_array_task_parse_ints(ufbxi_ascii_array_task *t, const char *src, const char *src_end)
{}

ufbxi_noinline static const char *ufbxi_ascii_array_task_parse(ufbxi_ascii_array_task *t, const char *src, const char *src_end)
{}

ufbxi_ascii_scan_state;

ufbxi_noinline static bool ufbxi_ascii_array_task_imp(ufbxi_ascii_array_task *t)
{}

ufbxi_noinline static bool ufbxi_ascii_array_task_fn(ufbxi_task *task)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_ascii_read_float_array(ufbxi_context *uc, char type, size_t *p_num_read)
{}

// Recursion limited by check at the start
ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_parse_node(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive)
	ufbxi_recursive_function(int, ufbxi_ascii_parse_node, (uc, depth, parent_state, p_end, tmp_buf, recursive), UFBXI_MAX_NODE_DEPTH + 1,
		(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive))
{}

// -- DOM retention

ufbxi_dom_mapping;

ufbxi_nodiscard static ufbxi_noinline ufbx_dom_node *ufbxi_get_dom_node_imp(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard static ufbxi_forceinline ufbx_dom_node *ufbxi_get_dom_node(ufbxi_context *uc, ufbxi_node *node)
{}

// Recursion limited by check in ufbxi_[binary/ascii]_parse_node()
ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_dom_node(ufbxi_context *uc, ufbxi_node *node, ufbx_dom_node **p_dom_node)
	ufbxi_recursive_function(int, ufbxi_retain_dom_node, (uc, node, p_dom_node), UFBXI_MAX_NODE_DEPTH + 1,
		(ufbxi_context *uc, ufbxi_node *node, ufbx_dom_node **p_dom_node))
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_toplevel(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_toplevel_child(ufbxi_context *uc, ufbxi_node *child)
{}

// -- General parsing

static ufbxi_noinline bool ufbxi_next_line(ufbx_string *line, ufbx_string *buf, bool skip_space)
{}

// Recursion limited by compile time patterns
static ufbxi_noinline const char *ufbxi_match_skip(const char *fmt, bool alternation)
	ufbxi_recursive_function(const char *, ufbxi_match_skip, (fmt, alternation), 4,
		(const char *fmt, bool alternation))
{}

// Recursion limited by compile time patterns
static ufbxi_noinline bool ufbxi_match_imp(const char **p_str, const char *end, const char **p_fmt)
	ufbxi_recursive_function(bool, ufbxi_match_imp, (p_str, end, p_fmt), 4,
		(const char **p_str, const char *end, const char **p_fmt))
{}

static ufbxi_noinline bool ufbxi_match(const ufbx_string *str, const char *fmt)
{}

static ufbxi_noinline bool ufbxi_is_format(const char *data, size_t size, ufbx_file_format format)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_determine_format(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_begin_parse(ufbxi_context *uc)
{}

ufbxi_nodiscard static int ufbxi_parse_toplevel_child_imp(ufbxi_context *uc, ufbxi_parse_state state, ufbxi_buf *buf, bool *p_end)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_toplevel(ufbxi_context *uc, const char *name)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_toplevel_child(ufbxi_context *uc, ufbxi_node **p_node, ufbxi_buf *tmp_buf)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_legacy_toplevel(ufbxi_context *uc)
{}

// -- Setup

ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_strings(ufbxi_context *uc)
{}

ufbxi_prop_type_name;

static const ufbxi_prop_type_name ufbxi_prop_type_names[] =;

static ufbx_prop_type ufbxi_get_prop_type(ufbxi_context *uc, const char *name)
{}

static ufbxi_noinline ufbx_prop *ufbxi_find_prop_with_key(const ufbx_props *props, const char *name, uint32_t key)
{}

ufbxi_texture_file_entry;

#define ufbxi_find_prop(props, name)

static ufbxi_forceinline ufbx_real ufbxi_find_real(const ufbx_props *props, const char *name, ufbx_real def)
{}

static ufbxi_forceinline ufbx_vec3 ufbxi_find_vec3(const ufbx_props *props, const char *name, ufbx_real def_x, ufbx_real def_y, ufbx_real def_z)
{}

static ufbxi_forceinline int64_t ufbxi_find_int(const ufbx_props *props, const char *name, int64_t def)
{}

static ufbxi_forceinline int64_t ufbxi_find_enum(const ufbx_props *props, const char *name, int64_t def, int64_t max_value)
{}

ufbxi_noinline static bool ufbxi_matrix_all_zero(const ufbx_matrix *matrix)
{}

static ufbxi_forceinline bool ufbxi_is_vec3_zero(ufbx_vec3 v)
{}

static ufbxi_forceinline bool ufbxi_is_vec4_zero(ufbx_vec4 v)
{}

static ufbxi_forceinline bool ufbxi_is_vec3_one(ufbx_vec3 v)
{}

static ufbxi_forceinline bool ufbxi_is_quat_identity(ufbx_quat v)
{}

static ufbxi_noinline bool ufbxi_is_transform_identity(const ufbx_transform *t)
{}

static ufbxi_forceinline uint32_t ufbxi_get_name_key(const char *name, size_t len)
{}

static ufbxi_forceinline uint32_t ufbxi_get_name_key_c(const char *name)
{}

static ufbxi_forceinline bool ufbxi_name_key_less(ufbx_prop *prop, const char *data, size_t name_len, uint32_t key)
{}

static const char *const ufbxi_node_prop_names[] =;

ufbxi_nodiscard static ufbxi_noinline int ufbxi_init_node_prop_names(ufbxi_context *uc)
{}

static bool ufbxi_is_node_property(ufbxi_context *uc, const char *name)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_maps(ufbxi_context *uc)
{}

// -- Reading the parsed data

ufbxi_noinline static void ufbxi_decode_base64(char *dst, const char *src, size_t src_length)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_embedded_blob(ufbxi_context *uc, ufbx_blob *dst_blob, ufbxi_node *node)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_property(ufbxi_context *uc, ufbxi_node *node, ufbx_prop *prop, int version)
{}

static ufbxi_forceinline bool ufbxi_prop_less(ufbx_prop *a, ufbx_prop *b)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_properties(ufbxi_context *uc, ufbx_prop *props, size_t count)
{}

ufbxi_noinline static void ufbxi_deduplicate_properties(ufbx_prop_list *list)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_properties(ufbxi_context *uc, ufbxi_node *parent, ufbx_props *props)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_thumbnail(ufbxi_context *uc, ufbxi_node *node, ufbx_thumbnail *thumbnail)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_scene_info(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_header_extension(ufbxi_context *uc)
{}

static bool ufbxi_match_version_string(const char *fmt, ufbx_string str, uint32_t *p_version)
{}

ufbxi_nodiscard static int ufbxi_match_exporter(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_document(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_definitions(ufbxi_context *uc)
{}

ufbxi_nodiscard static ufbx_props *ufbxi_find_template(ufbxi_context *uc, const char *name, const char *sub_type)
{}

// Name ID categories
#define UFBXI_SYNTHETIC_ID_BIT

ufbx_static_assert();

static ufbxi_forceinline uint64_t ufbxi_synthetic_id_from_pointer(const void *ptr)
{}

static ufbxi_forceinline uint64_t ufbxi_synthetic_id_from_string(const char *str)
{}

static ufbxi_noinline int ufbxi_push_synthetic_id(ufbxi_context *uc, uint64_t *p_dst)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_split_type_and_name(ufbxi_context *uc, ufbx_string type_and_name, ufbx_string *type, ufbx_string *name)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_insert_fbx_id(ufbxi_context *uc, uint64_t fbx_id, uint32_t element_id)
{}

static ufbxi_noinline ufbxi_fbx_id_entry *ufbxi_find_fbx_id(ufbxi_context *uc, uint64_t fbx_id)
{}

static ufbxi_forceinline bool ufbxi_fbx_id_exists(ufbxi_context *uc, uint64_t fbx_id)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_insert_fbx_attr(ufbxi_context *uc, uint64_t fbx_id, uint64_t attrib_fbx_id)
{}

ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_push_element_size(ufbxi_context *uc, ufbxi_element_info *info, size_t size, ufbx_element_type type)
{}

ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_push_synthetic_element_size(ufbxi_context *uc, uint64_t *p_fbx_id, ufbxi_node *node, const char *name, size_t size, ufbx_element_type type)
{}

#define ufbxi_push_element(uc, info, type_name, type_enum)
#define ufbxi_push_synthetic_element(uc, p_fbx_id, node, name, type_name, type_enum)

ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_oo(ufbxi_context *uc, uint64_t src, uint64_t dst)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_op(ufbxi_context *uc, uint64_t src, uint64_t dst, ufbx_string prop)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_pp(ufbxi_context *uc, uint64_t src, uint64_t dst, ufbx_string src_prop, ufbx_string dst_prop)
{}

ufbxi_noinline static void ufbxi_init_synthetic_int_prop(ufbx_prop *dst, const char *name, int64_t value, ufbx_prop_type type)
{}

ufbxi_noinline static void ufbxi_init_synthetic_real_prop(ufbx_prop *dst, const char *name, ufbx_real value, ufbx_prop_type type)
{}

ufbxi_noinline static void ufbxi_init_synthetic_vec3_prop(ufbx_prop *dst, const char *name, const ufbx_vec3 *value, ufbx_prop_type type)
{}

ufbxi_noinline static void ufbxi_set_own_prop_vec3_uniform(ufbx_props *props, const char *name, ufbx_real value)
{}

ufbxi_node_extra;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_setup_geometry_transform_helper(ufbxi_context *uc, ufbx_node *node, uint64_t node_fbx_id)
{}

ufbxi_scale_helper_prop;

static const ufbxi_scale_helper_prop ufbxi_scale_helper_props[] =;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_setup_scale_helper(ufbxi_context *uc, ufbx_node *node, uint64_t node_fbx_id)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_model(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_element(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, size_t size, ufbx_element_type type)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_unknown(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *element, ufbx_string type, ufbx_string sub_type, const char *node_name)
{}

ufbxi_tangent_layer;

static ufbx_real ufbxi_zero_element[8] =;

// Sentinel pointers used for zero/sequential index buffers
static const uint32_t ufbxi_sentinel_index_zero[1] =;
static const uint32_t ufbxi_sentinel_index_consecutive[1] =;

ufbxi_noinline static int ufbxi_fix_index(ufbxi_context *uc, uint32_t *p_dst, uint32_t index, size_t one_past_max_val)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_check_indices(ufbxi_context *uc, uint32_t **p_dst, uint32_t *indices, bool owns_indices, size_t num_indices, size_t num_indexers, size_t num_elems)
{}

ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();
ufbx_static_assert();

ufbxi_nodiscard ufbxi_noinline static int ufbxi_warn_polygon_mapping(ufbxi_context *uc, const char *data_name, const char *mapping)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_vertex_element(ufbxi_context *uc, ufbx_mesh *mesh, ufbxi_node *node,
	ufbx_vertex_attrib *attrib, const char *data_name, const char *index_name, const char *w_name, char data_type, size_t num_components)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_truncated_array(ufbxi_context *uc, void *p_data, size_t *p_count, ufbxi_node *node, const char *name, char fmt, size_t size)
{}

ufbxi_noinline static bool ufbxi_uv_set_less(void *user, const void *va, const void *vb)
{}

ufbxi_noinline static bool ufbxi_color_set_less(void *user, const void *va, const void *vb)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_uv_sets(ufbxi_context *uc, ufbx_uv_set *sets, size_t count)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_color_sets(ufbxi_context *uc, ufbx_color_set *sets, size_t count)
{}

ufbxi_blend_offset;

static ufbxi_noinline bool ufbxi_blend_offset_less(void *user, const void *va, const void *vb)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_blend_offsets(ufbxi_context *uc, ufbxi_blend_offset *offsets, size_t count)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_shape(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_synthetic_blend_shapes(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_process_indices(ufbxi_context *uc, ufbx_mesh *mesh, uint32_t *index_data)
{}

ufbxi_noinline static void ufbxi_patch_mesh_reals(ufbx_mesh *mesh)
{}

ufbxi_id_group;

static bool ufbxi_less_int32(void *user, const void *va, const void *vb)
{}

ufbx_static_assert();
ufbx_static_assert();
static ufbxi_forceinline void ufbxi_mesh_part_add_face(ufbx_mesh_part *part, uint32_t num_indices)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_assign_face_groups(ufbxi_buf *buf, ufbx_error *error, ufbx_mesh *mesh, size_t *p_consecutive_indices, bool retain_parts)
{}

ufbxi_nodiscard static ufbxi_noinline int ufbxi_update_face_groups(ufbxi_buf *buf, ufbx_error *error, ufbx_mesh *mesh, bool need_copy)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_mesh(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_noinline static ufbx_nurbs_topology ufbxi_read_nurbs_topology(const char *form)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_nurbs_curve(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_nurbs_surface(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_line(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_noinline static void ufbxi_read_transform_matrix(ufbx_matrix *m, ufbx_real *data)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_bone(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_marker(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type, ufbx_marker_type type)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_skin(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_skin_cluster(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_blend_channel(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_key_flags;

static ufbxi_noinline float ufbxi_solve_auto_tangent(ufbxi_context *uc, double prev_time, double time, double next_time, ufbx_real prev_value, ufbx_real value, ufbx_real next_value, float weight_left, float weight_right, float auto_bias, uint32_t flags)
{}

static float ufbxi_solve_auto_tangent_left(ufbxi_context *uc, double prev_time, double time, ufbx_real prev_value, ufbx_real value, float weight_left, float auto_bias, uint32_t flags)
{}

static float ufbxi_solve_auto_tangent_right(ufbxi_context *uc, double time, double next_time, ufbx_real value, ufbx_real next_value, float weight_right, float auto_bias, uint32_t flags)
{}

static void ufbxi_solve_tcb(float *p_slope_left, float *p_slope_right, double tension, double continuity, double bias, double slope_left, double slope_right, bool edge)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_animation_curve(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_material(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_texture(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_layered_texture(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_video(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_anim_stack(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_pose(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_shader_prop_bindings(ufbxi_context *uc, ufbx_shader_prop_binding *bindings, size_t count)
{}


ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_binding_table(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_selection_set(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_noinline static void ufbxi_find_uint32_list(ufbx_uint32_list *dst, ufbxi_node *node, const char *name)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_selection_node(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_character(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_audio_clip(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_constraint_type;

static const ufbxi_constraint_type ufbxi_constraint_types[] =;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_constraint(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_synthetic_attribute(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, ufbx_string type_str, const char *sub_type, const char *super_type)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_global_settings(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_object(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_objects(ufbxi_context *uc)
{}

ufbxi_object_batch;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_objects_threaded(ufbxi_context *uc)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_connections(ufbxi_context *uc)
{}

// -- Pre-7000 "Take" based animation

ufbxi_forceinline static char ufbxi_double_to_char(double value)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_anim_channel(ufbxi_context *uc, ufbxi_node *node, uint64_t value_fbx_id, const char *name, ufbx_real *p_default)
{}

// Recursion limited as it is further called only for `name="T"/"R"/"S"` and
// cannot enter the `name=="Transform"` branch.
ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_prop_channel(ufbxi_context *uc, ufbxi_node *node, uint64_t target_fbx_id, uint64_t layer_fbx_id, ufbx_string name)
	ufbxi_recursive_function(int, ufbxi_read_take_prop_channel, (uc, node, target_fbx_id, layer_fbx_id, name), 2,
		(ufbxi_context *uc, ufbxi_node *node, uint64_t target_fbx_id, uint64_t layer_fbx_id, ufbx_string name))
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_object(ufbxi_context *uc, ufbxi_node *node, uint64_t layer_fbx_id)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_takes(ufbxi_context *uc)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_settings(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_noinline static ufbx_matrix ufbxi_unscaled_transform_to_matrix(const ufbx_transform *t)
{}

ufbxi_noinline static void ufbxi_setup_root_node(ufbxi_context *uc, ufbx_node *root)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_root(ufbxi_context *uc)
{}

ufbxi_legacy_prop;

// Must be alphabetically sorted!
static const ufbxi_legacy_prop ufbxi_legacy_light_props[] =;

// Must be alphabetically sorted!
static const ufbxi_legacy_prop ufbxi_legacy_camera_props[] =;

// Must be alphabetically sorted!
static const ufbxi_legacy_prop ufbxi_legacy_bone_props[] =;

// Must be alphabetically sorted!
static const ufbxi_legacy_prop ufbxi_legacy_material_props[] =;

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_prop(ufbxi_node *node, ufbx_prop *prop, const ufbxi_legacy_prop *legacy_prop)
{}

ufbxi_nodiscard ufbxi_noinline static size_t ufbxi_read_legacy_props(ufbxi_node *node, ufbx_prop *props, const ufbxi_legacy_prop *legacy_props, size_t num_legacy)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_material(ufbxi_context *uc, ufbxi_node *node, uint64_t *p_fbx_id, const char *name)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_link(ufbxi_context *uc, ufbxi_node *node, uint64_t *p_fbx_id, const char *name)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_light(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_camera(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_limb_node(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_mesh(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_media(ufbxi_context *uc, ufbxi_node *node)
{}

ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_model(ufbxi_context *uc, ufbxi_node *node)
{}

// Read a pre-6000 FBX file where everything is stored at the root level
ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_legacy_root(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static size_t ufbxi_trim_delimiters(ufbxi_context *uc, const char *data, size_t length)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_init_file_paths(ufbxi_context *uc)
{}ufbxi_strblobstatic ufbxi_noinline void ufbxi_strblob_set(ufbxi_strblob *dst, const char *data, size_t length, bool raw)
{}static ufbxi_forceinline const char *ufbxi_strblob_data(const ufbxi_strblob *strblob, bool raw)
{}static ufbxi_forceinline size_t ufbxi_strblob_length(const ufbxi_strblob *strblob, bool raw)
{}ufbxi_nodiscard ufbxi_noinline static bool ufbxi_is_absolute_path(const char *path, size_t length)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_relative_filename(ufbxi_context *uc, ufbxi_strblob *p_dst, const ufbxi_strblob *p_src, bool raw)
{}static void *ufbxi_ator_alloc(void *user, size_t size)
{}static void *ufbxi_ator_realloc(void *user, void *old_ptr, size_t old_size, size_t new_size)
{}static void ufbxi_ator_free(void *user, void *ptr, size_t size)
{}static ufbxi_noinline void ufbxi_setup_ator_allocator(ufbx_allocator *allocator, ufbxi_allocator *ator)
{}static ufbxi_noinline bool ufbxi_open_file(const ufbx_open_file_cb *cb, ufbx_stream *stream, const char *path, size_t path_len, const ufbx_blob *original_filename, ufbxi_allocator *ator, ufbx_open_file_type type)
{}#define ufbxi_patch_zero(dst, src)static void ufbxi_update_vertex_first_index(ufbx_mesh *mesh)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_finalize_mesh(ufbxi_buf *buf, ufbx_error *error, ufbx_mesh *mesh)
{}#if UFBXI_FEATURE_FORMAT_OBJ#define ufbxi_obj_cmd1#define ufbxi_obj_cmd2#define ufbxi_obj_cmd3#elseufbxi_nodiscard static ufbxi_forceinline int ufbxi_obj_load(ufbxi_context *uc)
{}ufbxi_nodiscard static ufbxi_forceinline int ufbxi_mtl_load(ufbxi_context *uc)
{}static ufbxi_forceinline void ufbxi_obj_free(ufbxi_context *uc)
{}#endifufbxi_pre_connectionufbxi_pre_nodeufbxi_pre_meshufbxi_pre_anim_valueufbxi_nodiscard ufbxi_noinline static int ufbxi_pre_finalize_scene(ufbxi_context *uc)
{}static ufbxi_noinline ufbx_element *ufbxi_find_element_by_fbx_id(ufbxi_context *uc, uint64_t fbx_id)
{}ufbxi_forceinline static bool ufbxi_cmp_name_element_less(const ufbx_name_element *a, const ufbx_name_element *b)
{}ufbxi_forceinline static bool ufbxi_cmp_name_element_less_ref(const ufbx_name_element *a, ufbx_string name, ufbx_element_type type, uint32_t key)
{}ufbxi_forceinline static bool ufbxi_cmp_prop_less_ref(const ufbx_prop *a, ufbx_string name, uint32_t key)
{}ufbxi_forceinline static bool ufbxi_cmp_prop_less_concat(const ufbx_prop *a, const ufbx_string *parts, size_t num_parts, uint32_t key)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_name_elements(ufbxi_context *uc, ufbx_name_element *name_elems, size_t count)
{}ufbxi_noinline static bool ufbxi_cmp_node_less(ufbx_node *a, ufbx_node *b)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_node_ptrs(ufbxi_context *uc, ufbx_node **nodes, size_t count)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_cmp_tmp_material_texture_less(const ufbxi_tmp_material_texture *a, const ufbxi_tmp_material_texture *b)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_tmp_material_textures(ufbxi_context *uc, ufbxi_tmp_material_texture *mat_texs, size_t count)
{}ufbx_static_assert()ufbxi_forceinline static bool ufbxi_cmp_connection_less(ufbx_connection *a, ufbx_connection *b, size_t index)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_connections(ufbxi_context *uc, ufbx_connection *connections, size_t count, size_t index)
{}static uint64_t ufbxi_find_attribute_fbx_id(ufbxi_context *uc, uint64_t node_fbx_id)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_connections(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_add_connections_to_elements(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_linearize_nodes(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_connection_list ufbxi_find_dst_connections(ufbx_element *element, const char *prop)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_connection_list ufbxi_find_src_connections(ufbx_element *element, const char *prop)
{}ufbxi_nodiscard static ufbx_element *ufbxi_get_element_node(ufbx_element *element)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_dst_elements(ufbxi_context *uc, void *p_dst_list, ufbx_element *element, bool search_node, bool ignore_duplicates, const char *prop, ufbx_element_type src_type)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_src_elements(ufbxi_context *uc, void *p_dst_list, ufbx_element *element, bool search_node, bool ignore_duplicates, const char *prop, ufbx_element_type dst_type)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_fetch_dst_element(ufbx_element *element, bool search_node, const char *prop, ufbx_element_type src_type)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_fetch_src_element(ufbx_element *element, bool search_node, const char *prop, ufbx_element_type dst_type)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_textures(ufbxi_context *uc, ufbx_material_texture_list *list, ufbx_element *element, bool search_node)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_mesh_materials(ufbxi_context *uc, ufbx_material_list *list, ufbx_element *element, bool search_node)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_deformers(ufbxi_context *uc,  ufbx_element_list *list, ufbx_element *element, bool search_node)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_blend_keyframes(ufbxi_context *uc, ufbx_blend_keyframe_list *list, ufbx_element *element)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_texture_layers(ufbxi_context *uc, ufbx_texture_layer_list *list, ufbx_element *element)
{}static ufbxi_forceinline bool ufbxi_prop_connection_less(const ufbx_connection *a, const char *prop)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_connection *ufbxi_find_prop_connection(const ufbx_element *element, const char *prop)
{}ufbxi_forceinline static void ufbxi_patch_index_pointer(ufbxi_context *uc, uint32_t **p_index)
{}ufbxi_nodiscard static bool ufbxi_cmp_anim_prop_less(const ufbx_anim_prop *a, const ufbx_anim_prop *b)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_anim_props(ufbxi_context *uc, ufbx_anim_prop *aprops, size_t count)
{}ufbxi_noinline static bool ufbxi_material_texture_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_material_textures(ufbxi_context *uc, ufbx_material_texture *textures, size_t count)
{}static ufbxi_noinline bool ufbxi_bone_pose_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_anim_prop *ufbxi_find_anim_prop_start(ufbx_anim_layer *layer, const ufbx_element *element)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_bone_poses(ufbxi_context *uc, ufbx_pose *pose)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_skin_weights(ufbxi_context *uc, ufbx_skin_deformer *skin)
{}ufbxi_noinline static bool ufbxi_blend_keyframe_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_blend_keyframes(ufbxi_context *uc, ufbx_blend_keyframe *keyframes, size_t count)
{}ufbxi_mat_transform_fnstatic void ufbxi_mat_transform_invert_x(ufbx_vec4 *v) {}static void ufbxi_mat_transform_unknown_shininess(ufbx_vec4 *v) {}static void ufbxi_mat_transform_blender_opacity(ufbx_vec4 *v) {}static void ufbxi_mat_transform_blender_shininess(ufbx_vec4 *v) {}ufbxi_mat_transformufbxi_shader_mapping_flagufbxi_shader_feature_flagstatic const ufbxi_mat_transform_fn ufbxi_mat_transform_fns[] =ufbx_static_assert()ufbxi_shader_mappingufbxi_shader_mapping_list#define ufbxi_mat_string(str)static const ufbxi_shader_mapping ufbxi_base_fbx_mapping[] =static const ufbxi_shader_mapping ufbxi_obj_fbx_mapping[] =static const ufbxi_shader_mapping ufbxi_fbx_lambert_shader_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_fbx_phong_shader_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_osl_standard_shader_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_osl_standard_shader_features[] =static const ufbxi_shader_mapping ufbxi_arnold_shader_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_arnold_shader_features[] =static const ufbxi_shader_mapping ufbxi_3ds_max_physical_material_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_3ds_max_physical_material_features[] =static const ufbxi_shader_mapping ufbxi_gltf_material_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_3ds_max_pbr_metal_rough_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_3ds_max_pbr_spec_gloss_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_3ds_max_pbr_features[] =static const ufbxi_shader_mapping ufbxi_gltf_material_features[] =static const ufbxi_shader_mapping ufbxi_shaderfx_graph_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_blender_phong_shader_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_obj_pbr_mapping[] =static const ufbxi_shader_mapping ufbxi_obj_features[] =enum {}static const ufbxi_shader_mapping_list ufbxi_shader_pbr_mappings[] =ufbx_static_assert()enum {}ufbxi_noinline static void ufbxi_fetch_mapping_maps(ufbx_material *material, ufbx_material_map *maps, ufbx_material_feature_info *features,
	ufbx_shader *shader, const ufbxi_shader_mapping *mappings, size_t count, ufbx_string prefix, ufbx_string prefix2, ufbx_string suffix, uint32_t flags)
{}ufbxi_noinline static void ufbxi_update_factor(ufbx_material_map *factor_map, ufbx_material_map *color_map)
{}ufbxi_glossiness_remapstatic const ufbxi_glossiness_remap ufbxi_glossiness_remaps[] =ufbxi_noinline static void ufbxi_fetch_maps(ufbx_scene *scene, ufbx_material *material)
{}ufbxi_constraint_prop_typeufbxi_constraint_propstatic const ufbxi_constraint_prop ufbxi_constraint_props[] =ufbxi_nodiscard ufbxi_noinline static int ufbxi_add_constraint_prop(ufbxi_context *uc, ufbx_constraint *constraint, ufbx_node *node, const char *prop)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_nurbs_basis(ufbxi_context *uc, ufbx_nurbs_basis *basis)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_lod_group(ufbxi_context *uc, ufbx_lod_group *lod)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_generate_normals(ufbxi_context *uc, ufbx_mesh *mesh)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_push_prop_prefix(ufbxi_context *uc, ufbx_string *dst, ufbx_string prefix)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_shader_texture_find_prefix(ufbxi_context *uc, ufbx_texture *texture, ufbx_shader_texture *shader)
{}ufbxi_file_shaderstatic const ufbxi_file_shader ufbxi_file_shaders[] =ufbxi_noinline static void ufbxi_update_shader_texture(ufbx_texture *texture, ufbx_shader_texture *shader)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_shader_texture(ufbxi_context *uc, ufbx_texture *texture)
{}ufbxi_noinline static void ufbxi_propagate_main_textures(ufbx_scene *scene)
{}#define ufbxi_patch_empty(m_dst, m_len, m_src)ufbxi_nodiscard ufbxi_noinline static int ufbxi_insert_texture_file(ufbxi_context *uc, ufbx_texture *texture)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_pop_texture_files(ufbxi_context *uc)
{}ufbxi_ordered_textureufbxi_noinline static bool ufbxi_ordered_texture_less_texture(void *user, const void *va, const void *vb)
{}ufbxi_noinline static bool ufbxi_ordered_texture_less_order(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_deduplicate_textures(ufbxi_context *uc, ufbxi_buf *dst_buf, ufbxi_ordered_texture **p_dst, size_t *p_dst_count, size_t count)
{}ufbxi_file_texture_fetch_stateufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_file_textures(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static ufbx_node *ufbxi_get_geometry_transform_node(ufbx_element *element)
{}ufbxi_noinline static void ufbxi_mirror_vec3_list(const void *v_list, ufbx_mirror_axis axis, size_t stride)
{}ufbxi_noinline static void ufbxi_scale_vec3_list(const void *v_list, ufbx_real scale, size_t stride)
{}ufbxi_noinline static void ufbxi_transform_vec3_list(const void *v_list, const ufbx_matrix *matrix, size_t stride)
{}ufbxi_noinline static void ufbxi_normalize_vec3_list(const ufbx_vec3_list *list)
{}ufbxi_noinline static ufbx_transform ufbxi_get_geometry_transform(const ufbx_props *props, ufbx_node *node)ufbxi_nodiscard ufbxi_noinline static int ufbxi_flip_attrib_winding(ufbxi_context *uc, ufbx_mesh *mesh, ufbx_uint32_list *indices, bool is_position)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_flip_winding(ufbxi_context *uc, ufbx_mesh *mesh)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_modify_geometry(ufbxi_context *uc)
{}ufbxi_noinline static void ufbxi_postprocess_scene(ufbxi_context *uc)
{}ufbxi_noinline static size_t ufbxi_next_path_segment(const char *data, size_t begin, size_t length)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_absolute_to_relative_path(ufbxi_context *uc, ufbxi_strblob *p_dst, const ufbxi_strblob *p_rel, const ufbxi_strblob *p_src, bool raw)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_filenames(ufbxi_context *uc, ufbxi_strblob *filename, ufbxi_strblob *absolute_filename, ufbxi_strblob *relative_filename, bool raw)
{}ufbxi_noinline static bool ufbxi_file_content_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_file_contents(ufbxi_context *uc, ufbxi_file_content *content, size_t count)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_push_file_content(ufbxi_context *uc, ufbx_string *p_filename, ufbx_blob *p_data)
{}ufbxi_noinline static void ufbxi_fetch_file_content(ufbxi_context *uc, ufbx_string *p_filename, ufbx_blob *p_data)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_file_content(ufbxi_context *uc)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_validate_indices(ufbxi_context *uc, ufbx_uint32_list *indices, size_t max_index)
{}static bool ufbxi_material_part_usage_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_finalize_mesh_material(ufbxi_buf *buf, ufbx_error *error, ufbx_mesh *mesh)
{}ufbxi_anim_impufbxi_nodiscard ufbxi_noinline static int ufbxi_push_anim(ufbxi_context *uc, ufbx_anim **p_anim, ufbx_anim_layer **layers, size_t num_layers)
{}ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_scene(ufbxi_context *uc)
{}static ufbxi_forceinline void ufbxi_add_translate(ufbx_transform *t, ufbx_vec3 v)
{}static ufbxi_forceinline void ufbxi_sub_translate(ufbx_transform *t, ufbx_vec3 v)
{}static ufbxi_forceinline void ufbxi_mul_scale(ufbx_transform *t, ufbx_vec3 v)
{}static ufbxi_forceinline void ufbxi_mul_scale_real(ufbx_transform *t, ufbx_real v)
{}static ufbxi_noinline ufbx_quat ufbxi_mul_quat(ufbx_quat a, ufbx_quat b)
{}static ufbxi_forceinline void ufbxi_add_weighted_vec3(ufbx_vec3 *r, ufbx_vec3 b, ufbx_real w)
{}static ufbxi_forceinline void ufbxi_add_weighted_quat(ufbx_quat *r, ufbx_quat b, ufbx_real w)
{}static ufbxi_noinline void ufbxi_add_weighted_mat(ufbx_matrix *r, const ufbx_matrix *b, ufbx_real w)
{}static void ufbxi_mul_rotate(ufbx_transform *t, ufbx_vec3 v, ufbx_rotation_order order)
{}static void ufbxi_mul_rotate_quat(ufbx_transform *t, ufbx_quat q)
{}static void ufbxi_mul_inv_rotate(ufbx_transform *t, ufbx_vec3 v, ufbx_rotation_order order)
{}ufbxi_forceinline static void ufbxi_mirror_translation(ufbx_vec3 *p_vec, ufbx_mirror_axis axis)
{}ufbxi_forceinline static void ufbxi_mirror_rotation(ufbx_quat *p_quat, ufbx_mirror_axis axis)
{}ufbxi_noinline static ufbx_transform ufbxi_get_geometry_transform(const ufbx_props *props, ufbx_node *node)
{}ufbxi_noinline static ufbx_transform ufbxi_get_transform(const ufbx_props *props, ufbx_rotation_order order, const ufbx_node *node, const ufbx_vec3 *translation_scale)
{}ufbxi_noinline static ufbx_quat ufbxi_get_rotation(const ufbx_props *props, ufbx_rotation_order order, const ufbx_node *node)
{}ufbxi_noinline static ufbx_vec3 ufbxi_get_scale(const ufbx_props *props, const ufbx_node *node)
{}ufbxi_noinline static ufbx_transform ufbxi_get_texture_transform(const ufbx_props *props)
{}ufbxi_noinline static ufbx_transform ufbxi_get_constraint_transform(const ufbx_props *props)
{}ufbxi_noinline static void ufbxi_update_node(ufbx_node *node, const ufbx_transform_override *overrides, size_t num_overrides)
{}ufbxi_noinline static void ufbxi_update_light(ufbx_light *light)
{}ufbxi_aperture_formatstatic const ufbxi_aperture_format ufbxi_aperture_formats[] =ufbxi_noinline static void ufbxi_update_camera(ufbx_scene *scene, ufbx_camera *camera)
{}ufbxi_noinline static void ufbxi_update_bone(ufbx_scene *scene, ufbx_bone *bone)
{}ufbxi_noinline static void ufbxi_update_line_curve(ufbx_line_curve *line)
{}ufbxi_noinline static void ufbxi_update_pose(ufbx_pose *pose)
{}ufbxi_noinline static void ufbxi_update_skin_cluster(ufbx_skin_cluster *cluster)
{}ufbxi_noinline static void ufbxi_update_blend_channel(ufbx_blend_channel *channel)
{}ufbxi_noinline static void ufbxi_update_material(ufbx_scene *scene, ufbx_material *material)
{}ufbxi_noinline static void ufbxi_update_texture(ufbx_texture *texture)
{}ufbxi_noinline static void ufbxi_update_anim_stack(ufbx_scene *scene, ufbx_anim_stack *stack)
{}ufbxi_noinline static void ufbxi_update_display_layer(ufbx_display_layer *layer)
{}ufbxi_noinline static void ufbxi_find_bool3(bool *dst, ufbx_props *props, const char *name, bool default_value)
{}ufbxi_noinline static void ufbxi_update_constraint(ufbx_constraint *constraint)
{}ufbxi_noinline static void ufbxi_update_anim(ufbx_scene *scene)
{}static ufbxi_forceinline void ufbxi_mirror_matrix_dst(ufbx_matrix *m, ufbx_mirror_axis axis)
{}static ufbxi_forceinline void ufbxi_mirror_matrix_src(ufbx_matrix *m, ufbx_mirror_axis axis)
{}static ufbxi_noinline void ufbxi_mirror_matrix(ufbx_matrix *m, ufbx_mirror_axis axis)
{}ufbxi_noinline static void ufbxi_update_initial_clusters(ufbx_scene *scene)
{}ufbxi_noinline static ufbx_coordinate_axis ufbxi_find_axis(const ufbx_props *props, const char *axis_name, const char *sign_name)
{}static const ufbx_real ufbxi_time_mode_fps[] =static ufbxi_noinline bool ufbxi_axis_matrix(ufbx_matrix *mat, ufbx_coordinate_axes src, ufbx_coordinate_axes dst)
{}ufbxi_noinline static void ufbxi_update_adjust_transforms(ufbxi_context *uc, ufbx_scene *scene)
{}ufbxi_noinline static void ufbxi_update_scene(ufbx_scene *scene, bool initial, const ufbx_transform_override *transform_overrides, size_t num_transform_overrides)
{}static ufbxi_noinline void ufbxi_update_scene_metadata(ufbx_metadata *metadata)
{}static const ufbx_real ufbxi_pow10_targets[] =static ufbxi_noinline ufbx_real ufbxi_round_if_near(const ufbx_real *targets, size_t num_targets, ufbx_real value)
{}static ufbxi_noinline void ufbxi_update_scene_settings(ufbx_scene_settings *settings)
{}static ufbxi_noinline void ufbxi_update_scene_settings_obj(ufbxi_context *uc)
{}#if UFBXI_FEATURE_GEOMETRY_CACHE#define ufbxi_cache_mc_tag#elseufbxi_geometry_cache_impstatic ufbxi_noinline ufbx_geometry_cache *ufbxi_load_geometry_cache(ufbx_string filename, const ufbx_geometry_cache_opts *user_opts, ufbx_error *p_error)
{}static ufbxi_forceinline void ufbxi_free_geometry_cache_imp(ufbxi_geometry_cache_imp *imp)
{}#endifufbxi_external_file_typeufbxi_external_filestatic bool ufbxi_less_external_file(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_external_cache(ufbxi_context *uc, ufbxi_external_file *file)
{}static ufbxi_noinline ufbxi_external_file *ufbxi_find_external_file(ufbxi_external_file *files, size_t num_files, ufbxi_external_file_type type, const char *name)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_external_files(ufbxi_context *uc)
{}static ufbxi_noinline void ufbxi_transform_to_axes(ufbxi_context *uc, ufbx_coordinate_axes dst_axes)
{}static ufbxi_noinline int ufbxi_scale_units(ufbxi_context *uc, ufbx_real target_meters)
{}static ufbxi_forceinline double ufbxi_find_cubic_bezier_t(double p1, double p2, double x0)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_evaluate_skinning(ufbx_scene *scene, ufbx_error *error, ufbxi_buf *buf_result, ufbxi_buf *buf_tmp,
	double time, bool load_caches, ufbx_geometry_cache_data_opts *cache_opts)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_fixup_opts_string(ufbxi_context *uc, ufbx_string *str, bool push)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_resolve_warning_elements(ufbxi_context *uc)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_imp(ufbxi_context *uc)
{}static ufbxi_noinline void ufbxi_free_temp(ufbxi_context *uc)
{}static ufbxi_noinline void ufbxi_free_result(ufbxi_context *uc)
{}static ufbxi_noinline ufbx_scene *ufbxi_load(ufbxi_context *uc, const ufbx_load_opts *user_opts, ufbx_error *p_error)
{}static ufbxi_noinline ufbx_scene *ufbxi_load_not_found(const char *filename, size_t filename_len, ufbx_error *p_error)
{}static ufbxi_forceinline bool ufbxi_override_less_than_prop(const ufbx_prop_override *over, uint32_t element_id, const ufbx_prop *prop)
{}static ufbxi_forceinline bool ufbxi_override_equals_to_prop(const ufbx_prop_override *over, uint32_t element_id, const ufbx_prop *prop)
{}static ufbxi_noinline bool ufbxi_find_prop_override(const ufbx_prop_override_list *overrides, uint32_t element_id, ufbx_prop *prop)
{}static ufbxi_noinline ufbx_prop_override_list ufbxi_find_element_prop_overrides(const ufbx_prop_override_list *overrides, uint32_t element_id)
{}ufbxi_anim_layer_combine_ctxstatic ufbxi_noinline double ufbxi_pow_abs(double v, double e)
{}static ufbxi_noinline void ufbxi_combine_anim_layer(ufbxi_anim_layer_combine_ctx *ctx, ufbx_anim_layer *layer, ufbx_real weight, const char *prop_name, ufbx_vec3 *result, const ufbx_vec3 *value)
	ufbxi_recursive_function_void(ufbxi_combine_anim_layer, (ctx, layer, weight, prop_name, result, value), 2,
		(ufbxi_anim_layer_combine_ctx *ctx, ufbx_anim_layer *layer, ufbx_real weight, const char *prop_name, ufbx_vec3 *result, const ufbx_vec3 *value))
{}static ufbxi_forceinline bool ufbxi_anim_layer_might_contain_id(const ufbx_anim_layer *layer, uint32_t id)
{}static ufbxi_noinline void ufbxi_evaluate_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *props, size_t num_props)
{}static ufbxi_noinline void ufbxi_evaluate_connected_prop(ufbx_prop *prop, const ufbx_anim *anim, const ufbx_element *element, const char *name, double time)
	ufbxi_recursive_function_void(ufbxi_evaluate_connected_prop, (prop, anim, element, name, time), 3,
		(ufbx_prop *prop, const ufbx_anim *anim, const ufbx_element *element, const char *name, double time))
{}ufbxi_prop_iterstatic ufbxi_noinline void ufbxi_init_prop_iter_slow(ufbxi_prop_iter *iter, const ufbx_anim *anim, const ufbx_element *element)
{}static ufbxi_forceinline void ufbxi_init_prop_iter(ufbxi_prop_iter *iter, const ufbx_anim *anim, const ufbx_element *element)
{}static ufbxi_noinline const ufbx_prop *ufbxi_next_prop_slow(ufbxi_prop_iter *iter)
{}static ufbxi_forceinline const ufbx_prop *ufbxi_next_prop(ufbxi_prop_iter *iter)
{}static ufbxi_noinline ufbx_props ufbxi_evaluate_selected_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *props, const char *const *prop_names, size_t max_props)
{}#if UFBXI_FEATURE_SCENE_EVALUATION#endifufbxi_create_anim_contextufbxi_nodiscard static ufbxi_noinline int ufbxi_check_string(ufbx_error *error, ufbx_string *dst, const ufbx_string *src)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_anim_string(ufbxi_create_anim_context *ac, ufbx_string *str)
{}static bool ufbxi_prop_override_prop_name_less(void *user, const void *va, const void *vb)
{}static bool ufbxi_prop_override_less(void *user, const void *va, const void *vb)
{}static int ufbxi_cmp_transform_override(const void *va, const void *vb)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_create_anim_imp(ufbxi_create_anim_context *ac)
{}ufbxi_baked_anim_imp#if UFBXI_FEATURE_ANIMATION_BAKINGufbxi_bake_timeUFBX_LIST_TYPE()ufbxi_bake_contextufbxi_bake_propstatic int ufbxi_cmp_bake_prop(const void *va, const void *vb)
{}ufbx_static_assert()ufbx_static_assert()ufbx_static_assert()static ufbxi_forceinline int ufbxi_cmp_bake_time(ufbxi_bake_time a, ufbxi_bake_time b)
{}static int ufbxi_cmp_bake_time_fn(const void *va, const void *vb)
{}ufbxi_nodiscard static ufbxi_forceinline int ufbxi_bake_push_time(ufbxi_bake_context *bc, double time, uint32_t flags)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_times(ufbxi_bake_context *bc, const ufbx_anim_value *anim_value, bool resample_linear, uint32_t key_flag)
{}static const char *const ufbxi_transform_props[] =static const char *const ufbxi_complex_translation_props[] =static const char *const ufbxi_complex_rotation_props[] =static const char *const ufbxi_complex_rotation_sources[] =ufbxi_nodiscard static ufbxi_noinline bool ufbxi_in_list(const char *const *items, size_t count, const char *item)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_finalize_bake_times(ufbxi_bake_context *bc, ufbxi_bake_time_list *p_dst)
{}#define ufbxi_add_epsilon(a, epsilon)#define ufbxi_sub_epsilon(a, epsilon)static ufbxi_noinline bool ufbxi_postprocess_step(ufbxi_bake_context *bc, double prev_time, double next_time, double *p_time, uint32_t flags)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_postprocess_vec3(ufbxi_bake_context *bc, ufbx_baked_vec3_list *p_dst, bool *p_constant, ufbx_baked_vec3_list src)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_postprocess_quat(ufbxi_bake_context *bc, ufbx_baked_quat_list *p_dst, bool *p_constant, ufbx_baked_quat_list src)
{}static ufbxi_forceinline double ufbxi_bake_time_sample_time(ufbxi_bake_time time)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_resampled_times(ufbxi_bake_context *bc, const ufbx_baked_vec3_list *p_keys)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_node_imp(ufbxi_bake_context *bc, uint32_t element_id, ufbxi_bake_prop *props, size_t count)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_node(ufbxi_bake_context *bc, uint32_t element_id, ufbxi_bake_prop *props, size_t count)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_anim_prop(ufbxi_bake_context *bc, ufbx_element *element, const char *prop_name, ufbxi_bake_prop *props, size_t count)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_element(ufbxi_bake_context *bc, uint32_t element_id, ufbxi_bake_prop *props, size_t count)
{}static ufbxi_noinline bool ufbxi_baked_node_less(void *user, const void *va, const void *vb)
{}static ufbxi_noinline bool ufbxi_baked_element_less(void *user, const void *va, const void *vb)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_anim(ufbxi_bake_context *bc)
{}ufbxi_nodiscard static ufbxi_noinline int ufbxi_bake_anim_imp(ufbxi_bake_context *bc, const ufbx_anim *anim)
{}#endifstatic ufbxi_forceinline ufbx_real ufbxi_nurbs_weight(const ufbx_real_list *knots, size_t knot, size_t degree, ufbx_real u)
{}static ufbxi_forceinline ufbx_real ufbxi_nurbs_deriv(const ufbx_real_list *knots, size_t knot, size_t degree)
{}ufbxi_line_curve_impufbx_static_assert()#if UFBXI_FEATURE_TESSELLATION#endif#if UFBXI_FEATURE_KDufbxi_kd_nodeufbxi_ngon_contextufbxi_kd_triangleufbxi_noinline static ufbx_vec2 ufbxi_ngon_project(ufbxi_ngon_context *nc, uint32_t index)
{}ufbxi_forceinline static ufbx_real ufbxi_orient2d(ufbx_vec2 a, ufbx_vec2 b, ufbx_vec2 c)
{}ufbxi_noinline static bool ufbxi_kd_check_point(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t index)
{}ufbxi_noinline static bool ufbxi_kd_check_slow(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t begin, uint32_t count, uint32_t axis)
	ufbxi_recursive_function(bool, ufbxi_kd_check_slow, (nc, tri, begin, count, axis), 32 - UFBXI_KD_FAST_DEPTH,
		(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t begin, uint32_t count, uint32_t axis))
{}ufbxi_noinline static bool ufbxi_kd_check_fast(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t kd_index, uint32_t axis, uint32_t depth)
	ufbxi_recursive_function(bool, ufbxi_kd_check_fast, (nc, tri, kd_index, axis, depth), UFBXI_KD_FAST_DEPTH,
		(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t kd_index, uint32_t axis, uint32_t depth))
{}ufbxi_noinline static bool ufbxi_kd_check(ufbxi_ngon_context *nc, const ufbx_vec2 *points, const uint32_t *indices)
{}ufbxi_noinline static bool ufbxi_kd_index_less(void *user, const void *va, const void *vb)
{}ufbxi_noinline static void ufbxi_kd_build(ufbxi_ngon_context *nc, uint32_t *indices, uint32_t *tmp, uint32_t num, uint32_t axis, uint32_t fast_index, uint32_t depth)
	ufbxi_recursive_function_void(ufbxi_kd_build, (nc, indices, tmp, num, axis, fast_index, depth), 32,
		(ufbxi_ngon_context *nc, uint32_t *indices, uint32_t *tmp, uint32_t num, uint32_t axis, uint32_t fast_index, uint32_t depth))
{}#endif#if UFBXI_FEATURE_TRIANGULATIONufbxi_noinline static ufbx_real ufbxi_ngon_tri_weight(const ufbx_vec2 *points)
{}ufbxi_noinline static uint32_t ufbxi_triangulate_ngon(ufbxi_ngon_context *nc, uint32_t *indices, uint32_t num_indices)
{}#endifstatic int ufbxi_cmp_topo_index_prev_next(const void *va, const void *vb)
{}static int ufbxi_cmp_topo_index_index(const void *va, const void *vb)
{}ufbxi_noinline static void ufbxi_compute_topology(const ufbx_mesh *mesh, ufbx_topo_edge *topo)
{}static bool ufbxi_is_edge_smooth(const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index, bool assume_smooth)
{}#if UFBXI_FEATURE_SUBDIVISION#if defined(UFBX_REGRESSION)#endif#elseufbxi_noinline static ufbx_mesh *ufbxi_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *user_opts, ufbx_error *p_error)
{}#endif#if UFBXI_FEATURE_INDEX_GENERATION#if defined(UFBX_REGRESSION)#endif#elsestatic ufbxi_noinline size_t ufbxi_generate_indices(const ufbx_vertex_stream *user_streams, size_t num_streams, uint32_t *indices, size_t num_indices, const ufbx_allocator_opts *allocator, ufbx_error *error)
{}#endifstatic ufbxi_noinline void ufbxi_free_scene_imp(ufbxi_scene_imp *imp)
{}static ufbxi_noinline void ufbxi_init_ref(ufbxi_refcount *refcount, uint32_t magic, ufbxi_refcount *parent)
{}static ufbxi_noinline void ufbxi_retain_ref(ufbxi_refcount *refcount)
{}static ufbxi_noinline void ufbxi_release_ref(ufbxi_refcount *refcount)
{}static ufbxi_noinline void *ufbxi_uninitialized_options(ufbx_error *p_error)
{}#define ufbxi_check_opts_ptr(m_type, m_opts, m_error)#define ufbxi_check_opts_return(m_value, m_opts, m_error)#define ufbxi_check_opts_return_no_error(m_value, m_opts)#ifdef __cplusplus#endifufbx_abi_data_defconst ufbx_string ufbx_empty_string =ufbx_abi_data_defconst ufbx_blob ufbx_empty_blob =ufbx_abi_data_defconst ufbx_matrix ufbx_identity_matrix =ufbx_abi_data_defconst ufbx_transform ufbx_identity_transform =ufbx_abi_data_defconst ufbx_vec2 ufbx_zero_vec2 =ufbx_abi_data_defconst ufbx_vec3 ufbx_zero_vec3 =ufbx_abi_data_defconst ufbx_vec4 ufbx_zero_vec4 =ufbx_abi_data_defconst ufbx_quat ufbx_identity_quat =ufbx_abi_data_defconst ufbx_coordinate_axes ufbx_axes_right_handed_y_up =ufbx_abi_data_defconst ufbx_coordinate_axes ufbx_axes_right_handed_z_up =ufbx_abi_data_defconst ufbx_coordinate_axes ufbx_axes_left_handed_y_up =ufbx_abi_data_defconst ufbx_coordinate_axes ufbx_axes_left_handed_z_up =ufbx_abi_data_defconst size_t ufbx_element_type_size[UFBX_ELEMENT_TYPE_COUNT] =ufbx_abibool ufbx_open_file(ufbx_stream *stream, const char *path, size_t path_len)
{}ufbx_abibool ufbx_default_open_file(void *user, ufbx_stream *stream, const char *path, size_t path_len, const ufbx_open_file_info *info)
{}ufbx_abibool ufbx_open_memory(ufbx_stream *stream, const void *data, size_t data_size, const ufbx_open_memory_opts *opts, ufbx_error *error)
{}ufbx_abibool ufbx_is_thread_safe(void)
{}ufbx_abiufbx_scene *ufbx_load_memory(const void *data, size_t size, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_file(const char *filename, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_file_len(const char *filename, size_t filename_len, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_stdio(void *file_void, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_stdio_prefix(void *file_void, const void *prefix, size_t prefix_size, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_stream(const ufbx_stream *stream, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_scene *ufbx_load_stream_prefix(const ufbx_stream *stream, const void *prefix, size_t prefix_size, const ufbx_load_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_free_scene(ufbx_scene *scene)
{}ufbx_abivoid ufbx_retain_scene(ufbx_scene *scene)
{}ufbx_abiufbxi_noinline size_t ufbx_format_error(char *dst, size_t dst_size, const ufbx_error *error)
{}ufbx_abiufbx_prop *ufbx_find_prop_len(const ufbx_props *props, const char *name, size_t name_len)
{}ufbx_abiufbx_real ufbx_find_real_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_real def)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_find_vec3_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_vec3 def)
{}ufbx_abiufbxi_noinline int64_t ufbx_find_int_len(const ufbx_props *props, const char *name, size_t name_len, int64_t def)
{}ufbx_abibool ufbx_find_bool_len(const ufbx_props *props, const char *name, size_t name_len, bool def)
{}ufbx_abiufbxi_noinline ufbx_string ufbx_find_string_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_string def)
{}ufbx_abiufbx_blob ufbx_find_blob_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_blob def)
{}ufbx_abiufbx_prop *ufbx_find_prop_concat(const ufbx_props *props, const ufbx_string *parts, size_t num_parts)
{}ufbx_abiufbx_element *ufbx_find_element_len(const ufbx_scene *scene, ufbx_element_type type, const char *name, size_t name_len)
{}ufbx_abiufbx_element *ufbx_get_prop_element(const ufbx_element *element, const ufbx_prop *prop, ufbx_element_type type)
{}ufbx_abiufbx_element *ufbx_find_prop_element_len(const ufbx_element *element, const char *name, size_t name_len, ufbx_element_type type)
{}ufbx_abiufbx_node *ufbx_find_node_len(const ufbx_scene *scene, const char *name, size_t name_len)
{}ufbx_abiufbx_anim_stack *ufbx_find_anim_stack_len(const ufbx_scene *scene, const char *name, size_t name_len)
{}ufbx_abiufbx_material *ufbx_find_material_len(const ufbx_scene *scene, const char *name, size_t name_len)
{}ufbx_abiufbx_anim_prop *ufbx_find_anim_prop_len(const ufbx_anim_layer *layer, const ufbx_element *element, const char *prop, size_t prop_len)
{}ufbx_abiufbxi_noinline ufbx_anim_prop_list ufbx_find_anim_props(const ufbx_anim_layer *layer, const ufbx_element *element)
{}ufbx_abiufbxi_noinline ufbx_matrix ufbx_get_compatible_matrix_for_normals(const ufbx_node *node)
{}ufbx_abiufbx_real ufbx_evaluate_curve(const ufbx_anim_curve *curve, double time, ufbx_real default_value)
{}ufbx_abiufbxi_noinline ufbx_real ufbx_evaluate_anim_value_real(const ufbx_anim_value *anim_value, double time)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_evaluate_anim_value_vec3(const ufbx_anim_value *anim_value, double time)
{}ufbx_abiufbxi_noinline ufbx_prop ufbx_evaluate_prop_len(const ufbx_anim *anim, const ufbx_element *element, const char *name, size_t name_len, double time)
{}ufbx_abiufbxi_noinline ufbx_props ufbx_evaluate_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *buffer, size_t buffer_size)
{}ufbx_abiufbxi_noinline ufbx_transform ufbx_evaluate_transform(const ufbx_anim *anim, const ufbx_node *node, double time)
{}static const char *const ufbxi_transform_props_all[] =static const char *const ufbxi_transform_props_rotation[] =static const char *const ufbxi_transform_props_scale[] =static const char *const ufbxi_transform_props_rotation_scale[] =ufbx_abiufbxi_noinline ufbx_transform ufbx_evaluate_transform_flags(const ufbx_anim *anim, const ufbx_node *node, double time, uint32_t flags)
{}ufbx_abiufbx_real ufbx_evaluate_blend_weight(const ufbx_anim *anim, const ufbx_blend_channel *channel, double time)
{}ufbx_abiufbx_scene *ufbx_evaluate_scene(const ufbx_scene *scene, const ufbx_anim *anim, double time, const ufbx_evaluate_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_anim *ufbx_create_anim(const ufbx_scene *scene, const ufbx_anim_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_free_anim(ufbx_anim *anim)
{}ufbx_abivoid ufbx_retain_anim(ufbx_anim *anim)
{}ufbx_abiufbx_baked_anim *ufbx_bake_anim(const ufbx_scene *scene, const ufbx_anim *anim, const ufbx_bake_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_retain_baked_anim(ufbx_baked_anim *bake)
{}ufbx_abivoid ufbx_free_baked_anim(ufbx_baked_anim *bake)
{}ufbx_abiufbx_baked_node *ufbx_find_baked_node_by_typed_id(ufbx_baked_anim *bake, uint32_t typed_id)
{}ufbx_abiufbx_baked_node *ufbx_find_baked_node(ufbx_baked_anim *bake, ufbx_node *node)
{}ufbx_abiufbx_baked_element *ufbx_find_baked_element_by_element_id(ufbx_baked_anim *bake, uint32_t element_id)
{}ufbx_abiufbx_baked_element *ufbx_find_baked_element(ufbx_baked_anim *bake, ufbx_element *element)
{}ufbx_abiufbx_vec3 ufbx_evaluate_baked_vec3(ufbx_baked_vec3_list keyframes, double time)
{}ufbx_abiufbx_quat ufbx_evaluate_baked_quat(ufbx_baked_quat_list keyframes, double time)
{}ufbx_abiufbx_bone_pose *ufbx_get_bone_pose(const ufbx_pose *pose, const ufbx_node *node)
{}ufbx_abiufbx_texture *ufbx_find_prop_texture_len(const ufbx_material *material, const char *name, size_t name_len)
{}ufbx_abiufbx_string ufbx_find_shader_prop_len(const ufbx_shader *shader, const char *name, size_t name_len)
{}ufbx_abiufbx_shader_prop_binding_list ufbx_find_shader_prop_bindings_len(const ufbx_shader *shader, const char *name, size_t name_len)
{}ufbx_abiufbx_shader_texture_input *ufbx_find_shader_texture_input_len(const ufbx_shader_texture *shader, const char *name, size_t name_len)
{}ufbx_abibool ufbx_coordinate_axes_valid(ufbx_coordinate_axes axes)
{}ufbx_abiufbx_quat ufbx_quat_mul(ufbx_quat a, ufbx_quat b)
{}ufbx_abiufbx_vec3 ufbx_vec3_normalize(ufbx_vec3 v)
{}ufbx_abiufbxi_noinline ufbx_real ufbx_quat_dot(ufbx_quat a, ufbx_quat b)
{}ufbx_abiufbxi_noinline ufbx_quat ufbx_quat_normalize(ufbx_quat q)
{}ufbx_abiufbxi_noinline ufbx_quat ufbx_quat_fix_antipodal(ufbx_quat q, ufbx_quat reference)
{}ufbx_abiufbxi_noinline ufbx_quat ufbx_quat_slerp(ufbx_quat a, ufbx_quat b, ufbx_real t)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_quat_rotate_vec3(ufbx_quat q, ufbx_vec3 v)
{}ufbx_abiufbxi_noinline ufbx_quat ufbx_euler_to_quat(ufbx_vec3 v, ufbx_rotation_order order)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_quat_to_euler(ufbx_quat q, ufbx_rotation_order order)
{}ufbx_abiufbxi_noinline ufbx_matrix ufbx_matrix_mul(const ufbx_matrix *a, const ufbx_matrix *b)
{}ufbx_abiufbx_real ufbx_matrix_determinant(const ufbx_matrix *m)
{}ufbx_abiufbx_matrix ufbx_matrix_invert(const ufbx_matrix *m)
{}ufbx_abiufbxi_noinline ufbx_matrix ufbx_matrix_for_normals(const ufbx_matrix *m)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_transform_position(const ufbx_matrix *m, ufbx_vec3 v)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_transform_direction(const ufbx_matrix *m, ufbx_vec3 v)
{}ufbx_abiufbxi_noinline ufbx_matrix ufbx_transform_to_matrix(const ufbx_transform *t)
{}ufbx_abiufbxi_noinline ufbx_transform ufbx_matrix_to_transform(const ufbx_matrix *m)
{}ufbx_abiufbxi_noinline ufbx_matrix ufbx_catch_get_skin_vertex_matrix(ufbx_panic *panic, const ufbx_skin_deformer *skin, size_t vertex, const ufbx_matrix *fallback)
{}ufbx_abiufbxi_noinline uint32_t ufbx_get_blend_shape_offset_index(const ufbx_blend_shape *shape, size_t vertex)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_get_blend_shape_vertex_offset(const ufbx_blend_shape *shape, size_t vertex)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_get_blend_vertex_offset(const ufbx_blend_deformer *blend, size_t vertex)
{}ufbx_abivoid ufbx_add_blend_shape_vertex_offsets(const ufbx_blend_shape *shape, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight)
{}ufbx_abivoid ufbx_add_blend_vertex_offsets(const ufbx_blend_deformer *blend, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight)
{}ufbx_abisize_t ufbx_evaluate_nurbs_basis(const ufbx_nurbs_basis *basis, ufbx_real u, ufbx_real *weights, size_t num_weights, ufbx_real *derivatives, size_t num_derivatives)
{}ufbx_abiufbxi_noinline ufbx_curve_point ufbx_evaluate_nurbs_curve(const ufbx_nurbs_curve *curve, ufbx_real u)
{}ufbx_abiufbxi_noinline ufbx_surface_point ufbx_evaluate_nurbs_surface(const ufbx_nurbs_surface *surface, ufbx_real u, ufbx_real v)
{}ufbx_abiufbx_line_curve *ufbx_tessellate_nurbs_curve(const ufbx_nurbs_curve *curve, const ufbx_tessellate_curve_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_mesh *ufbx_tessellate_nurbs_surface(const ufbx_nurbs_surface *surface, const ufbx_tessellate_surface_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_free_line_curve(ufbx_line_curve *line_curve)
{}ufbx_abivoid ufbx_retain_line_curve(ufbx_line_curve *line_curve)
{}ufbx_abiuint32_t ufbx_find_face_index(ufbx_mesh *mesh, size_t index)
{}ufbx_abiufbxi_noinline uint32_t ufbx_catch_triangulate_face(ufbx_panic *panic, uint32_t *indices, size_t num_indices, const ufbx_mesh *mesh, ufbx_face face)
{}ufbx_abivoid ufbx_catch_compute_topology(ufbx_panic *panic, const ufbx_mesh *mesh, ufbx_topo_edge *indices, size_t num_indices)
{}ufbx_abiuint32_t ufbx_catch_topo_next_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index)
{}ufbx_abiuint32_t ufbx_catch_topo_prev_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_catch_get_weighted_face_normal(ufbx_panic *panic, const ufbx_vertex_vec3 *positions, ufbx_face face)
{}size_t ufbx_catch_generate_normal_mapping(ufbx_panic *panic, const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth)
{}ufbx_abisize_t ufbx_generate_normal_mapping(const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth)
{}ufbx_abivoid ufbx_catch_compute_normals(ufbx_panic *panic, const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions, const uint32_t *normal_indices, size_t num_normal_indices, ufbx_vec3 *normals, size_t num_normals)
{}ufbx_abivoid ufbx_compute_normals(const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions, const uint32_t *normal_indices, size_t num_normal_indices, ufbx_vec3 *normals, size_t num_normals)
{}ufbx_abiufbx_mesh *ufbx_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_free_mesh(ufbx_mesh *mesh)
{}ufbx_abivoid ufbx_retain_mesh(ufbx_mesh *mesh)
{}ufbx_abiufbx_geometry_cache *ufbx_load_geometry_cache(
	const char *filename,
	const ufbx_geometry_cache_opts *opts, ufbx_error *error)
{}ufbx_abiufbx_geometry_cache *ufbx_load_geometry_cache_len(
	const char *filename, size_t filename_len,
	const ufbx_geometry_cache_opts *opts, ufbx_error *error)
{}ufbx_abivoid ufbx_free_geometry_cache(ufbx_geometry_cache *cache)
{}ufbx_abivoid ufbx_retain_geometry_cache(ufbx_geometry_cache *cache)
{}ufbxi_geometry_cache_bufferufbx_abiufbxi_noinline size_t ufbx_read_geometry_cache_real(const ufbx_cache_frame *frame, ufbx_real *data, size_t count, const ufbx_geometry_cache_data_opts *user_opts)
{}ufbx_abiufbxi_noinline size_t ufbx_sample_geometry_cache_real(const ufbx_cache_channel *channel, double time, ufbx_real *data, size_t count, const ufbx_geometry_cache_data_opts *user_opts)
{}ufbx_abiufbxi_noinline size_t ufbx_read_geometry_cache_vec3(const ufbx_cache_frame *frame, ufbx_vec3 *data, size_t count, const ufbx_geometry_cache_data_opts *opts)
{}ufbx_abiufbxi_noinline size_t ufbx_sample_geometry_cache_vec3(const ufbx_cache_channel *channel, double time, ufbx_vec3 *data, size_t count, const ufbx_geometry_cache_data_opts *opts)
{}ufbx_abiufbx_dom_node *ufbx_dom_find_len(const ufbx_dom_node *parent, const char *name, size_t name_len)
{}ufbx_abisize_t ufbx_generate_indices(const ufbx_vertex_stream *streams, size_t num_streams, uint32_t *indices, size_t num_indices, const ufbx_allocator_opts *allocator, ufbx_error *error)
{}ufbx_abivoid ufbx_thread_pool_run_task(ufbx_thread_pool_context ctx, uint32_t index)
{}ufbx_abivoid ufbx_thread_pool_set_user_ptr(ufbx_thread_pool_context ctx, void *user)
{}ufbx_abivoid *ufbx_thread_pool_get_user_ptr(ufbx_thread_pool_context ctx)
{}ufbx_abiufbxi_noinline ufbx_real ufbx_catch_get_vertex_real(ufbx_panic *panic, const ufbx_vertex_real *v, size_t index)
{}ufbx_abiufbxi_noinline ufbx_vec2 ufbx_catch_get_vertex_vec2(ufbx_panic *panic, const ufbx_vertex_vec2 *v, size_t index)
{}ufbx_abiufbxi_noinline ufbx_vec3 ufbx_catch_get_vertex_vec3(ufbx_panic *panic, const ufbx_vertex_vec3 *v, size_t index)
{}ufbx_abiufbxi_noinline ufbx_vec4 ufbx_catch_get_vertex_vec4(ufbx_panic *panic, const ufbx_vertex_vec4 *v, size_t index)
{}ufbx_abiufbx_real ufbx_catch_get_vertex_w_vec3(ufbx_panic *panic, const ufbx_vertex_vec3 *v, size_t index)
{}ufbx_abiufbx_unknown *ufbx_as_unknown(const ufbx_element *element) {}ufbx_abiufbx_node *ufbx_as_node(const ufbx_element *element) {}ufbx_abiufbx_mesh *ufbx_as_mesh(const ufbx_element *element) {}ufbx_abiufbx_light *ufbx_as_light(const ufbx_element *element) {}ufbx_abiufbx_camera *ufbx_as_camera(const ufbx_element *element) {}ufbx_abiufbx_bone *ufbx_as_bone(const ufbx_element *element) {}ufbx_abiufbx_empty *ufbx_as_empty(const ufbx_element *element) {}ufbx_abiufbx_line_curve *ufbx_as_line_curve(const ufbx_element *element) {}ufbx_abiufbx_nurbs_curve *ufbx_as_nurbs_curve(const ufbx_element *element) {}ufbx_abiufbx_nurbs_surface *ufbx_as_nurbs_surface(const ufbx_element *element) {}ufbx_abiufbx_nurbs_trim_surface *ufbx_as_nurbs_trim_surface(const ufbx_element *element) {}ufbx_abiufbx_nurbs_trim_boundary *ufbx_as_nurbs_trim_boundary(const ufbx_element *element) {}ufbx_abiufbx_procedural_geometry *ufbx_as_procedural_geometry(const ufbx_element *element) {}ufbx_abiufbx_stereo_camera *ufbx_as_stereo_camera(const ufbx_element *element) {}ufbx_abiufbx_camera_switcher *ufbx_as_camera_switcher(const ufbx_element *element) {}ufbx_abiufbx_marker *ufbx_as_marker(const ufbx_element *element) {}ufbx_abiufbx_lod_group *ufbx_as_lod_group(const ufbx_element *element) {}ufbx_abiufbx_skin_deformer *ufbx_as_skin_deformer(const ufbx_element *element) {}ufbx_abiufbx_skin_cluster *ufbx_as_skin_cluster(const ufbx_element *element) {}ufbx_abiufbx_blend_deformer *ufbx_as_blend_deformer(const ufbx_element *element) {}ufbx_abiufbx_blend_channel *ufbx_as_blend_channel(const ufbx_element *element) {}ufbx_abiufbx_blend_shape *ufbx_as_blend_shape(const ufbx_element *element) {}ufbx_abiufbx_cache_deformer *ufbx_as_cache_deformer(const ufbx_element *element) {}ufbx_abiufbx_cache_file *ufbx_as_cache_file(const ufbx_element *element) {}ufbx_abiufbx_material *ufbx_as_material(const ufbx_element *element) {}ufbx_abiufbx_texture *ufbx_as_texture(const ufbx_element *element) {}ufbx_abiufbx_video *ufbx_as_video(const ufbx_element *element) {}ufbx_abiufbx_shader *ufbx_as_shader(const ufbx_element *element) {}ufbx_abiufbx_shader_binding *ufbx_as_shader_binding(const ufbx_element *element) {}ufbx_abiufbx_anim_stack *ufbx_as_anim_stack(const ufbx_element *element) {}ufbx_abiufbx_anim_layer *ufbx_as_anim_layer(const ufbx_element *element) {}ufbx_abiufbx_anim_value *ufbx_as_anim_value(const ufbx_element *element) {}ufbx_abiufbx_anim_curve *ufbx_as_anim_curve(const ufbx_element *element) {}ufbx_abiufbx_display_layer *ufbx_as_display_layer(const ufbx_element *element) {}ufbx_abiufbx_selection_set *ufbx_as_selection_set(const ufbx_element *element) {}ufbx_abiufbx_selection_node *ufbx_as_selection_node(const ufbx_element *element) {}ufbx_abiufbx_character *ufbx_as_character(const ufbx_element *element) {}ufbx_abiufbx_constraint *ufbx_as_constraint(const ufbx_element *element) {}ufbx_abiufbx_audio_layer *ufbx_as_audio_layer(const ufbx_element *element) {}ufbx_abiufbx_audio_clip *ufbx_as_audio_clip(const ufbx_element *element) {}ufbx_abiufbx_pose *ufbx_as_pose(const ufbx_element *element) {}ufbx_abiufbx_metadata_object *ufbx_as_metadata_object(const ufbx_element *element) {}#ifdef __cplusplus#endif#endif#if defined(_MSC_VER)#pragma warning(pop)#elif defined(__clang__)#pragma clang diagnostic pop#elif defined(__GNUC__)#pragma GCC diagnostic pop#endif