Compare commits

...

11 Commits

Author SHA1 Message Date
Syoyo Fujita
58ceed1d89 Add CMake file and Makefile for examples/build-gltf 2021-02-26 18:34:00 +09:00
Dov Grobgeld
d1b6b3a5aa Add example for creating a triangle gltf file from scratch 2021-02-26 09:30:05 +02:00
Syoyo Fujita
c56d069726 Merge pull request #306 from mahiuchun/const
Drop an unnecessary 'const'.
2021-02-21 16:07:51 +09:00
Hill Ma
d1e32865f1 Drop an unnecessary 'const'. 2021-02-20 22:30:44 -08:00
Syoyo Fujita
869a9d273c Merge pull request #305 from Selmar/patch-2
check correct `extensionsUsed` for serialization
2021-02-02 14:17:34 +09:00
Selmar
1208f057d6 check correct extensionsUsed for serialization 2021-02-01 19:24:41 +01:00
Syoyo Fujita
f684dde9f1 Merge pull request #303 from syoyo/int-minmax-serialize
Issue #301. Serialize accessor min/vax value as int
2021-01-22 03:40:52 +09:00
Syoyo Fujita
7905a5b4dc Issue #301. Serialize accessor min/vax value as int if its component type is an integer. 2021-01-21 20:33:11 +09:00
Syoyo Fujita
f161782001 Merge pull request #299 from DethRaid/patch-1
Add my project to the README
2020-12-23 15:46:32 +09:00
David Dubois
654bcf733c Add my project to the README
My personal project uses tinygltf so i want to add it to the "Projects using TinyGLTF" section of the README
2020-12-22 22:32:59 -08:00
Syoyo Fujita
2c521b3432 Remove sampler.wrapR parameter(unused tinygltf extension). Fixes #287
Suppress clang `-Wdocumentation-unknown-command` warning.
2020-12-04 00:50:46 +09:00
6 changed files with 193 additions and 33 deletions

View File

