Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Rendering distance in Qt Quick 3D
QtWS25 Last Chance

Rendering distance in Qt Quick 3D

Scheduled Pinned Locked Moved Solved Game Development
4 Posts 2 Posters 579 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bluezoo
    wrote on 20 Sept 2024, 10:23 last edited by
    #1

    Hi

    I realise that most of the discussion here is about Qt3D, but i have a question about Qt Quick 3D. Even in basic example, the max rendering distance from the camera seems to be fixed.

    E.g. positioning a sphere at the origin looks like this
    ac97c996-a9fd-4ffd-b49c-0d06821349ba-image.png
    But when you zoom out one step further, the sphere disappears:
    9604b315-1100-4a93-9f3c-93315960a1a6-image.png

    I see there is a clipFar property on the PerspectiveCamera that i am using, but it doesn't seem to change this behaviour. Is there any way to get it to keep rendering a larger distance away?

    Thanks in advance.

    Minimal QML for this is as below:

    import QtQuick
    import QtQuick3D
    import QtQuick3D.Helpers
    
    Item {
        anchors.fill: parent
    
        Node {
            id: sceneRoot
    
            Model {
                source: "#Sphere"
                materials: [
                    PrincipledMaterial {
                        baseColor: "red"
                    }
                ]
    
                scale: Qt.vector3d(10.0, 20.0, 20.0)
                position:  Qt.vector3d(-100.0, 200.0, 0.0)
                eulerRotation.y: 30
            }
        }
    
        View3D {
            anchors.fill: parent
            importScene: sceneRoot
    
            environment: ExtendedSceneEnvironment {
                backgroundMode: SceneEnvironment.SkyBox
                lightProbe: Texture {
                    textureData: ProceduralSkyTextureData{}
                }
    
                InfiniteGrid {
                    gridInterval: 100
                }
            }
    
            Node {
                id: originNode
                eulerRotation.x: -60
    
                PerspectiveCamera {
                    id: cameraNode
                    z: 400
    
                    clipFar: 100000.0
                }
            }
    
            OrbitCameraController {
                origin: originNode
                camera: cameraNode
            }
        }
    }
    
    
    J 1 Reply Last reply 22 Sept 2024, 07:46
    0
    • B bluezoo
      20 Sept 2024, 10:23

      Hi

      I realise that most of the discussion here is about Qt3D, but i have a question about Qt Quick 3D. Even in basic example, the max rendering distance from the camera seems to be fixed.

      E.g. positioning a sphere at the origin looks like this
      ac97c996-a9fd-4ffd-b49c-0d06821349ba-image.png
      But when you zoom out one step further, the sphere disappears:
      9604b315-1100-4a93-9f3c-93315960a1a6-image.png

      I see there is a clipFar property on the PerspectiveCamera that i am using, but it doesn't seem to change this behaviour. Is there any way to get it to keep rendering a larger distance away?

      Thanks in advance.

      Minimal QML for this is as below:

      import QtQuick
      import QtQuick3D
      import QtQuick3D.Helpers
      
      Item {
          anchors.fill: parent
      
          Node {
              id: sceneRoot
      
              Model {
                  source: "#Sphere"
                  materials: [
                      PrincipledMaterial {
                          baseColor: "red"
                      }
                  ]
      
                  scale: Qt.vector3d(10.0, 20.0, 20.0)
                  position:  Qt.vector3d(-100.0, 200.0, 0.0)
                  eulerRotation.y: 30
              }
          }
      
          View3D {
              anchors.fill: parent
              importScene: sceneRoot
      
              environment: ExtendedSceneEnvironment {
                  backgroundMode: SceneEnvironment.SkyBox
                  lightProbe: Texture {
                      textureData: ProceduralSkyTextureData{}
                  }
      
                  InfiniteGrid {
                      gridInterval: 100
                  }
              }
      
              Node {
                  id: originNode
                  eulerRotation.x: -60
      
                  PerspectiveCamera {
                      id: cameraNode
                      z: 400
      
                      clipFar: 100000.0
                  }
              }
      
              OrbitCameraController {
                  origin: originNode
                  camera: cameraNode
              }
          }
      }
      
      
      J Offline
      J Offline
      johngod
      wrote on 22 Sept 2024, 07:46 last edited by
      #2

      @bluezoo Hi

      This seems like a bug of OrbitController. I replaced in your code moving the camera with the mouse whell and changing clipFar to different distances, it works.

      import QtQuick
      import QtQuick3D
      import QtQuick3D.Helpers
      
      
      Window {
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          View3D {
              anchors.fill: parent
              camera: cameraNode
      
              environment: ExtendedSceneEnvironment {
                  backgroundMode: SceneEnvironment.SkyBox
                  lightProbe: Texture {
                      textureData: ProceduralSkyTextureData{}
                  }
      
                  InfiniteGrid {
                      gridInterval: 100
                  }
              }
      
              Node {
                  id: originNode
                  //eulerRotation.x: -60
                  PerspectiveCamera {
                      id: cameraNode
                      y: 100
                      z: 3000
                      clipNear: 1
                      clipFar: 20000
                      onPositionChanged: console.log("camera position: ", position)
                  }
      
                  Model {
                      source: "#Sphere"
                      materials: [
                          PrincipledMaterial {
                              baseColor: "red"
                          }
                      ]
      
                      scale: Qt.vector3d(10.0, 20.0, 20.0)
                      //position:  Qt.vector3d(-100.0, 200.0, 0.0)
                      //eulerRotation.y: 30
                  }
      
              }//originNode
      
              /*OrbitCameraController {
                  anchors.fill: parent
                  origin: originNode
                  camera: cameraNode
              }*/
      
          }//View3D
      
          MouseArea {
              anchors.fill: parent
              onWheel: {
                  console.log("angleDelta: ", wheel.angleDelta.y)
                  if (wheel.angleDelta.y > 0)
                      cameraNode.position.z += 100
                  else
                      cameraNode.position.z -= 100
              }
          }
      }
      

      If you comment MouseArea and uncomment OrbitCameraController it will fail. Note that I adated your code slighty has it was crashing, also remove the euler rotations for simplicity. Please fill a bug report at https://bugreports.qt.io
      As a workaround you could try to mimic OrbitCameraController with MouseArea and quaternions which is not very trivial, or try to scale down the all view, so that it will not go further than the 10000 distance units.

      1 Reply Last reply
      1
      • B Offline
        B Offline
        bluezoo
        wrote on 23 Sept 2024, 13:24 last edited by
        #3

        Ah I see - thanks for working this out...this was going to be a showstopper for what I was trying to achieve, so this is much appreciated. I will work on a replacement for the OrbitCameraController, and file the bug report. Apologies for the non-working code - I excised it from a larger project and didn't get a chance to test it before I posted.

        J 1 Reply Last reply 24 Sept 2024, 02:27
        0
        • B bluezoo has marked this topic as solved on 23 Sept 2024, 13:25
        • B bluezoo
          23 Sept 2024, 13:24

          Ah I see - thanks for working this out...this was going to be a showstopper for what I was trying to achieve, so this is much appreciated. I will work on a replacement for the OrbitCameraController, and file the bug report. Apologies for the non-working code - I excised it from a larger project and didn't get a chance to test it before I posted.

          J Offline
          J Offline
          johngod
          wrote on 24 Sept 2024, 02:27 last edited by johngod
          #4

          @bluezoo Hi again

          Here is quick fix fully working, I just checked OrbitCameraController.qml code, indeed it has the clipNear and clipFar values hardcoded. Add a new qml file to your project, call it NewController or whatever, copy paste the OrbitCameraController.qml code and remove the connection that is causing the bug. Then just use the NewController component instead of OrbitCameraController.

          NewController.qml:

          // Copyright (C) 2022 The Qt Company Ltd.
          // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
          
          import QtQuick
          import QtQuick3D
          
          Item {
              id: root
              required property Node origin
              required property Camera camera
          
              property real xSpeed: 0.1
              property real ySpeed: 0.1
          
              property bool xInvert: false
              property bool yInvert: true
          
              property bool mouseEnabled: true
              property bool panEnabled: true
          
              readonly property bool inputsNeedProcessing: status.useMouse || status.isPanning
          
              implicitWidth: parent.width
              implicitHeight: parent.height
          
              /*Connections {
                  target: root.camera
                  function onZChanged() {
                      // Adjust near/far values based on distance
                      let distance = root.camera.z
                      if (distance < 1) {
                          root.camera.clipNear = 0.01
                          root.camera.clipFar = 100
                          if (camera.z === 0) {
                              console.warn("camera z set to 0, setting it to near clip")
                              root.camera.z = camera.clipNear
                              }
                      } else if (distance < 100) {
                          root.camera.clipNear = 0.1
                          root.camera.clipFar = 1000
                      } else {
                          root.camera.clipNear = 1
                          root.camera.clipFar = 10000
                      }
                  }
              }*/
          
              DragHandler {
                  id: dragHandler
                  target: null
                  enabled: root.mouseEnabled
                  acceptedModifiers: Qt.NoModifier
                  onCentroidChanged: {
                      root.mouseMoved(Qt.vector2d(centroid.position.x, centroid.position.y), false);
                  }
          
                  onActiveChanged: {
                      if (active)
                          root.mousePressed(Qt.vector2d(centroid.position.x, centroid.position.y));
                      else
                          root.mouseReleased(Qt.vector2d(centroid.position.x, centroid.position.y));
                  }
              }
          
              DragHandler {
                  id: ctrlDragHandler
                  target: null
                  enabled: root.mouseEnabled && root.panEnabled
                  acceptedModifiers: Qt.ControlModifier
                  onCentroidChanged: {
                      root.panEvent(Qt.vector2d(centroid.position.x, centroid.position.y));
                  }
          
                  onActiveChanged: {
                      if (active)
                          root.startPan(Qt.vector2d(centroid.position.x, centroid.position.y));
                      else
                          root.endPan();
                  }
              }
          
              PinchHandler {
                  id: pinchHandler
                  target: null
                  enabled: root.mouseEnabled
          
                  property real distance: 0.0
                  onCentroidChanged: {
                      root.panEvent(Qt.vector2d(centroid.position.x, centroid.position.y))
                  }
          
                  onActiveChanged: {
                      if (active) {
                          root.startPan(Qt.vector2d(centroid.position.x, centroid.position.y))
                          distance = root.camera.z
                      } else {
                          root.endPan()
                          distance = 0.0
                      }
                  }
                  onScaleChanged: {
                      root.camera.z = distance * (1 / scale)
                  }
              }
          
              TapHandler {
                  onTapped: root.forceActiveFocus() // qmllint disable signal-handler-parameters
              }
          
              WheelHandler {
                  id: wheelHandler
                  orientation: Qt.Vertical
                  target: null
                  enabled: root.mouseEnabled
                  acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
                  onWheel: event => {
                      let delta = -event.angleDelta.y * 0.01;
                      root.camera.z += root.camera.z * 0.1 * delta
                  }
              }
          
              function mousePressed(newPos) {
                  root.forceActiveFocus()
                  status.currentPos = newPos
                  status.lastPos = newPos
                  status.useMouse = true;
              }
          
              function mouseReleased(newPos) {
                  status.useMouse = false;
              }
          
              function mouseMoved(newPos: vector2d) {
                  status.currentPos = newPos;
              }
          
              function startPan(pos: vector2d) {
                  status.isPanning = true;
                  status.currentPanPos = pos;
                  status.lastPanPos = pos;
              }
          
              function endPan() {
                  status.isPanning = false;
              }
          
              function panEvent(newPos: vector2d) {
                  status.currentPanPos = newPos;
              }
          
              FrameAnimation {
                  id: updateTimer
                  running: root.inputsNeedProcessing
                  onTriggered: status.processInput(frameTime * 100)
              }
          
              QtObject {
                  id: status
          
                  property bool useMouse: false
                  property bool isPanning: false
          
                  property vector2d lastPos: Qt.vector2d(0, 0)
                  property vector2d lastPanPos: Qt.vector2d(0, 0)
                  property vector2d currentPos: Qt.vector2d(0, 0)
                  property vector2d currentPanPos: Qt.vector2d(0, 0)
          
                  function negate(vector) {
                      return Qt.vector3d(-vector.x, -vector.y, -vector.z)
                  }
          
                  function processInput(frameDelta) {
                      if (useMouse) {
                          // Get the delta
                          var rotationVector = root.origin.eulerRotation;
                          var delta = Qt.vector2d(lastPos.x - currentPos.x,
                                                  lastPos.y - currentPos.y);
                          // rotate x
                          var rotateX = delta.x * xSpeed * frameDelta
                          if (xInvert)
                              rotateX = -rotateX;
                          rotationVector.y += rotateX;
          
                          // rotate y
                          var rotateY = delta.y * -ySpeed * frameDelta
                          if (yInvert)
                              rotateY = -rotateY;
                          rotationVector.x += rotateY;
                          origin.setEulerRotation(rotationVector);
                          lastPos = currentPos;
                      }
                      if (isPanning) {
                          let delta = currentPanPos.minus(lastPanPos);
                          delta.x = -delta.x
          
                          delta.x = (delta.x / root.width) * camera.z * frameDelta
                          delta.y = (delta.y / root.height) * camera.z * frameDelta
          
                          let velocity = Qt.vector3d(0, 0, 0)
                          // X Movement
                          let xDirection = origin.right
                          velocity = velocity.plus(Qt.vector3d(xDirection.x * delta.x,
                                                               xDirection.y * delta.x,
                                                               xDirection.z * delta.x));
                          // Y Movement
                          let yDirection = origin.up
                          velocity = velocity.plus(Qt.vector3d(yDirection.x * delta.y,
                                                               yDirection.y * delta.y,
                                                               yDirection.z * delta.y));
          
                          origin.position = origin.position.plus(velocity)
          
                          lastPanPos = currentPanPos
                      }
                  }
              }
          }
          
          

          In main.qml replace OrbitCameraController with NewController

          NewController {
                      anchors.fill: parent
                      origin: originNode
                      camera: cameraNode
                  }
          

          Edit: I created a bug report here https://bugreports.qt.io/browse/QTBUG-129253

          Edit 2: I see you also created a bug report, thank you, I did search before I post the bug report but since I did not find it, I went ahead, sorry :)

          1 Reply Last reply
          0

          4/4

          24 Sept 2024, 02:27

          • Login

          • Login or register to search.
          4 out of 4
          • First post
            4/4
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved