Revision control

++ // Copyright (C) 2022 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ import QtQuick
++ import QtQuick3D
++
++ Node {
++ id: root
++ required property Camera camera
++ required property var distances
++ property real fadeDistance: 0.0
++
++ onChildrenChanged: {
++ // Add distance threshold values to instanced children
++ var distIndex = 0; // Handle distance index separately to allow non-node children
++ for (var i = 0; i < children.length; i++) {
++ if (!(children[i] instanceof Model) || !children[i].instancing)
++ continue;
++
++ if (distIndex - 1 >= 0)
++ children[i].instancingLodMin = distances[distIndex - 1];
++
++ if (distances.length > distIndex)
++ children[i].instancingLodMax = distances[distIndex];
++
++ distIndex++;
++ }
++ }
++
++ function update() {
++ var distIndex = 0; // Handle distance index separately to allow non-node children
++ for (var i = 0; i < root.children.length; i++) {
++ var node = root.children[i];
++ if (!(node instanceof Node))
++ continue;
++ if (node instanceof Model && node.instancing)
++ continue;
++ if (distIndex > distances.length)
++ break;
++
++ // Hide all nodes by default
++ node.visible = false;
++
++ var minThreshold = 0;
++ var maxThreshold = -1;
++
++ if (distIndex - 1 >= 0)
++ minThreshold = distances[distIndex - 1] - fadeDistance;
++
++ if (distances.length > distIndex)
++ maxThreshold = distances[distIndex] + fadeDistance;
++
++ // Show nodes that are inside the minimum and maximum distance thresholds
++ var distance = node.scenePosition.minus(camera.scenePosition).length();
++ if (distance >= minThreshold && (maxThreshold < 0 || distance < maxThreshold))
++ node.visible = true;
++
++ // Fade models by adjusting opacity if fadeDistance is set
++ if (children[i] instanceof Model && fadeDistance > 0) {
++ var fadeAlpha = -(minThreshold - distance) / fadeDistance;
++ if (fadeAlpha > 1.0 && maxThreshold > 0)
++ fadeAlpha = (maxThreshold - distance) / fadeDistance;
++
++ children[i].opacity = fadeAlpha;
++ }
++
++ distIndex++;
++ }
++ }
++ Component.onCompleted: {
++ root.update()
++ }
++
++ Connections {
++ target: root.camera
++ function onScenePositionChanged() {
++ root.update()
++ }
++ }
++ }