@@ -6,7 +6,8 @@ SET(CMAKE_CXX_STANDARD 11)
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example" ON)
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF)
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator example" OFF)
option(TINYGLTF_BUILD_BUILDER_EXAMPLE "Build glTF builder example" OFF)
if (TINYGLTF_BUILD_LOADER_EXAMPLE)
ADD_EXECUTABLE ( loader_example
@@ -22,6 +23,11 @@ endif (TINYGLTF_BUILD_GL_EXAMPLES)
if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
ADD_SUBDIRECTORY ( examples/validator )
endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
if (TINYGLTF_BUILD_BUILDER_EXAMPLE)
ADD_SUBDIRECTORY ( examples/build-gltf )
endif (TINYGLTF_BUILD_BUILDER_EXAMPLE)
#
# TinuGLTF is a header-only library, so no library build. just install header files.
#

View File

@@ -77,6 +77,7 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [glview](examples/glview) : Simple glTF geometry viewer.
* [validator](examples/validator) : Simple glTF validator with JSON schema.
* [basic](examples/basic) : Basic glTF viewer with texturing support.
* [build-gltf](examples/build-gltf) : Build simple glTF scene from a scratch.
## Projects using TinyGLTF
@@ -90,6 +91,7 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [GlslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - live GLSL coding for MacOS and Linux
* [Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples) - The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications.
* [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11
* [SanityEngine](https://github.com/DethRaid/SanityEngine) - A C++/D3D12 renderer focused on the personal and proessional development of its developer
* Your projects here! (Please send PR)
## TODOs

View File

@@ -0,0 +1,2 @@
all:
$(CXX) -o create_triangle_gltf -I../../ create_triangle_gltf.cpp

View File

@@ -0,0 +1,121 @@
// An example of how to generate a gltf file from scratch. This example
// was translated from the pygltlib documentation in the pypi project page,
// which in turn is based on the Khronos Sample Models at:
//
// https://github.com/KhronosGroup/glTF-Sample-Models
//
// This example is released under the MIT license.
//
// 2021-02-25 Thu
// Dov Grobgeld <dov.grobgeld@gmail.com>
// Define these only in *one* .cc file.
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
#include "tiny_gltf.h"
int main(int argc, char **argv)
{
// Create a model with a single mesh and save it as a gltf file
tinygltf::Model m;
tinygltf::Scene scene;
tinygltf::Mesh mesh;
tinygltf::Primitive primitive;
tinygltf::Node node;
tinygltf::Buffer buffer;
tinygltf::BufferView bufferView1;
tinygltf::BufferView bufferView2;
tinygltf::Accessor accessor1;
tinygltf::Accessor accessor2;
tinygltf::Asset asset;
// This is the raw data buffer.
buffer.data = {
// 6 bytes of indices and two bytes of padding
0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,
// 36 bytes of floating point numbers
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
0x00,0x00,0x00,0x00};
// "The indices of the vertices (ELEMENT_ARRAY_BUFFER) take up 6 bytes in the
// start of the buffer.
bufferView1.buffer = 0;
bufferView1.byteOffset=0;
bufferView1.byteLength=6;
bufferView1.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
// The vertices take up 36 bytes (3 vertices * 3 floating points * 4 bytes)
// at position 8 in the buffer and are of type ARRAY_BUFFER
bufferView2.buffer = 0;
bufferView2.byteOffset=8;
bufferView2.byteLength=36;
bufferView2.target = TINYGLTF_TARGET_ARRAY_BUFFER;
// Describe the layout of bufferView1, the indices of the vertices
accessor1.bufferView = 0;
accessor1.byteOffset = 0;
accessor1.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
accessor1.count = 3;
accessor1.type = TINYGLTF_TYPE_SCALAR;
accessor1.maxValues.push_back(2);
accessor1.minValues.push_back(0);
// Describe the layout of bufferView2, the vertices themself
accessor2.bufferView = 1;
accessor2.byteOffset = 0;
accessor2.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
accessor2.count = 3;
accessor2.type = TINYGLTF_TYPE_VEC3;
accessor2.maxValues = {1.0, 1.0, 0.0};
accessor2.minValues = {0.0, 0.0, 0.0};
// Build the mesh primitive and add it to the mesh
primitive.indices = 0; // The index of the accessor for the vertex indices
primitive.attributes["POSITION"] = 1; // The index of the accessor for positions
primitive.material = 0;
primitive.mode = TINYGLTF_MODE_TRIANGLES;
mesh.primitives.push_back(primitive);
// Other tie ups
node.mesh = 0;
scene.nodes.push_back(0); // Default scene
// Define the asset. The version is required
asset.version = "2.0";
asset.generator = "tinygltf";
// Now all that remains is to tie back all the loose objects into the
// our single model.
m.scenes.push_back(scene);
m.meshes.push_back(mesh);
m.nodes.push_back(node);
m.buffers.push_back(buffer);
m.bufferViews.push_back(bufferView1);
m.bufferViews.push_back(bufferView2);
m.accessors.push_back(accessor1);
m.accessors.push_back(accessor2);
m.asset = asset;
// Create a simple material
tinygltf::Material mat;
mat.pbrMetallicRoughness.baseColorFactor = {1.0f, 0.9f, 0.9f, 1.0f};
mat.doubleSided = true;
m.materials.push_back(mat);
// Save it to a file
tinygltf::TinyGLTF gltf;
gltf.WriteGltfSceneToFile(&m, "triangle.gltf",
true, // embedImages
true, // embedBuffers
true, // pretty print
false); // write binary
exit(0);
}

View File

@@ -610,7 +610,7 @@ void Viewer::buildSamplerDescs() {
samplerDesc.AddressU = toTextureAddressMode(glTFSampler.wrapS);
samplerDesc.AddressV = toTextureAddressMode(glTFSampler.wrapT);
samplerDesc.AddressW = toTextureAddressMode(glTFSampler.wrapR);
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplerDesc.MaxLOD = 256;
samplerDescs_.push_back(samplerDesc);
@@ -1289,4 +1289,4 @@ void Viewer::drawNode(uint64_t nodeIndex) {
for (auto childNodeIndex : glTFNode.children) {
drawNode(childNodeIndex);
}
}
}

View File

@@ -27,7 +27,8 @@
// Version:
// - v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
// - v2.4.3 Fix null object output when when material has all default parameters.
// - v2.4.3 Fix null object output when when material has all default
// parameters.
// - v2.4.2 Decode percent-encoded URI.
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
// `extras` property.
@@ -297,7 +298,7 @@ class Value {
DEFAULT_METHODS(Value)
char Type() const { return static_cast<const char>(type_); }
char Type() const { return static_cast<char>(type_); }
bool IsBool() const { return (type_ == BOOL_TYPE); }
@@ -613,7 +614,7 @@ struct Sampler {
int wrapT =
TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
// "REPEAT"], default "REPEAT"
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension. currently not used.
Value extras;
ExtensionMap extensions;
@@ -626,8 +627,7 @@ struct Sampler {
: minFilter(-1),
magFilter(-1),
wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT),
wrapR(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
DEFAULT_METHODS(Sampler)
bool operator==(const Sampler &) const;
};
@@ -850,8 +850,10 @@ struct Accessor {
std::string extras_json_string;
std::string extensions_json_string;
std::vector<double> minValues; // optional
std::vector<double> maxValues; // optional
std::vector<double>
minValues; // optional. integer value is promoted to double
std::vector<double>
maxValues; // optional. integer value is promoted to double
struct {
int count;
@@ -1191,7 +1193,8 @@ enum SectionCheck {
///
typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
std::string *, int, int,
const unsigned char *, int, void *user_pointer);
const unsigned char *, int,
void *user_pointer);
///
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
@@ -1256,7 +1259,7 @@ bool FileExists(const std::string &abs_filename, void *);
///
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
/// `C:\Users\tinygltf\AppData`)
/// `C:\\Users\\tinygltf\\AppData`)
///
/// @param[in] filepath File path string. Assume UTF-8
/// @param[in] userdata User data. Set to `nullptr` if you don't need it.
@@ -1398,9 +1401,7 @@ class TinyGLTF {
preserve_image_channels_ = onoff;
}
bool GetPreserveImageChannels() const {
return preserve_image_channels_;
}
bool GetPreserveImageChannels() const { return preserve_image_channels_; }
private:
///
@@ -1421,7 +1422,8 @@ class TinyGLTF {
bool store_original_json_for_extras_and_extensions_ = false;
bool preserve_image_channels_ = false; /// Default false(expand channels to RGBA) for backward compatibility.
bool preserve_image_channels_ = false; /// Default false(expand channels to
/// RGBA) for backward compatibility.
FsCallbacks fs = {
#ifndef TINYGLTF_NO_FS
@@ -1708,14 +1710,14 @@ namespace tinygltf {
///
/// Internal LoadImageDataOption struct.
/// This struct is passed through `user_pointer` in LoadImageData.
/// The struct is not passed when the user supply their own LoadImageData callbacks.
/// The struct is not passed when the user supply their own LoadImageData
/// callbacks.
///
struct LoadImageDataOption
{
// true: preserve image channels(e.g. load as RGB image if the image has RGB channels)
// default `false`(channels are expanded to RGBA for backward compatiblity).
struct LoadImageDataOption {
// true: preserve image channels(e.g. load as RGB image if the image has RGB
// channels) default `false`(channels are expanded to RGBA for backward
// compatiblity).
bool preserve_channels{false};
};
// Equals function for Value, for recursivity
@@ -1930,8 +1932,9 @@ bool Sampler::operator==(const Sampler &other) const {
return this->extensions == other.extensions && 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;
//this->wrapR == other.wrapR && this->wrapS == other.wrapS &&
}
bool Scene::operator==(const Scene &other) const {
return this->extensions == other.extensions && this->extras == other.extras &&
@@ -2363,8 +2366,8 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
unsigned char *data = nullptr;
// preserve_channels true: Use channels stored in the image file.
// false: force 32-bit textures for common Vulkan compatibility. It appears that
// some GPU drivers do not support 24-bit images for Vulkan
// false: force 32-bit textures for common Vulkan compatibility. It appears
// that some GPU drivers do not support 24-bit images for Vulkan
req_comp = option.preserve_channels ? 0 : 4;
int bits = 8;
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
@@ -5086,12 +5089,12 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
int magFilter = -1;
int wrapS = TINYGLTF_TEXTURE_WRAP_REPEAT;
int wrapT = TINYGLTF_TEXTURE_WRAP_REPEAT;
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
ParseIntegerProperty(&minFilter, err, o, "minFilter", false);
ParseIntegerProperty(&magFilter, err, o, "magFilter", false);
ParseIntegerProperty(&wrapS, err, o, "wrapS", false);
ParseIntegerProperty(&wrapT, err, o, "wrapT", false);
ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
//ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
// TODO(syoyo): Check the value is alloed one.
// (e.g. we allow 9728(NEAREST), but don't allow 9727)
@@ -5100,7 +5103,7 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
sampler->magFilter = magFilter;
sampler->wrapS = wrapS;
sampler->wrapT = wrapT;
sampler->wrapR = wrapR;
//sampler->wrapR = wrapR;
ParseExtensionsProperty(&(sampler->extensions), err, o);
ParseExtrasProperty(&(sampler->extras), o);
@@ -6621,8 +6624,33 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
SerializeNumberProperty<int>("componentType", accessor.componentType, o);
SerializeNumberProperty<size_t>("count", accessor.count, o);
SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
if ((accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) ||
(accessor.componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE)) {
SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
} else {
// Issue #301. Serialize as integer.
// Assume int value is within [-2**31-1, 2**31-1]
{
std::vector<int> values;
std::transform(accessor.minValues.begin(), accessor.minValues.end(),
std::back_inserter(values),
[](double v) { return static_cast<int>(v); });
SerializeNumberArrayProperty<int>("min", values, o);
}
{
std::vector<int> values;
std::transform(accessor.maxValues.begin(), accessor.maxValues.end(),
std::back_inserter(values),
[](double v) { return static_cast<int>(v); });
SerializeNumberArrayProperty<int>("max", values, o);
}
}
if (accessor.normalized)
SerializeValue("normalized", Value(accessor.normalized), o);
std::string type;
@@ -7133,7 +7161,7 @@ static void SerializeGltfSampler(Sampler &sampler, json &o) {
if (sampler.minFilter != -1) {
SerializeNumberProperty("minFilter", sampler.minFilter, o);
}
SerializeNumberProperty("wrapR", sampler.wrapR, o);
//SerializeNumberProperty("wrapR", sampler.wrapR, o);
SerializeNumberProperty("wrapS", sampler.wrapS, o);
SerializeNumberProperty("wrapT", sampler.wrapT, o);
@@ -7299,7 +7327,8 @@ static void SerializeGltfModel(Model *model, json &o) {
if (JsonIsNull(material)) {
// Issue 294.
// `material` does not have any required parameters
// so the result may be null(unmodified) when all material parameters have default value.
// so the result may be null(unmodified) when all material parameters
// have default value.
//
// null is not allowed thus we create an empty JSON object.
JsonSetObject(material);
@@ -7442,7 +7471,7 @@ static void SerializeGltfModel(Model *model, json &o) {
}
// Extensions used
if (model->extensionsUsed.size()) {
if (extensionsUsed.size()) {
SerializeStringArrayProperty("extensionsUsed", extensionsUsed, o);
}