143 lines
5.5 KiB
C++
143 lines
5.5 KiB
C++
/**
|
|
* @file llgltfmaterial_templates.h
|
|
* @brief Material template definition
|
|
*
|
|
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2023, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "llgltfmaterial.h"
|
|
|
|
// Use templates here as workaround for the different similar texture info classes in tinygltf
|
|
// Includer must first include tiny_gltf.h with the desired flags
|
|
|
|
template<typename T>
|
|
std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info)
|
|
{
|
|
const S32 texture_idx = texture_info.index;
|
|
if (texture_idx < 0 || texture_idx >= model.textures.size())
|
|
{
|
|
return "";
|
|
}
|
|
const tinygltf::Texture& texture = model.textures[texture_idx];
|
|
|
|
// Ignore texture.sampler for now
|
|
|
|
const S32 image_idx = texture.source;
|
|
if (image_idx < 0 || image_idx >= model.images.size())
|
|
{
|
|
return "";
|
|
}
|
|
const tinygltf::Image& image = model.images[image_idx];
|
|
|
|
return image.uri;
|
|
}
|
|
|
|
template<typename T>
|
|
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id)
|
|
{
|
|
setFromTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id]);
|
|
const std::string uri = gltf_get_texture_image(model, texture_info);
|
|
}
|
|
|
|
// static
|
|
template<typename T>
|
|
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform)
|
|
{
|
|
LL_PROFILE_ZONE_SCOPED;
|
|
const std::string uri = gltf_get_texture_image(model, texture_info);
|
|
texture_id.set(uri);
|
|
|
|
const tinygltf::Value::Object& extensions_object = texture_info.extensions;
|
|
const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
|
|
if (transform_it != extensions_object.end())
|
|
{
|
|
const tinygltf::Value& transform_json = std::get<1>(*transform_it);
|
|
if (transform_json.IsObject())
|
|
{
|
|
const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>();
|
|
transform.mOffset = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset());
|
|
transform.mScale = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale());
|
|
transform.mRotation = floatFromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation());
|
|
}
|
|
}
|
|
}
|
|
|
|
// static
|
|
template<typename T>
|
|
void LLGLTFMaterial::allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri)
|
|
{
|
|
const S32 image_idx = static_cast<S32>(model.images.size());
|
|
model.images.emplace_back();
|
|
model.images[image_idx].uri = uri;
|
|
|
|
// The texture, not to be confused with the texture info
|
|
const S32 texture_idx = static_cast<S32>(model.textures.size());
|
|
model.textures.emplace_back();
|
|
tinygltf::Texture& texture = model.textures[texture_idx];
|
|
texture.source = image_idx;
|
|
|
|
texture_info.index = texture_idx;
|
|
}
|
|
|
|
// static
|
|
template<typename T>
|
|
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const
|
|
{
|
|
writeToTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id], force_write);
|
|
}
|
|
|
|
// static
|
|
template<typename T>
|
|
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write)
|
|
{
|
|
LL_PROFILE_ZONE_SCOPED;
|
|
const bool is_blank_transform = transform == sDefault.mTextureTransform[0];
|
|
// Check if this material matches all the fallback values, and if so, then
|
|
// skip including it to reduce material size
|
|
if (!force_write && texture_id.isNull() && is_blank_transform)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// tinygltf will discard this texture info if there is no valid texture,
|
|
// causing potential loss of information for overrides, so ensure one is
|
|
// defined. -Cosmic,2023-01-30
|
|
allocateTextureImage(model, texture_info, texture_id.asString());
|
|
|
|
if (!is_blank_transform)
|
|
{
|
|
tinygltf::Value::Object transform_map;
|
|
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
|
|
tinygltf::Value(transform.mOffset.mV[VX]),
|
|
tinygltf::Value(transform.mOffset.mV[VY])
|
|
}));
|
|
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
|
|
tinygltf::Value(transform.mScale.mV[VX]),
|
|
tinygltf::Value(transform.mScale.mV[VY])
|
|
}));
|
|
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
|
|
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
|
|
}
|
|
}
|