mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-15 01:15:53 +08:00
Merge branch 'master' of github.com:syoyo/tinygltf
This commit is contained in:
commit
39a263c2a8
@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
|
||||||
* ALL RIGHTS RESERVED
|
|
||||||
* Permission to use, copy, modify, and distribute this software for
|
|
||||||
* any purpose and without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice appear in all copies and that both the copyright notice
|
|
||||||
* and this permission notice appear in supporting documentation, and that
|
|
||||||
* the name of Silicon Graphics, Inc. not be used in advertising
|
|
||||||
* or publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission.
|
|
||||||
*
|
|
||||||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
|
||||||
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
|
||||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
|
||||||
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
|
||||||
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
|
||||||
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
|
||||||
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
|
||||||
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
* US Government Users Restricted Rights
|
|
||||||
* Use, duplication, or disclosure by the Government is subject to
|
|
||||||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
|
||||||
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
|
||||||
* clause at DFARS 252.227-7013 and/or in similar or successor
|
|
||||||
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
|
||||||
* Unpublished-- rights reserved under the copyright laws of the
|
|
||||||
* United States. Contractor/manufacturer is Silicon Graphics,
|
|
||||||
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
|
||||||
*
|
|
||||||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Trackball code:
|
|
||||||
*
|
|
||||||
* Implementation of a virtual trackball.
|
|
||||||
* Implemented by Gavin Bell, lots of ideas from Thant Tessman and
|
|
||||||
* the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
|
|
||||||
*
|
|
||||||
* Vector manip code:
|
|
||||||
*
|
|
||||||
* Original code from:
|
|
||||||
* David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
|
|
||||||
*
|
|
||||||
* Much mucking with by:
|
|
||||||
* Gavin Bell
|
|
||||||
*/
|
|
||||||
#include <math.h>
|
|
||||||
#include "trackball.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This size should really be based on the distance from the center of
|
|
||||||
* rotation to the point on the object underneath the mouse. That
|
|
||||||
* point would then track the mouse as closely as possible. This is a
|
|
||||||
* simple example, though, so that is left as an Exercise for the
|
|
||||||
* Programmer.
|
|
||||||
*/
|
|
||||||
#define TRACKBALLSIZE (0.8)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local function prototypes (not defined in trackball.h)
|
|
||||||
*/
|
|
||||||
static float tb_project_to_sphere(float, float, float);
|
|
||||||
static void normalize_quat(float[4]);
|
|
||||||
|
|
||||||
static void vzero(float *v) {
|
|
||||||
v[0] = 0.0;
|
|
||||||
v[1] = 0.0;
|
|
||||||
v[2] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vset(float *v, float x, float y, float z) {
|
|
||||||
v[0] = x;
|
|
||||||
v[1] = y;
|
|
||||||
v[2] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vsub(const float *src1, const float *src2, float *dst) {
|
|
||||||
dst[0] = src1[0] - src2[0];
|
|
||||||
dst[1] = src1[1] - src2[1];
|
|
||||||
dst[2] = src1[2] - src2[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vcopy(const float *v1, float *v2) {
|
|
||||||
register int i;
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
v2[i] = v1[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vcross(const float *v1, const float *v2, float *cross) {
|
|
||||||
float temp[3];
|
|
||||||
|
|
||||||
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
|
|
||||||
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
|
|
||||||
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
|
|
||||||
vcopy(temp, cross);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float vlength(const float *v) {
|
|
||||||
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vscale(float *v, float div) {
|
|
||||||
v[0] *= div;
|
|
||||||
v[1] *= div;
|
|
||||||
v[2] *= div;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); }
|
|
||||||
|
|
||||||
static float vdot(const float *v1, const float *v2) {
|
|
||||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vadd(const float *src1, const float *src2, float *dst) {
|
|
||||||
dst[0] = src1[0] + src2[0];
|
|
||||||
dst[1] = src1[1] + src2[1];
|
|
||||||
dst[2] = src1[2] + src2[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ok, simulate a track-ball. Project the points onto the virtual
|
|
||||||
* trackball, then figure out the axis of rotation, which is the cross
|
|
||||||
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
|
|
||||||
* Note: This is a deformed trackball-- is a trackball in the center,
|
|
||||||
* but is deformed into a hyperbolic sheet of rotation away from the
|
|
||||||
* center. This particular function was chosen after trying out
|
|
||||||
* several variations.
|
|
||||||
*
|
|
||||||
* It is assumed that the arguments to this routine are in the range
|
|
||||||
* (-1.0 ... 1.0)
|
|
||||||
*/
|
|
||||||
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) {
|
|
||||||
float a[3]; /* Axis of rotation */
|
|
||||||
float phi; /* how much to rotate about axis */
|
|
||||||
float p1[3], p2[3], d[3];
|
|
||||||
float t;
|
|
||||||
|
|
||||||
if (p1x == p2x && p1y == p2y) {
|
|
||||||
/* Zero rotation */
|
|
||||||
vzero(q);
|
|
||||||
q[3] = 1.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, figure out z-coordinates for projection of P1 and P2 to
|
|
||||||
* deformed sphere
|
|
||||||
*/
|
|
||||||
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
|
|
||||||
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now, we want the cross product of P1 and P2
|
|
||||||
*/
|
|
||||||
vcross(p2, p1, a);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out how much to rotate around that axis.
|
|
||||||
*/
|
|
||||||
vsub(p1, p2, d);
|
|
||||||
t = vlength(d) / (2.0 * TRACKBALLSIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Avoid problems with out-of-control values...
|
|
||||||
*/
|
|
||||||
if (t > 1.0)
|
|
||||||
t = 1.0;
|
|
||||||
if (t < -1.0)
|
|
||||||
t = -1.0;
|
|
||||||
phi = 2.0 * asin(t);
|
|
||||||
|
|
||||||
axis_to_quat(a, phi, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an axis and angle, compute quaternion.
|
|
||||||
*/
|
|
||||||
void axis_to_quat(float a[3], float phi, float q[4]) {
|
|
||||||
vnormal(a);
|
|
||||||
vcopy(a, q);
|
|
||||||
vscale(q, sin(phi / 2.0));
|
|
||||||
q[3] = cos(phi / 2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
|
|
||||||
* if we are away from the center of the sphere.
|
|
||||||
*/
|
|
||||||
static float tb_project_to_sphere(float r, float x, float y) {
|
|
||||||
float d, t, z;
|
|
||||||
|
|
||||||
d = sqrt(x * x + y * y);
|
|
||||||
if (d < r * 0.70710678118654752440) { /* Inside sphere */
|
|
||||||
z = sqrt(r * r - d * d);
|
|
||||||
} else { /* On hyperbola */
|
|
||||||
t = r / 1.41421356237309504880;
|
|
||||||
z = t * t / d;
|
|
||||||
}
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given two rotations, e1 and e2, expressed as quaternion rotations,
|
|
||||||
* figure out the equivalent single rotation and stuff it into dest.
|
|
||||||
*
|
|
||||||
* This routine also normalizes the result every RENORMCOUNT times it is
|
|
||||||
* called, to keep error from creeping in.
|
|
||||||
*
|
|
||||||
* NOTE: This routine is written so that q1 or q2 may be the same
|
|
||||||
* as dest (or each other).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define RENORMCOUNT 97
|
|
||||||
|
|
||||||
void add_quats(float q1[4], float q2[4], float dest[4]) {
|
|
||||||
static int count = 0;
|
|
||||||
float t1[4], t2[4], t3[4];
|
|
||||||
float tf[4];
|
|
||||||
|
|
||||||
vcopy(q1, t1);
|
|
||||||
vscale(t1, q2[3]);
|
|
||||||
|
|
||||||
vcopy(q2, t2);
|
|
||||||
vscale(t2, q1[3]);
|
|
||||||
|
|
||||||
vcross(q2, q1, t3);
|
|
||||||
vadd(t1, t2, tf);
|
|
||||||
vadd(t3, tf, tf);
|
|
||||||
tf[3] = q1[3] * q2[3] - vdot(q1, q2);
|
|
||||||
|
|
||||||
dest[0] = tf[0];
|
|
||||||
dest[1] = tf[1];
|
|
||||||
dest[2] = tf[2];
|
|
||||||
dest[3] = tf[3];
|
|
||||||
|
|
||||||
if (++count > RENORMCOUNT) {
|
|
||||||
count = 0;
|
|
||||||
normalize_quat(dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0
|
|
||||||
* If they don't add up to 1.0, dividing by their magnitued will
|
|
||||||
* renormalize them.
|
|
||||||
*
|
|
||||||
* Note: See the following for more information on quaternions:
|
|
||||||
*
|
|
||||||
* - Shoemake, K., Animating rotation with quaternion curves, Computer
|
|
||||||
* Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
|
|
||||||
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
|
|
||||||
* graphics, The Visual Computer 5, 2-13, 1989.
|
|
||||||
*/
|
|
||||||
static void normalize_quat(float q[4]) {
|
|
||||||
int i;
|
|
||||||
float mag;
|
|
||||||
|
|
||||||
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
q[i] /= mag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build a rotation matrix, given a quaternion rotation.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void build_rotmatrix(float m[4][4], const float q[4]) {
|
|
||||||
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
|
|
||||||
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
|
|
||||||
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
|
|
||||||
m[0][3] = 0.0;
|
|
||||||
|
|
||||||
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
|
|
||||||
m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
|
|
||||||
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
|
|
||||||
m[1][3] = 0.0;
|
|
||||||
|
|
||||||
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
|
|
||||||
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
|
|
||||||
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
|
|
||||||
m[2][3] = 0.0;
|
|
||||||
|
|
||||||
m[3][0] = 0.0;
|
|
||||||
m[3][1] = 0.0;
|
|
||||||
m[3][2] = 0.0;
|
|
||||||
m[3][3] = 1.0;
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
|
||||||
* ALL RIGHTS RESERVED
|
|
||||||
* Permission to use, copy, modify, and distribute this software for
|
|
||||||
* any purpose and without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice appear in all copies and that both the copyright notice
|
|
||||||
* and this permission notice appear in supporting documentation, and that
|
|
||||||
* the name of Silicon Graphics, Inc. not be used in advertising
|
|
||||||
* or publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission.
|
|
||||||
*
|
|
||||||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
|
||||||
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
|
||||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
|
||||||
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
|
||||||
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
|
||||||
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
|
||||||
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
|
||||||
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
* US Government Users Restricted Rights
|
|
||||||
* Use, duplication, or disclosure by the Government is subject to
|
|
||||||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
|
||||||
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
|
||||||
* clause at DFARS 252.227-7013 and/or in similar or successor
|
|
||||||
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
|
||||||
* Unpublished-- rights reserved under the copyright laws of the
|
|
||||||
* United States. Contractor/manufacturer is Silicon Graphics,
|
|
||||||
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
|
||||||
*
|
|
||||||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* trackball.h
|
|
||||||
* A virtual trackball implementation
|
|
||||||
* Written by Gavin Bell for Silicon Graphics, November 1988.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pass the x and y coordinates of the last and current positions of
|
|
||||||
* the mouse, scaled so they are from (-1.0 ... 1.0).
|
|
||||||
*
|
|
||||||
* The resulting rotation is returned as a quaternion rotation in the
|
|
||||||
* first paramater.
|
|
||||||
*/
|
|
||||||
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
|
|
||||||
|
|
||||||
void negate_quat(float *q, float *qn);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given two quaternions, add them together to get a third quaternion.
|
|
||||||
* Adding quaternions to get a compound rotation is analagous to adding
|
|
||||||
* translations to get a compound translation. When incrementally
|
|
||||||
* adding rotations, the first argument here should be the new
|
|
||||||
* rotation, the second and third the total rotation (which will be
|
|
||||||
* over-written with the resulting new total rotation).
|
|
||||||
*/
|
|
||||||
void add_quats(float *q1, float *q2, float *dest);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A useful function, builds a rotation matrix in Matrix based on
|
|
||||||
* given quaternion.
|
|
||||||
*/
|
|
||||||
void build_rotmatrix(float m[4][4], const float q[4]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function computes a quaternion based on an axis (defined by
|
|
||||||
* the given vector) and an angle about which to rotate. The angle is
|
|
||||||
* expressed in radians. The result is put into the third argument.
|
|
||||||
*/
|
|
||||||
void axis_to_quat(float a[3], float phi, float q[4]);
|
|
446
tiny_gltf.h
446
tiny_gltf.h
@ -26,6 +26,7 @@
|
|||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
// Version:
|
// Version:
|
||||||
|
// - v2.0.1 Add comparsion feature(Thanks to @Selmar).
|
||||||
// - v2.0.0 glTF 2.0!.
|
// - v2.0.0 glTF 2.0!.
|
||||||
//
|
//
|
||||||
// Tiny glTF loader is using following third party libraries:
|
// Tiny glTF loader is using following third party libraries:
|
||||||
@ -40,6 +41,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -134,6 +136,9 @@ namespace tinygltf {
|
|||||||
#define TINYGLTF_SHADER_TYPE_VERTEX_SHADER (35633)
|
#define TINYGLTF_SHADER_TYPE_VERTEX_SHADER (35633)
|
||||||
#define TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER (35632)
|
#define TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER (35632)
|
||||||
|
|
||||||
|
#define TINYGLTF_DOUBLE_EPS (1.e-12)
|
||||||
|
#define TINYGLTF_DOUBLE_EQUAL(a, b) (std::fabs((b) - (a)) < TINYGLTF_DOUBLE_EPS)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NULL_TYPE = 0,
|
NULL_TYPE = 0,
|
||||||
NUMBER_TYPE = 1,
|
NUMBER_TYPE = 1,
|
||||||
@ -190,9 +195,8 @@ static inline int32_t GetTypeSizeInBytes(uint32_t ty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsDataURI(const std::string &in);
|
bool IsDataURI(const std::string &in);
|
||||||
bool DecodeDataURI(std::vector<unsigned char> *out,
|
bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
|
||||||
std::string &mime_type, const std::string &in,
|
const std::string &in, size_t reqBytes, bool checkSize);
|
||||||
size_t reqBytes, bool checkSize);
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@ -294,6 +298,8 @@ class Value {
|
|||||||
|
|
||||||
size_t Size() const { return (IsArray() ? ArrayLen() : Keys().size()); }
|
size_t Size() const { return (IsArray() ? ArrayLen() : Keys().size()); }
|
||||||
|
|
||||||
|
bool operator==(const tinygltf::Value &other) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int type_;
|
int type_;
|
||||||
|
|
||||||
@ -338,12 +344,12 @@ TINYGLTF_VALUE_GET(Value::Object, object_value_)
|
|||||||
using ColorValue = std::array<double, 4>;
|
using ColorValue = std::array<double, 4>;
|
||||||
|
|
||||||
struct Parameter {
|
struct Parameter {
|
||||||
bool bool_value;
|
bool bool_value = false;
|
||||||
bool has_number_value = false;
|
bool has_number_value = false;
|
||||||
std::string string_value;
|
std::string string_value;
|
||||||
std::vector<double> number_array;
|
std::vector<double> number_array;
|
||||||
std::map<std::string, double> json_double_value;
|
std::map<std::string, double> json_double_value;
|
||||||
double number_value;
|
double number_value = 0.0;
|
||||||
// context sensitive methods. depending the type of the Parameter you are
|
// context sensitive methods. depending the type of the Parameter you are
|
||||||
// accessing, these are either valid or not
|
// accessing, these are either valid or not
|
||||||
// If this parameter represent a texture map in a material, will return the
|
// If this parameter represent a texture map in a material, will return the
|
||||||
@ -374,6 +380,8 @@ struct Parameter {
|
|||||||
number_array[0], number_array[1], number_array[2],
|
number_array[0], number_array[1], number_array[2],
|
||||||
(number_array.size() > 3 ? number_array[3] : 1.0)}};
|
(number_array.size() > 3 ? number_array[3] : 1.0)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const Parameter &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@ -396,6 +404,7 @@ struct AnimationChannel {
|
|||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
AnimationChannel() : sampler(-1), target_node(-1) {}
|
AnimationChannel() : sampler(-1), target_node(-1) {}
|
||||||
|
bool operator==(const AnimationChannel &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationSampler {
|
struct AnimationSampler {
|
||||||
@ -406,6 +415,7 @@ struct AnimationSampler {
|
|||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
AnimationSampler() : input(-1), output(-1), interpolation("LINEAR") {}
|
AnimationSampler() : input(-1), output(-1), interpolation("LINEAR") {}
|
||||||
|
bool operator==(const AnimationSampler &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Animation {
|
struct Animation {
|
||||||
@ -413,6 +423,8 @@ struct Animation {
|
|||||||
std::vector<AnimationChannel> channels;
|
std::vector<AnimationChannel> channels;
|
||||||
std::vector<AnimationSampler> samplers;
|
std::vector<AnimationSampler> samplers;
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Animation &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Skin {
|
struct Skin {
|
||||||
@ -425,6 +437,7 @@ struct Skin {
|
|||||||
inverseBindMatrices = -1;
|
inverseBindMatrices = -1;
|
||||||
skeleton = -1;
|
skeleton = -1;
|
||||||
}
|
}
|
||||||
|
bool operator==(const Skin &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sampler {
|
struct Sampler {
|
||||||
@ -443,6 +456,7 @@ struct Sampler {
|
|||||||
Sampler()
|
Sampler()
|
||||||
: wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
: wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
||||||
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
||||||
|
bool operator==(const Sampler &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Image {
|
struct Image {
|
||||||
@ -458,25 +472,33 @@ struct Image {
|
|||||||
Value extras;
|
Value extras;
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
|
|
||||||
// When this flag is true, data is stored to `image` in as-is format(e.g. jpeg compressed for "image/jpeg" mime)
|
// When this flag is true, data is stored to `image` in as-is format(e.g. jpeg
|
||||||
// This feature is good if you use custom image loader function.
|
// compressed for "image/jpeg" mime) This feature is good if you use custom
|
||||||
// (e.g. delayed decoding of images for faster glTF parsing)
|
// image loader function. (e.g. delayed decoding of images for faster glTF
|
||||||
// Default parser for Image does not provide as-is loading feature at the moment.
|
// parsing) Default parser for Image does not provide as-is loading feature at
|
||||||
// (You can manipulate this by providing your own LoadImageData function)
|
// the moment. (You can manipulate this by providing your own LoadImageData
|
||||||
bool as_is;
|
// function)
|
||||||
|
bool as_is;
|
||||||
|
|
||||||
Image() : as_is(false) { bufferView = -1; }
|
Image() : as_is(false) {
|
||||||
|
bufferView = -1;
|
||||||
|
width = -1;
|
||||||
|
height = -1;
|
||||||
|
component = -1;
|
||||||
|
}
|
||||||
|
bool operator==(const Image &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture {
|
struct Texture {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
int sampler;
|
int sampler;
|
||||||
int source; // Required (not specified in the spec ?)
|
int source;
|
||||||
Value extras;
|
Value extras;
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
|
|
||||||
Texture() : sampler(-1), source(-1) {}
|
Texture() : sampler(-1), source(-1) {}
|
||||||
|
bool operator==(const Texture &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Each extension should be stored in a ParameterMap.
|
// Each extension should be stored in a ParameterMap.
|
||||||
@ -490,6 +512,8 @@ struct Material {
|
|||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Material &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BufferView {
|
struct BufferView {
|
||||||
@ -503,6 +527,7 @@ struct BufferView {
|
|||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
BufferView() : byteOffset(0), byteStride(0) {}
|
BufferView() : byteOffset(0), byteStride(0) {}
|
||||||
|
bool operator==(const BufferView &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Accessor {
|
struct Accessor {
|
||||||
@ -559,32 +584,35 @@ struct Accessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Accessor() { bufferView = -1; }
|
Accessor() { bufferView = -1; }
|
||||||
|
bool operator==(const tinygltf::Accessor &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PerspectiveCamera {
|
struct PerspectiveCamera {
|
||||||
float aspectRatio; // min > 0
|
double aspectRatio; // min > 0
|
||||||
float yfov; // required. min > 0
|
double yfov; // required. min > 0
|
||||||
float zfar; // min > 0
|
double zfar; // min > 0
|
||||||
float znear; // required. min > 0
|
double znear; // required. min > 0
|
||||||
|
|
||||||
PerspectiveCamera()
|
PerspectiveCamera()
|
||||||
: aspectRatio(0.0f),
|
: aspectRatio(0.0),
|
||||||
yfov(0.0f),
|
yfov(0.0),
|
||||||
zfar(0.0f) // 0 = use infinite projecton matrix
|
zfar(0.0) // 0 = use infinite projecton matrix
|
||||||
,
|
,
|
||||||
znear(0.0f) {}
|
znear(0.0) {}
|
||||||
|
bool operator==(const PerspectiveCamera &) const;
|
||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OrthographicCamera {
|
struct OrthographicCamera {
|
||||||
float xmag; // required. must not be zero.
|
double xmag; // required. must not be zero.
|
||||||
float ymag; // required. must not be zero.
|
double ymag; // required. must not be zero.
|
||||||
float zfar; // required. `zfar` must be greater than `znear`.
|
double zfar; // required. `zfar` must be greater than `znear`.
|
||||||
float znear; // required
|
double znear; // required
|
||||||
|
|
||||||
OrthographicCamera() : xmag(0.0f), ymag(0.0f), zfar(0.0f), znear(0.0f) {}
|
OrthographicCamera() : xmag(0.0), ymag(0.0), zfar(0.0), znear(0.0) {}
|
||||||
|
bool operator==(const OrthographicCamera &) const;
|
||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
@ -598,6 +626,7 @@ struct Camera {
|
|||||||
OrthographicCamera orthographic;
|
OrthographicCamera orthographic;
|
||||||
|
|
||||||
Camera() {}
|
Camera() {}
|
||||||
|
bool operator==(const Camera &) const;
|
||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
@ -612,7 +641,7 @@ struct Primitive {
|
|||||||
// when rendering.
|
// when rendering.
|
||||||
int indices; // The index of the accessor that contains the indices.
|
int indices; // The index of the accessor that contains the indices.
|
||||||
int mode; // one of TINYGLTF_MODE_***
|
int mode; // one of TINYGLTF_MODE_***
|
||||||
std::vector<std::map<std::string, int>> targets; // array of morph targets,
|
std::vector<std::map<std::string, int> > targets; // array of morph targets,
|
||||||
// where each target is a dict with attribues in ["POSITION, "NORMAL",
|
// where each target is a dict with attribues in ["POSITION, "NORMAL",
|
||||||
// "TANGENT"] pointing
|
// "TANGENT"] pointing
|
||||||
// to their corresponding accessors
|
// to their corresponding accessors
|
||||||
@ -622,15 +651,18 @@ struct Primitive {
|
|||||||
material = -1;
|
material = -1;
|
||||||
indices = -1;
|
indices = -1;
|
||||||
}
|
}
|
||||||
|
bool operator==(const Primitive &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mesh {
|
struct Mesh {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<Primitive> primitives;
|
std::vector<Primitive> primitives;
|
||||||
std::vector<double> weights; // weights to be applied to the Morph Targets
|
std::vector<double> weights; // weights to be applied to the Morph Targets
|
||||||
std::vector<std::map<std::string, int>> targets;
|
std::vector<std::map<std::string, int> > targets;
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Mesh &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
@ -653,8 +685,8 @@ class Node {
|
|||||||
extensions = rhs.extensions;
|
extensions = rhs.extensions;
|
||||||
extras = rhs.extras;
|
extras = rhs.extras;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Node() {}
|
~Node() {}
|
||||||
|
bool operator==(const Node &) const;
|
||||||
|
|
||||||
int camera; // the index of the camera referenced by this node
|
int camera; // the index of the camera referenced by this node
|
||||||
|
|
||||||
@ -678,6 +710,8 @@ struct Buffer {
|
|||||||
std::string
|
std::string
|
||||||
uri; // considered as required here but not in the spec (need to clarify)
|
uri; // considered as required here but not in the spec (need to clarify)
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Buffer &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Asset {
|
struct Asset {
|
||||||
@ -687,6 +721,8 @@ struct Asset {
|
|||||||
std::string copyright;
|
std::string copyright;
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Asset &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Scene {
|
struct Scene {
|
||||||
@ -695,18 +731,23 @@ struct Scene {
|
|||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
|
bool operator==(const Scene &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Light {
|
struct Light {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<double> color;
|
std::vector<double> color;
|
||||||
std::string type;
|
std::string type;
|
||||||
|
|
||||||
|
bool operator==(const Light &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Model {
|
class Model {
|
||||||
public:
|
public:
|
||||||
Model() {}
|
Model() {}
|
||||||
~Model() {}
|
~Model() {}
|
||||||
|
bool operator==(const Model &) const;
|
||||||
|
|
||||||
std::vector<Accessor> accessors;
|
std::vector<Accessor> accessors;
|
||||||
std::vector<Animation> animations;
|
std::vector<Animation> animations;
|
||||||
@ -952,7 +993,7 @@ class TinyGLTF {
|
|||||||
|
|
||||||
#endif // TINY_GLTF_H_
|
#endif // TINY_GLTF_H_
|
||||||
|
|
||||||
#ifdef TINYGLTF_IMPLEMENTATION
|
#if defined(TINYGLTF_IMPLEMENTATION) || defined(__INTELLISENSE__)
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
//#include <cassert>
|
//#include <cassert>
|
||||||
#ifndef TINYGLTF_NO_FS
|
#ifndef TINYGLTF_NO_FS
|
||||||
@ -1045,6 +1086,220 @@ using nlohmann::json;
|
|||||||
|
|
||||||
namespace tinygltf {
|
namespace tinygltf {
|
||||||
|
|
||||||
|
// Equals function for Value, for recursivity
|
||||||
|
static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
|
||||||
|
if (one.Type() != other.Type()) return false;
|
||||||
|
|
||||||
|
switch (one.Type()) {
|
||||||
|
case NULL_TYPE:
|
||||||
|
return true;
|
||||||
|
case BOOL_TYPE:
|
||||||
|
return one.Get<bool>() == other.Get<bool>();
|
||||||
|
case NUMBER_TYPE:
|
||||||
|
return TINYGLTF_DOUBLE_EQUAL(one.Get<double>(), other.Get<double>());
|
||||||
|
case INT_TYPE:
|
||||||
|
return one.Get<int>() == other.Get<int>();
|
||||||
|
case OBJECT_TYPE: {
|
||||||
|
auto oneObj = one.Get<tinygltf::Value::Object>();
|
||||||
|
auto otherObj = other.Get<tinygltf::Value::Object>();
|
||||||
|
if (oneObj.size() != otherObj.size()) return false;
|
||||||
|
for (auto &it : oneObj) {
|
||||||
|
auto otherIt = otherObj.find(it.first);
|
||||||
|
if (otherIt == otherObj.end()) return false;
|
||||||
|
|
||||||
|
if (!Equals(it.second, otherIt->second)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ARRAY_TYPE: {
|
||||||
|
if (one.Size() != other.Size()) return false;
|
||||||
|
for (int i = 0; i < int(one.Size()); ++i)
|
||||||
|
if (Equals(one.Get(i), other.Get(i))) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case STRING_TYPE:
|
||||||
|
return one.Get<std::string>() == other.Get<std::string>();
|
||||||
|
case BINARY_TYPE:
|
||||||
|
return one.Get<std::vector<unsigned char> >() ==
|
||||||
|
other.Get<std::vector<unsigned char> >();
|
||||||
|
default: {
|
||||||
|
// unhandled type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals function for std::vector<double> using TINYGLTF_DOUBLE_EPSILON
|
||||||
|
static bool Equals(const std::vector<double> &one,
|
||||||
|
const std::vector<double> &other) {
|
||||||
|
if (one.size() != other.size()) return false;
|
||||||
|
for (int i = 0; i < int(one.size()); ++i) {
|
||||||
|
if (!TINYGLTF_DOUBLE_EQUAL(one[size_t(i)], other[size_t(i)])) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Accessor::operator==(const Accessor &other) const {
|
||||||
|
return this->bufferView == other.bufferView &&
|
||||||
|
this->byteOffset == other.byteOffset &&
|
||||||
|
this->componentType == other.componentType &&
|
||||||
|
this->count == other.count && this->extras == other.extras &&
|
||||||
|
Equals(this->maxValues, other.maxValues) &&
|
||||||
|
Equals(this->minValues, other.minValues) && this->name == other.name &&
|
||||||
|
this->normalized == other.normalized && this->type == other.type;
|
||||||
|
}
|
||||||
|
bool Animation::operator==(const Animation &other) const {
|
||||||
|
return this->channels == other.channels && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->samplers == other.samplers;
|
||||||
|
}
|
||||||
|
bool AnimationChannel::operator==(const AnimationChannel &other) const {
|
||||||
|
return this->extras == other.extras &&
|
||||||
|
this->target_node == other.target_node &&
|
||||||
|
this->target_path == other.target_path &&
|
||||||
|
this->sampler == other.sampler;
|
||||||
|
}
|
||||||
|
bool AnimationSampler::operator==(const AnimationSampler &other) const {
|
||||||
|
return this->extras == other.extras && this->input == other.input &&
|
||||||
|
this->interpolation == other.interpolation &&
|
||||||
|
this->output == other.output;
|
||||||
|
}
|
||||||
|
bool Asset::operator==(const Asset &other) const {
|
||||||
|
return this->copyright == other.copyright &&
|
||||||
|
this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
this->generator == other.generator &&
|
||||||
|
this->minVersion == other.minVersion && this->version == other.version;
|
||||||
|
}
|
||||||
|
bool Buffer::operator==(const Buffer &other) const {
|
||||||
|
return this->data == other.data && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->uri == other.uri;
|
||||||
|
}
|
||||||
|
bool BufferView::operator==(const BufferView &other) const {
|
||||||
|
return this->buffer == other.buffer && this->byteLength == other.byteLength &&
|
||||||
|
this->byteOffset == other.byteOffset &&
|
||||||
|
this->byteStride == other.byteStride && this->name == other.name &&
|
||||||
|
this->target == other.target && this->extras == other.extras;
|
||||||
|
}
|
||||||
|
bool Camera::operator==(const Camera &other) const {
|
||||||
|
return this->name == other.name && this->extensions == other.extensions &&
|
||||||
|
this->extras == other.extras &&
|
||||||
|
this->orthographic == other.orthographic &&
|
||||||
|
this->perspective == other.perspective && this->type == other.type;
|
||||||
|
}
|
||||||
|
bool Image::operator==(const Image &other) const {
|
||||||
|
return this->bufferView == other.bufferView &&
|
||||||
|
this->component == other.component && this->extras == other.extras &&
|
||||||
|
this->height == other.height && this->image == other.image &&
|
||||||
|
this->mimeType == other.mimeType && this->name == other.name &&
|
||||||
|
this->uri == other.uri && this->width == other.width;
|
||||||
|
}
|
||||||
|
bool Light::operator==(const Light &other) const {
|
||||||
|
return Equals(this->color, other.color) && this->name == other.name &&
|
||||||
|
this->type == other.type;
|
||||||
|
}
|
||||||
|
bool Material::operator==(const Material &other) const {
|
||||||
|
return this->additionalValues == other.additionalValues &&
|
||||||
|
this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->values == other.values;
|
||||||
|
}
|
||||||
|
bool Mesh::operator==(const Mesh &other) const {
|
||||||
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->primitives == other.primitives &&
|
||||||
|
this->targets == other.targets && Equals(this->weights, other.weights);
|
||||||
|
}
|
||||||
|
bool Model::operator==(const Model &other) const {
|
||||||
|
return this->accessors == other.accessors &&
|
||||||
|
this->animations == other.animations && this->asset == other.asset &&
|
||||||
|
this->buffers == other.buffers &&
|
||||||
|
this->bufferViews == other.bufferViews &&
|
||||||
|
this->cameras == other.cameras &&
|
||||||
|
this->defaultScene == other.defaultScene &&
|
||||||
|
this->extensions == other.extensions &&
|
||||||
|
this->extensionsRequired == other.extensionsRequired &&
|
||||||
|
this->extensionsUsed == other.extensionsUsed &&
|
||||||
|
this->extras == other.extras && this->images == other.images &&
|
||||||
|
this->lights == other.lights && this->materials == other.materials &&
|
||||||
|
this->meshes == other.meshes && this->nodes == other.nodes &&
|
||||||
|
this->samplers == other.samplers && this->scenes == other.scenes &&
|
||||||
|
this->skins == other.skins && this->textures == other.textures;
|
||||||
|
}
|
||||||
|
bool Node::operator==(const Node &other) const {
|
||||||
|
return this->camera == other.camera && this->children == other.children &&
|
||||||
|
this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
Equals(this->matrix, other.matrix) && this->mesh == other.mesh &&
|
||||||
|
this->name == other.name && Equals(this->rotation, other.rotation) &&
|
||||||
|
Equals(this->scale, other.scale) && this->skin == other.skin &&
|
||||||
|
Equals(this->translation, other.translation) &&
|
||||||
|
Equals(this->weights, other.weights);
|
||||||
|
}
|
||||||
|
bool OrthographicCamera::operator==(const OrthographicCamera &other) const {
|
||||||
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->xmag, other.xmag) &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->ymag, other.ymag) &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->zfar, other.zfar) &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->znear, other.znear);
|
||||||
|
}
|
||||||
|
bool Parameter::operator==(const Parameter &other) const {
|
||||||
|
if (this->bool_value != other.bool_value ||
|
||||||
|
this->has_number_value != other.has_number_value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TINYGLTF_DOUBLE_EQUAL(this->number_value, other.number_value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (this->json_double_value.size() != other.json_double_value.size())
|
||||||
|
return false;
|
||||||
|
for (auto &it : this->json_double_value) {
|
||||||
|
auto otherIt = other.json_double_value.find(it.first);
|
||||||
|
if (otherIt == other.json_double_value.end()) return false;
|
||||||
|
|
||||||
|
if (!TINYGLTF_DOUBLE_EQUAL(it.second, otherIt->second)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Equals(this->number_array, other.number_array)) return false;
|
||||||
|
|
||||||
|
if (this->string_value != other.string_value) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool PerspectiveCamera::operator==(const PerspectiveCamera &other) const {
|
||||||
|
return TINYGLTF_DOUBLE_EQUAL(this->aspectRatio, other.aspectRatio) &&
|
||||||
|
this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->yfov, other.yfov) &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->zfar, other.zfar) &&
|
||||||
|
TINYGLTF_DOUBLE_EQUAL(this->znear, other.znear);
|
||||||
|
}
|
||||||
|
bool Primitive::operator==(const Primitive &other) const {
|
||||||
|
return this->attributes == other.attributes && this->extras == other.extras &&
|
||||||
|
this->indices == other.indices && this->material == other.material &&
|
||||||
|
this->mode == other.mode && this->targets == other.targets;
|
||||||
|
}
|
||||||
|
bool Sampler::operator==(const Sampler &other) const {
|
||||||
|
return this->extras == other.extras && this->magFilter == other.magFilter &&
|
||||||
|
this->minFilter == other.minFilter && this->name == other.name &&
|
||||||
|
this->wrapR == other.wrapR && this->wrapS == other.wrapS &&
|
||||||
|
this->wrapT == other.wrapT;
|
||||||
|
}
|
||||||
|
bool Scene::operator==(const Scene &other) const {
|
||||||
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->nodes == other.nodes;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
bool Skin::operator==(const Skin &other) const {
|
||||||
|
return this->inverseBindMatrices == other.inverseBindMatrices &&
|
||||||
|
this->joints == other.joints && this->name == other.name &&
|
||||||
|
this->skeleton == other.skeleton;
|
||||||
|
}
|
||||||
|
bool Texture::operator==(const Texture &other) const {
|
||||||
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
|
this->name == other.name && this->sampler == other.sampler &&
|
||||||
|
this->source == other.source;
|
||||||
|
}
|
||||||
|
bool Value::operator==(const Value &other) const {
|
||||||
|
return Equals(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
static void swap4(unsigned int *val) {
|
static void swap4(unsigned int *val) {
|
||||||
#ifdef TINYGLTF_LITTLE_ENDIAN
|
#ifdef TINYGLTF_LITTLE_ENDIAN
|
||||||
(void)val;
|
(void)val;
|
||||||
@ -1248,8 +1503,8 @@ std::string base64_decode(std::string const &encoded_string) {
|
|||||||
|
|
||||||
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||||
std::string *warn, const std::string &filename,
|
std::string *warn, const std::string &filename,
|
||||||
const std::string &basedir, bool required, size_t reqBytes,
|
const std::string &basedir, bool required,
|
||||||
bool checkSize, FsCallbacks *fs) {
|
size_t reqBytes, bool checkSize, FsCallbacks *fs) {
|
||||||
if (fs == nullptr || fs->FileExists == nullptr ||
|
if (fs == nullptr || fs->FileExists == nullptr ||
|
||||||
fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
|
fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
|
||||||
// This is a developer error, assert() ?
|
// This is a developer error, assert() ?
|
||||||
@ -1259,7 +1514,7 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string* failMsgOut = required ? err : warn;
|
std::string *failMsgOut = required ? err : warn;
|
||||||
|
|
||||||
out->clear();
|
out->clear();
|
||||||
|
|
||||||
@ -1281,16 +1536,17 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
|||||||
fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
|
fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
|
||||||
if (!fileRead) {
|
if (!fileRead) {
|
||||||
if (failMsgOut) {
|
if (failMsgOut) {
|
||||||
(*failMsgOut) += "File read error : " + filepath + " : " + fileReadErr + "\n";
|
(*failMsgOut) +=
|
||||||
|
"File read error : " + filepath + " : " + fileReadErr + "\n";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sz = buf.size();
|
size_t sz = buf.size();
|
||||||
if (sz == 0) {
|
if (sz == 0) {
|
||||||
if(failMsgOut) {
|
if (failMsgOut) {
|
||||||
(*failMsgOut) += "File is empty : " + filepath + "\n";
|
(*failMsgOut) += "File is empty : " + filepath + "\n";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1325,18 +1581,19 @@ bool LoadImageData(Image *image, std::string *err, std::string *warn,
|
|||||||
(void)warn;
|
(void)warn;
|
||||||
|
|
||||||
int w, h, comp, req_comp;
|
int w, h, comp, req_comp;
|
||||||
|
|
||||||
// force 32-bit textures for common Vulkan compatibility. It appears that
|
// force 32-bit textures for common Vulkan compatibility. It appears that
|
||||||
// some GPU drivers do not support 24-bit images for Vulkan
|
// some GPU drivers do not support 24-bit images for Vulkan
|
||||||
req_comp = 4;
|
req_comp = 4;
|
||||||
|
|
||||||
// if image cannot be decoded, ignore parsing and keep it by its path
|
// if image cannot be decoded, ignore parsing and keep it by its path
|
||||||
// don't break in this case
|
// don't break in this case
|
||||||
// FIXME we should only enter this function if the image is embedded. If
|
// FIXME we should only enter this function if the image is embedded. If
|
||||||
// image->uri references
|
// image->uri references
|
||||||
// an image file, it should be left as it is. Image loading should not be
|
// an image file, it should be left as it is. Image loading should not be
|
||||||
// mandatory (to support other formats)
|
// mandatory (to support other formats)
|
||||||
unsigned char *data = stbi_load_from_memory(bytes, size, &w, &h, &comp, req_comp);
|
unsigned char *data =
|
||||||
|
stbi_load_from_memory(bytes, size, &w, &h, &comp, req_comp);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// NOTE: you can use `warn` instead of `err`
|
// NOTE: you can use `warn` instead of `err`
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -1409,18 +1666,25 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
|
|||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
|
|
||||||
if (ext == "png") {
|
if (ext == "png") {
|
||||||
stbi_write_png_to_func(WriteToMemory_stbi, &data, image->width,
|
if (!stbi_write_png_to_func(WriteToMemory_stbi, &data, image->width,
|
||||||
image->height, image->component, &image->image[0],
|
image->height, image->component,
|
||||||
0);
|
&image->image[0], 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
header = "data:image/png;base64,";
|
header = "data:image/png;base64,";
|
||||||
} else if (ext == "jpg") {
|
} else if (ext == "jpg") {
|
||||||
stbi_write_jpg_to_func(WriteToMemory_stbi, &data, image->width,
|
if (!stbi_write_jpg_to_func(WriteToMemory_stbi, &data, image->width,
|
||||||
image->height, image->component, &image->image[0],
|
image->height, image->component,
|
||||||
100);
|
&image->image[0], 100)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
header = "data:image/jpeg;base64,";
|
header = "data:image/jpeg;base64,";
|
||||||
} else if (ext == "bmp") {
|
} else if (ext == "bmp") {
|
||||||
stbi_write_bmp_to_func(WriteToMemory_stbi, &data, image->width,
|
if (!stbi_write_bmp_to_func(WriteToMemory_stbi, &data, image->width,
|
||||||
image->height, image->component, &image->image[0]);
|
image->height, image->component,
|
||||||
|
&image->image[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
header = "data:image/bmp;base64,";
|
header = "data:image/bmp;base64,";
|
||||||
} else if (!embedImages) {
|
} else if (!embedImages) {
|
||||||
// Error: can't output requested format to file
|
// Error: can't output requested format to file
|
||||||
@ -1445,6 +1709,7 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
|
|||||||
if (!fs->WriteWholeFile(&writeError, imagefilepath, data,
|
if (!fs->WriteWholeFile(&writeError, imagefilepath, data,
|
||||||
fs->user_data)) {
|
fs->user_data)) {
|
||||||
// Could not write image file to disc; Throw error ?
|
// Could not write image file to disc; Throw error ?
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Throw error?
|
// Throw error?
|
||||||
@ -1671,9 +1936,8 @@ bool IsDataURI(const std::string &in) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecodeDataURI(std::vector<unsigned char> *out,
|
bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
|
||||||
std::string &mime_type, const std::string &in,
|
const std::string &in, size_t reqBytes, bool checkSize) {
|
||||||
size_t reqBytes, bool checkSize) {
|
|
||||||
std::string header = "data:application/octet-stream;base64,";
|
std::string header = "data:application/octet-stream;base64,";
|
||||||
std::string data;
|
std::string data;
|
||||||
if (in.find(header) == 0) {
|
if (in.find(header) == 0) {
|
||||||
@ -2135,6 +2399,7 @@ static bool ParseImage(Image *image, std::string *err, std::string *warn,
|
|||||||
|
|
||||||
ParseStringProperty(&image->name, err, o, "name", false);
|
ParseStringProperty(&image->name, err, o, "name", false);
|
||||||
ParseExtensionsProperty(&image->extensions, err, o);
|
ParseExtensionsProperty(&image->extensions, err, o);
|
||||||
|
ParseExtrasProperty(&image->extras, o);
|
||||||
|
|
||||||
if (hasBufferView) {
|
if (hasBufferView) {
|
||||||
double bufferView = -1;
|
double bufferView = -1;
|
||||||
@ -2285,8 +2550,8 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// External .bin file.
|
// External .bin file.
|
||||||
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, buffer->uri,
|
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr,
|
||||||
basedir, true, bytes, true, fs)) {
|
buffer->uri, basedir, true, bytes, true, fs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2837,10 +3102,10 @@ static bool ParsePerspectiveCamera(PerspectiveCamera *camera, std::string *err,
|
|||||||
double zfar = 0.0; // = invalid
|
double zfar = 0.0; // = invalid
|
||||||
ParseNumberProperty(&zfar, err, o, "zfar", false, "PerspectiveCamera");
|
ParseNumberProperty(&zfar, err, o, "zfar", false, "PerspectiveCamera");
|
||||||
|
|
||||||
camera->aspectRatio = float(aspectRatio);
|
camera->aspectRatio = aspectRatio;
|
||||||
camera->zfar = float(zfar);
|
camera->zfar = zfar;
|
||||||
camera->yfov = float(yfov);
|
camera->yfov = yfov;
|
||||||
camera->znear = float(znear);
|
camera->znear = znear;
|
||||||
|
|
||||||
ParseExtensionsProperty(&camera->extensions, err, o);
|
ParseExtensionsProperty(&camera->extensions, err, o);
|
||||||
ParseExtrasProperty(&(camera->extras), o);
|
ParseExtrasProperty(&(camera->extras), o);
|
||||||
@ -2876,10 +3141,10 @@ static bool ParseOrthographicCamera(OrthographicCamera *camera,
|
|||||||
ParseExtensionsProperty(&camera->extensions, err, o);
|
ParseExtensionsProperty(&camera->extensions, err, o);
|
||||||
ParseExtrasProperty(&(camera->extras), o);
|
ParseExtrasProperty(&(camera->extras), o);
|
||||||
|
|
||||||
camera->xmag = float(xmag);
|
camera->xmag = xmag;
|
||||||
camera->ymag = float(ymag);
|
camera->ymag = ymag;
|
||||||
camera->zfar = float(zfar);
|
camera->zfar = zfar;
|
||||||
camera->znear = float(znear);
|
camera->znear = znear;
|
||||||
|
|
||||||
// TODO(syoyo): Validate parameter values.
|
// TODO(syoyo): Validate parameter values.
|
||||||
|
|
||||||
@ -3891,6 +4156,7 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerializeStringProperty("type", type, o);
|
SerializeStringProperty("type", type, o);
|
||||||
|
if (!accessor.name.empty()) SerializeStringProperty("name", accessor.name, o);
|
||||||
|
|
||||||
if (accessor.extras.Type() != NULL_TYPE) {
|
if (accessor.extras.Type() != NULL_TYPE) {
|
||||||
SerializeValue("extras", accessor.extras, o);
|
SerializeValue("extras", accessor.extras, o);
|
||||||
@ -3921,7 +4187,8 @@ static void SerializeGltfAnimationSampler(AnimationSampler &sampler, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfAnimation(Animation &animation, json &o) {
|
static void SerializeGltfAnimation(Animation &animation, json &o) {
|
||||||
SerializeStringProperty("name", animation.name, o);
|
if (!animation.name.empty())
|
||||||
|
SerializeStringProperty("name", animation.name, o);
|
||||||
json channels;
|
json channels;
|
||||||
for (unsigned int i = 0; i < animation.channels.size(); ++i) {
|
for (unsigned int i = 0; i < animation.channels.size(); ++i) {
|
||||||
json channel;
|
json channel;
|
||||||
@ -4112,7 +4379,7 @@ static void SerializeGltfMesh(Mesh &mesh, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfLight(Light &light, json &o) {
|
static void SerializeGltfLight(Light &light, json &o) {
|
||||||
SerializeStringProperty("name", light.name, o);
|
if (!light.name.empty()) SerializeStringProperty("name", light.name, o);
|
||||||
SerializeNumberArrayProperty("color", light.color, o);
|
SerializeNumberArrayProperty("color", light.color, o);
|
||||||
SerializeStringProperty("type", light.type, o);
|
SerializeStringProperty("type", light.type, o);
|
||||||
}
|
}
|
||||||
@ -4147,7 +4414,7 @@ static void SerializeGltfNode(Node &node, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerializeExtensionMap(node.extensions, o);
|
SerializeExtensionMap(node.extensions, o);
|
||||||
SerializeStringProperty("name", node.name, o);
|
if (!node.name.empty()) SerializeStringProperty("name", node.name, o);
|
||||||
SerializeNumberArrayProperty<int>("children", node.children, o);
|
SerializeNumberArrayProperty<int>("children", node.children, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4237,18 +4504,21 @@ static void SerializeGltfTexture(Texture &texture, json &o) {
|
|||||||
if (texture.sampler > -1) {
|
if (texture.sampler > -1) {
|
||||||
SerializeNumberProperty("sampler", texture.sampler, o);
|
SerializeNumberProperty("sampler", texture.sampler, o);
|
||||||
}
|
}
|
||||||
SerializeNumberProperty("source", texture.source, o);
|
if (texture.source > -1) {
|
||||||
|
SerializeNumberProperty("source", texture.source, o);
|
||||||
|
}
|
||||||
if (texture.extras.Type() != NULL_TYPE) {
|
if (texture.extras.Type() != NULL_TYPE) {
|
||||||
SerializeValue("extras", texture.extras, o);
|
SerializeValue("extras", texture.extras, o);
|
||||||
}
|
}
|
||||||
SerializeExtensionMap(texture.extensions, o);
|
SerializeExtensionMap(texture.extensions, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteGltfFile(const std::string &output,
|
static bool WriteGltfFile(const std::string &output,
|
||||||
const std::string &content) {
|
const std::string &content) {
|
||||||
std::ofstream gltfFile(output.c_str());
|
std::ofstream gltfFile(output.c_str());
|
||||||
|
if (!gltfFile.is_open()) return false;
|
||||||
gltfFile << content << std::endl;
|
gltfFile << content << std::endl;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
||||||
@ -4284,31 +4554,50 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
|||||||
SerializeGltfAsset(model->asset, asset);
|
SerializeGltfAsset(model->asset, asset);
|
||||||
output["asset"] = asset;
|
output["asset"] = asset;
|
||||||
|
|
||||||
std::string binFilename = GetBaseFilename(filename);
|
std::string defaultBinFilename = GetBaseFilename(filename);
|
||||||
std::string ext = ".bin";
|
std::string defaultBinFileExt = ".bin";
|
||||||
std::string::size_type pos = binFilename.rfind('.', binFilename.length());
|
std::string::size_type pos = defaultBinFilename.rfind('.', defaultBinFilename.length());
|
||||||
|
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
binFilename = binFilename.substr(0, pos) + ext;
|
defaultBinFilename = defaultBinFilename.substr(0, pos);
|
||||||
} else {
|
|
||||||
binFilename = binFilename + ".bin";
|
|
||||||
}
|
}
|
||||||
std::string baseDir = GetBaseDir(filename);
|
std::string baseDir = GetBaseDir(filename);
|
||||||
if (baseDir.empty()) {
|
if (baseDir.empty()) {
|
||||||
baseDir = "./";
|
baseDir = "./";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string binSaveFilePath = JoinPath(baseDir, binFilename);
|
// BUFFERS
|
||||||
|
std::vector<std::string> usedUris;
|
||||||
// BUFFERS (We expect only one buffer here)
|
|
||||||
json buffers;
|
json buffers;
|
||||||
for (unsigned int i = 0; i < model->buffers.size(); ++i) {
|
for (unsigned int i = 0; i < model->buffers.size(); ++i) {
|
||||||
json buffer;
|
json buffer;
|
||||||
if (embedBuffers) {
|
if (embedBuffers) {
|
||||||
SerializeGltfBuffer(model->buffers[i], buffer);
|
SerializeGltfBuffer(model->buffers[i], buffer);
|
||||||
} else {
|
} else {
|
||||||
SerializeGltfBuffer(model->buffers[i], buffer, binSaveFilePath,
|
std::string binSavePath;
|
||||||
binFilename);
|
std::string binUri;
|
||||||
|
if (!model->buffers[i].uri.empty()
|
||||||
|
&& !IsDataURI(model->buffers[i].uri)) {
|
||||||
|
binUri = model->buffers[i].uri;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
binUri = defaultBinFilename + defaultBinFileExt;
|
||||||
|
bool inUse = true;
|
||||||
|
int numUsed = 0;
|
||||||
|
while(inUse) {
|
||||||
|
inUse = false;
|
||||||
|
for (const std::string& usedName : usedUris) {
|
||||||
|
if (binUri.compare(usedName) != 0) continue;
|
||||||
|
inUse = true;
|
||||||
|
binUri = defaultBinFilename + std::to_string(numUsed++) + defaultBinFileExt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usedUris.push_back(binUri);
|
||||||
|
binSavePath = JoinPath(baseDir, binUri);
|
||||||
|
SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
|
||||||
|
binUri);
|
||||||
}
|
}
|
||||||
buffers.push_back(buffer);
|
buffers.push_back(buffer);
|
||||||
}
|
}
|
||||||
@ -4471,8 +4760,7 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
|||||||
SerializeValue("extras", model->extras, output);
|
SerializeValue("extras", model->extras, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteGltfFile(filename, output.dump());
|
return WriteGltfFile(filename, output.dump());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tinygltf
|
} // namespace tinygltf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user