Merge branch 'anim-mtlx-phase2' into anim-mtlx-phase3

This commit is contained in:
Syoyo Fujita
2025-12-25 00:00:50 +09:00
3 changed files with 140 additions and 37 deletions

View File

@@ -408,9 +408,11 @@ class TraceManager {
// Format timestamp as ISO 8601 string
#ifndef __EMSCRIPTEN__
// Emscripten has issues with time_point duration conversion
// Use duration_cast to handle different clock duration types
auto start_time_t = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() +
(record.start_time - std::chrono::high_resolution_clock::now()));
std::chrono::duration_cast<std::chrono::system_clock::duration>(
record.start_time - std::chrono::high_resolution_clock::now()));
std::stringstream timestamp_ss;
timestamp_ss << std::put_time(std::gmtime(&start_time_t), "%Y-%m-%dT%H:%M:%S");

View File

@@ -2452,8 +2452,10 @@ struct TimeSamples {
/// Add POD scalar sample using unified storage (Phase 3 path)
/// This is for single POD values (not arrays)
/// Small types (sizeof(T) <= 8) - stored directly in _small_values
template<typename T>
bool add_pod_sample(double t, const T& value, std::string* err = nullptr) {
typename std::enable_if<(sizeof(T) <= 8), bool>::type
add_pod_sample(double t, const T& value, std::string* err = nullptr) {
static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
"add_pod_sample requires POD types");
@@ -2474,24 +2476,54 @@ struct TimeSamples {
_times.push_back(t);
_blocked.push_back(0); // Not blocked
// Storage optimization: small scalars (sizeof(T) <= 8) stored directly in _small_values
// Large scalars (sizeof(T) > 8) stored in _values with offset table
if (sizeof(T) <= 8) {
// Direct storage for small scalars - no offset entry needed
uint64_t small_value = 0;
std::memcpy(&small_value, &value, sizeof(T));
_small_values.push_back(small_value);
} else {
// Offset-based storage for large scalars
size_t byte_offset = _values.size();
_values.resize(byte_offset + sizeof(T));
std::memcpy(_values.data() + byte_offset, &value, sizeof(T));
// Direct storage for small scalars - no offset entry needed
uint64_t small_value = 0;
std::memcpy(&small_value, &value, sizeof(T));
_small_values.push_back(small_value);
// Create encoded offset (not array)
uint64_t encoded_offset = PODTimeSamples::make_offset(byte_offset, false);
_offsets.push_back(encoded_offset);
// Update metadata (scalar, not array)
_is_array = false;
_array_size = 1;
_element_size = sizeof(T);
_dirty = true;
return true;
}
/// Add POD scalar sample using unified storage (Phase 3 path)
/// Large types (sizeof(T) > 8) - stored in _values with offset table
template<typename T>
typename std::enable_if<(sizeof(T) > 8), bool>::type
add_pod_sample(double t, const T& value, std::string* err = nullptr) {
static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
"add_pod_sample requires POD types");
// Auto-initialize on first sample
if (empty()) {
if (!init(value::TypeTraits<T>::type_id())) {
if (err) *err = "Failed to initialize TimeSamples";
return false;
}
}
// If already using _pod_samples (backward compat), delegate to it
if (!_pod_samples.empty()) {
return _pod_samples.add_sample<T>(t, value, err);
}
// Use unified storage for scalar POD
_times.push_back(t);
_blocked.push_back(0); // Not blocked
// Offset-based storage for large scalars
size_t byte_offset = _values.size();
_values.resize(byte_offset + sizeof(T));
std::memcpy(_values.data() + byte_offset, &value, sizeof(T));
// Create encoded offset (not array)
uint64_t encoded_offset = PODTimeSamples::make_offset(byte_offset, false);
_offsets.push_back(encoded_offset);
// Update metadata (scalar, not array)
_is_array = false;
_array_size = 1;

View File

@@ -2672,12 +2672,7 @@ namespace {
bool ListUVNames(const RenderMaterial &material,
const std::vector<UVTexture> &textures,
StringAndIdMap &si_map) {
// Check if material has surface shader
if (!material.surfaceShader.has_value()) {
return true; // No surface shader, return success but empty map
}
// TODO: Use auto
// Helper lambdas to extract UV names from shader parameters
auto fun_vec3 = [&](const ShaderParam<vec3> &param) {
int32_t texId = param.texture_id;
if ((texId >= 0) && (size_t(texId) < textures.size())) {
@@ -2706,17 +2701,88 @@ bool ListUVNames(const RenderMaterial &material,
}
};
fun_vec3(material.surfaceShader->diffuseColor);
fun_vec3(material.surfaceShader->normal);
fun_float(material.surfaceShader->metallic);
fun_float(material.surfaceShader->roughness);
fun_float(material.surfaceShader->clearcoat);
fun_float(material.surfaceShader->clearcoatRoughness);
fun_float(material.surfaceShader->opacity);
fun_float(material.surfaceShader->opacityThreshold);
fun_float(material.surfaceShader->ior);
fun_float(material.surfaceShader->displacement);
fun_float(material.surfaceShader->occlusion);
// Check UsdPreviewSurface shader
if (material.surfaceShader.has_value()) {
fun_vec3(material.surfaceShader->diffuseColor);
fun_vec3(material.surfaceShader->normal);
fun_float(material.surfaceShader->metallic);
fun_float(material.surfaceShader->roughness);
fun_float(material.surfaceShader->clearcoat);
fun_float(material.surfaceShader->clearcoatRoughness);
fun_float(material.surfaceShader->opacity);
fun_float(material.surfaceShader->opacityThreshold);
fun_float(material.surfaceShader->ior);
fun_float(material.surfaceShader->displacement);
fun_float(material.surfaceShader->occlusion);
}
// Check MaterialX OpenPBR shader
if (material.openPBRShader.has_value()) {
// Base layer
fun_float(material.openPBRShader->base_weight);
fun_vec3(material.openPBRShader->base_color);
fun_float(material.openPBRShader->base_roughness);
fun_float(material.openPBRShader->base_metalness);
fun_float(material.openPBRShader->base_diffuse_roughness);
// Specular layer
fun_float(material.openPBRShader->specular_weight);
fun_vec3(material.openPBRShader->specular_color);
fun_float(material.openPBRShader->specular_roughness);
fun_float(material.openPBRShader->specular_ior);
fun_float(material.openPBRShader->specular_ior_level);
fun_float(material.openPBRShader->specular_anisotropy);
fun_float(material.openPBRShader->specular_rotation);
// Transmission
fun_float(material.openPBRShader->transmission_weight);
fun_vec3(material.openPBRShader->transmission_color);
fun_float(material.openPBRShader->transmission_depth);
fun_vec3(material.openPBRShader->transmission_scatter);
fun_float(material.openPBRShader->transmission_scatter_anisotropy);
fun_float(material.openPBRShader->transmission_dispersion);
// Subsurface
fun_float(material.openPBRShader->subsurface_weight);
fun_vec3(material.openPBRShader->subsurface_color);
fun_vec3(material.openPBRShader->subsurface_radius);
fun_float(material.openPBRShader->subsurface_scale);
fun_float(material.openPBRShader->subsurface_anisotropy);
// Sheen
fun_float(material.openPBRShader->sheen_weight);
fun_vec3(material.openPBRShader->sheen_color);
fun_float(material.openPBRShader->sheen_roughness);
// Fuzz
fun_float(material.openPBRShader->fuzz_weight);
fun_vec3(material.openPBRShader->fuzz_color);
fun_float(material.openPBRShader->fuzz_roughness);
// Thin film
fun_float(material.openPBRShader->thin_film_weight);
fun_float(material.openPBRShader->thin_film_thickness);
fun_float(material.openPBRShader->thin_film_ior);
// Coat
fun_float(material.openPBRShader->coat_weight);
fun_vec3(material.openPBRShader->coat_color);
fun_float(material.openPBRShader->coat_roughness);
fun_float(material.openPBRShader->coat_anisotropy);
fun_float(material.openPBRShader->coat_rotation);
fun_float(material.openPBRShader->coat_ior);
fun_vec3(material.openPBRShader->coat_affect_color);
fun_float(material.openPBRShader->coat_affect_roughness);
// Emission
fun_float(material.openPBRShader->emission_luminance);
fun_vec3(material.openPBRShader->emission_color);
// Geometry
fun_float(material.openPBRShader->opacity);
fun_vec3(material.openPBRShader->normal);
fun_vec3(material.openPBRShader->tangent);
}
return true;
}
@@ -5685,9 +5751,12 @@ nonstd::expected<bool, std::string> GetConnectedMtlxTexture(
// Log this node
traversal_log += current_shader->info_id + " -> ";
// Check if this is an ND_image_color4 node
// Check if this is an ND_image node (color or vector variants)
if (current_shader->info_id == "ND_image_color4" ||
current_shader->info_id == "ND_image_color3") {
current_shader->info_id == "ND_image_color3" ||
current_shader->info_id == "ND_image_vector4" ||
current_shader->info_id == "ND_image_vector3" ||
current_shader->info_id == "ND_image_float") {
image_shader = current_shader;
if (tex_abs_path) {
*tex_abs_path = current_path;
@@ -5783,7 +5852,7 @@ nonstd::expected<bool, std::string> GetConnectedMtlxTexture(
}
return nonstd::make_unexpected(
fmt::format("No ND_image_color4 texture node found. {}\n", traversal_log));
fmt::format("No ND_image texture node found (supported: ND_image_color4/color3/vector4/vector3/float). {}\n", traversal_log));
}
static bool RawAssetRead(