diff --git a/src/tydra/render-data.cc b/src/tydra/render-data.cc index ae318b1c..d6c8bff8 100644 --- a/src/tydra/render-data.cc +++ b/src/tydra/render-data.cc @@ -1129,6 +1129,9 @@ nonstd::expected GetTextureCoordinate( (void)stage; + // HACK + return nonstd::make_unexpected("Disabled"); + std::string err; GeomPrimvar primvar; if (!GetGeomPrimvar(stage, &mesh, name, &primvar, &err)) { @@ -1140,6 +1143,7 @@ nonstd::expected GetTextureCoordinate( "\n"); } + TUSDZ_LOG_I("get tex\n"); // TODO: allow float2? if (primvar.get_type_id() != value::TypeTraits>::type_id()) { @@ -1148,8 +1152,10 @@ nonstd::expected GetTextureCoordinate( primvar.get_type_name() + "\n"); } + TUSDZ_LOG_I("flatten_with_indices\n"); std::vector uvs; if (!primvar.flatten_with_indices(t, &uvs, tinterp)) { + TUSDZ_LOG_I("flatten_with_indices failed\n"); return nonstd::make_unexpected( "Failed to retrieve texture coordinate primvar with concrete type.\n"); } @@ -1167,6 +1173,7 @@ nonstd::expected GetTextureCoordinate( } + TUSDZ_LOG_I("texcoord. " << name << ", " << uvs.size()); DCOUT("texcoord " << name << " : " << uvs); vattr.format = VertexAttributeFormat::Vec2; @@ -1175,6 +1182,7 @@ nonstd::expected GetTextureCoordinate( vattr.indices.clear(); // just in case. vattr.name = name; // TODO: add "primvars:" namespace? + TUSDZ_LOG_I("end"); return std::move(vattr); } @@ -3634,6 +3642,8 @@ bool RenderSceneConverter::ConvertMesh( if (ret) { const VertexAttribute &vattr = ret.value(); + TUSDZ_LOG_I("uv attr"); + // Use slotId 0 uvAttrs[0] = vattr; } else { @@ -3699,6 +3709,7 @@ bool RenderSceneConverter::ConvertMesh( } } + TUSDZ_LOG_I("done uvAttr"); if (mesh.has_primvar(env.mesh_config.default_tangents_primvar_name)) { GeomPrimvar pvar; @@ -5494,6 +5505,7 @@ bool RenderSceneConverter::ConvertUVTexture(const RenderSceneConverterEnv &env, } } else { + TUSDZ_LOG_I("get_value"); Animatable fallbacks = texture.st.get_value(); value::texcoord2f uv; if (fallbacks.get(env.timecode, &uv)) { @@ -5503,6 +5515,7 @@ bool RenderSceneConverter::ConvertUVTexture(const RenderSceneConverterEnv &env, // TODO: report warning. PUSH_WARN("Failed to get fallback `st` texcoord attribute."); } + TUSDZ_LOG_I("uv done"); } } diff --git a/src/usdGeom.cc b/src/usdGeom.cc index bfb65952..61ff05b7 100644 --- a/src/usdGeom.cc +++ b/src/usdGeom.cc @@ -21,6 +21,7 @@ #include "math-util.inc" #include "str-util.hh" #include "value-pprint.hh" +#include "logger.hh" #define SET_ERROR_AND_RETURN(msg) \ if (err) { \ @@ -257,10 +258,12 @@ bool GeomPrimvar::flatten_with_indices(const double t, std::vector *dest, con return false; } + TUSDZ_LOG_I("get_value"); std::vector value; if (_attr.get_value>(t, &value, tinterp)) { uint32_t elementSize = _attr.metas().elementSize.value_or(1); + TUSDZ_LOG_I("elementSize" << elementSize); // Get indices at specified time std::vector indices; @@ -273,9 +276,11 @@ bool GeomPrimvar::flatten_with_indices(const double t, std::vector *dest, con } else { _ts_indices.get(&indices, t, tinterp); } + TUSDZ_LOG_I("indices.size " << indices.size()); std::vector expanded_val; auto ret = ExpandWithIndices(value, elementSize, indices, &expanded_val); + TUSDZ_LOG_I("ExpandWithIndices done"); if (ret) { (*dest) = expanded_val; // Currently we ignore ret.value() diff --git a/web/CMakeLists.txt b/web/CMakeLists.txt index 10b0e6cd..edea0be4 100644 --- a/web/CMakeLists.txt +++ b/web/CMakeLists.txt @@ -23,7 +23,17 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -if (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + + if (TINYUSDZ_WASM64) + set(CMAKE_CXX_FLAGS_DEBUG "-g4 -sMEMORY64") + set(CMAKE_C_FLAGS_DEBUG "-g4 -sMEMORY64") + else() + set(CMAKE_CXX_FLAGS_DEBUG "-g4") # -sMEMORY64" + set(CMAKE_C_FLAGS_DEBUG "-g4") # -sMEMORY64" + endif() + +elseif (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") # Use Oz to reduce size further than Os if (TINYUSDZ_WASM64) @@ -97,16 +107,29 @@ endif() # --source-map-base http://localhost:8021/ # flags = try to lower heap memory use -set(TINYUSDZ_EMCC_LINK_FLAGS "-Oz -sENVIRONMENT='web,worker,node' \ - -sMALLOC=emmalloc \ - -sSTACK_SIZE=512000 \ - -sALLOW_MEMORY_GROWTH=1 \ - -sFILESYSTEM=0 \ - -sSAFE_HEAP=0 \ - -sWASM_BIGINT=1 \ - -sMODULARIZE=1 -sEXPORT_ES6 \ - -sINVOKE_RUN=0 --bind ") +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(TINYUSDZ_EMCC_LINK_FLAGS "-g4 -sENVIRONMENT='web,worker,node' \ + -sMALLOC=emmalloc \ + -sSTACK_SIZE=1024000 \ + -sALLOW_MEMORY_GROWTH=1 \ + -sFILESYSTEM=0 \ + -sSAFE_HEAP=1 \ + -sWASM_BIGINT=1 \ + -sMODULARIZE=1 -sEXPORT_ES6 \ + -sINVOKE_RUN=0 --bind ") +else() + set(TINYUSDZ_EMCC_LINK_FLAGS "-Oz -sENVIRONMENT='web,worker,node' \ + -sMALLOC=emmalloc \ + -sSTACK_SIZE=512000 \ + -sALLOW_MEMORY_GROWTH=1 \ + -sFILESYSTEM=0 \ + -sSAFE_HEAP=10 \ + -sWASM_BIGINT=1 \ + -sMODULARIZE=1 -sEXPORT_ES6 \ + -sINVOKE_RUN=0 --bind ") +endif() + if (TINYUSDZ_WASM64) # assertion=1 cause runtime error(Cannot mix BigInt and ... in assert()), so use 2 string(APPEND TINYUSDZ_EMCC_LINK_FLAGS " -sASSERTIONS=2 -sMEMORY64 -sMAXIMUM_MEMORY=8GB") diff --git a/web/bootstrap-linux-debug.sh b/web/bootstrap-linux-debug.sh new file mode 100755 index 00000000..e9d105ba --- /dev/null +++ b/web/bootstrap-linux-debug.sh @@ -0,0 +1,4 @@ +rm -rf build_debug +mkdir build_debug + +emcmake cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_VERBOSE_MAKEFILE=1 -Bbuild_debug diff --git a/web/js/animation-info.js b/web/js/animation-info.js index 9633fa21..ac2fb850 100644 --- a/web/js/animation-info.js +++ b/web/js/animation-info.js @@ -25,7 +25,7 @@ function reportMemUsage() { } // Print animation clip info -function printAnimationClips(usd, detailed = false) { +function printAnimationClips(usd, detailed = false, dumpKeyframes = false) { const numAnims = usd.numAnimations(); if (numAnims === 0) { @@ -110,6 +110,60 @@ function printAnimationClips(usd, detailed = false) { if (sampler.times && sampler.times.length > 0) { console.log(` Keyframes: ${sampler.times.length}`); console.log(` Time Range: ${sampler.times[0].toFixed(3)}s - ${sampler.times[sampler.times.length - 1].toFixed(3)}s`); + + // Dump keyframe data if --keyframes flag is set + if (dumpKeyframes) { + console.log(` Keyframe Data:`); + for (let k = 0; k < sampler.times.length; k++) { + const time = sampler.times[k].toFixed(3); + let valueStr = ''; + + if (sampler.values) { + // Handle different value types + if (channel.path && channel.path.includes('translation')) { + // Translation: 3 floats per keyframe + const idx = k * 3; + if (sampler.values[idx] !== undefined) { + valueStr = `[${sampler.values[idx].toFixed(3)}, ${sampler.values[idx+1].toFixed(3)}, ${sampler.values[idx+2].toFixed(3)}]`; + } + } else if (channel.path && channel.path.includes('rotation')) { + // Rotation: could be 3 (euler) or 4 (quaternion) floats + const componentsPerKey = sampler.values.length / sampler.times.length; + const idx = k * componentsPerKey; + if (componentsPerKey === 4) { + valueStr = `[${sampler.values[idx].toFixed(3)}, ${sampler.values[idx+1].toFixed(3)}, ${sampler.values[idx+2].toFixed(3)}, ${sampler.values[idx+3].toFixed(3)}]`; + } else if (componentsPerKey === 3) { + valueStr = `[${sampler.values[idx].toFixed(3)}, ${sampler.values[idx+1].toFixed(3)}, ${sampler.values[idx+2].toFixed(3)}]`; + } + } else if (channel.path && channel.path.includes('scale')) { + // Scale: 3 floats per keyframe + const idx = k * 3; + if (sampler.values[idx] !== undefined) { + valueStr = `[${sampler.values[idx].toFixed(3)}, ${sampler.values[idx+1].toFixed(3)}, ${sampler.values[idx+2].toFixed(3)}]`; + } + } else { + // Generic handling: try to determine component count + const componentsPerKey = sampler.values.length / sampler.times.length; + const idx = k * componentsPerKey; + const components = []; + for (let c = 0; c < componentsPerKey; c++) { + if (sampler.values[idx + c] !== undefined) { + components.push(sampler.values[idx + c].toFixed(3)); + } + } + if (components.length > 0) { + valueStr = componentsPerKey === 1 ? components[0] : `[${components.join(', ')}]`; + } + } + } + + if (valueStr) { + console.log(` Frame ${k}: t=${time}s, value=${valueStr}`); + } else { + console.log(` Frame ${k}: t=${time}s`); + } + } + } } if (sampler.interpolation) { console.log(` Interpolation: ${sampler.interpolation}`); @@ -123,18 +177,73 @@ function printAnimationClips(usd, detailed = false) { console.log(` Skeletal Joint Channels: ${skeletalChannels}`); } - // Legacy track information (if present) + // Track information (main animation data in TinyUSDZ) if (anim.tracks && anim.tracks.length) { - console.log(`\n Legacy Track Information:`); - console.log(` Tracks: ${anim.tracks.length}`); + console.log(`\n Track Information:`); + console.log(` Total Tracks: ${anim.tracks.length}`); anim.tracks.forEach((track, idx) => { - console.log(` Track ${idx}: ${track.name || 'unnamed'}`); - if (track.type) console.log(` Type: ${track.type}`); - if (track.keyframes && track.keyframes.length) { - console.log(` Keyframes: ${track.keyframes.length}`); - const times = track.times || []; - if (times.length > 0) { - console.log(` Time range: ${times[0].toFixed(3)}s - ${times[times.length - 1].toFixed(3)}s`); + console.log(`\n Track ${idx}: ${track.name || 'unnamed'}`); + if (track.type) console.log(` Type: ${track.type}`); + if (track.path) console.log(` Path: ${track.path}`); + if (track.target) console.log(` Target: ${track.target}`); + if (track.interpolation) console.log(` Interpolation: ${track.interpolation}`); + + // Show keyframe count and time range + if (track.times && track.times.length > 0) { + console.log(` Keyframes: ${track.times.length}`); + console.log(` Time range: ${track.times[0].toFixed(3)}s - ${track.times[track.times.length - 1].toFixed(3)}s`); + } else if (track.keyframes && track.keyframes.length) { + console.log(` Keyframes: ${track.keyframes.length}`); + } + + // Dump keyframe data if requested + if (dumpKeyframes) { + if (track.times && track.values) { + console.log(` Keyframe Data:`); + for (let k = 0; k < track.times.length; k++) { + const time = track.times[k].toFixed(3); + let valueStr = ''; + + // Determine the number of components per keyframe + const numValues = track.values.length; + const numKeys = track.times.length; + const componentsPerKey = numValues / numKeys; + + // Extract value based on component count + const idx = k * componentsPerKey; + if (componentsPerKey === 1) { + valueStr = track.values[idx].toFixed(3); + } else if (componentsPerKey === 3) { + valueStr = `[${track.values[idx].toFixed(3)}, ${track.values[idx+1].toFixed(3)}, ${track.values[idx+2].toFixed(3)}]`; + } else if (componentsPerKey === 4) { + valueStr = `[${track.values[idx].toFixed(3)}, ${track.values[idx+1].toFixed(3)}, ${track.values[idx+2].toFixed(3)}, ${track.values[idx+3].toFixed(3)}]`; + } else { + // Generic handling for any number of components + const components = []; + for (let c = 0; c < componentsPerKey; c++) { + components.push(track.values[idx + c].toFixed(3)); + } + valueStr = `[${components.join(', ')}]`; + } + + console.log(` Frame ${k}: t=${time}s, value=${valueStr}`); + } + } else if (track.keyframes) { + console.log(` Keyframe Data:`); + track.keyframes.forEach((keyframe, k) => { + let timeStr = keyframe.time !== undefined ? keyframe.time.toFixed(3) : 'unknown'; + let valueStr = ''; + + if (keyframe.value !== undefined) { + if (Array.isArray(keyframe.value)) { + valueStr = `[${keyframe.value.map(v => v.toFixed(3)).join(', ')}]`; + } else { + valueStr = keyframe.value.toFixed(3); + } + } + + console.log(` Frame ${k}: t=${timeStr}s, value=${valueStr}`); + }); } } }); @@ -180,11 +289,13 @@ async function main() { console.log('Arguments:'); console.log(' Path to USD file (.usd, .usda, .usdc, .usdz)'); console.log(' --detailed Print detailed animation track information'); + console.log(' --keyframes Dump all keyframe data (times and values)'); console.log(' --memory Print memory usage statistics'); console.log(' --help Show this help message\n'); console.log('Examples:'); console.log(' node animation-info.js ../../models/suzanne-subd-lv4.usdc'); console.log(' node animation-info.js animation.usd --detailed'); + console.log(' node animation-info.js cube-animation.usda --detailed --keyframes'); console.log(' node animation-info.js model.usdz --detailed --memory'); return; } @@ -194,6 +305,7 @@ async function main() { const detailed = args.includes('--detailed'); const showMemory = args.includes('--memory'); const showHelp = args.includes('--help'); + const dumpKeyframes = args.includes('--keyframes'); if (showHelp) { console.log('node animation-info.js - USD Animation Information Viewer\n'); @@ -201,6 +313,7 @@ async function main() { console.log('Arguments:'); console.log(' Path to USD file (.usd, .usda, .usdc, .usdz)'); console.log(' --detailed Print detailed animation track information'); + console.log(' --keyframes Dump all keyframe data (times and values)'); console.log(' --memory Print memory usage statistics'); console.log(' --help Show this help message'); return; @@ -247,7 +360,7 @@ async function main() { // Print information printSceneInfo(usd); - printAnimationClips(usd, detailed); + printAnimationClips(usd, detailed, dumpKeyframes); // Print memory usage if requested if (showMemory) { diff --git a/web/js/animation.html b/web/js/animation.html index 05decbc8..72ae9659 100644 --- a/web/js/animation.html +++ b/web/js/animation.html @@ -82,11 +82,11 @@ The scene loads a USD model and can play both synthetic and USD-embedded animations.

- Current file: suzanne.usdc + Current file:

- +