Skip to content

Sync with upstream#3

Open
HeDo88TH wants to merge 35 commits into
DroneDB:masterfrom
cnr-isti-vclab:master
Open

Sync with upstream#3
HeDo88TH wants to merge 35 commits into
DroneDB:masterfrom
cnr-isti-vclab:master

Conversation

@HeDo88TH

Copy link
Copy Markdown

No description provided.

Copilot AI review requested due to automatic review settings February 20, 2026 08:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Syncs repository with upstream changes, adding DeepZoom I/O support, new mesh loader capabilities (scale + TS/colormap), and introducing the Nexus3D web package/build pipelines.

Changes:

  • Modernize CMake/Qt discovery and add install/export packaging support.
  • Add DeepZoom support across save/load paths (external node/texture files in _files/).
  • Add new TS loader + colormap utilities and introduce the nexus3d JS package with new CI workflows.

Reviewed changes

Copilot reviewed 53 out of 57 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/nxsview/CMakeLists.txt Raise CMake min version; update Qt OpenGL discovery.
src/nxsedit/extractor.cpp Add DeepZoom extraction mode writing nodes/textures into _files/.
src/nxsedit/CMakeLists.txt Raise CMake min version; remove duplicated cmake/project declarations.
src/nxsbuild/tsloader.h Add TS mesh loader interface.
src/nxsbuild/tsloader.cpp Implement TS loader, colormap parsing, and streaming triangle/vertex reads.
src/nxsbuild/stlloader.cpp Apply scale during STL import.
src/nxsbuild/plyloader.cpp Apply scale and fix texture-flag handling.
src/nxsbuild/objloader.h Change MTL parsing signature to accept the OBJ file handle.
src/nxsbuild/objloader.cpp Auto-discover mtllib and apply scale during OBJ import.
src/nxsbuild/nxsbuild.pro Add TS loader + colormap sources/headers to qmake build.
src/nxsbuild/meshstream.h Add scale and TS colormap options to Stream.
src/nxsbuild/meshstream.cpp Route .ts files to TsLoader; propagate scale.
src/nxsbuild/meshloader.h Add scale property for all loaders.
src/nxsbuild/main.cpp Add CLI options for scale and TS colormap; improve default output naming.
src/nxsbuild/colormap.h Add colormap utility class.
src/nxsbuild/colormap.cpp Implement predefined colormaps + CSV loading + mapping.
src/nxsbuild/CMakeLists.txt Raise CMake min version; remove duplicated cmake/project declarations.
src/corto Update corto submodule SHA.
src/common/signature.h Add Signature::isDeepzoom().
src/common/renderer.cpp Disable custom log2 definition under WIN32.
src/common/qtnexusfile.h Extend NexusFile Qt implementation with DeepZoom APIs + fileName().
src/common/qtnexusfile.cpp Implement DeepZoom node/texture file reads.
src/common/nexusfile.h Extend NexusFile interface for DeepZoom node/texture loading.
src/common/nexusdata.cpp Load node/texture data via DeepZoom APIs; adjust drop/unmap logic.
src/common/nexus.cpp Load textures via DeepZoom APIs in loadImageFromData.
src/CMakeLists.txt Raise CMake min version; add install headers + exported targets.
nexus3d/webpacklib.config.js Add webpack config for building Nexus3D library bundle.
nexus3d/webpack.config.js Add webpack config for the example/dev server.
nexus3d/src/index.js Add example app using Nexus3D with three.js.
nexus3d/src/Traversal.js Add traversal/selection logic for streamed rendering.
nexus3d/src/PriorityQueue.js Add heap-based priority queue used by traversal.
nexus3d/src/Nexus3D.js Add main Nexus3D three.js mesh integration + renderer patching.
nexus3d/src/NXSRaw.js Add legacy/raw nexus renderer implementation.
nexus3d/src/NXS.js Add legacy scenegraph-based nexus implementation.
nexus3d/src/Monitor.js Add runtime monitor UI for cache/error/fps/progress.
nexus3d/src/Mesh.js Add NXS file loader (header/index parsing + deepzoom baseurl).
nexus3d/src/Cache.js Add streaming cache (pending requests, eviction, corto worker).
nexus3d/src/Binary.js Add binary parsing + matrix utilities for Nexus3D.
nexus3d/rollup.config.js Add rollup build for library + corto worker bundling.
nexus3d/package.json Define npm package metadata, scripts, exports and dependencies.
nexus3d/dist/index.html Add example HTML shell for webpack output.
nexus3d/build/nexus3D.min.js Add prebuilt/minified Nexus3D bundle artifact.
nexus3d/build/nexus3D.js Add prebuilt/dev Nexus3D bundle artifact (webpack eval).
nexus3d/README.md Add docs for installing/using Nexus3D.
html/js/nexus.js Add IndexedDB caching; fix texture load call + minor indentation.
NEXUS_VERSION Update version string to 2025.05.
Config.cmake.in Add CMake package config template for downstream find_package(nexus).
CMakeLists.txt Raise CMake min version; prefer system vcglib/corto when available; export/install targets.
.github/workflows/Windows.yml Remove legacy Windows CI workflow.
.github/workflows/MacOS.yml Remove legacy macOS CI workflow.
.github/workflows/Linux.yml Remove legacy Linux CI workflow.
.github/workflows/CreateRelease.yml Add manual release workflow (version bump + build + upload + release).
.github/workflows/BuildNexus.yml Add unified build workflow using composite actions.
.github/actions/upload/action.yml Add composite action to archive/upload per-OS artifacts.
.github/actions/build_and_deploy/action.yml Add composite action to build + deploy per OS/arch.
Comments suppressed due to low confidence (20)

