mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-09 03:33:49 +00:00
Compare commits
28 Commits
separate-s
...
int-minmax
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7905a5b4dc | ||
|
|
a159945db9 | ||
|
|
010ee9c67b | ||
|
|
a23971c603 | ||
|
|
1923067982 | ||
|
|
68adc4ba5e | ||
|
|
42a8cd50ff | ||
|
|
0543640a83 | ||
|
|
9c59a0b64c | ||
|
|
452541a231 | ||
|
|
78fe8d9b89 | ||
|
|
51e5508fa0 | ||
|
|
91da299729 | ||
|
|
50ae8a31a8 | ||
|
|
0af0435ef1 | ||
|
|
7c342533e9 | ||
|
|
7842c1276f | ||
|
|
125e4a2033 | ||
|
|
c9d6c5b9b4 | ||
|
|
96a8b2c69b | ||
|
|
01d54380ac | ||
|
|
6cd8fdb2c8 | ||
|
|
fe01af2f01 | ||
|
|
efdd2b04dc | ||
|
|
2e642b3322 | ||
|
|
1739d025a9 | ||
|
|
39418e5728 | ||
|
|
5622d2762d |
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
30
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Issue report
|
||||
about: Create a report
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the issue**
|
||||
|
||||
A clear and concise description of what the issue is.
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
- OS
|
||||
- Compiler, compiler version, compile options
|
||||
- Please attach minimal and reproducible .glTF file if you got an issue related to .glTF data
|
||||
|
||||
**Expected behaviour**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
11
README.md
11
README.md
@@ -3,7 +3,7 @@
|
||||
`TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library.
|
||||
|
||||
`TinyGLTF` uses Niels Lohmann's json library(https://github.com/nlohmann/json), so now it requires C++11 compiler.
|
||||
If you are looking for old, C++03 version, please use `devel-picojson` branch.
|
||||
If you are looking for old, C++03 version, please use `devel-picojson` branch(but not maintained anymore).
|
||||
|
||||
## Status
|
||||
|
||||
@@ -13,6 +13,10 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch.
|
||||
- v2.1.0 release(Draco support)
|
||||
- v2.0.0 release(22 Aug, 2018)!
|
||||
|
||||
### Branches
|
||||
|
||||
* `sajson` : Use sajson to parse JSON. Parsing only but faster compile time(2x reduction compared to json.hpp and RapidJson)
|
||||
|
||||
## Builds
|
||||
|
||||
[](https://travis-ci.org/syoyo/tinygltf)
|
||||
@@ -151,9 +155,12 @@ if (!ret) {
|
||||
}
|
||||
```
|
||||
|
||||
#### Loader options
|
||||
|
||||
* `TinyGLTF::SetPreserveimageChannels(bool onoff)`. `true` to preserve image channels as stored in image file for loaded image. `false` by default for backward compatibility(image channels are widen to `RGBA` 4 channels). Effective only when using builtin image loader(STB image loader).
|
||||
|
||||
## Compile options
|
||||
|
||||
* `TINYGLTF_ENABLE_SERIALIZER` : Enable glTF serialization feature.
|
||||
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
|
||||
* `TINYGLTF_NO_STB_IMAGE` : Do not load images with stb_image. Instead use `TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)` to set a callback for loading images.
|
||||
* `TINYGLTF_NO_STB_IMAGE_WRITE` : Do not write images with stb_image_write. Instead use `TinyGLTF::SetImageWriter(WriteimageDataFunction WriteImageData, void *user_data)` to set a callback for writing images.
|
||||
|
||||
1
examples/basic/.gitignore
vendored
1
examples/basic/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.vs
|
||||
Debug
|
||||
Release
|
||||
x64
|
||||
packages
|
||||
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{0589AC44-0CF3-40D8-8D89-68393CFD40F3}</ProjectGuid>
|
||||
<RootNamespace>basic</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -329,7 +329,7 @@ static void error_callback(int error, const char *description) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::string filename = "../../models/Cube/Cube.gltf";
|
||||
std::string filename = "../../../models/Cube/Cube.gltf";
|
||||
|
||||
if (argc > 1) {
|
||||
filename = argv[1];
|
||||
@@ -341,9 +341,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Force create OpenGL 3.3
|
||||
// NOTE(syoyo): Linux + NVIDIA driver segfaults for some reason? commenting out glfwWindowHint will work.
|
||||
// Note (PE): On laptops with intel hd graphics card you can overcome the segfault by enabling experimental, see below (tested on lenovo thinkpad)
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glewExperimental = GL_TRUE;
|
||||
|
||||
#ifdef __APPLE__
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
#endif
|
||||
|
||||
36
examples/dxview/CMakeLists.txt
Normal file
36
examples/dxview/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(dxview)
|
||||
|
||||
find_package(glfw3 CONFIG REQUIRED)
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
|
||||
add_executable(dxview
|
||||
src/Viewer.h
|
||||
src/Viewer.cc
|
||||
src/dxview.cc
|
||||
)
|
||||
|
||||
target_include_directories(dxview
|
||||
PRIVATE
|
||||
../../
|
||||
)
|
||||
|
||||
target_compile_definitions(dxview
|
||||
PRIVATE
|
||||
DXVIEW_SWAP_CHAIN_BUFFER_COUNT=3
|
||||
DXVIEW_RES_DIR=L"${PROJECT_SOURCE_DIR}/res"
|
||||
)
|
||||
|
||||
target_link_libraries(dxview
|
||||
PRIVATE
|
||||
dxgi
|
||||
d3dcompiler
|
||||
d3d12
|
||||
glfw
|
||||
spdlog::spdlog
|
||||
)
|
||||
|
||||
set_target_properties(dxview
|
||||
PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
)
|
||||
37
examples/dxview/README.md
Normal file
37
examples/dxview/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# DirectX glTF Viewer
|
||||
|
||||
## Overview
|
||||
|
||||
This project was motivated by a lack of sample code demonstrating the graphics API agnostic nature of the glTF specification. The sample code is written using modern C++ and DirectX 12 for the client application.
|
||||
|
||||
## Features
|
||||
|
||||
* [x] DirectX 12
|
||||
* [ ] Loader
|
||||
* [ ] Animation
|
||||
* [ ] Morph Target
|
||||
* [ ] Physical Base Rendering
|
||||
* [ ] Environment Map
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [CMake](https://github.com/Kitware/CMake)
|
||||
* [Vcpkg](https://github.com/Microsoft/vcpkg)
|
||||
* [GLFW](https://github.com/glfw/glfw)
|
||||
* [spdlog](https://github.com/gabime/spdlog)
|
||||
|
||||
## Building
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```
|
||||
vcpkg install glfw3:x64-windows
|
||||
vcpkg install spdlog:x64-windows
|
||||
```
|
||||
|
||||
### Generate Project Files
|
||||
|
||||
```
|
||||
mkdir build
|
||||
cmake . -B build -DCMAKE_TOOLCHAIN_FILE=${VCPKG_DIR}/script/buildsystem/vcpkg.cmake
|
||||
```
|
||||
3
examples/dxview/res/gray.hlsl
Normal file
3
examples/dxview/res/gray.hlsl
Normal file
@@ -0,0 +1,3 @@
|
||||
float4 main() : SV_Target {
|
||||
return float4(0.5, 0.5, 0.5, 1.0);
|
||||
}
|
||||
52
examples/dxview/res/lighting.hlsl
Normal file
52
examples/dxview/res/lighting.hlsl
Normal file
@@ -0,0 +1,52 @@
|
||||
struct RS2PS {
|
||||
float4 position : SV_POSITION;
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
float2 texcoord_0: TEXCOORD_0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
uint textureIndex;
|
||||
uint samplerIndex;
|
||||
};
|
||||
|
||||
struct PBRMetallicRoughness {
|
||||
float4 baseColorFactor;
|
||||
TextureInfo baseColorTexture;
|
||||
float metallicFactor;
|
||||
float roughnessFactor;
|
||||
TextureInfo metallicRoughnessTexture;
|
||||
};
|
||||
|
||||
cbuffer Material : register(b2) {
|
||||
PBRMetallicRoughness pbrMetallicRoughness;
|
||||
};
|
||||
|
||||
Texture2D textures[5] : register(t0);
|
||||
SamplerState samplerState[5] : register(s0);
|
||||
|
||||
float4 getBaseColor(float2 uv) {
|
||||
float4 baseColor = pbrMetallicRoughness.baseColorFactor;
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
TextureInfo baseColorTexture = pbrMetallicRoughness.baseColorTexture;
|
||||
if (baseColorTexture.textureIndex >= 0) {
|
||||
baseColor *= textures[baseColorTexture.textureIndex].Sample(samplerState[baseColorTexture.samplerIndex], uv);
|
||||
}
|
||||
#endif
|
||||
|
||||
return baseColor;
|
||||
}
|
||||
|
||||
float4 main(RS2PS input) : SV_Target {
|
||||
float2 uv = float2(0.0, 0.0);
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
uv = input.texcoord_0;
|
||||
#endif
|
||||
|
||||
float4 color = getBaseColor(uv);
|
||||
|
||||
return color;
|
||||
}
|
||||
46
examples/dxview/res/primitive.hlsl
Normal file
46
examples/dxview/res/primitive.hlsl
Normal file
@@ -0,0 +1,46 @@
|
||||
struct IA2VS {
|
||||
float3 position : POSITION;
|
||||
|
||||
#ifdef HAS_NORMAL
|
||||
float3 normal : NORMAL;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TANGENT
|
||||
float4 tangent : TANGENT;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
float2 texcoord_0: TEXCOORD_0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct VS2RS {
|
||||
float4 position : SV_POSITION;
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
float2 texcoord_0: TEXCOORD_0;
|
||||
#endif
|
||||
};
|
||||
|
||||
cbuffer Camera : register(b0) {
|
||||
float4x4 V;
|
||||
float4x4 P;
|
||||
float4x4 VP;
|
||||
};
|
||||
|
||||
cbuffer Node : register(b1) {
|
||||
float4x4 M;
|
||||
};
|
||||
|
||||
VS2RS main(IA2VS input) {
|
||||
VS2RS output;
|
||||
output.position = mul(float4(input.position, 1.0), M);
|
||||
output.position = mul(output.position, V);
|
||||
output.position = mul(output.position, P);
|
||||
|
||||
#ifdef HAS_TEXCOORD_0
|
||||
output.texcoord_0 = input.texcoord_0;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
1292
examples/dxview/src/Viewer.cc
Normal file
1292
examples/dxview/src/Viewer.cc
Normal file
File diff suppressed because it is too large
Load Diff
130
examples/dxview/src/Viewer.h
Normal file
130
examples/dxview/src/Viewer.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#ifndef DXVIEW_VIEWER_GUARD
|
||||
#define DXVIEW_VIEWER_GUARD
|
||||
|
||||
#include <DirectXMath.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <tiny_gltf.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
enum RenderPassType { RENDER_PASS_TYPE_PRESENT = 0, RENDER_PASS_TYPE_COUNT };
|
||||
|
||||
struct RenderTarget {
|
||||
ComPtr<ID3D12Resource> pTexture;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE viewDescriptor;
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
int32_t textureIndex;
|
||||
int32_t samplerIndex;
|
||||
};
|
||||
|
||||
struct PBRMetallicRoughness {
|
||||
DirectX::XMFLOAT4 baseColorFactor;
|
||||
TextureInfo baseColorTexture;
|
||||
float metallicFactor;
|
||||
float roughnessFactor;
|
||||
TextureInfo metallicRoughnessTexture;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
std::string name;
|
||||
D3D12_BLEND_DESC blendDesc;
|
||||
D3D12_RASTERIZER_DESC rasterizerDesc;
|
||||
ComPtr<ID3D12Resource> pBuffer;
|
||||
void* pBufferData;
|
||||
ComPtr<ID3D12DescriptorHeap> pSRVDescriptorHeap;
|
||||
ComPtr<ID3D12DescriptorHeap> pSamplerDescriptorHeap;
|
||||
};
|
||||
|
||||
struct Attribute {
|
||||
std::string name;
|
||||
DXGI_FORMAT format;
|
||||
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
|
||||
};
|
||||
|
||||
struct Primitive {
|
||||
std::vector<Attribute> attributes;
|
||||
uint32_t vertexCount;
|
||||
D3D12_PRIMITIVE_TOPOLOGY primitiveTopology;
|
||||
D3D12_INDEX_BUFFER_VIEW indexBufferView;
|
||||
uint32_t indexCount;
|
||||
Material* pMaterial;
|
||||
ComPtr<ID3D12RootSignature> pRootSignature;
|
||||
ComPtr<ID3D12PipelineState> pPipelineState;
|
||||
};
|
||||
|
||||
struct Mesh {
|
||||
std::string name;
|
||||
std::vector<Primitive> primitives;
|
||||
};
|
||||
|
||||
struct Node {
|
||||
DirectX::XMFLOAT4X4 M;
|
||||
};
|
||||
|
||||
struct Camera {
|
||||
DirectX::XMFLOAT4X4 V;
|
||||
DirectX::XMFLOAT4X4 P;
|
||||
DirectX::XMFLOAT4X4 VP;
|
||||
};
|
||||
|
||||
class Viewer {
|
||||
public:
|
||||
Viewer(HWND window, tinygltf::Model* pModel);
|
||||
|
||||
void update(double deltaTime);
|
||||
void render(double deltaTime);
|
||||
|
||||
private:
|
||||
void initDirectX(HWND window);
|
||||
void buildRenderTargets();
|
||||
void buildResources();
|
||||
void buildBuffers(std::vector<ComPtr<ID3D12Resource> >* pStagingResources);
|
||||
void buildImages(std::vector<ComPtr<ID3D12Resource> >* pStagingResources);
|
||||
void buildSamplerDescs();
|
||||
void buildMaterials();
|
||||
void buildMeshes();
|
||||
void buildNodes();
|
||||
|
||||
void drawNode(uint64_t nodeIndex);
|
||||
|
||||
private:
|
||||
tinygltf::Model* pModel_;
|
||||
ComPtr<IDXGIFactory1> pFactory_;
|
||||
ComPtr<IDXGIAdapter1> pAdapter_;
|
||||
ComPtr<ID3D12Device> pDevice_;
|
||||
ComPtr<ID3D12CommandQueue> pDirectCommandQueue_;
|
||||
UINT64 directFenceValue_;
|
||||
ComPtr<ID3D12Fence> pDirectFence_;
|
||||
ComPtr<ID3D12CommandQueue> pCopyCommandQueue_;
|
||||
UINT64 copyFenceValue_;
|
||||
ComPtr<ID3D12Fence> pCopyFence_;
|
||||
ComPtr<IDXGISwapChain3> pSwapChain_;
|
||||
ComPtr<ID3D12Resource> pSwapChainBuffers_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||
ComPtr<ID3D12CommandAllocator>
|
||||
pDirectCommandAllocators_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||
ComPtr<ID3D12GraphicsCommandList> pDirectCommandList_;
|
||||
ComPtr<ID3D12CommandAllocator> pCopyCommandAllocator_;
|
||||
ComPtr<ID3D12GraphicsCommandList> pCopyCommandList_;
|
||||
UINT descriptorIncrementSize_[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||
ComPtr<ID3D12DescriptorHeap>
|
||||
pRTVDescriptorHeaps_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||
std::vector<RenderTarget> renderTargets_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||
std::vector<ComPtr<ID3D12Resource> > pBuffers_;
|
||||
std::vector<ComPtr<ID3D12Resource> > pTextures_;
|
||||
std::vector<D3D12_SAMPLER_DESC> samplerDescs_;
|
||||
std::vector<Material> materials_;
|
||||
std::vector<Mesh> meshes_;
|
||||
std::vector<ComPtr<ID3D12Resource> > pNodeBuffers_;
|
||||
ComPtr<ID3D12Resource> pCameraBuffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
90
examples/dxview/src/dxview.cc
Normal file
90
examples/dxview/src/dxview.cc
Normal file
@@ -0,0 +1,90 @@
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#define TINYGLTF_IMPLEMENTATION
|
||||
#define STBI_MSC_SECURE_CRT
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <tiny_gltf.h>
|
||||
|
||||
#undef GLFW_EXPOSE_NATIVE_WIN32
|
||||
#undef TINYGLTF_IMPLEMENTATION
|
||||
#undef STBI_MSC_SECURE_CRT
|
||||
#undef STB_IMAGE_IMPLEMENTATION
|
||||
#undef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "Viewer.h"
|
||||
|
||||
static void onError(int error, const char* message) {
|
||||
spdlog::error("[{}] {}", error, message);
|
||||
}
|
||||
|
||||
static void onRender(Viewer* pViewer, double deltaTime) {
|
||||
pViewer->update(deltaTime);
|
||||
pViewer->render(deltaTime);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
tinygltf::TinyGLTF context;
|
||||
|
||||
tinygltf::Model model;
|
||||
std::string error;
|
||||
std::string warning;
|
||||
if (!context.LoadASCIIFromFile(&model, &error, &warning, argv[1])) {
|
||||
if (!error.empty()) {
|
||||
spdlog::error("{}", error);
|
||||
}
|
||||
|
||||
if (!warning.empty()) {
|
||||
spdlog::warn("{}", warning);
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
GLFWwindow* pWindow;
|
||||
|
||||
glfwSetErrorCallback(onError);
|
||||
|
||||
if (!glfwInit()) {
|
||||
spdlog::error("Fail to initialize GLFW!!!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
pWindow = glfwCreateWindow(512, 512, "dxview", nullptr, nullptr);
|
||||
if (!pWindow) {
|
||||
spdlog::error("Fail to create GLFWwindow!!!");
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto pViewer = std::make_unique<Viewer>(glfwGetWin32Window(pWindow), &model);
|
||||
if (!pViewer) {
|
||||
spdlog::error("Fail to create Viewer");
|
||||
glfwDestroyWindow(pWindow);
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto prevTimeStamp = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(pWindow)) {
|
||||
auto currTimeStamp = glfwGetTime();
|
||||
|
||||
onRender(pViewer.get(), currTimeStamp - prevTimeStamp);
|
||||
prevTimeStamp = currTimeStamp;
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
glfwDestroyWindow(pWindow);
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
Binary file not shown.
@@ -3,6 +3,9 @@
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "tiny_gltf.h"
|
||||
|
||||
// Nlohmann json(include ../json.hpp)
|
||||
#include "json.hpp"
|
||||
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include "catch.hpp"
|
||||
|
||||
@@ -412,6 +415,28 @@ TEST_CASE("image-uri-spaces", "[issue-236]") {
|
||||
REQUIRE(true == ret);
|
||||
}
|
||||
|
||||
TEST_CASE("serialize-empty-material", "[issue-294]") {
|
||||
|
||||
tinygltf::Model m;
|
||||
|
||||
tinygltf::Material mat;
|
||||
mat.pbrMetallicRoughness.baseColorFactor = {1.0f, 1.0f, 1.0f, 1.0f}; // default baseColorFactor
|
||||
m.materials.push_back(mat);
|
||||
|
||||
std::stringstream os;
|
||||
|
||||
tinygltf::TinyGLTF ctx;
|
||||
ctx.WriteGltfSceneToStream(&m, os, false, false);
|
||||
|
||||
// use nlohmann json
|
||||
nlohmann::json j = nlohmann::json::parse(os.str());
|
||||
|
||||
REQUIRE(1 == j["materials"].size());
|
||||
REQUIRE(j["asset"].is_null());
|
||||
REQUIRE(j["materials"][0].is_object());
|
||||
|
||||
}
|
||||
|
||||
#ifndef TINYGLTF_NO_FS
|
||||
TEST_CASE("expandpath-utf-8", "[pr-226]") {
|
||||
|
||||
|
||||
186
tiny_gltf.h
186
tiny_gltf.h
@@ -26,7 +26,9 @@
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Version:
|
||||
// - v2.4.3 Introduce TINYGLTF_ENABLE_SERIALIZER.
|
||||
// - 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.2 Decode percent-encoded URI.
|
||||
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
|
||||
// `extras` property.
|
||||
@@ -665,6 +667,8 @@ struct Image {
|
||||
width = -1;
|
||||
height = -1;
|
||||
component = -1;
|
||||
bits = -1;
|
||||
pixel_type = -1;
|
||||
}
|
||||
DEFAULT_METHODS(Image)
|
||||
|
||||
@@ -847,8 +851,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;
|
||||
@@ -997,6 +1003,7 @@ struct Primitive {
|
||||
Primitive() {
|
||||
material = -1;
|
||||
indices = -1;
|
||||
mode = -1;
|
||||
}
|
||||
DEFAULT_METHODS(Primitive)
|
||||
bool operator==(const Primitive &) const;
|
||||
@@ -1187,7 +1194,8 @@ enum SectionCheck {
|
||||
///
|
||||
typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
|
||||
std::string *, int, int,
|
||||
const unsigned char *, int, void *);
|
||||
const unsigned char *, int,
|
||||
void *user_pointer);
|
||||
|
||||
///
|
||||
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
|
||||
@@ -1251,7 +1259,8 @@ struct FsCallbacks {
|
||||
bool FileExists(const std::string &abs_filename, void *);
|
||||
|
||||
///
|
||||
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to `C:\Users\tinygltf\AppData`)
|
||||
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
|
||||
/// `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.
|
||||
@@ -1324,8 +1333,6 @@ class TinyGLTF {
|
||||
const std::string &base_dir = "",
|
||||
unsigned int check_sections = REQUIRE_VERSION);
|
||||
|
||||
#if defined(TINYGLTF_ENABLE_SERIALIZER)
|
||||
|
||||
///
|
||||
/// Write glTF to stream, buffers and images will be embeded
|
||||
///
|
||||
@@ -1339,22 +1346,21 @@ class TinyGLTF {
|
||||
bool embedImages, bool embedBuffers,
|
||||
bool prettyPrint, bool writeBinary);
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Set callback to use for loading image data
|
||||
///
|
||||
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
|
||||
|
||||
#if defined(TINYGLTF_ENABLE_SERIALIZER)
|
||||
///
|
||||
/// Unset(remove) callback of loading image data
|
||||
///
|
||||
void RemoveImageLoader();
|
||||
|
||||
///
|
||||
/// Set callback to use for writing image data
|
||||
///
|
||||
void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data);
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Set callbacks to use for filesystem (fs) access and their user data
|
||||
///
|
||||
@@ -1388,6 +1394,16 @@ class TinyGLTF {
|
||||
return store_original_json_for_extras_and_extensions_;
|
||||
}
|
||||
|
||||
///
|
||||
/// Specify whether preserve image channales when loading images or not.
|
||||
/// (Not effective when the user suppy their own LoadImageData callbacks)
|
||||
///
|
||||
void SetPreserveImageChannels(bool onoff) {
|
||||
preserve_image_channels_ = onoff;
|
||||
}
|
||||
|
||||
bool GetPreserveImageChannels() const { return preserve_image_channels_; }
|
||||
|
||||
private:
|
||||
///
|
||||
/// Loads glTF asset from string(memory).
|
||||
@@ -1407,6 +1423,9 @@ 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.
|
||||
|
||||
FsCallbacks fs = {
|
||||
#ifndef TINYGLTF_NO_FS
|
||||
&tinygltf::FileExists, &tinygltf::ExpandFilePath,
|
||||
@@ -1426,7 +1445,8 @@ class TinyGLTF {
|
||||
#else
|
||||
nullptr;
|
||||
#endif
|
||||
void *load_image_user_data_ = reinterpret_cast<void *>(&fs);
|
||||
void *load_image_user_data_{nullptr};
|
||||
bool user_image_loader_{false};
|
||||
|
||||
WriteImageDataFunction WriteImageData =
|
||||
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
||||
@@ -1434,7 +1454,7 @@ class TinyGLTF {
|
||||
#else
|
||||
nullptr;
|
||||
#endif
|
||||
void *write_image_user_data_ = reinterpret_cast<void *>(&fs);
|
||||
void *write_image_user_data_{nullptr};
|
||||
};
|
||||
|
||||
#ifdef __clang__
|
||||
@@ -1688,6 +1708,19 @@ void JsonParse(JsonDocument &doc, const char *str, size_t length,
|
||||
|
||||
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.
|
||||
///
|
||||
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
|
||||
static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
|
||||
if (one.Type() != other.Type()) return false;
|
||||
@@ -2302,22 +2335,40 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
||||
LoadImageData = func;
|
||||
load_image_user_data_ = user_data;
|
||||
user_image_loader_ = true;
|
||||
}
|
||||
|
||||
void TinyGLTF::RemoveImageLoader() {
|
||||
LoadImageData =
|
||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||
&tinygltf::LoadImageData;
|
||||
#else
|
||||
nullptr;
|
||||
#endif
|
||||
|
||||
load_image_user_data_ = nullptr;
|
||||
user_image_loader_ = false;
|
||||
}
|
||||
|
||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||
bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
||||
std::string *warn, int req_width, int req_height,
|
||||
const unsigned char *bytes, int size, void *user_data) {
|
||||
(void)user_data;
|
||||
(void)warn;
|
||||
|
||||
LoadImageDataOption option;
|
||||
if (user_data) {
|
||||
option = *reinterpret_cast<LoadImageDataOption *>(user_data);
|
||||
}
|
||||
|
||||
int w = 0, h = 0, comp = 0, req_comp = 0;
|
||||
|
||||
unsigned char *data = nullptr;
|
||||
|
||||
// force 32-bit textures for common Vulkan compatibility. It appears that
|
||||
// some GPU drivers do not support 24-bit images for Vulkan
|
||||
req_comp = 4;
|
||||
// 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
|
||||
req_comp = option.preserve_channels ? 0 : 4;
|
||||
int bits = 8;
|
||||
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||
|
||||
@@ -2389,28 +2440,29 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
||||
}
|
||||
}
|
||||
|
||||
if (req_comp != 0) {
|
||||
// loaded data has `req_comp` channels(components)
|
||||
comp = req_comp;
|
||||
}
|
||||
|
||||
image->width = w;
|
||||
image->height = h;
|
||||
image->component = req_comp;
|
||||
image->component = comp;
|
||||
image->bits = bits;
|
||||
image->pixel_type = pixel_type;
|
||||
image->image.resize(static_cast<size_t>(w * h * req_comp) * size_t(bits / 8));
|
||||
std::copy(data, data + w * h * req_comp * (bits / 8), image->image.begin());
|
||||
image->image.resize(static_cast<size_t>(w * h * comp) * size_t(bits / 8));
|
||||
std::copy(data, data + w * h * comp * (bits / 8), image->image.begin());
|
||||
stbi_image_free(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TINYGLTF_ENABLE_SERIALIZER)
|
||||
|
||||
void TinyGLTF::SetImageWriter(WriteImageDataFunction func, void *user_data) {
|
||||
WriteImageData = func;
|
||||
write_image_user_data_ = user_data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
||||
static void WriteToMemory_stbi(void *context, void *data, int size) {
|
||||
std::vector<unsigned char> *buffer =
|
||||
@@ -2505,7 +2557,7 @@ static inline std::wstring UTF8ToWchar(const std::string &str) {
|
||||
|
||||
static inline std::string WcharToUTF8(const std::wstring &wstr) {
|
||||
int str_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(),
|
||||
nullptr, 0, NULL, NULL);
|
||||
nullptr, 0, NULL, NULL);
|
||||
std::string str(str_size, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), &str[0],
|
||||
(int)str.size(), NULL, NULL);
|
||||
@@ -2648,7 +2700,8 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
|
||||
__gnu_cxx::stdio_filebuf<char> wfile_buf(file_descriptor, std::ios_base::in);
|
||||
std::istream f(&wfile_buf);
|
||||
#elif defined(_MSC_VER) || defined(_LIBCPP_VERSION)
|
||||
// For libcxx, assume _LIBCPP_HAS_OPEN_WITH_WCHAR is defined to accept `wchar_t *`
|
||||
// For libcxx, assume _LIBCPP_HAS_OPEN_WITH_WCHAR is defined to accept
|
||||
// `wchar_t *`
|
||||
std::ifstream f(UTF8ToWchar(filepath).c_str(), std::ifstream::binary);
|
||||
#else
|
||||
// Unknown compiler/runtime
|
||||
@@ -3010,7 +3063,9 @@ json_const_iterator ObjectEnd(const json &o) {
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *GetKey(json_const_iterator &it) {
|
||||
// Making this a const char* results in a pointer to a temporary when
|
||||
// TINYGLTF_USE_RAPIDJSON is off.
|
||||
std::string GetKey(json_const_iterator &it) {
|
||||
#ifdef TINYGLTF_USE_RAPIDJSON
|
||||
return it->name.GetString();
|
||||
#else
|
||||
@@ -5715,10 +5770,13 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
|
||||
for (auto &target : primitive.targets) {
|
||||
for (auto &attribute : target) {
|
||||
model
|
||||
->bufferViews[size_t(
|
||||
model->accessors[size_t(attribute.second)].bufferView)]
|
||||
.target = TINYGLTF_TARGET_ARRAY_BUFFER;
|
||||
auto bufferView =
|
||||
model->accessors[size_t(attribute.second)].bufferView;
|
||||
// bufferView could be null(-1) for sparse morph target
|
||||
if (bufferView >= 0) {
|
||||
model->bufferViews[size_t(bufferView)].target =
|
||||
TINYGLTF_TARGET_ARRAY_BUFFER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5828,6 +5886,18 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
}
|
||||
|
||||
// 11. Parse Image
|
||||
void *load_image_user_data{nullptr};
|
||||
|
||||
LoadImageDataOption load_image_option;
|
||||
|
||||
if (user_image_loader_) {
|
||||
// Use user supplied pointer
|
||||
load_image_user_data = load_image_user_data_;
|
||||
} else {
|
||||
load_image_option.preserve_channels = preserve_image_channels_;
|
||||
load_image_user_data = reinterpret_cast<void *>(&load_image_option);
|
||||
}
|
||||
|
||||
{
|
||||
int idx = 0;
|
||||
bool success = ForEachInArray(v, "images", [&](const json &o) {
|
||||
@@ -5840,7 +5910,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
Image image;
|
||||
if (!ParseImage(&image, idx, err, warn, o,
|
||||
store_original_json_for_extras_and_extensions_, base_dir,
|
||||
&fs, &this->LoadImageData, load_image_user_data_)) {
|
||||
&fs, &this->LoadImageData, load_image_user_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5878,7 +5948,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
bool ret = LoadImageData(
|
||||
&image, idx, err, warn, image.width, image.height,
|
||||
&buffer.data[bufferView.byteOffset],
|
||||
static_cast<int>(bufferView.byteLength), load_image_user_data_);
|
||||
static_cast<int>(bufferView.byteLength), load_image_user_data);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
@@ -6227,8 +6297,6 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(TINYGLTF_ENABLE_SERIALIZER)
|
||||
|
||||
///////////////////////
|
||||
// GLTF Serialization
|
||||
///////////////////////
|
||||
@@ -6556,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;
|
||||
@@ -7230,6 +7323,16 @@ static void SerializeGltfModel(Model *model, json &o) {
|
||||
for (unsigned int i = 0; i < model->materials.size(); ++i) {
|
||||
json material;
|
||||
SerializeGltfMaterial(model->materials[i], material);
|
||||
|
||||
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.
|
||||
//
|
||||
// null is not allowed thus we create an empty JSON object.
|
||||
JsonSetObject(material);
|
||||
}
|
||||
JsonPushBack(materials, std::move(material));
|
||||
}
|
||||
JsonAddMember(o, "materials", std::move(materials));
|
||||
@@ -7355,8 +7458,9 @@ static void SerializeGltfModel(Model *model, json &o) {
|
||||
|
||||
// Also add "KHR_lights_punctual" to `extensionsUsed`
|
||||
{
|
||||
auto has_khr_lights_punctual = std::find_if(
|
||||
extensionsUsed.begin(), extensionsUsed.end(), [](const std::string &s) {
|
||||
auto has_khr_lights_punctual =
|
||||
std::find_if(extensionsUsed.begin(), extensionsUsed.end(),
|
||||
[](const std::string &s) {
|
||||
return (s.compare("KHR_lights_punctual") == 0);
|
||||
});
|
||||
|
||||
@@ -7634,8 +7738,6 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // TINYGLTF_ENABLE_SERIALIZER
|
||||
|
||||
} // namespace tinygltf
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
Reference in New Issue
Block a user