Update OpenFBX

Updated to commit 365f52c1edad6bd283c8a645f1d8d2347dbd1e35
This commit is contained in:
2024-05-25 11:30:48 +03:00
parent e0791eacad
commit 7454e9abd2
5 changed files with 6693 additions and 1423 deletions

4193
Source/ThirdParty/OpenFBX/libdeflate.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

411
Source/ThirdParty/OpenFBX/libdeflate.h vendored Normal file
View File

@@ -0,0 +1,411 @@
/*
* libdeflate.h - public header for libdeflate
*/
#ifndef LIBDEFLATE_H
#define LIBDEFLATE_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define LIBDEFLATE_VERSION_MAJOR 1
#define LIBDEFLATE_VERSION_MINOR 18
#define LIBDEFLATE_VERSION_STRING "1.18"
/*
* Users of libdeflate.dll on Windows can define LIBDEFLATE_DLL to cause
* __declspec(dllimport) to be used. This should be done when it's easy to do.
* Otherwise it's fine to skip it, since it is a very minor performance
* optimization that is irrelevant for most use cases of libdeflate.
*/
#ifndef LIBDEFLATEAPI
# if defined(LIBDEFLATE_DLL) && (defined(_WIN32) || defined(__CYGWIN__))
# define LIBDEFLATEAPI __declspec(dllimport)
# else
# define LIBDEFLATEAPI
# endif
#endif
/* ========================================================================== */
/* Compression */
/* ========================================================================== */
struct libdeflate_compressor;
struct libdeflate_options;
/*
* libdeflate_alloc_compressor() allocates a new compressor that supports
* DEFLATE, zlib, and gzip compression. 'compression_level' is the compression
* level on a zlib-like scale but with a higher maximum value (1 = fastest, 6 =
* medium/default, 9 = slow, 12 = slowest). Level 0 is also supported and means
* "no compression", specifically "create a valid stream, but only emit
* uncompressed blocks" (this will expand the data slightly).
*
* The return value is a pointer to the new compressor, or NULL if out of memory
* or if the compression level is invalid (i.e. outside the range [0, 12]).
*
* Note: for compression, the sliding window size is defined at compilation time
* to 32768, the largest size permissible in the DEFLATE format. It cannot be
* changed at runtime.
*
* A single compressor is not safe to use by multiple threads concurrently.
* However, different threads may use different compressors concurrently.
*/
LIBDEFLATEAPI struct libdeflate_compressor *
libdeflate_alloc_compressor(int compression_level);
/*
* Like libdeflate_alloc_compressor(), but adds the 'options' argument.
*/
LIBDEFLATEAPI struct libdeflate_compressor *
libdeflate_alloc_compressor_ex(int compression_level,
const struct libdeflate_options *options);
/*
* libdeflate_deflate_compress() performs raw DEFLATE compression on a buffer of
* data. It attempts to compress 'in_nbytes' bytes of data located at 'in' and
* write the result to 'out', which has space for 'out_nbytes_avail' bytes. The
* return value is the compressed size in bytes, or 0 if the data could not be
* compressed to 'out_nbytes_avail' bytes or fewer (but see note below).
*
* If compression is successful, then the output data is guaranteed to be a
* valid DEFLATE stream that decompresses to the input data. No other
* guarantees are made about the output data. Notably, different versions of
* libdeflate can produce different compressed data for the same uncompressed
* data, even at the same compression level. Do ***NOT*** do things like
* writing tests that compare compressed data to a golden output, as this can
* break when libdeflate is updated. (This property isn't specific to
* libdeflate; the same is true for zlib and other compression libraries too.)
*/
LIBDEFLATEAPI size_t
libdeflate_deflate_compress(struct libdeflate_compressor *compressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail);
/*
* libdeflate_deflate_compress_bound() returns a worst-case upper bound on the
* number of bytes of compressed data that may be produced by compressing any
* buffer of length less than or equal to 'in_nbytes' using
* libdeflate_deflate_compress() with the specified compressor. This bound will
* necessarily be a number greater than or equal to 'in_nbytes'. It may be an
* overestimate of the true upper bound. The return value is guaranteed to be
* the same for all invocations with the same compressor and same 'in_nbytes'.
*
* As a special case, 'compressor' may be NULL. This causes the bound to be
* taken across *any* libdeflate_compressor that could ever be allocated with
* this build of the library, with any options.
*
* Note that this function is not necessary in many applications. With
* block-based compression, it is usually preferable to separately store the
* uncompressed size of each block and to store any blocks that did not compress
* to less than their original size uncompressed. In that scenario, there is no
* need to know the worst-case compressed size, since the maximum number of
* bytes of compressed data that may be used would always be one less than the
* input length. You can just pass a buffer of that size to
* libdeflate_deflate_compress() and store the data uncompressed if
* libdeflate_deflate_compress() returns 0, indicating that the compressed data
* did not fit into the provided output buffer.
*/
LIBDEFLATEAPI size_t
libdeflate_deflate_compress_bound(struct libdeflate_compressor *compressor,
size_t in_nbytes);
/*
* Like libdeflate_deflate_compress(), but uses the zlib wrapper format instead
* of raw DEFLATE.
*/
LIBDEFLATEAPI size_t
libdeflate_zlib_compress(struct libdeflate_compressor *compressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail);
/*
* Like libdeflate_deflate_compress_bound(), but assumes the data will be
* compressed with libdeflate_zlib_compress() rather than with
* libdeflate_deflate_compress().
*/
LIBDEFLATEAPI size_t
libdeflate_zlib_compress_bound(struct libdeflate_compressor *compressor,
size_t in_nbytes);
/*
* Like libdeflate_deflate_compress(), but uses the gzip wrapper format instead
* of raw DEFLATE.
*/
LIBDEFLATEAPI size_t
libdeflate_gzip_compress(struct libdeflate_compressor *compressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail);
/*
* Like libdeflate_deflate_compress_bound(), but assumes the data will be
* compressed with libdeflate_gzip_compress() rather than with
* libdeflate_deflate_compress().
*/
LIBDEFLATEAPI size_t
libdeflate_gzip_compress_bound(struct libdeflate_compressor *compressor,
size_t in_nbytes);
/*
* libdeflate_free_compressor() frees a compressor that was allocated with
* libdeflate_alloc_compressor(). If a NULL pointer is passed in, no action is
* taken.
*/
LIBDEFLATEAPI void
libdeflate_free_compressor(struct libdeflate_compressor *compressor);
/* ========================================================================== */
/* Decompression */
/* ========================================================================== */
struct libdeflate_decompressor;
struct libdeflate_options;
/*
* libdeflate_alloc_decompressor() allocates a new decompressor that can be used
* for DEFLATE, zlib, and gzip decompression. The return value is a pointer to
* the new decompressor, or NULL if out of memory.
*
* This function takes no parameters, and the returned decompressor is valid for
* decompressing data that was compressed at any compression level and with any
* sliding window size.
*
* A single decompressor is not safe to use by multiple threads concurrently.
* However, different threads may use different decompressors concurrently.
*/
LIBDEFLATEAPI struct libdeflate_decompressor *
libdeflate_alloc_decompressor(void);
/*
* Like libdeflate_alloc_decompressor(), but adds the 'options' argument.
*/
LIBDEFLATEAPI struct libdeflate_decompressor *
libdeflate_alloc_decompressor_ex(const struct libdeflate_options *options);
/*
* Result of a call to libdeflate_deflate_decompress(),
* libdeflate_zlib_decompress(), or libdeflate_gzip_decompress().
*/
enum libdeflate_result {
/* Decompression was successful. */
LIBDEFLATE_SUCCESS = 0,
/* Decompression failed because the compressed data was invalid,
* corrupt, or otherwise unsupported. */
LIBDEFLATE_BAD_DATA = 1,
/* A NULL 'actual_out_nbytes_ret' was provided, but the data would have
* decompressed to fewer than 'out_nbytes_avail' bytes. */
LIBDEFLATE_SHORT_OUTPUT = 2,
/* The data would have decompressed to more than 'out_nbytes_avail'
* bytes. */
LIBDEFLATE_INSUFFICIENT_SPACE = 3,
};
/*
* libdeflate_deflate_decompress() decompresses a DEFLATE stream from the buffer
* 'in' with compressed size up to 'in_nbytes' bytes. The uncompressed data is
* written to 'out', a buffer with size 'out_nbytes_avail' bytes. If
* decompression succeeds, then 0 (LIBDEFLATE_SUCCESS) is returned. Otherwise,
* a nonzero result code such as LIBDEFLATE_BAD_DATA is returned, and the
* contents of the output buffer are undefined.
*
* Decompression stops at the end of the DEFLATE stream (as indicated by the
* BFINAL flag), even if it is actually shorter than 'in_nbytes' bytes.
*
* libdeflate_deflate_decompress() can be used in cases where the actual
* uncompressed size is known (recommended) or unknown (not recommended):
*
* - If the actual uncompressed size is known, then pass the actual
* uncompressed size as 'out_nbytes_avail' and pass NULL for
* 'actual_out_nbytes_ret'. This makes libdeflate_deflate_decompress() fail
* with LIBDEFLATE_SHORT_OUTPUT if the data decompressed to fewer than the
* specified number of bytes.
*
* - If the actual uncompressed size is unknown, then provide a non-NULL
* 'actual_out_nbytes_ret' and provide a buffer with some size
* 'out_nbytes_avail' that you think is large enough to hold all the
* uncompressed data. In this case, if the data decompresses to less than
* or equal to 'out_nbytes_avail' bytes, then
* libdeflate_deflate_decompress() will write the actual uncompressed size
* to *actual_out_nbytes_ret and return 0 (LIBDEFLATE_SUCCESS). Otherwise,
* it will return LIBDEFLATE_INSUFFICIENT_SPACE if the provided buffer was
* not large enough but no other problems were encountered, or another
* nonzero result code if decompression failed for another reason.
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_deflate_decompress(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_out_nbytes_ret);
/*
* Like libdeflate_deflate_decompress(), but adds the 'actual_in_nbytes_ret'
* argument. If decompression succeeds and 'actual_in_nbytes_ret' is not NULL,
* then the actual compressed size of the DEFLATE stream (aligned to the next
* byte boundary) is written to *actual_in_nbytes_ret.
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_deflate_decompress_ex(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_in_nbytes_ret,
size_t *actual_out_nbytes_ret);
/*
* Like libdeflate_deflate_decompress(), but assumes the zlib wrapper format
* instead of raw DEFLATE.
*
* Decompression will stop at the end of the zlib stream, even if it is shorter
* than 'in_nbytes'. If you need to know exactly where the zlib stream ended,
* use libdeflate_zlib_decompress_ex().
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_zlib_decompress(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_out_nbytes_ret);
/*
* Like libdeflate_zlib_decompress(), but adds the 'actual_in_nbytes_ret'
* argument. If 'actual_in_nbytes_ret' is not NULL and the decompression
* succeeds (indicating that the first zlib-compressed stream in the input
* buffer was decompressed), then the actual number of input bytes consumed is
* written to *actual_in_nbytes_ret.
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_zlib_decompress_ex(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_in_nbytes_ret,
size_t *actual_out_nbytes_ret);
/*
* Like libdeflate_deflate_decompress(), but assumes the gzip wrapper format
* instead of raw DEFLATE.
*
* If multiple gzip-compressed members are concatenated, then only the first
* will be decompressed. Use libdeflate_gzip_decompress_ex() if you need
* multi-member support.
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_gzip_decompress(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_out_nbytes_ret);
/*
* Like libdeflate_gzip_decompress(), but adds the 'actual_in_nbytes_ret'
* argument. If 'actual_in_nbytes_ret' is not NULL and the decompression
* succeeds (indicating that the first gzip-compressed member in the input
* buffer was decompressed), then the actual number of input bytes consumed is
* written to *actual_in_nbytes_ret.
*/
LIBDEFLATEAPI enum libdeflate_result
libdeflate_gzip_decompress_ex(struct libdeflate_decompressor *decompressor,
const void *in, size_t in_nbytes,
void *out, size_t out_nbytes_avail,
size_t *actual_in_nbytes_ret,
size_t *actual_out_nbytes_ret);
/*
* libdeflate_free_decompressor() frees a decompressor that was allocated with
* libdeflate_alloc_decompressor(). If a NULL pointer is passed in, no action
* is taken.
*/
LIBDEFLATEAPI void
libdeflate_free_decompressor(struct libdeflate_decompressor *decompressor);
/* ========================================================================== */
/* Checksums */
/* ========================================================================== */
/*
* libdeflate_adler32() updates a running Adler-32 checksum with 'len' bytes of
* data and returns the updated checksum. When starting a new checksum, the
* required initial value for 'adler' is 1. This value is also returned when
* 'buffer' is specified as NULL.
*/
LIBDEFLATEAPI uint32_t
libdeflate_adler32(uint32_t adler, const void *buffer, size_t len);
/*
* libdeflate_crc32() updates a running CRC-32 checksum with 'len' bytes of data
* and returns the updated checksum. When starting a new checksum, the required
* initial value for 'crc' is 0. This value is also returned when 'buffer' is
* specified as NULL.
*/
LIBDEFLATEAPI uint32_t
libdeflate_crc32(uint32_t crc, const void *buffer, size_t len);
/* ========================================================================== */
/* Custom memory allocator */
/* ========================================================================== */
/*
* Install a custom memory allocator which libdeflate will use for all memory
* allocations by default. 'malloc_func' is a function that must behave like
* malloc(), and 'free_func' is a function that must behave like free().
*
* The per-(de)compressor custom memory allocator that can be specified in
* 'struct libdeflate_options' takes priority over this.
*
* This doesn't affect the free() function that will be used to free
* (de)compressors that were already in existence when this is called.
*/
LIBDEFLATEAPI void
libdeflate_set_memory_allocator(void *(*malloc_func)(size_t),
void (*free_func)(void *));
/*
* Advanced options. This is the options structure that
* libdeflate_alloc_compressor_ex() and libdeflate_alloc_decompressor_ex()
* require. Most users won't need this and should just use the non-"_ex"
* functions instead. If you do need this, it should be initialized like this:
*
* struct libdeflate_options options;
*
* memset(&options, 0, sizeof(options));
* options.sizeof_options = sizeof(options);
* // Then set the fields that you need to override the defaults for.
*/
struct libdeflate_options {
/*
* This field must be set to the struct size. This field exists for
* extensibility, so that fields can be appended to this struct in
* future versions of libdeflate while still supporting old binaries.
*/
size_t sizeof_options;
/*
* An optional custom memory allocator to use for this (de)compressor.
* 'malloc_func' must be a function that behaves like malloc(), and
* 'free_func' must be a function that behaves like free().
*
* This is useful in cases where a process might have multiple users of
* libdeflate who want to use different memory allocators. For example,
* a library might want to use libdeflate with a custom memory allocator
* without interfering with user code that might use libdeflate too.
*
* This takes priority over the "global" memory allocator (which by
* default is malloc() and free(), but can be changed by
* libdeflate_set_memory_allocator()). Moreover, libdeflate will never
* call the "global" memory allocator if a per-(de)compressor custom
* allocator is always given.
*/
void *(*malloc_func)(size_t);
void (*free_func)(void *);
};
#ifdef __cplusplus
}
#endif
#endif /* LIBDEFLATE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -9,10 +9,10 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#ifdef _WIN32
typedef long long i64;
typedef unsigned long long u64;
#else
typedef long i64;
typedef long long i64;
typedef unsigned long long u64;
#else
typedef long i64;
typedef unsigned long u64;
#endif
@@ -21,46 +21,71 @@ static_assert(sizeof(u32) == 4, "u32 is not 4 bytes");
static_assert(sizeof(u64) == 8, "u64 is not 8 bytes");
static_assert(sizeof(i64) == 8, "i64 is not 8 bytes");
typedef decltype(sizeof(0)) usize;
using JobFunction = void (*)(void*);
using JobProcessor = void (*)(JobFunction, void*, void*, u32, u32);
enum class LoadFlags : u64 {
TRIANGULATE = 1 << 0,
// Ignoring certain nodes will only stop them from being processed not tokenised (i.e. they will still be in the tree)
enum class LoadFlags : u16
{
NONE = 0,
UNUSED = 1 << 0, // can be reused
IGNORE_GEOMETRY = 1 << 1,
IGNORE_BLEND_SHAPES = 1 << 2,
IGNORE_CAMERAS = 1 << 3,
IGNORE_LIGHTS = 1 << 4,
IGNORE_TEXTURES = 1 << 5,
IGNORE_SKIN = 1 << 6,
IGNORE_BONES = 1 << 7,
IGNORE_PIVOTS = 1 << 8,
IGNORE_ANIMATIONS = 1 << 9,
IGNORE_MATERIALS = 1 << 10,
IGNORE_POSES = 1 << 11,
IGNORE_VIDEOS = 1 << 12,
IGNORE_LIMBS = 1 << 13,
IGNORE_MESHES = 1 << 14,
IGNORE_MODELS = 1 << 15,
};
struct Vec2
constexpr LoadFlags operator|(LoadFlags lhs, LoadFlags rhs)
{
double x, y;
};
return static_cast<LoadFlags>(static_cast<u16>(lhs) | static_cast<u16>(rhs));
}
struct Vec3
inline LoadFlags& operator|=(LoadFlags& lhs, LoadFlags rhs)
{
double x, y, z;
};
return lhs = lhs | rhs;
}
struct DVec2 { double x, y; };
struct DVec3 { double x, y, z; };
struct DVec4 { double x, y, z, w; };
struct DMatrix { double m[16]; /* last 4 are translation */ };
struct DQuat{ double x, y, z, w; };
struct Vec4
{
double x, y, z, w;
};
struct Matrix
{
double m[16]; // last 4 are translation
};
struct Quat
{
double x, y, z, w;
};
struct FVec2 { float x, y; };
struct FVec3 { float x, y, z; };
struct FVec4 { float x, y, z, w; };
struct FMatrix { float m[16]; };
struct FQuat{ float x, y, z, w; };
#define OFBX_SINGLE_PRECISION
#ifdef OFBX_SINGLE_PRECISION
// use floats for vertices, normals, uvs, ...
using Vec2 = FVec2;
using Vec3 = FVec3;
using Vec4 = FVec4;
using Matrix = FMatrix;
using Quat = FQuat;
#else
// use doubles for vertices, normals, uvs, ...
using Vec2 = DVec2;
using Vec3 = DVec3;
using Vec4 = DVec4;
using Matrix = DMatrix;
using Quat = DQuat;
#endif
struct Color
{
@@ -81,9 +106,10 @@ struct DataView
i64 toI64() const;
int toInt() const;
u32 toU32() const;
bool toBool() const;
double toDouble() const;
float toFloat() const;
template <int N>
void toString(char(&out)[N]) const
{
@@ -113,7 +139,8 @@ struct IElementProperty
ARRAY_INT = 'i',
ARRAY_LONG = 'l',
ARRAY_FLOAT = 'f',
BINARY = 'R'
BINARY = 'R',
NONE = ' '
};
virtual ~IElementProperty() {}
virtual Type getType() const = 0;
@@ -168,6 +195,8 @@ struct Object
TEXTURE,
LIMB_NODE,
NULL_NODE,
CAMERA,
LIGHT,
NODE_ATTRIBUTE,
CLUSTER,
SKIN,
@@ -189,22 +218,22 @@ struct Object
Object* resolveObjectLink(int idx) const;
Object* resolveObjectLink(Type type, const char* property, int idx) const;
Object* resolveObjectLinkReverse(Type type) const;
Object* getParent() const;
Object* getParent() const { return parent; }
RotationOrder getRotationOrder() const;
Vec3 getRotationOffset() const;
Vec3 getRotationPivot() const;
Vec3 getPostRotation() const;
Vec3 getScalingOffset() const;
Vec3 getScalingPivot() const;
Vec3 getPreRotation() const;
Vec3 getLocalTranslation() const;
Vec3 getLocalRotation() const;
Vec3 getLocalScaling() const;
Matrix getGlobalTransform() const;
Matrix getLocalTransform() const;
Matrix evalLocal(const Vec3& translation, const Vec3& rotation) const;
Matrix evalLocal(const Vec3& translation, const Vec3& rotation, const Vec3& scaling) const;
DVec3 getRotationOffset() const;
DVec3 getRotationPivot() const;
DVec3 getPostRotation() const;
DVec3 getScalingOffset() const;
DVec3 getScalingPivot() const;
DVec3 getPreRotation() const;
DVec3 getLocalTranslation() const;
DVec3 getLocalRotation() const;
DVec3 getLocalScaling() const;
DMatrix getGlobalTransform() const;
DMatrix getLocalTransform() const;
DMatrix evalLocal(const DVec3& translation, const DVec3& rotation) const;
DMatrix evalLocal(const DVec3& translation, const DVec3& rotation, const DVec3& scaling) const;
bool isNode() const { return is_node; }
@@ -214,11 +243,14 @@ struct Object
}
u64 id;
u32 depth = 0xffFFffFF;
Object* parent = nullptr;
char name[128];
const IElement& element;
const Object* node_attribute;
protected:
friend struct Scene;
bool is_node;
const Scene& scene;
};
@@ -228,7 +260,7 @@ struct Pose : Object {
static const Type s_type = Type::POSE;
Pose(const Scene& _scene, const IElement& _element);
virtual Matrix getMatrix() const = 0;
virtual DMatrix getMatrix() const = 0;
virtual const Object* getNode() const = 0;
};
@@ -255,6 +287,124 @@ struct Texture : Object
virtual DataView getEmbeddedData() const = 0;
};
struct Light : Object
{
public:
enum class LightType
{
POINT,
DIRECTIONAL,
SPOT,
AREA,
VOLUME,
COUNT
};
enum class DecayType
{
NO_DECAY,
LINEAR,
QUADRATIC,
CUBIC,
COUNT
};
Light(const Scene& _scene, const IElement& _element)
: Object(_scene, _element)
{
// Initialize the light properties here
}
// Light type
virtual LightType getLightType() const = 0;
// Light properties
virtual bool doesCastLight() const = 0;
virtual bool doesDrawVolumetricLight() const = 0;
virtual bool doesDrawGroundProjection() const = 0;
virtual bool doesDrawFrontFacingVolumetricLight() const = 0;
virtual Color getColor() const = 0;
virtual double getIntensity() const = 0;
virtual double getInnerAngle() const = 0;
virtual double getOuterAngle() const = 0;
virtual double getFog() const = 0;
virtual DecayType getDecayType() const = 0;
virtual double getDecayStart() const = 0;
// Near attenuation
virtual bool doesEnableNearAttenuation() const = 0;
virtual double getNearAttenuationStart() const = 0;
virtual double getNearAttenuationEnd() const = 0;
// Far attenuation
virtual bool doesEnableFarAttenuation() const = 0;
virtual double getFarAttenuationStart() const = 0;
virtual double getFarAttenuationEnd() const = 0;
// Shadows
virtual const Texture* getShadowTexture() const = 0;
virtual bool doesCastShadows() const = 0;
virtual Color getShadowColor() const = 0;
};
struct Camera : Object
{
enum class ProjectionType
{
PERSPECTIVE,
ORTHOGRAPHIC,
COUNT
};
enum class ApertureMode // Used to determine how to calculate the FOV
{
HORIZANDVERT,
HORIZONTAL,
VERTICAL,
FOCALLENGTH,
COUNT
};
enum class GateFit
{
NONE,
VERTICAL,
HORIZONTAL,
FILL,
OVERSCAN,
STRETCH,
COUNT
};
static const Type s_type = Type::CAMERA;
Camera(const Scene& _scene, const IElement& _element)
: Object(_scene, _element)
{
}
virtual Type getType() const { return Type::CAMERA; }
virtual ProjectionType getProjectionType() const = 0;
virtual ApertureMode getApertureMode() const = 0;
virtual double getFilmHeight() const = 0;
virtual double getFilmWidth() const = 0;
virtual double getAspectHeight() const = 0;
virtual double getAspectWidth() const = 0;
virtual double getNearPlane() const = 0;
virtual double getFarPlane() const = 0;
virtual bool doesAutoComputeClipPanes() const = 0;
virtual GateFit getGateFit() const = 0;
virtual double getFilmAspectRatio() const = 0;
virtual double getFocalLength() const = 0;
virtual double getFocusDistance() const = 0;
virtual DVec3 getBackgroundColor() const = 0;
virtual DVec3 getInterestPosition() const = 0;
};
struct Material : Object
{
@@ -291,8 +441,8 @@ struct Cluster : Object
virtual int getIndicesCount() const = 0;
virtual const double* getWeights() const = 0;
virtual int getWeightsCount() const = 0;
virtual Matrix getTransformMatrix() const = 0;
virtual Matrix getTransformLinkMatrix() const = 0;
virtual DMatrix getTransformMatrix() const = 0;
virtual DMatrix getTransformLinkMatrix() const = 0;
virtual const Object* getLink() const = 0;
};
@@ -341,26 +491,74 @@ struct NodeAttribute : Object
};
struct Geometry : Object
{
struct Vec2Attributes {
const Vec2* values = nullptr;
const int* indices = nullptr;
int count = 0;
Vec2Attributes() {}
Vec2Attributes(const Vec2* v, const int* i, int c) : values(v), indices(i), count(c) {}
Vec2 get(int i) const { return indices ? values[indices[i]] : values[i]; }
};
struct Vec3Attributes {
const Vec3* values = nullptr;
const int* indices = nullptr;
int count = 0;
int values_count = 0;
Vec3Attributes() {}
Vec3Attributes(const Vec3* v, const int* i, int c, int vc) : values(v), indices(i), count(c), values_count(vc) {}
Vec3 get(int i) const { return indices ? values[indices[i]] : values[i]; }
};
struct Vec4Attributes {
const Vec4* values = nullptr;
const int* indices = nullptr;
int count = 0;
Vec4Attributes() {}
Vec4Attributes(const Vec4* v, const int* i, int c) : values(v), indices(i), count(c) {}
Vec4 get(int i) const { return indices ? values[indices[i]] : values[i]; }
};
// subset of polygons with same material
struct GeometryPartition {
struct Polygon {
const int from_vertex; // index into VecNAttributes::indices
const int vertex_count;
};
const Polygon* polygons;
const int polygon_count;
const int max_polygon_triangles; // max triangles in single polygon, can be used for preallocation
const int triangles_count; // number of triangles after polygon triangulation, can be used for preallocation
};
struct GeometryData {
virtual ~GeometryData() {}
virtual Vec3Attributes getPositions() const = 0;
virtual Vec3Attributes getNormals() const = 0;
virtual Vec2Attributes getUVs(int index = 0) const = 0;
virtual Vec4Attributes getColors() const = 0;
virtual Vec3Attributes getTangents() const = 0;
virtual int getPartitionCount() const = 0;
virtual GeometryPartition getPartition(int partition_index) const = 0;
};
struct Geometry : Object {
static const Type s_type = Type::GEOMETRY;
static const int s_uvs_max = 4;
Geometry(const Scene& _scene, const IElement& _element);
virtual const Vec3* getVertices() const = 0;
virtual int getVertexCount() const = 0;
virtual const int* getFaceIndices() const = 0;
virtual int getIndexCount() const = 0;
virtual const Vec3* getNormals() const = 0;
virtual const Vec2* getUVs(int index = 0) const = 0;
virtual const Vec4* getColors() const = 0;
virtual const Vec3* getTangents() const = 0;
virtual const GeometryData& getGeometryData() const = 0;
virtual const Skin* getSkin() const = 0;
virtual const BlendShape* getBlendShape() const = 0;
virtual const int* getMaterials() const = 0;
};
@@ -373,21 +571,27 @@ struct Shape : Object
virtual const Vec3* getVertices() const = 0;
virtual int getVertexCount() const = 0;
virtual const int* getIndices() const = 0;
virtual int getIndexCount() const = 0;
virtual const Vec3* getNormals() const = 0;
};
struct Mesh : Object
{
struct Mesh : Object {
static const Type s_type = Type::MESH;
Mesh(const Scene& _scene, const IElement& _element);
virtual const Pose* getPose() const = 0;
virtual const Geometry* getGeometry() const = 0;
virtual Matrix getGeometricMatrix() const = 0;
virtual DMatrix getGeometricMatrix() const = 0;
virtual const Material* getMaterial(int idx) const = 0;
virtual int getMaterialCount() const = 0;
// this will use data from `Geometry` if available and from `Mesh` otherwise
virtual const GeometryData& getGeometryData() const = 0;
virtual const Skin* getSkin() const = 0;
virtual const BlendShape* getBlendShape() const = 0;
};
@@ -429,8 +633,9 @@ struct AnimationCurveNode : Object
AnimationCurveNode(const Scene& _scene, const IElement& _element);
virtual DataView getBoneLinkProperty() const = 0;
virtual const AnimationCurve* getCurve(int idx) const = 0;
virtual Vec3 getNodeLocalTransform(double time) const = 0;
virtual DVec3 getNodeLocalTransform(double time) const = 0;
virtual const Object* getBone() const = 0;
};
@@ -449,17 +654,9 @@ struct TakeInfo
// Specifies which canonical axis represents up in the system (typically Y or Z).
enum UpVector
{
UpVector_AxisX = 1,
UpVector_AxisY = 2,
UpVector_AxisZ = 3
};
// Vector with origin at the screen pointing toward the camera.
enum FrontVector
{
FrontVector_ParityEven = 1,
FrontVector_ParityOdd = 2
UpVector_AxisX = 0,
UpVector_AxisY = 1,
UpVector_AxisZ = 2
};
@@ -494,9 +691,11 @@ enum FrameRate
struct GlobalSettings
{
UpVector UpAxis = UpVector_AxisX;
UpVector UpAxis = UpVector_AxisY;
int UpAxisSign = 1;
FrontVector FrontAxis = FrontVector_ParityOdd;
// this seems to be 1-2 in Autodesk (odd/even parity), and 0-2 in Blender (axis as in UpAxis)
// I recommend to ignore FrontAxis and use just UpVector
int FrontAxis = 1;
int FrontAxisSign = 1;
CoordSystem CoordAxis = CoordSystem_RightHanded;
int CoordAxisSign = 1;
@@ -511,41 +710,105 @@ struct GlobalSettings
};
struct GlobalInfo
{
char AppVendor[128];
char AppName[128];
char AppVersion[128];
};
struct IScene
{
virtual void destroy() = 0;
// Root Node
virtual const IElement* getRootElement() const = 0;
virtual const Object* getRoot() const = 0;
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
// Meshes
virtual int getMeshCount() const = 0;
virtual float getSceneFrameRate() const = 0;
virtual const GlobalInfo* getGlobalInfo() const = 0;
virtual const GlobalSettings* getGlobalSettings() const = 0;
virtual const Mesh* getMesh(int index) const = 0;
// Geometry
virtual int getGeometryCount() const = 0;
virtual const Geometry* getGeometry(int index) const = 0;
// Animations
virtual int getAnimationStackCount() const = 0;
virtual const AnimationStack* getAnimationStack(int index) const = 0;
// Cameras
virtual int getCameraCount() const = 0;
virtual const Camera* getCamera(int index) const = 0;
// Lights
virtual int getLightCount() const = 0;
virtual const Light* getLight(int index) const = 0;
// Scene Objects (Everything in scene)
virtual const Object* const* getAllObjects() const = 0;
virtual int getAllObjectCount() const = 0;
// Embedded files/Data
virtual int getEmbeddedDataCount() const = 0;
virtual DataView getEmbeddedData(int index) const = 0;
virtual DataView getEmbeddedFilename(int index) const = 0;
virtual bool isEmbeddedBase64(int index) const = 0;
// data are encoded in returned property and all ->next properties
virtual const IElementProperty* getEmbeddedBase64Data(int index) const = 0;
// Scene Misc
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
virtual float getSceneFrameRate() const = 0;
virtual const GlobalSettings* getGlobalSettings() const = 0;
protected:
virtual ~IScene() {}
};
IScene* load(const u8* data, int size, u64 flags, JobProcessor job_processor = nullptr, void* job_user_ptr = nullptr);
IScene* load(const u8* data, usize size, u16 flags, JobProcessor job_processor = nullptr, void* job_user_ptr = nullptr);
const char* getError();
double fbxTimeToSeconds(i64 value);
i64 secondsToFbxTime(double value);
// TODO nonconvex
inline u32 triangulate(const GeometryData& geom, const GeometryPartition::Polygon& polygon, int* tri_indices) {
if (polygon.vertex_count < 3) return 0;
if (polygon.vertex_count == 3) {
tri_indices[0] = polygon.from_vertex;
tri_indices[1] = polygon.from_vertex + 1;
tri_indices[2] = polygon.from_vertex + 2;
return 3;
}
else if (polygon.vertex_count == 4) {
tri_indices[0] = polygon.from_vertex + 0;
tri_indices[1] = polygon.from_vertex + 1;
tri_indices[2] = polygon.from_vertex + 2;
tri_indices[3] = polygon.from_vertex + 0;
tri_indices[4] = polygon.from_vertex + 2;
tri_indices[5] = polygon.from_vertex + 3;
return 6;
}
for (int tri = 0; tri < polygon.vertex_count - 2; ++tri) {
tri_indices[tri * 3 + 0] = polygon.from_vertex;
tri_indices[tri * 3 + 1] = polygon.from_vertex + 1 + tri;
tri_indices[tri * 3 + 2] = polygon.from_vertex + 2 + tri;
}
return 3 * (polygon.vertex_count - 2);
}
} // namespace ofbx
#ifdef OFBX_DEFAULT_DELETER
#include <memory>
template <> struct ::std::default_delete<ofbx::IScene>
{
default_delete() = default;
template <class U> constexpr default_delete(default_delete<U>) noexcept {}
void operator()(ofbx::IScene* scene) const noexcept
{
if (scene)
{
scene->destroy();
}
}
};
#endif