src/nxsbuild/stlloader.cpp:1

  • The Z scaling is applied to d[0] instead of d[2], which will distort geometry (X scaled twice, Z not scaled). Change line 67 to multiply d[2] by scale[2].
    src/nxsbuild/tsloader.cpp:1
  • This condition is always true because a line can't start with both "VRTX" and "PVRTX" at the same time, so all vertices are skipped. Use && here (skip only if it's neither VRTX nor PVRTX).
    src/nxsbuild/tsloader.cpp:1
  • line[0] is a QChar, but it's being compared to a string literal (\"}\"), which will not compile (or will behave incorrectly if it compiles via implicit conversions). Compare against a character literal ('}') or use line.startsWith(\"}\").
    src/nxsbuild/tsloader.cpp:1
  • The bounds checks don't match the indexed access: parts[5 + property_position] requires parts.size() > 5 + property_position, but the current condition checks parts.size() < property_position (which is also incorrect when property_position is negative). Update the condition to validate the exact index and consider splitting with skip-empty-parts to handle multiple spaces.
    src/nxsbuild/tsloader.cpp:1
  • The bounds checks don't match the indexed access: parts[5 + property_position] requires parts.size() > 5 + property_position, but the current condition checks parts.size() < property_position (which is also incorrect when property_position is negative). Update the condition to validate the exact index and consider splitting with skip-empty-parts to handle multiple spaces.
    src/nxsbuild/tsloader.cpp:1
  • When handling ATOM, a new vertex is appended but n_vertices is never incremented, so the next write overwrites the same slot and the count becomes inconsistent. Increment n_vertices after writing the duplicated vertex (and validate id - 1 is within the current cache range).
    src/nxsbuild/tsloader.cpp:1
  • The error message contains a %1 placeholder but doesn't .arg(...) the missing colormap name, so the thrown message is incomplete. Also, return false; is unreachable after throw and can be removed.
    src/nxsbuild/tsloader.cpp:1
  • Correct spelling of 'Proble' to 'Problem' in the error message.
    src/nxsbuild/tsloader.cpp:1
  • Correct spelling of 'Proble' to 'Problem' in the error message.
    src/common/qtnexusfile.cpp:1
  • This returns a pointer into a temporary QByteArray that is destroyed at function exit, leaving a dangling pointer. Store the UTF-8 bytes in a member (e.g., QByteArray cachedName) and return cachedName.constData(), or change the API to return a std::string/QString (or const char* backed by stable storage).
    src/common/nexus.cpp:1
  • dropDZTex takes a char* buffer (per NexusFile interface), but this code passes the texture index t. This is a type/logic mismatch and will either fail to compile or free the wrong thing. Call file->dropDZTex(data.memory) in the DeepZoom case (and keep unmap for the mmap case).
    src/common/nexus.cpp:1
  • dropDZTex takes a char* buffer (per NexusFile interface), but this code passes the texture index t. This is a type/logic mismatch and will either fail to compile or free the wrong thing. Call file->dropDZTex(data.memory) in the DeepZoom case (and keep unmap for the mmap case).
    src/common/nexusdata.cpp:1
  • In DeepZoom mode this loads a texture using loadDZTex(n) where n is the node id, but it should load by texture index t. Also loadImageFromData is commented out, so the mapped/allocated texture data is never consumed nor released here, which leaks memory and breaks texture loading.
    src/common/nexusdata.cpp:1
  • In DeepZoom mode this loads a texture using loadDZTex(n) where n is the node id, but it should load by texture index t. Also loadImageFromData is commented out, so the mapped/allocated texture data is never consumed nor released here, which leaks memory and breaks texture loading.
    src/nxsbuild/colormap.cpp:1
  • The clamp macro includes a trailing semicolon, which can create surprising extra empty statements at call sites, and it also shadows common names (e.g., std::clamp). Prefer an inline function (or std::clamp if available). Also remove the cout << \"Returning true\" debug print to avoid noisy stdout in library code.
    src/nxsbuild/colormap.cpp:1
  • The clamp macro includes a trailing semicolon, which can create surprising extra empty statements at call sites, and it also shadows common names (e.g., std::clamp). Prefer an inline function (or std::clamp if available). Also remove the cout << \"Returning true\" debug print to avoid noisy stdout in library code.
    src/nxsbuild/main.cpp:1
  • If the input filename has no '.', lastIndexOf returns -1 and left(-1) yields an empty/invalid output base. Handle the last == -1 case by using the full filename (or only stripping an extension if one exists).
    src/nxsbuild/main.cpp:1
  • scalate is an unclear name for a user-facing CLI option backing variable. Consider renaming it to something like scaleStr / scaleOption (and keep scale for the parsed numeric vector).
    src/nxsbuild/main.cpp:1
  • scalate is an unclear name for a user-facing CLI option backing variable. Consider renaming it to something like scaleStr / scaleOption (and keep scale for the parsed numeric vector).
    src/nxsbuild/objloader.cpp:1
  • readMTL advances the passed-in OBJ QFile read position while scanning for mtllib, but it no longer preserves/restores the original position (the old pos = file.pos() logic was removed). Saving the initial position and seeking back at the end would make this function safer and less coupled to the caller's file-seek behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nexus3d/src/Traversal.js
