diff --git a/demo/GLTFLoader.js b/demo/GLTFLoader.js index dc25a055a..46d3cfe99 100644 --- a/demo/GLTFLoader.js +++ b/demo/GLTFLoader.js @@ -14,6 +14,7 @@ THREE.GLTFLoader = ( function () { this.dracoLoader = null; this.ddsLoader = null; + this.basisLoader = null; this.meshoptDecoder = null; } @@ -111,6 +112,13 @@ THREE.GLTFLoader = ( function () { }, + setBasisLoader: function ( basisLoader ) { + + this.basisLoader = basisLoader; + return this; + + }, + setMeshoptDecoder: function ( decoder ) { this.meshoptDecoder = decoder; @@ -222,7 +230,9 @@ THREE.GLTFLoader = ( function () { path: path || this.resourcePath || '', crossOrigin: this.crossOrigin, - manager: this.manager + manager: this.manager, + ddsLoader: this.ddsLoader, + basisLoader: this.basisLoader, } ); @@ -1970,11 +1980,43 @@ THREE.GLTFLoader = ( function () { var loader = options.manager.getHandler( sourceURI ); + if ( ! loader && textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) { + + loader = parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader + + } + + if ( ! loader && options.ddsLoader ) { + + if ( source.uri !== undefined && source.uri.toLowerCase().endsWith(".dds") ) { + + loader = options.ddsLoader; + + } else if ( source.bufferView !== undefined && source.mimeType == "image/vnd-ms.dds" ) { + + loader = options.ddsLoader; + + } + + } + + if ( ! loader && options.basisLoader ) { + + if ( source.uri !== undefined && source.uri.toLowerCase().endsWith(".basis") ) { + + loader = options.basisLoader; + + } else if ( source.bufferView !== undefined && source.mimeType == "image/basis" ) { + + loader = options.basisLoader; + + } + + } + if ( ! loader ) { - loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] - ? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader - : textureLoader; + loader = textureLoader; } diff --git a/tools/gltfpack.cpp b/tools/gltfpack.cpp index 26577d0da..22378d91e 100644 --- a/tools/gltfpack.cpp +++ b/tools/gltfpack.cpp @@ -34,7 +34,9 @@ #include #include -#ifndef _WIN32 +#ifdef _WIN32 +#include +#else #include #endif @@ -1663,9 +1665,9 @@ StreamFormat writeKeyframeStream(std::string& bin, cgltf_animation_path_type typ const Attr& a = data[i]; float v[3] = { - meshopt_quantizeFloat(a.f[0], bits), - meshopt_quantizeFloat(a.f[1], bits), - meshopt_quantizeFloat(a.f[2], bits)}; + meshopt_quantizeFloat(a.f[0], bits), + meshopt_quantizeFloat(a.f[1], bits), + meshopt_quantizeFloat(a.f[2], bits)}; bin.append(reinterpret_cast(v), sizeof(v)); } @@ -2740,9 +2742,46 @@ bool writeFile(const char* path, const std::string& data) return result == data.size(); } -bool encodeBasisFile(const char* input, const char* output, bool normal_map, int quality) +struct TempFile +{ + std::string path; + int fd; + + TempFile(const char* suffix) + : fd(-1) + { +#ifdef _WIN32 + const char* temp_dir = getenv("TEMP"); + path = temp_dir ? temp_dir : "."; + path += "\\gltfpack-XXXXXX"; + (void)_mktemp(&path[0]); + path += suffix; +#else + path = "/tmp/gltfpack-XXXXXX"; + path += suffix; + fd = mkstemps(&path[0], strlen(suffix)); +#endif + } + + ~TempFile() + { + unlink(path.c_str()); +#ifndef _WIN32 + close(fd); +#endif + } +}; + +bool encodeBasis(const std::string& data, std::string& result, bool normal_map, int quality) { - std::string cmd = "basisu"; + TempFile temp_input(".raw"); + TempFile temp_output(".basis"); + + if (!writeFile(temp_input.path.c_str(), data)) + return false; + + const char* basisu_path = getenv("BASISU_PATH"); + std::string cmd = basisu_path ? basisu_path : "basisu"; char ql[16]; sprintf(ql, "%d", (quality * 255 + 50) / 100); @@ -2758,9 +2797,9 @@ bool encodeBasisFile(const char* input, const char* output, bool normal_map, int } cmd += " -file "; - cmd += input; + cmd += temp_input.path; cmd += " -output_file "; - cmd += output; + cmd += temp_output.path; #ifdef _WIN32 cmd += " >nul"; @@ -2768,23 +2807,9 @@ bool encodeBasisFile(const char* input, const char* output, bool normal_map, int cmd += " >/dev/null"; #endif - return system(cmd.c_str()) == 0; -} + int rc = system(cmd.c_str()); -bool encodeBasisData(const std::string& data, std::string& result, bool normal_map, int quality, const char* output_path) -{ - std::string temp_name = getFileName(output_path) + ".temp"; - std::string temp_input = getFullPath(temp_name.c_str(), output_path) + ".png"; - std::string temp_output = getFullPath(temp_name.c_str(), output_path) + ".basis"; - - bool ok = - writeFile(temp_input.c_str(), data) && - encodeBasisFile(temp_input.c_str(), temp_output.c_str(), normal_map, quality) && - readFile(temp_output.c_str(), result); - - unlink(temp_input.c_str()); - unlink(temp_output.c_str()); - return ok; + return rc == 0 && readFile(temp_output.path.c_str(), result); } void writeImage(std::string& json, std::vector& views, const cgltf_image& image, const ImageInfo& info, size_t index, const char* input_path, const char* output_path, const Settings& settings) @@ -2821,7 +2846,7 @@ void writeImage(std::string& json, std::vector& views, const cgltf_i { std::string encoded; - if (encodeBasisData(img_data, encoded, info.normal_map, settings.texture_quality, output_path)) + if (encodeBasis(img_data, encoded, info.normal_map, settings.texture_quality)) { writeEmbeddedImage(json, views, encoded.c_str(), encoded.size(), "image/basis"); } @@ -2843,15 +2868,28 @@ void writeImage(std::string& json, std::vector& views, const cgltf_i std::string basis_path = getFileName(image.uri) + ".basis"; std::string basis_full_path = getFullPath(basis_path.c_str(), output_path); - if (encodeBasisFile(full_path.c_str(), basis_full_path.c_str(), info.normal_map, settings.texture_quality)) + if (!readFile(full_path.c_str(), img_data)) { - append(json, "\"uri\":\""); - append(json, basis_path); - append(json, "\""); + fprintf(stderr, "Warning: unable to read image %s, skipping\n", image.uri); } else { - fprintf(stderr, "Warning: unable to encode image %s with Basis, skipping\n", image.uri); + std::string encoded; + + if (!encodeBasis(img_data, encoded, info.normal_map, settings.texture_quality)) + { + fprintf(stderr, "Warning: unable to encode image %s with Basis, skipping\n", image.uri); + } + else if (!writeFile(basis_full_path.c_str(), encoded)) + { + fprintf(stderr, "Warning: unable to save Basis image %s, skipping\n", image.uri); + } + else + { + append(json, "\"uri\":\""); + append(json, basis_path); + append(json, "\""); + } } } else