| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // Copyright (C) 2025 The Qt Company Ltd.
- // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
- import QtQuick
- import QtQuick.Controls
- import QtQuick.Layouts
- import QtQuick.Window
- import QtQuick.Dialogs
- import QtQuick3D
- import QtQuick3D.Helpers
- import QtQuick3D.lightmapviewer
- import LightmapFile 1.0
- ColumnLayout {
- id: root
- anchors.fill: parent
- property string selectedModelCandidate: ""
- onSelectedModelCandidateChanged: {
- if (!selectedModelCandidate || selectedModelCandidate === "") {
- view.lmTextureCandidates = []
- lview.mSelectedTextureCandidate = -1
- return
- }
- view.lmTextureCandidates = LightmapFile.texturesAvailableFor(
- selectedModelCandidate)
- view.lmSelectedTextureCandidate
- = view.lmTextureCandidates.length ? view.lmTextureCandidates[0].value : -1
- }
- Pane {
- Layout.fillWidth: true
- padding: 8
- ColumnLayout {
- width: parent.width
- spacing: 6
- ColumnLayout {
- RowLayout {
- Label {
- text: "Key:"
- }
- ComboBox {
- id: comboLmModelCandidate
- Layout.preferredWidth: 220
- model: view.lmModelCandidates
- onActivated: root.selectedModelCandidate = currentText
- currentIndex: {
- const i = view.lmModelCandidates.indexOf(
- root.selectedModelCandidate)
- return (i >= 0 ? i : -1)
- }
- enabled: !!selectedEntry
- && selectedEntry.kind === "mesh"
- }
- Label {
- text: "Texture:"
- }
- ComboBox {
- id: comboLmTextureCandidate
- Layout.preferredWidth: 220
- model: view.lmTextureCandidates
- textRole: "name"
- valueRole: "value"
- function indexForValue(val) {
- for (var i = 0; i < view.lmTextureCandidates.length; ++i)
- if (view.lmTextureCandidates[i].value === val)
- return i
- return -1
- }
- onActivated: view.lmSelectedTextureCandidate = Number(
- currentValue)
- currentIndex: indexForValue(
- view.lmSelectedTextureCandidate)
- enabled: !!selectedEntry
- && selectedEntry.kind === "mesh"
- }
- }
- RowLayout {
- CheckBox {
- id: checkboxBfCull
- text: "Backface Culling"
- checked: true
- }
- CheckBox {
- id: checkboxDebugUV
- text: "Debug UV"
- checked: false
- }
- }
- }
- }
- }
- View3D {
- id: view
- Layout.fillWidth: true
- Layout.fillHeight: true
- enabled: meshLoader.visible
- visible: meshLoader.visible
- property var lmModelCandidates: []
- property var lmTextureCandidates: []
- property int lmSelectedTextureCandidate: -1
- property real boundsDiameter: 0
- property vector3d boundsCenter
- property vector3d boundsSize
- function updateBounds(bounds) {
- boundsSize = Qt.vector3d(bounds.maximum.x - bounds.minimum.x,
- bounds.maximum.y - bounds.minimum.y,
- bounds.maximum.z - bounds.minimum.z)
- boundsDiameter = Math.max(boundsSize.x, boundsSize.y, boundsSize.z)
- boundsCenter = Qt.vector3d(
- (bounds.maximum.x + bounds.minimum.x) / 2,
- (bounds.maximum.y + bounds.minimum.y) / 2,
- (bounds.maximum.z + bounds.minimum.z) / 2)
- model.position = Qt.vector3d(-boundsCenter.x, -boundsCenter.y,
- -boundsCenter.z)
- cameraNode.clipNear = boundsDiameter / 100
- cameraNode.clipFar = boundsDiameter * 10
- resetCamera()
- }
- function resetCamera() {
- cameraNode.position = boundsCenter
- cameraNode.position = Qt.vector3d(0, 0, 2 * boundsDiameter)
- cameraNode.eulerRotation = Qt.vector3d(0, 0, 0)
- }
- function refreshLightmapSelection() {
- if (!selectedEntry) {
- lmModelCandidates = []
- root.selectedModelCandidate = ""
- lmTextureCandidates = []
- lmSelectedTextureCandidate = -1
- return
- }
- if (selectedEntry.kind === "image") {
- lmModelCandidates = [selectedEntry.key]
- root.selectedModelCandidate = selectedEntry.key
- } else if (selectedEntry.kind === "mesh") {
- lmModelCandidates = LightmapFile.keysReferencingMesh(
- selectedEntry.key)
- root.selectedModelCandidate = lmModelCandidates.length ? lmModelCandidates[0] : ""
- } else {
- lmModelCandidates = []
- root.selectedModelCandidate = ""
- lmTextureCandidates = []
- lmSelectedTextureCandidate = -1
- }
- }
- Component.onCompleted: refreshLightmapSelection()
- Connections {
- target: window
- function onSelectedEntryChanged() {
- view.refreshLightmapSelection()
- }
- }
- environment: SceneEnvironment {
- backgroundMode: SceneEnvironment.Color
- clearColor: "black"
- }
- PerspectiveCamera {
- id: cameraNode
- z: 300
- }
- Node {
- id: modelNode
- Model {
- id: model
- geometry: LightmapMesh {
- source: LightmapFile.source
- key: selectedEntry.key
- onBoundsChanged: view.updateBounds(bounds)
- }
- materials: CustomMaterial {
- shadingMode: CustomMaterial.Unshaded
- cullMode: checkboxBfCull.checked ? Material.BackFaceCulling : Material.NoCulling
- property TextureInput baseMap: TextureInput {
- texture: Texture {
- id: lmTexture
- minFilter: Texture.Linear
- magFilter: Texture.Linear
- mipFilter: Texture.None
- tilingModeHorizontal: Texture.ClampToEdge
- tilingModeVertical: Texture.ClampToEdge
- textureData: LightmapFile.textureDataFor(
- root.selectedModelCandidate,
- view.lmSelectedTextureCandidate)
- }
- }
- property bool debugUV: checkboxDebugUV.checked
- vertexShader: "mesh.vert"
- fragmentShader: "mesh.frag"
- }
- }
- }
- ArcballController {
- id: arcballController
- controlledObject: modelNode
- function jumpToAxis(axis) {
- cameraRotation.from = arcballController.controlledObject.rotation
- cameraRotation.to = originGizmo.quaternionForAxis(
- axis, arcballController.controlledObject.rotation)
- cameraRotation.duration = 200
- cameraRotation.start()
- }
- function jumpToRotation(qRotation) {
- cameraRotation.from = arcballController.controlledObject.rotation
- cameraRotation.to = qRotation
- cameraRotation.duration = 100
- cameraRotation.start()
- }
- QuaternionAnimation {
- id: cameraRotation
- target: arcballController.controlledObject
- property: "rotation"
- type: QuaternionAnimation.Slerp
- running: false
- loops: 1
- }
- }
- OriginGizmo {
- id: originGizmo
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.margins: 10
- width: 120
- height: 120
- targetNode: modelNode
- onAxisClicked: axis => {
- arcballController.jumpToAxis(axis)
- }
- }
- DragHandler {
- id: dragHandler
- target: null
- acceptedModifiers: Qt.NoModifier
- onCentroidChanged: {
- arcballController.mouseMoved(toNDC(centroid.position.x,
- centroid.position.y))
- }
- onActiveChanged: {
- if (active) {
- view.forceActiveFocus()
- arcballController.mousePressed(toNDC(centroid.position.x,
- centroid.position.y))
- } else
- arcballController.mouseReleased(toNDC(centroid.position.x,
- centroid.position.y))
- }
- function toNDC(x, y) {
- return Qt.vector2d((2.0 * x / width) - 1.0,
- 1.0 - (2.0 * y / height))
- }
- }
- WheelHandler {
- id: wheelHandler
- orientation: Qt.Vertical
- target: null
- acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
- onWheel: event => {
- let delta = -event.angleDelta.y * 0.01
- cameraNode.z += cameraNode.z * 0.1 * delta
- }
- }
- Keys.onPressed: event => {
- if (event.key === Qt.Key_Space) {
- let rotation = originGizmo.quaternionAlign(
- arcballController.controlledObject.rotation)
- arcballController.jumpToRotation(rotation)
- } else if (event.key === Qt.Key_S) {
- settingsPane.toggleHide()
- } else if (event.key === Qt.Key_Left
- || event.key === Qt.Key_A) {
- let rotation = originGizmo.quaternionRotateLeft(
- arcballController.controlledObject.rotation)
- arcballController.jumpToRotation(rotation)
- } else if (event.key === Qt.Key_Right
- || event.key === Qt.Key_D) {
- let rotation = originGizmo.quaternionRotateRight(
- arcballController.controlledObject.rotation)
- arcballController.jumpToRotation(rotation)
- }
- }
- }
- }
|