Comment on lines +50 to +51
p[16] = -m[2] + m[3]; p[17] = -m[6] + m[7]; p[18] = -m[10] + m[11]; p[19] = -m[14] + m[15]; //near
p[20] = -m[2] + m[3]; p[21] = -m[6] + m[7]; p[22] = -m[10] + m[11]; p[23] = -m[14] + m[15]; //far

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Near and far planes are computed identically, which makes frustum culling incorrect (far plane never differs from near). Update the far-plane extraction formula to the correct row/column combination (typically m[3] - m[2], etc., depending on the matrix layout used elsewhere in this file).

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Traversal.js
Comment on lines +137 to +145
if(cache.nodes.has(mesh)) {
for(let id of cache.nodes.get(mesh)) {
let error = t.nodeError(id);
if(t.instance_errors[id] == 0) {
t.instance_errors[i] = error;
mesh.errors[id] = Math.max(mesh.errors[id], error);
}
}
}

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This writes t.instance_errors[i] = error, but i is not the loop variable here (it refers to an unrelated outer variable), so errors are stored in the wrong slot (or throw in strict mode). This should write to t.instance_errors[id].

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Binary.js
var lo = view.getUint32(view.offset, true);
var hi = view.getUint32(view.offset + 4, true);
view.offset += 8;
return ((hi * (1 << 32)) + lo);

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In JavaScript, (1 << 32) is 1 due to 32-bit shift semantics, so getUint64 returns incorrect values for any hi != 0. Use hi * 2**32 + lo (still limited by IEEE-754 precision) or switch to BigInt arithmetic to represent full 64-bit values reliably.

Suggested change
return ((hi * (1 << 32)) + lo);
return (hi * 2 ** 32 + lo);

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Cache.js
Comment on lines +42 to +43
extract : false, //extraction disabled}
}

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The braces are unbalanced: line 42 closes the object literal, and line 43 closes the _Cache constructor early, leaving subsequent constructor initialization outside the function (breaking module execution). Remove the stray } on line 42 (or move it to its own line) so the object literal closes correctly and the constructor continues.

Suggested change
extract : false, //extraction disabled}
}
extract : false //extraction disabled
};

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Cache.js
Comment on lines +205 to +209
if(mesh.reqAttempt[id] > maxReqAttempt) {
if(this.debug.verbose) console.log("Max request limit for " + m.url + " node: " + n);
t.removeNode(mesh, id);
return;
}

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m and n are undefined in this scope (should be mesh and id), which will throw when these log lines execute and can break recovery logic. Update the log statements to reference the actual parameters.

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Cache.js
switch (mode){
case 0:
t.requestNodeGeometry(mesh, id);
if(this.debug.verbose) console.log("Recovering geometry for " + m.url + " node: " + n);

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m and n are undefined in this scope (should be mesh and id), which will throw when these log lines execute and can break recovery logic. Update the log statements to reference the actual parameters.

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Cache.js
break;
case 1:
t.requestNodeTexture(mesh, id);
if(this.debug.verbose) console.log("Recovering texture for " + m.url + " node: " + n);

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m and n are undefined in this scope (should be mesh and id), which will throw when these log lines execute and can break recovery logic. Update the log statements to reference the actual parameters.

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Monitor.js
Comment on lines +211 to +224
e.cacheStyle.style.background_color = greenToRed(cacheFraction);
e.cacheStyle.style.width = cacheFraction;

e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.background_color = greenToRed(errorFraction);
e.errorStyle.style.width = errorFraction;

e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.background_color = greenToRed(fpsFraction);
e.fpsStyle.style.width = fpsFraction;

e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
e.progressStyle.style.background_color = greenToRed(progressFraction);
e.progressStyle.style.width = progressFraction;

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOM style properties should use camelCase (backgroundColor), and style.width needs a unit (e.g., '42%'). Also progressFraction is computed as a 0..1 fraction but is passed to greenToRed as if it were a percent; convert to 0..100 consistently.

Suggested change
e.cacheStyle.style.background_color = greenToRed(cacheFraction);
e.cacheStyle.style.width = cacheFraction;
e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.background_color = greenToRed(errorFraction);
e.errorStyle.style.width = errorFraction;
e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.background_color = greenToRed(fpsFraction);
e.fpsStyle.style.width = fpsFraction;
e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
e.progressStyle.style.background_color = greenToRed(progressFraction);
e.progressStyle.style.width = progressFraction;
e.cacheStyle.style.backgroundColor = greenToRed(cacheFraction);
e.cacheStyle.style.width = cacheFraction + 'px';
e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.backgroundColor = greenToRed(errorFraction);
e.errorStyle.style.width = errorFraction + 'px';
e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.backgroundColor = greenToRed(fpsFraction);
e.fpsStyle.style.width = fpsFraction + 'px';
e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
let progressPercent = progressFraction * 100;
e.progressStyle.style.backgroundColor = greenToRed(progressPercent);
e.progressStyle.style.width = progressPercent + 'px';

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/src/Monitor.js
Comment on lines +205 to +224

let rendered = context.rendered;

let e = this.elements;

e.cacheLabel.setAttribute('data-label', `${toHuman(cacheSize, 'B')}/${toHuman(maxCacheSize, 'B')}`);
e.cacheStyle.style.background_color = greenToRed(cacheFraction);
e.cacheStyle.style.width = cacheFraction;

e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.background_color = greenToRed(errorFraction);
e.errorStyle.style.width = errorFraction;

e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.background_color = greenToRed(fpsFraction);
e.fpsStyle.style.width = fpsFraction;

e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
e.progressStyle.style.background_color = greenToRed(progressFraction);
e.progressStyle.style.width = progressFraction;

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOM style properties should use camelCase (backgroundColor), and style.width needs a unit (e.g., '42%'). Also progressFraction is computed as a 0..1 fraction but is passed to greenToRed as if it were a percent; convert to 0..100 consistently.

Suggested change
let rendered = context.rendered;
let e = this.elements;
e.cacheLabel.setAttribute('data-label', `${toHuman(cacheSize, 'B')}/${toHuman(maxCacheSize, 'B')}`);
e.cacheStyle.style.background_color = greenToRed(cacheFraction);
e.cacheStyle.style.width = cacheFraction;
e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.background_color = greenToRed(errorFraction);
e.errorStyle.style.width = errorFraction;
e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.background_color = greenToRed(fpsFraction);
e.fpsStyle.style.width = fpsFraction;
e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
e.progressStyle.style.background_color = greenToRed(progressFraction);
e.progressStyle.style.width = progressFraction;
let progressPercent = progressFraction * 100;
let rendered = context.rendered;
let e = this.elements;
e.cacheLabel.setAttribute('data-label', `${toHuman(cacheSize, 'B')}/${toHuman(maxCacheSize, 'B')}`);
e.cacheStyle.style.backgroundColor = greenToRed(cacheFraction);
e.cacheStyle.style.width = `${cacheFraction}%`;
e.errorLabel.setAttribute('data-label', `Real: ${realError.toFixed(1)} px Target: ${currentError.toFixed(1)} px`);
e.errorStyle.style.backgroundColor = greenToRed(errorFraction);
e.errorStyle.style.width = `${errorFraction}%`;
e.fpsLabel.setAttribute('data-label', `${parseInt(Math.round(currentFps))} fps`);
e.fpsStyle.style.backgroundColor = greenToRed(fpsFraction);
e.fpsStyle.style.width = `${fpsFraction}%`;
e.progressLabel.setAttribute('data-label', `${parseInt(Math.round(progressNodes))} nodes`);
e.progressStyle.style.backgroundColor = greenToRed(progressPercent);
e.progressStyle.style.width = `${progressPercent}%`;

Copilot uses AI. Check for mistakes.
Comment thread nexus3d/build/nexus3D.js
Comment on lines +1 to +8
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This committed build artifact is a development bundle using webpack eval devtool, which is not suitable for production or distribution and makes diffs noisy. Prefer generating build outputs in CI/releases (or via npm run build) and exclude them from the repo, or ensure committed artifacts are production builds with stable source maps.

Suggested change
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants