XR physics-base Teleportation demo

This demo shows how to navigate and interact with objects
in the virtual environment using physics-affected locomotion.

Pick-to: 6.8 6.8.0
Change-Id: Iff6e0f2801e8f603f8a2019aea9c89087de5ed0e
Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io>
This commit is contained in:
Sadegh Taghavi 2024-08-07 14:51:39 +03:00 committed by Nicholas Bennett
parent cac7fbfad0
commit a800651471
125 changed files with 3714 additions and 0 deletions

View File

@ -22,6 +22,7 @@ find_package(Qt6 ${PROJECT_VERSION} QUIET CONFIG
Qml
Quick
Quick3D
Quick3DXr
Quick3DPhysics
Test
Sql

View File

@ -63,3 +63,6 @@ else()
message(WARNING "To build the Lightning Viewer Example, ensure the required features and modules are enabled: "
"SSL, WebSocket, Positioning, Location, zstd")
endif()
if(TARGET Qt::Quick AND TARGET Qt::Quick3D AND TARGET Qt::Quick3DXr AND TARGET Qt::Quick3DPhysics AND TARGET Qt::Multimedia)
qt_internal_add_example(xr_physicsbase_teleportation)
endif()

View File

@ -6,6 +6,10 @@ qtHaveModule(quick) {
clocks \
maroon
qtHaveModule(quick3d):qtHaveModule(quick3dphysics):qtHaveModule(quick3dxr):qtHaveModule(multimedia) {
SUBDIRS += xr_physicsbase_teleportation
}
qtHaveModule(quickcontrols2) {
SUBDIRS += coffee \
colorpaletteclient \

View File

@ -0,0 +1,90 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
Model {
id: beamModel
pickable: false
property color color: "red"
function generate(beamParts, segments, tubeRadius) {
beamMesh.generateMesh(beamParts, segments, tubeRadius)
}
function show() {
opacity = 0.7
}
function hide() {
opacity = 0.
}
visible: opacity > 0.1
opacity: 0.7
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
materials: [
PrincipledMaterial {
baseColor: beamModel.color
lighting: PrincipledMaterial.NoLighting
}
]
geometry: ProceduralMesh {
id: beamMesh
function generateMesh(beamParts, segments = 3, tubeRadius = 1) {
let verts = []
let norms = []
let uvs = []
let indices = []
const rings = beamParts.length
for (var i = 0; i < rings; ++i) {
const pos = beamParts[i]
const fwd = i > 0 ? beamParts[i].minus(beamParts[i - 1]) : beamParts[1].minus(beamParts[0])
const quat = Quaternion.fromAxisAndAngle(fwd, 360/segments)
let perp = Qt.vector3d(0, tubeRadius, 0)
for (var j = 0; j <= segments; ++j) {
const posX = pos.x + perp.x
const posY = pos.y + perp.y
const posZ = pos.z + perp.z
perp = quat.times(perp)
verts.push(Qt.vector3d(posX, posY, posZ));
const normal = Qt.vector3d(posX - pos.x, posY, posZ - pos.z).normalized();
norms.push(normal);
uvs.push(Qt.vector2d(i / rings, j / segments));
}
}
for (let i = 0; i < rings - 1; ++i) {
for (let j = 0; j < segments; ++j) {
const a = (segments + 1) * i + j;
const b = (segments + 1) * (i + 1) + j;
const c = (segments + 1) * (i + 1) + j + 1;
const d = (segments + 1) * i + j + 1;
// Generate two triangles for each quad in the mesh
// Adjust order to be counter-clockwise
indices.push(a, d, b);
indices.push(b, d, c);
}
}
positions = verts
normals = norms
uv0s = uvs
indexes = indices
}
}
}

View File

@ -0,0 +1,181 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.14)
project(xr_physicsbase_teleportation LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/vr/${PROJECT_NAME}")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Quick3D Quick3DPhysics Quick3DXr Multimedia)
qt6_policy(SET QTP0002 NEW)
qt_add_executable(${PROJECT_NAME}
main.cpp
android/AndroidManifest.xml
)
set_target_properties(${PROJECT_NAME} PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(${PROJECT_NAME} PUBLIC
Qt::Core
Qt::Gui
Qt::Quick
Qt::Quick3D
Qt::Quick3DPhysics
Qt::Quick3DXr
Qt6::Multimedia
)
set(qml_singletons
FireResources.qml
ParticleResources.qml
CampfireMaterial.qml
InvisibleMaterial.qml
CommonResources.qml
)
set_source_files_properties(${qml_singletons}
PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
# Resources:
qt_add_qml_module(${PROJECT_NAME}
URI EXAMPLE
VERSION 1.0
QML_FILES
${qml_singletons}
Main.qml
ValueFader.qml
BeamModel.qml
TargetIndicator.qml
PhysicsbaseTeleporter.qml
Grass.qml
House.qml
Fire.qml
Firewood.qml
Torch.qml
TorchGripper.qml
Fence.qml
Table.qml
Chair.qml
Campfire.qml
Stands.qml
Smoke.qml
Ground.qml
Prompter.qml
RESOURCES
"media/meshes/fence_instances.xml.bin"
"media/meshes/block_instances.xml.bin"
"media/meshes/firewood_instances.xml.bin"
"media/shaders/invisible.vert"
"media/shaders/invisible.frag"
"media/shaders/target_indicator.vert"
"media/shaders/target_indicator.frag"
"media/shaders/grass.vert"
"media/shaders/grass.frag"
"media/shaders/fire.vert"
"media/shaders/fire.frag"
"media/textures/OpenfootageNET_lowerAustria01-1024.hdr"
"media/meshes/cylinder_invert.mesh"
"media/meshes/house/cube_004_mesh.mesh"
"media/meshes/house/cube_006_mesh.mesh"
"media/meshes/house/cube_007_mesh.mesh"
"media/meshes/house/cube_010_mesh.mesh"
"media/meshes/house/cube_012_mesh.mesh"
"media/meshes/house/cube_014_mesh.mesh"
"media/meshes/house/cube_016_mesh.mesh"
"media/meshes/house/cube_019_mesh.mesh"
"media/meshes/house/cube_020_mesh.mesh"
"media/textures/house/wood_bc.jpg"
"media/textures/house/wood_n.jpg"
"media/textures/house/wood_r.jpg"
"media/textures/house/rock_bc.jpg"
"media/textures/house/rock_n.jpg"
"media/textures/house/rock_r.jpg"
"media/meshes/torch/object_1_mesh.mesh"
"media/textures/torch/torch_bc.jpg"
"media/textures/torch/torch_n.jpg"
"media/textures/torch/torch_r.jpg"
"media/meshes/table/defaultMaterial_mesh7.mesh"
"media/meshes/table/defaultMaterial_mesh17.mesh"
"media/meshes/table/defaultMaterial_mesh20.mesh"
"media/meshes/table/defaultMaterial_mesh23.mesh"
"media/meshes/table/defaultMaterial_mesh26.mesh"
"media/meshes/table/defaultMaterial_mesh27.mesh"
"media/textures/table/table_bc.jpg"
"media/textures/table/table_n.jpg"
"media/textures/table/table_mr.jpg"
"media/meshes/campfire/cube_003_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_004_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_005_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_006_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_007_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_0012_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_0022_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_0032_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cube21_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cylinder_002_low_campfire_0_mesh.mesh"
"media/meshes/campfire/cylinder_low_campfire_0_mesh.mesh"
"media/textures/campfire/campfire_bc.jpg"
"media/textures/campfire/campfire_n.jpg"
"media/textures/campfire/campfire_mr.jpg"
"media/meshes/chair/defaultMaterial_mesh5.mesh"
"media/meshes/chair/defaultMaterial_mesh13.mesh"
"media/meshes/chair/defaultMaterial_mesh16.mesh"
"media/meshes/chair/defaultMaterial_mesh19.mesh"
"media/textures/chair/chair_bc.jpg"
"media/textures/chair/chair_n.jpg"
"media/textures/chair/chair_mr.jpg"
"media/meshes/firewood/plane_mesh.mesh"
"media/textures/firewood/firewood_bc.jpg"
"media/textures/firewood/firewood_n.jpg"
"media/textures/firewood/firewood_r.jpg"
"media/textures/firewood/firewood_a.jpg"
"media/meshes/block/defaultMaterial_mesh.mesh"
"media/textures/block/block_bc.jpg"
"media/textures/block/block_n.jpg"
"media/textures/block/block_mr.jpg"
"media/textures/ground_bc.jpg"
"media/textures/ground_n.jpg"
"media/textures/ground_r.jpg"
"media/textures/bark_bc.jpg"
"media/textures/bark_n.jpg"
"media/textures/turbulence.png"
"media/textures/perlin.jpg"
"media/textures/grass_bc.jpg"
"media/textures/fire.mp4"
"media/textures/smoke_sprite.png"
NO_RESOURCE_TARGET_PATH
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
if(ANDROID)
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android)
endif()

View File

@ -0,0 +1,230 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
Node {
id: node
property alias isOn: fire.isOn
property alias fireColor: fire.fireColor
property alias lightColor: fire.lightColor
function startFire() {
fire.life = 1
}
function stopFire() {
fire.life = 0
}
// Resources
StaticRigidBody {
y: 50
collisionShapes: BoxShape {
}
Model {
y: -35
scale: Qt.vector3d(1.1, 1., 1.1)
source: "#Cone"
pickable: true
materials: [InvisibleMaterial]
}
}
Fire {
id: fire
Timer {
running: fire.isOn
interval: 60000 + Math.random() * 60000
onTriggered: {
fire.stop()
}
}
scale: Qt.vector3d(1.6, 4., 1.6)
StaticRigidBody {
objectName: "Fire"
scale: Qt.vector3d(0.5, 0.1, 0.5)
y: 20
sendTriggerReports: true
collisionShapes: [
CapsuleShape {eulerRotation: Qt.vector3d(0, 0, -90)}
]
}
}
Smoke {
visible: fire.isOn
position: Qt.vector3d(0, 210, 0)
}
// Nodes:
Node {
eulerRotation: Qt.vector3d(-90, 0, 0)
Node {
rotation: Qt.quaternion(0.707107, 0.707107, 0, 0)
scale: Qt.vector3d(0.5, 0.5, 0.5)
Node {
id: rootNode
objectName: "RootNode"
y: 66
Node {
position: Qt.vector3d(0, 135.393, 0)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cylinder_low_campfire_0
objectName: "Cylinder_low_campfire_0"
source: "media/meshes/campfire/cylinder_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(-0.0740571, 19.4206, 69.8315)
rotation: Qt.quaternion(0.707098, -0.707098, -0.00352214, -0.00352214)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_low_campfire_0
objectName: "Cube_low_campfire_0"
source: "media/meshes/campfire/cube_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(0, -3.0181, 0)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cylinder_002_low_campfire_0
objectName: "Cylinder.002_low_campfire_0"
source: "media/meshes/campfire/cylinder_002_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(0, -5.36013, 78.4066)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_004_low_campfire_0
objectName: "Cube.004_low_campfire_0"
source: "media/meshes/campfire/cube_004_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(78.4066, -5.36013, -5.96046e-06)
rotation: Qt.quaternion(-0.5, 0.5, -0.5, -0.5)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_005_low_campfire_0
objectName: "Cube.005_low_campfire_0"
source: "media/meshes/campfire/cube_005_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(-1.19209e-05, -5.36013, -78.4066)
rotation: Qt.quaternion(-1.37679e-07, 1.37679e-07, 0.707107, 0.707107)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_006_low_campfire_0
objectName: "Cube.006_low_campfire_0"
source: "media/meshes/campfire/cube_006_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(-78.4066, -5.36013, 1.78814e-05)
rotation: Qt.quaternion(0.5, -0.5, -0.5, -0.5)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_007_low_campfire_0
objectName: "Cube.007_low_campfire_0"
source: "media/meshes/campfire/cube_007_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(55.845, 19.4206, 41.9258)
rotation: Qt.quaternion(0.633932, -0.633932, 0.313257, 0.313257)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_003_low_campfire_0
objectName: "Cube.003_low_campfire_0"
source: "media/meshes/campfire/cube_003_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(0, 135.393, 91.0465)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube21_low_campfire_0
objectName: "Cube21_low_campfire_0"
source: "media/meshes/campfire/cube21_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(0, -5.54692, 84.0394)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_0012_low_campfire_0
objectName: "Cube.0012_low_campfire_0"
source: "media/meshes/campfire/cube_0012_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(84.0394, -5.54692, -5.96046e-06)
rotation: Qt.quaternion(-0.5, 0.5, -0.5, -0.5)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_0022_low_campfire_0
objectName: "Cube.0022_low_campfire_0"
source: "media/meshes/campfire/cube_0022_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
Node {
position: Qt.vector3d(91.0465, 135.393, -5.96046e-06)
rotation: Qt.quaternion(-0.5, 0.5, -0.5, -0.5)
scale: Qt.vector3d(100, 100, 100)
Model {
id: cube_0032_low_campfire_0
objectName: "Cube.0032_low_campfire_0"
source: "media/meshes/campfire/cube_0032_low_campfire_0_mesh.mesh"
materials: [
CampfireMaterial
]
}
}
}
}
}
// Animations:
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma Singleton
import QtQuick
import QtQuick3D
PrincipledMaterial {
Texture {
id: campfire_bc
generateMipmaps: true
source: "media/textures/campfire/campfire_bc.jpg"
}
Texture {
id: campfire_mr
generateMipmaps: true
source: "media/textures/campfire/campfire_mr.jpg"
}
Texture {
id: campfire_n
generateMipmaps: true
source: "media/textures/campfire/campfire_n.jpg"
}
baseColorMap: campfire_bc
metalnessMap: campfire_mr
metalnessChannel: PrincipledMaterial.R
roughnessMap: campfire_mr
roughnessChannel: PrincipledMaterial.G
metalness: 1
roughness: 1
normalMap: campfire_n
occlusionMap: campfire_mr
occlusionChannel: PrincipledMaterial.B
}

View File

@ -0,0 +1,96 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
Node {
id: node0
// Resources
Texture {
id: chair_bc
generateMipmaps: true
source: "media/textures/chair/chair_bc.jpg"
}
Texture {
id: chair_mr
generateMipmaps: true
source: "media/textures/chair/chair_mr.jpg"
}
Texture {
id: chair_n
generateMipmaps: true
source: "media/textures/chair/chair_n.jpg"
}
PrincipledMaterial {
id: chair_material
baseColorMap: chair_bc
metalnessMap: chair_mr
metalnessChannel: PrincipledMaterial.R
roughnessMap: chair_mr
roughnessChannel: PrincipledMaterial.G
metalness: 1
roughness: 1
normalMap: chair_n
occlusionMap: chair_mr
occlusionChannel: PrincipledMaterial.B
}
// Nodes:
DynamicRigidBody {
collisionShapes: BoxShape {
extents: Qt.vector3d(90, 200, 90)
}
Model {
y: -100
pickable: true
scale: Qt.vector3d(1.7, 1., 1.7)
source: "#Cone"
materials: [InvisibleMaterial]
}
Node {
scale: Qt.vector3d(100, 100, 100)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
Node {
rotation: Qt.quaternion(0.707107, 0.707107, 0, 0)
Node {
id: node3_low3
objectName: "3_low"
Model {
source: "media/meshes/chair/defaultMaterial_mesh5.mesh"
materials: [
chair_material
]
}
}
Node {
Model {
source: "media/meshes/chair/defaultMaterial_mesh13.mesh"
materials: [
chair_material
]
}
}
Node {
Model {
source: "media/meshes/chair/defaultMaterial_mesh16.mesh"
materials: [
chair_material
]
}
}
Node {
Model {
source: "media/meshes/chair/defaultMaterial_mesh19.mesh"
materials: [
chair_material
]
}
}
}
}
}
// Animations:
}

View File

@ -0,0 +1,18 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma Singleton
import QtQuick
import QtQuick3D
Node {
property alias turbulenceTexture: turbulence_texture
Texture {
id: turbulence_texture
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/turbulence.png"
}
}

View File

@ -0,0 +1,55 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Physics
Node {
StaticRigidBody {
objectName: "Fence"
scale: Qt.vector3d(1990, 1990, 1990)
eulerRotation: Qt.vector3d(-90, 0, 0)
collisionShapes: TriangleMeshShape {
source: "media/meshes/cylinder_invert.mesh"
}
Model {
source: "media/meshes/cylinder_invert.mesh"
pickable: true
materials: [
InvisibleMaterial
]
}
}
Model {
id: model
source: "#Cylinder"
scale: Qt.vector3d(0.3, 3., 0.3)
position: Qt.vector3d(0, 50 * scale.y, 0)
instancing: FileInstancing {
source: "media/meshes/fence_instances.xml.bin"
}
materials: [
PrincipledMaterial {
baseColorMap: Texture {
generateMipmaps: true
source: "media/textures/bark_bc.jpg"
scaleU: 3
scaleV: 8
}
roughness: 1.
normalMap: Texture {
generateMipmaps: true
source: "media/textures/bark_n.jpg"
scaleU: 3
scaleV: 8
}
}
]
}
}

View File

@ -0,0 +1,85 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtMultimedia
Node {
id: fire
scale: Qt.vector3d(1, 1, 1)
property alias windDir: material.windDir
property alias windstrength: material.windstrength
property alias fireColor: material.color
property alias lightColor: light.color
property alias baseSize: material.baseSize
property real brightness: 10
property real life: 0
readonly property bool isOn: (life > 0)
function start() {
life = 1
}
function stop() {
life = 0
}
Behavior on life {
NumberAnimation {
duration: 500
easing.type: Easing.OutBack
}
}
CustomMaterial {
id: material
shadingMode: CustomMaterial.Unshaded
sourceBlend: CustomMaterial.One
destinationBlend: CustomMaterial.OneMinusSrcColor
sourceAlphaBlend: CustomMaterial.One
destinationAlphaBlend: CustomMaterial.OneMinusSrcColor
cullMode: Material.NoCulling
vertexShader: "media/shaders/fire.vert"
fragmentShader: "media/shaders/fire.frag"
property real time: 0
property color color: "white"
property real baseSize: 0
FrameAnimation {
id: frameAnimation
running: true
onTriggered: {
material.time += 0.1 * frameTime
}
}
property real windstrength: 1.0
property vector2d windDir: Qt.vector2d(0.5, 0.5);
property TextureInput fireTexture : TextureInput {
texture: Texture {
sourceItem: FireResources.fireVideo
}
}
property TextureInput turbulence : TextureInput {
texture: CommonResources.turbulenceTexture
}
}
PointLight {
id: light
brightness:fire.brightness * fire.life + 0.01
color: "orange"
}
Model {
visible: fire.isOn
materials: [
material
]
opacity: Math.min(1., fire.life)
scale: Qt.vector3d(fire.life, fire.life, fire.life)
geometry: FireResources.fireMesh
}
}

View File

@ -0,0 +1,103 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma Singleton
import QtQuick
import QtQuick3D
import QtMultimedia
import QtQuick3D.Helpers
Node {
property alias fireVideo: video_out
property alias fireMesh: fire_mesh
VideoOutput {
id: video_out
fillMode: VideoOutput.Stretch
width: 512
height: 512
visible: false
MediaPlayer {
id: player
source: "media/textures/fire.mp4"
loops: MediaPlayer.Infinite
autoPlay: true
videoOutput: FireResources.fireVideo
}
}
ProceduralMesh {
id: fire_mesh
Component.onCompleted: {
generateMesh()
}
function generateMesh() {
let verts = []
let uvs = []
let indices = []
let colrs = []
const xOffset = 0.
const zOffset = 0.
const countX = 5.
const countZ = 5.
const segments = 30.
const height = 100.
const thickness = 100.
const thicknessHalf = thickness * 0.5
const segmentHeight = height / segments
let pos = Qt.vector3d(0, 0, 0)
let index = 0
let blade = 0.0;
for (var xx = 0.; xx < countX; ++xx) {
for (var zz = 0.; zz < countZ; ++zz) {
pos.x = xx * xOffset
pos.z = zz * zOffset
const xxNorm = xx / countX
const zzNorm = zz / countZ
const fBlade = blade / (countX*countZ)
++blade
for (var ss = 0.; ss <= segments; ++ss) {
const uvY = ss / segments
const posLX = pos.x - thicknessHalf
const posLY = segmentHeight * ss + pos.y
const posLZ = pos.z
verts.push(Qt.vector3d(posLX, posLY, posLZ));
uvs.push(Qt.vector2d(0, uvY))
colrs.push(Qt.vector4d(fBlade, 0, xxNorm, zzNorm))
const posRX = pos.x + thicknessHalf
const posRY = segmentHeight * ss + pos.y
const posRZ = pos.z
verts.push(Qt.vector3d(posRX, posRY, posRZ));
uvs.push(Qt.vector2d(1.0, uvY))
colrs.push(Qt.vector4d(fBlade, 0, xxNorm, zzNorm))
if (ss < segments) {
indices.push(index, index + 1, index + 2)
indices.push(index + 2, index + 1, index + 3)
}
index += 2
}
}
}
positions = verts
uv0s = uvs
colors = colrs
indexes = indices
}
}
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
Node {
id: firewood
property alias instancing: model.instancing
// Resources
Texture {
id: firewood_bc
generateMipmaps: true
source: "media/textures/firewood/firewood_bc.jpg"
}
Texture {
id: firewood_r
generateMipmaps: true
source: "media/textures/firewood/firewood_r.jpg"
}
Texture {
id: firewood_n
generateMipmaps: true
source: "media/textures/firewood/firewood_n.jpg"
}
Texture {
id: firewood_a
generateMipmaps: true
source: "media/textures/firewood/firewood_a.jpg"
}
PrincipledMaterial {
id: firewood_material
baseColorMap: firewood_bc
metalnessMap: firewood_r
occlusionMap: firewood_a
// metalness: 1
baseColor: "gray"
roughness: 1
normalMap: firewood_n
}
Model {
id: model
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
source: "media/meshes/firewood/plane_mesh.mesh"
materials: [
firewood_material
]
}
// Animations:
}

View File

@ -0,0 +1,145 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
Model {
id: grassChunkModel
pickable: false
property alias windDir: material.windDir
property alias windstrength: material.windstrength
property alias baseColor: material.baseColor
Component.onCompleted: {
generate()
}
function generate() {
grassChunkMesh.generateMesh()
}
function show() {
opacity = 1.0
}
function hide() {
opacity = 0.
}
visible: opacity > 0.1
opacity: 1.0
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
materials: [
CustomMaterial {
id: material
cullMode: Material.NoCulling
vertexShader: "media/shaders/grass.vert"
fragmentShader: "media/shaders/grass.frag"
property real time: 0
property color baseColor: "white"
FrameAnimation {
id: frameAnimation
running: true
onTriggered: {
material.time += 0.1 * frameTime
}
}
property real windstrength: 1.0
property vector2d windDir: Qt.vector2d(0.5, 0.5);
property TextureInput grass_base : TextureInput {
texture: Texture {
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/grass_bc.jpg"
}
}
property TextureInput turbulence : TextureInput {
texture: CommonResources.turbulenceTexture
}
property TextureInput perlin : TextureInput {
texture: Texture {
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/perlin.jpg"
}
}
}
]
geometry: ProceduralMesh {
id: grassChunkMesh
function generateMesh() {
let verts = []
let uvs = []
let indices = []
let colrs = []
const xOffset = 10.
const zOffset = 10.
const countX = 100.
const countZ = 100.
const segments = 9.
const height = 150.
const thickness = 5.
const thicknessHalf = thickness * 0.5
const segmentHeight = height / segments
let pos = Qt.vector3d(0, 0, 0)
let index = 0
const countXHalf = countX / 2;
const countZHalf = countZ / 2;
for (let xx = -countXHalf; xx < countXHalf; ++xx) {
for (let zz = -countZHalf; zz < countZHalf; ++zz) {
pos.x = xx * xOffset
pos.z = zz * zOffset
const xxNorm = xx / countX + 0.5
const zzNorm = zz / countZ + 0.5
for (let ss = 0; ss <= segments; ++ss) {
const uvY = ss / segments
const posLX = pos.x - thicknessHalf
const posLY = segmentHeight * ss + pos.y
const posLZ = pos.z
verts.push(Qt.vector3d(posLX, posLY, posLZ))
uvs.push(Qt.vector2d(0, uvY))
colrs.push(Qt.vector4d(pos.x, pos.z, xxNorm, zzNorm))
const posRX = pos.x + thicknessHalf
const posRY = segmentHeight * ss + pos.y
const posRZ = pos.z
verts.push(Qt.vector3d(posRX, posRY, posRZ))
uvs.push(Qt.vector2d(1.0, uvY))
colrs.push(Qt.vector4d(pos.x, pos.z, xxNorm, zzNorm))
if (ss < segments) {
indices.push(index, index + 1, index + 2)
indices.push(index + 2, index + 1, index + 3)
}
index += 2
}
}
}
positions = verts
uv0s = uvs
colors = colrs
indexes = indices
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Physics
Node {
StaticRigidBody {
objectName: "Ground"
eulerRotation: Qt.vector3d(-90, 0, 0)
collisionShapes: PlaneShape {}
}
Model {
pickable: true
source: "#Rectangle"
scale:Qt.vector3d(1000, 1000, 1000)
eulerRotation: Qt.vector3d(-90, 0, 0)
materials: [
PrincipledMaterial {
baseColorMap: Texture {
scaleU: 200
scaleV: 200
generateMipmaps: true
source: "media/textures/ground_bc.jpg"
}
normalMap: Texture {
scaleU: 200
scaleV: 200
generateMipmaps: true
source: "media/textures/ground_n.jpg"
}
roughnessMap: Texture {
scaleU: 200
scaleV: 200
generateMipmaps: true
source: "media/textures/ground_r.jpg"
}
roughness: 1
}
]
}
}

View File

@ -0,0 +1,417 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
Node {
id: house
// Resources
Texture {
id: wood_bc
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/wood_bc.jpg"
scaleU: 2
scaleV: 2
}
Texture {
id: wood_n
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/wood_n.jpg"
scaleU: 2
scaleV: 2
}
Texture {
id: wood_r
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/wood_r.jpg"
scaleU: 2
scaleV: 2
}
Texture {
id: rock_bc
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/rock_bc.jpg"
scaleU: 3
scaleV: 3
}
Texture {
id: rock_n
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/rock_n.jpg"
scaleU: 3
scaleV: 3
}
Texture {
id: rock_r
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/house/rock_r.jpg"
scaleU: 3
scaleV: 3
}
PrincipledMaterial {
id: darkwood_material
roughness: 1
baseColorMap : wood_bc
baseColor: "gray"
normalMap : wood_n
normalStrength: 3.
roughnessMap : wood_r
}
PrincipledMaterial {
id: lightwood_material
roughness: 1
baseColorMap : wood_bc
baseColor: "white"
normalMap : wood_n
normalStrength: 3.
roughnessMap : wood_r
}
PrincipledMaterial {
id: rock_material
roughness: 1
objectName: "rock"
baseColorMap : rock_bc
baseColor: "white"
normalMap : rock_n
normalStrength: 3.
roughnessMap : rock_r
}
Node {
id: rootNode1
objectName: "RootNode"
StaticRigidBody {
objectName: "HouseFloor"
scale: Qt.vector3d(11.0, 0.1, 10.6)
position: Qt.vector3d(0, 195, 0)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
objectName: "HouseBackWall"
scale: Qt.vector3d(10.8, 0.8, 20)
position: Qt.vector3d(-500, 500, 0)
eulerRotation: Qt.vector3d(-90, -90, 0)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
objectName: "HouseLeftWall"
scale: Qt.vector3d(20, 1.3, 10.4)
position: Qt.vector3d(0, 500, -500)
eulerRotation: Qt.vector3d(0, -90, -90)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
objectName: "HouseRightWall"
scale: Qt.vector3d(20, 1.6, 10.4)
position: Qt.vector3d(0, 500, 520)
eulerRotation: Qt.vector3d(0, -90, -90)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
scale: Qt.vector3d(10.8, 0.8, 20)
position: Qt.vector3d(500, 1520, 0)
eulerRotation: Qt.vector3d(-90, -90, 0)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
scale: Qt.vector3d(4.32, 0.8, 20)
position: Qt.vector3d(500, 500, 310)
eulerRotation: Qt.vector3d(-90, -90, 0)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
scale: Qt.vector3d(4.32, 0.8, 20)
position: Qt.vector3d(500, 500, -310)
eulerRotation: Qt.vector3d(-90, -90, 0)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
position: Qt.vector3d(470, 50 * scale.y, 0)
scale: Qt.vector3d(1.5, 2.0, 3.7)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
position: Qt.vector3d(537, 50 * scale.y, 0)
scale: Qt.vector3d(2, 1.44, 2.5)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
position: Qt.vector3d(605, 50 * scale.y, 0)
scale: Qt.vector3d(2, 0.95, 2.5)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
StaticRigidBody {
position: Qt.vector3d(678, 50 * scale.y, 0)
scale: Qt.vector3d(2, 0.40, 2.5)
collisionShapes: BoxShape {
}
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
TriggerBody {
position: Qt.vector3d(600, 270, 0)
scale: Qt.vector3d(5, 5, 2.5)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
materials: [InvisibleMaterial]
}
onBodyEntered: {
door.angle = -45
}
onBodyExited: {
door.angle = -180
}
}
Model {
id: construction_006
objectName: "ceilling"
position: Qt.vector3d(492.157, 378.451, -95.0073)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(43.9016, 43.9016, 43.9016)
source: "media/meshes/house/cube_020_mesh.mesh"
materials: [
lightwood_material
]
}
Model {
id: construction_005
objectName: "floor"
position: Qt.vector3d(492.157, 378.451, -95.0073)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(43.9016, 43.9016, 43.9016)
source: "media/meshes/house/cube_019_mesh.mesh"
materials: [
lightwood_material
]
}
Model {
id: construction_003
objectName: "walls"
position: Qt.vector3d(0, -122.331, 0)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(51.7539, 51.7539, 51.7539)
source: "media/meshes/house/cube_016_mesh.mesh"
materials: [
lightwood_material
]
}
Node {
id: door
property real angle: -180
Behavior on angle {
NumberAnimation {
duration: 1000
easing.type: Easing.OutBack
}
}
eulerRotation: Qt.vector3d(0, angle, 0)
position: Qt.vector3d(492.157, 370, -95.0073)
Node {
scale: Qt.vector3d(0.2, 3.2, 2.2)
position: Qt.vector3d(0, 0, -50 * scale.z)
Model {
pickable: true
source: "#Cube"
materials: [InvisibleMaterial]
}
}
}
Model {
objectName: "door"
position: Qt.vector3d(492.157, 374.603, -95.0073)
eulerRotation: Qt.vector3d(90, door.angle, 0)
scale: Qt.vector3d(100, 100, 100)
source: "media/meshes/house/cube_014_mesh.mesh"
materials: [
lightwood_material
]
}
Model {
id: cube_007
position: Qt.vector3d(0, -122.331, 0)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
objectName: "base"
source: "media/meshes/house/cube_012_mesh.mesh"
materials: [
rock_material
]
}
Model {
position: Qt.vector3d(0, -122.331, 0)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
id: cube_006
objectName: "stairs"
pickable: true
source: "media/meshes/house/cube_007_mesh.mesh"
materials: [
darkwood_material
]
}
Model {
id: cube_005
objectName: "supports"
position: Qt.vector3d(0, 77.6693, 2.84217e-13)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 100, 100)
source: "media/meshes/house/cube_006_mesh.mesh"
materials: [
darkwood_material
]
}
Model {
id: cube_003
objectName: "roof2"
position: Qt.vector3d(-9.53674e-05, 77.6691, 2.55795e-12)
rotation: Qt.quaternion(0.5, -0.5, 0.5, 0.5)
scale: Qt.vector3d(40, 25, 50)
source: "media/meshes/house/cube_010_mesh.mesh"
materials: [
darkwood_material
]
}
Model {
id: cube_004
objectName: "supports_roof"
position: Qt.vector3d(0, 77.6693, 2.84217e-13)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
scale: Qt.vector3d(100, 80, 100)
source: "media/meshes/house/cube_004_mesh.mesh"
materials: [
darkwood_material
]
}
Fire {
id: fire
Component.onCompleted: {
start()
}
StaticRigidBody {
objectName: "Fire"
scale: Qt.vector3d(0.5, 0.1, 0.5)
y: 25
sendTriggerReports: true
collisionShapes: [
CapsuleShape {eulerRotation: Qt.vector3d(0, 0, -90)}
]
}
windstrength: 0
baseSize: 1.
scale: Qt.vector3d(1.3, 2.0, 1.3)
position: Qt.vector3d(0, 220, 520)
}
Smoke {
size: 1.3
position: Qt.vector3d(fire.x, fire.y + 720, fire.z)
}
}
// Animations:
}

View File

@ -0,0 +1,14 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma Singleton
import QtQuick
import QtQuick3D
CustomMaterial {
shadingMode: CustomMaterial.Unshaded
cullMode: Material.BackFaceCulling
vertexShader: "media/shaders/invisible.vert"
fragmentShader: "media/shaders/invisible.frag"
}

View File

@ -0,0 +1,327 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Physics
import QtQuick3D.Physics.Helpers as Helpers
import QtQuick3D.Xr
import QtQuick3D.Particles3D
XrView {
id: xrView
XrErrorDialog { id: err }
onInitializeFailed: (errorString) => err.run("XR physics-base teleportation", errorString)
referenceSpace: XrView.ReferenceSpaceStage
environment: ExtendedSceneEnvironment {
id: extendedSceneEnvironment
backgroundMode: SceneEnvironment.Color
probeExposure: 0.7
lightProbe: Texture {
source: "media/textures/OpenfootageNET_lowerAustria01-1024.hdr"
}
skyboxBlurAmount: 0.0
specularAAEnabled: true
clearColor: theFog.color
exposure: teleporter.screenVisibility
fog: Fog {
id: theFog
color:"gray"
enabled: true
depthEnabled: true
depthNear: 1500
depthFar: 3000
}
}
Component.onCompleted: {
ParticleResources.init(xrView)
}
xrOrigin: XrOrigin {
id: xrOrigin
camera: XrCamera {
id: trackingCamera
Prompter {
id: prompter
}
}
XrController {
id: xrLeftController
controller: XrController.ControllerLeft
poseSpace: XrController.AimPose
TorchGripper {
hand: XrInputAction.LeftHand
}
}
XrController {
id: xrRightController
controller: XrController.ControllerRight
poseSpace: XrController.AimPose
XrInputAction {
id: thumbstickX
hand: XrInputAction.RightHand
actionId: [XrInputAction.ThumbstickX]
}
XrInputAction {
id: thumbstickY
hand: XrInputAction.RightHand
actionId: [XrInputAction.ThumbstickY]
}
XrInputAction {
id: trackpadX
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadX]
}
XrInputAction {
id: trackpadY
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadY]
}
XrInputAction {
id: trackpadPressed
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadPressed]
}
TorchGripper {
hand: XrInputAction.RightHand
}
property real xValue: trackpadPressed.pressed ? trackpadX.value : thumbstickX.value
property real yValue: trackpadPressed.pressed ? trackpadY.value : thumbstickY.value
}
}
PhysicsbaseTeleporter {
id: teleporter
rayPicker: xrView
cameraOrigin: xrOrigin
camera: xrOrigin.camera
beamHandle: xrRightController
characterController: character
xStickValue: xrRightController.xValue
yStickValue: xrRightController.yValue
onDoTeleportation: (cameraOriginPosition, characterControllerPosition)=> {
xrOrigin.position = cameraOriginPosition
character.teleport(characterControllerPosition)
}
onDoRotation: (cameraOriginRotation, cameraOriginPosition)=> {
xrOrigin.rotation = cameraOriginRotation
xrOrigin.position = cameraOriginPosition
}
}
PhysicsWorld {
id: physicsWorld
running: true
scene: xrView
gravity: Qt.vector3d(0, -981, 0)
}
CharacterController {
id: character
property bool inTheHouse: true
signal enteredTheHouse
signal leftTheHouse
onEnteredTheHouse: {
inTheHouse = true
}
onLeftTheHouse: {
inTheHouse = false
}
property vector3d startPos: Qt.vector3d(0, 200, 0)
scale: Qt.vector3d(0.5, 1.75, 0.5)
Component.onCompleted: {
prompter.prompt = Prompter.DarknessFalling
prompter.prompt = Prompter.PickupTorch
teleporter.teleportTo(character.startPos)
}
collisionShapes: CapsuleShape {
id: capsuleShape
}
onShapeHit: (body, position, impulse, normal)=>{
if (body.objectName === "Ground")
leftTheHouse()
else if (body.objectName === "HouseFloor")
enteredTheHouse()
}
enableShapeHitCallback: true
sendTriggerReports: true
gravity: physicsWorld.gravity.times(10) //make it fall faster
}
Ground {
}
Fence {
}
House {
}
Chair {
eulerRotation: Qt.vector3d(0, -45, 0)
position: Qt.vector3d(-200, 200, -300)
}
Table {
position: Qt.vector3d(-30, 200, -300)
}
Torch {
id: torch
position: Qt.vector3d(0, 350, -300)
eulerRotation: Qt.vector3d(-90, 0, 0)
windEnabled: !character.inTheHouse
onAttachedToChanged: {
if (attachedTo)
prompter.prompt = Prompter.LightupTorch
}
onIsOnChanged: {
prompter.prompt = Prompter.DefendCrop
}
}
Grass {
id: field
z: -1200
}
Stands {
}
Campfire {
id: campFire1
position: Qt.vector3d(1000, 185 ,1000)
function updateColors(){
if (campFire1.isOn && campFire2.isOn &&
campFire3.isOn && campFire4.isOn) {
campFire1.fireColor = "white"
campFire1.lightColor = Qt.lighter("orange", 1.5)
enemy.run = true
}else {
campFire1.fireColor = "orange"
campFire1.lightColor = "orange"
enemy.run = false
}
campFire2.fireColor = campFire1.fireColor
campFire2.lightColor = campFire1.lightColor
campFire3.fireColor = campFire1.fireColor
campFire3.lightColor = campFire1.lightColor
campFire4.fireColor = campFire1.fireColor
campFire4.lightColor = campFire1.lightColor
}
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire2
position: Qt.vector3d(1000, 185 ,-1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire3
position: Qt.vector3d(-1000, 185 ,1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire4
position: Qt.vector3d(-1000, 185 ,-1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Smoke {
id: enemy
readonly property real maxY: 5000
readonly property real startY: 40000
property bool run: false
position: Qt.vector3d(0, startY, 0)
color: "black"
colorVariation: 0.0
size: run ? 6.0 : 4.0
FrameAnimation {
running: true
property real time: 0
property real fieldEncounterTime: 0
onTriggered: {
time += 0.5 * frameTime
let enemyLinearY = enemy.scenePosition.y / enemy.maxY
let enemyOffset = enemyLinearY * 5000 + 200
let targetBase = field.scenePosition
let enemyMovementSpeed = 20.
let chaseTheCamera = false
if (fieldEncounterTime > 0.99 && !character.inTheHouse && !enemy.run) {
targetBase = xrOrigin.camera.scenePosition
enemyOffset = 20
chaseTheCamera = true
enemyMovementSpeed = 5
}
let target = Qt.vector3d(targetBase.x + Math.cos(time) * enemyOffset ,
targetBase.y + Math.abs(Math.cos(time)) * 100,
targetBase.z + Math.sin(time) * enemyOffset)
if (torch.isOn) {
let enemyToTorchDir =  torch.scenePosition.minus(enemy.position)
let enemyToTorchLen = enemyToTorchDir.length()
let dis = Math.max(0, 500 - enemyToTorchLen)
target.y += dis * dis * dis
}
if (enemy.run)
target.y += enemy.maxY
if (!chaseTheCamera) {
field.baseColor = ""
if (field.scenePosition.minus(enemy.scenePosition).length() < 500)
fieldEncounterTime += frameTime * 0.02
else
fieldEncounterTime -= frameTime * 0.01
fieldEncounterTime = Math.min(Math.max(fieldEncounterTime, 0), 1.)
field.baseColor = Qt.darker("white", Math.exp(fieldEncounterTime))
}
let enemyToTargetDir = target.minus(enemy.scenePosition).normalized().times(enemyMovementSpeed)
enemy.position = enemy.scenePosition.plus(enemyToTargetDir)
}
}
}
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma Singleton
import QtQuick
import QtQuick3D
import QtQuick3D.Particles3D
Node {
function init(scene) {
particleSystem.parent = scene
}
property alias system: particleSystem
property alias smokeSpriteTexture: smokeTexture
ParticleSystem3D {
id: particleSystem
}
Texture {
id: smokeTexture
source: "media/textures/smoke_sprite.png"
}
}

View File

@ -0,0 +1,191 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
Node {
id: teleporter
required property var rayPicker //any object that has implemented rayPick(pos, dir)
required property Node cameraOrigin
required property Node camera
required property Node beamHandle
required property CharacterController characterController
property real cameraSnapRotation: 30
property real xStickValue: 0
property real yStickValue: 0
property alias screenVisibility: screenValueFader.value
property bool targetValid: false
property color rayHitColor: "green"
property color rayMissColor: "red"
property int blinkSpeed: 150
property real movementChangedThreshold: 5
property real xzMovementTeleportationThreshold: 30
property real yMovementTeleportationThreshold: 10
property bool teleporting: false
property bool rotating: false
function teleportTo(position, byCharacterController = false) {
teleporter.teleporting = true
let offset = camera.scenePosition.minus(cameraOrigin.scenePosition)
let cameraOriginPosition = position.minus(offset)
cameraOriginPosition.y = position.y
let characterControllerHeight = teleporter.characterController.scale.y * 50 + //half of the controller height
50 * teleporter.characterController.scale.x //half of the cap of the controller capsule shape
if (byCharacterController)
cameraOriginPosition.y -= characterControllerHeight
screenValueFader.blink(()=>{
teleporter.doTeleportation(cameraOriginPosition,
//putting back the height of the character controller
Qt.vector3d(position.x, position.y + (byCharacterController ? 0 : characterControllerHeight), position.z))
},()=>{
characterControllerLastYPosition = characterController.scenePosition.y
teleporter.teleporting = false
}, teleporter.blinkSpeed)
}
function rotateBy(degrees) {
teleporter.rotating = true
let r = Quaternion.fromEulerAngles(0, degrees, 0)
let origin = Qt.vector3d(camera.position.x, 0, camera.position.z)
let mappedOrigin = cameraOrigin.rotation.times(origin).plus(cameraOrigin.position)
let rotatedOrigin = r.times(origin)
let mappedRO = cameraOrigin.rotation.times(rotatedOrigin).plus(cameraOrigin.position)
let delta = mappedRO.minus(mappedOrigin)
doRotation(cameraOrigin.rotation.times(r), cameraOrigin.position.minus(delta))
teleporter.rotating = false
}
signal doTeleportation(var cameraOriginPosition, var characterControllerPosition)
signal doRotation(var cameraOriginRotation, var cameraOriginPosition)
readonly property bool xPlusRotation: xStickValue > 0.5
onXPlusRotationChanged: {
if (xPlusRotation)
rotateBy(-cameraSnapRotation)
}
readonly property bool xMinusRotation: xStickValue < -0.5
onXMinusRotationChanged: {
if (xMinusRotation)
rotateBy(cameraSnapRotation)
}
readonly property vector3d cameraPosition: camera.scenePosition
onCameraPositionChanged: {
var deltaXZ = teleporter.camera.scenePosition.minus(teleporter.characterController.scenePosition)
deltaXZ.y = 0.0
let deltaLen = deltaXZ.length()
if (deltaLen >= teleporter.movementChangedThreshold &&
teleporter.rotating == false &&
teleporter.teleporting === false)
characterController.movement = deltaXZ.times(10.)
else
characterController.movement = Qt.vector3d(0, 0, 0)
if (deltaLen >= teleporter.xzMovementTeleportationThreshold &&
teleporter.rotating == false &&
teleporter.teleporting === false &&
(characterController.collisions & CharacterController.Down) &&
(characterController.collisions & CharacterController.Side) ) {
teleportTo(characterControllerPosition, true)
}
}
readonly property vector3d characterControllerPosition: teleporter.characterController.scenePosition
property real characterControllerLastYPosition: 0
onCharacterControllerPositionChanged: {
let deltaY = characterControllerPosition.y - characterControllerLastYPosition
if (Math.abs(deltaY) > teleporter.yMovementTeleportationThreshold &&
teleporter.rotating === false &&
teleporter.teleporting === false &&
characterController.collisions == CharacterController.Down)
teleportTo(characterControllerPosition, true)
}
ValueFader {
id: screenValueFader
}
TargetIndicator {
id: targetIndicator
}
BeamModel {
id: beamModel
color: teleporter.targetValid ? teleporter.rayHitColor : teleporter.rayMissColor
}
FrameAnimation {
running: teleporter.yStickValue > 0.7
onTriggered: {
teleporter.updateTarget()
}
onRunningChanged: {
if (running) {
beamModel.show()
}else {
beamModel.hide()
targetIndicator.hide()
if (teleporter.targetValid)
teleporter.teleportTo(targetIndicator.scenePosition)
}
}
}
function updateTarget() : bool {
// Not a pure gravity parabola: We want a flatter curve
let beamPositions = [];
let pos = beamHandle.scenePosition
const dx = beamHandle.forward.x
const dz = beamHandle.forward.z
const a = Qt.vector3d(dx * 2, -4, dz * 2)
let d = beamHandle.forward.times(50)
let index = 0
let hit = false
let pickResult = null
let penetrate = false
let lastPos = Qt.vector3d(pos.x, pos.y, pos.z)
let characterPos = characterController.scenePosition
let handleToCharacterDir = pos.minus(characterPos)
pickResult = teleporter.rayPicker.rayPick(characterPos, handleToCharacterDir.normalized())
if (pickResult.objectHit && pickResult.distance <= handleToCharacterDir.length() + 25) {
penetrate = true
beamModel.hide()
}else {
beamModel.show()
beamPositions.push(Qt.vector3d(pos.x, pos.y, pos.z))
for (let i = 0; !hit && i < 50; ++i) {
pos = pos.plus(d)
d = d.plus(a)
let lastPosToPos = pos.minus(lastPos)
pickResult = teleporter.rayPicker.rayPick(lastPos, lastPosToPos.normalized())
hit = pickResult.objectHit && pickResult.distance <= lastPosToPos.length() + 25
beamPositions.push(Qt.vector3d(pos.x, pos.y, pos.z))
lastPos = Qt.vector3d(pos.x, pos.y, pos.z)
}
beamModel.generate(beamPositions)
}
if (!penetrate && hit && pickResult.sceneNormal.normalized().y > 0.9) {
teleporter.targetValid = true
targetIndicator.moveTo(pickResult.scenePosition)
targetIndicator.show()
} else {
teleporter.targetValid = false
targetIndicator.hide()
}
return teleporter.targetValid
}
}

View File

@ -0,0 +1,96 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Xr
XrItem {
id: prompter
property int prompt: Prompt.None
enum Prompt {
None,
DarknessFalling,
PickupTorch,
LightupTorch,
DefendCrop
}
property var prompts : [
"",
"Darkness is descending, enveloping the field.",
"Lift the torch and prepare for the journey ahead.",
"Light up the torch and illuminate your path.",
"Defend the field by igniting the fire pits."
]
property int hasShown: 0
onPromptChanged: {
var bitmask = (1<<prompt)
if (hasShown & bitmask)
return
if (textTransition.running)
textTransition.startAfterFinished = true
else
textTransition.restart()
hasShown |= bitmask
}
SequentialAnimation {
property bool startAfterFinished: false
id: textTransition
ScriptAction {
script: {
text.text = prompter.prompts[prompter.prompt]
}
}
NumberAnimation {
duration: 600
from: 0
to: 1
target: text
easing.type: Easing.OutCubic
properties: "animateValue"
}
NumberAnimation {
duration: 10000
}
NumberAnimation {
duration: 600
from: 1
to: 0
easing.type: Easing.OutCubic
target: text
properties: "animateValue"
}
onRunningChanged: {
if (!running && startAfterFinished) {
startAfterFinished = false
restart()
}
}
}
z: -30
x: -50
width: 100
height: 40
color: "transparent"
contentItem: Item {
width: 100
height: 50
Text {
id: text
property real animateValue: 0
opacity: animateValue
anchors.verticalCenterOffset: (1-animateValue) * 10
anchors.centerIn: parent
font.pointSize: 1
color: "#4a0a0a"
text: ""
styleColor: "#000000"
style: Text.Outline
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
}

View File

@ -0,0 +1,48 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Particles3D
Node {
id: smoke
property real size: 1.0
property color color: "gray"
property real colorVariation: 0.5
SpriteParticle3D {
id: smokeSpriteParticle
sprite: ParticleResources.smokeSpriteTexture
maxAmount: 200
spriteSequence: SpriteSequence3D {
frameCount: 15
interpolate: true
}
billboard: true
color: smoke.color
colorVariation: Qt.vector4d(smoke.colorVariation, smoke.colorVariation, smoke.colorVariation, 0.2)
unifiedColorVariation: true
fadeOutEffect: Particle3D.FadeOpacity
fadeOutDuration: 2000
}
ParticleEmitter3D {
system: ParticleResources.system
enabled: smoke.visible
id: smokeEmitter
particle: smokeSpriteParticle
particleScale: 25 * smoke.size
particleScaleVariation: 10 * smoke.size
particleEndScale: 35 * smoke.size
particleEndScaleVariation: 15 * smoke.size
particleRotationVariation: Qt.vector3d(0, 0, 180)
particleRotationVelocityVariation: Qt.vector3d(0, 0, 40)
emitRate: 30
lifeSpan: 2000
lifeSpanVariation: 1000
velocity: VectorDirection3D {
direction: Qt.vector3d(50.0, 70, -50.0)
directionVariation: Qt.vector3d(10, 10, 10)
}
}
}

View File

@ -0,0 +1,80 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Physics
Node {
id: stand
property var poses : [
Qt.vector3d(1000, 0, 1000),
Qt.vector3d(1000, 0, -1000),
Qt.vector3d(-1000, 0, 1000),
Qt.vector3d(-1000, 0, -1000)
]
Firewood {
instancing: FileInstancing {
source: "media/meshes/firewood_instances.xml.bin"
}
}
Repeater3D {
model: 4
delegate: StaticRigidBody {
scale: Qt.vector3d(3, 1.9, 3)
position: Qt.vector3d(stand.poses[index].x,
50 * scale.y,
stand.poses[index].z)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
pickable: true
materials: [InvisibleMaterial]
}
}
}
// Resources
Texture {
id: block_bc
generateMipmaps: true
source: "media/textures/block/block_bc.jpg"
}
Texture {
id: block_mr
generateMipmaps: true
source: "media/textures/block/block_mr.jpg"
}
Texture {
id: block_n
generateMipmaps: true
source: "media/textures/block/block_n.jpg"
}
PrincipledMaterial {
id: block_material
baseColorMap: block_bc
metalnessMap: block_mr
metalnessChannel: PrincipledMaterial.R
roughnessMap: block_mr
roughnessChannel: PrincipledMaterial.G
metalness: 1
roughness: 1
normalMap: block_n
}
Model {
y: 50
scale: Qt.vector3d(50, 50, 50)
instancing: FileInstancing {
source: "media/meshes/block_instances.xml.bin"
}
source: "media/meshes/block/defaultMaterial_mesh.mesh"
materials: [
block_material
]
}
}

View File

@ -0,0 +1,123 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
Node {
id: node1
// Resources
Texture {
id: table_bc
generateMipmaps: true
source: "media/textures/table/table_bc.jpg"
}
Texture {
id: table_mr
generateMipmaps: true
source: "media/textures/table/table_mr.jpg"
}
Texture {
id: table_n
generateMipmaps: true
source: "media/textures/table/table_n.jpg"
}
PrincipledMaterial {
id: table_material
baseColorMap: table_bc
metalnessMap: table_mr
metalnessChannel: PrincipledMaterial.R
roughnessMap: table_mr
roughnessChannel: PrincipledMaterial.G
metalness: 1
roughness: 1
normalMap: table_n
occlusionMap: table_mr
occlusionChannel: PrincipledMaterial.B
}
// Nodes:
DynamicRigidBody {
collisionShapes: BoxShape {
y: -2
extents: Qt.vector3d(122, 103, 200)
}
Model {
pickable: true
scale: Qt.vector3d(1.22, 1.05, 2.0)
source: "#Cube"
materials: [InvisibleMaterial]
}
Node {
scale: Qt.vector3d(100, 100, 100)
rotation: Qt.quaternion(0.707107, -0.707107, 0, 0)
Node {
rotation: Qt.quaternion(0.707107, 0.707107, 0, 0)
Node {
id: rail_low19
objectName: "Metal_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh7.mesh"
materials: [
table_material
]
}
}
Node {
id: legs_low10
objectName: "Legs_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh17.mesh"
materials: [
table_material
]
}
}
Node {
id: corners_low14
objectName: "Corners_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh20.mesh"
materials: [
table_material
]
}
}
Node {
id: base_low17
objectName: "Base_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh23.mesh"
materials: [
table_material
]
}
}
Node {
id: defaultMaterial15
objectName: "Rail_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh26.mesh"
materials: [
table_material
]
}
}
Node {
id: table_low23
objectName: "Table_low"
Model {
source: "media/meshes/table/defaultMaterial_mesh27.mesh"
materials: [
table_material
]
}
}
}
}
}
// Animations:
}

View File

@ -0,0 +1,77 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
Node {
id: targetIndicator
function show(){
hideAnimation.stop()
showAnimation.start()
}
function hide(){
showAnimation.stop()
hideAnimation.start()
}
function moveTo(pos : vector3d) {
targetIndicator.position = pos
}
visible: opacity > 0.01
ParallelAnimation {
id: showAnimation
NumberAnimation {
target: targetIndicator
properties: "opacity"
to: 0.99
duration: 50
}
NumberAnimation {
target: targetIndicator
properties: "scaleValue"
to: 0.5
easing.type: Easing.OutBack
}
}
ParallelAnimation {
id: hideAnimation
NumberAnimation {
target: targetIndicator
properties: "opacity"
to: 0.0
duration: 200
}
NumberAnimation {
target: targetIndicator
properties: "scaleValue"
to: 0.0
easing.type: Easing.OutBack
}
}
property real scaleValue: 0.0
scale: Qt.vector3d(scaleValue, 3.0, scaleValue)
opacity: 0.0
Model {
y: 50
source: "#Cylinder"
materials: CustomMaterial {
id: material
property real time: 0
NumberAnimation {
target: material
property: "time"
running: targetIndicator.visible
loops: -1
from: 0
to: Math.PI
duration: 500
}
property vector3d indicatorColor: Qt.vector3d(0, 1, 0)
depthDrawMode: Material.AlwaysDepthDraw
shadingMode: CustomMaterial.Unshaded
cullMode: Material.BackFaceCulling
vertexShader: "media/shaders/target_indicator.vert"
fragmentShader: "media/shaders/target_indicator.frag"
}
}
}

View File

@ -0,0 +1,179 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
DynamicRigidBody {
id: torch
objectName: "Torch"
property bool windEnabled: false
property vector3d globalWindDir: Qt.vector3d(0.5, 0, -0.5)
property Node attachedTo: null
property alias isOn: fire.isOn
function startFire() {
fire.life = 1
}
function stopFire() {
fire.life = 0
}
physicsMaterial: PhysicsMaterial {
restitution: 0.1
dynamicFriction: 10.0
staticFriction: 10.0
}
FrameAnimation {
running: (attachedTo)
onRunningChanged: {
if (running) {
torch.collisionShapes = null
torch.simulationEnabled = false
torch.pivot = Qt.vector3d(0, 10, 0)
}else {
torch.collisionShapes = torch.shapes
torch.pivot = Qt.vector3d(0, 0, 0)
torch.simulationEnabled = true
}
}
onTriggered: {
if (torch.attachedTo) {
torch.position = torch.attachedTo.scenePosition
torch.rotation = torch.attachedTo.sceneRotation
torch.reset(torch.position, torch.rotation.toEulerAngles())
}
}
}
// Resources
Texture {
id: torch_bc
source: "media/textures/torch/torch_bc.jpg"
}
Texture {
id: torch_n
source: "media/textures/torch/torch_n.jpg"
}
Texture {
id: torch_r
source: "media/textures/torch/torch_r.jpg"
}
PrincipledMaterial {
id: torch_material
baseColor: "#ffcccccc"
baseColorMap: torch_bc
normalMap: torch_n
roughnessMap: torch_r
roughness: 1
}
property list<CollisionShape> shapes: [CapsuleShape {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(0, 25, 0)
diameter: 5
height: 40
},
SphereShape {
diameter: 20
y: 60
}
]
collisionShapes: shapes
sendTriggerReports: true
Node {
position: Qt.vector3d(0, 50, 0)
TriggerBody {
scale: Qt.vector3d(0.05, 0.05, 0.05)
collisionShapes: [SphereShape{}]
onBodyEntered: (body)=>{
if (body.objectName === "Fire") {
if (body.parent.isOn)
fire.start()
else if (fire.isOn)
body.parent.start()
}
}
}
Fire {
id: fire
Timer {
running: fire.isOn
interval: 30000 + Math.random() * 30000
onTriggered: {
fire.stop()
}
}
FrameAnimation{
running: true
property vector3d lastPosition: Qt.vector3d(0,0,0)
onTriggered: {
let mappedDirVelocity = fire.mapDirectionFromScene(lastPosition.minus(fire.scenePosition))
let mappedDirVelocityLen = mappedDirVelocity.length() * 0.4
mappedDirVelocity = mappedDirVelocity.normalized()
let dir2DVelocity = Qt.vector2d(-mappedDirVelocity.z, mappedDirVelocity.x).normalized()
dir2DVelocity = dir2DVelocity.times((1.0 - Math.max(0, mappedDirVelocity.y)))
lastPosition = fire.scenePosition
fire.windstrength = 1.5
fire.windDir = dir2DVelocity.times(Math.min(mappedDirVelocityLen, 1.0))
if (torch.windEnabled) {
let mappedDirWind = fire.mapDirectionFromScene(torch.globalWindDir)
let dir2DWind = Qt.vector2d(-mappedDirWind.z, mappedDirWind.x).normalized()
dir2DWind = dir2DWind.times((1.0 - Math.max(0, mappedDirWind.y)))
fire.windDir = fire.windDir.plus(dir2DWind)
}
let mappedDirUp = fire.mapDirectionFromScene(Qt.vector3d(0, 1.0, 0))
let dir2DUp = Qt.vector2d(-mappedDirUp.z, mappedDirUp.x).normalized()
dir2DUp = dir2DUp.times((1.0 - Math.max(0, mappedDirUp.y)))
fire.windDir = fire.windDir.plus(dir2DUp)
fire.windDir = Qt.vector2d( Math.min(fire.windDir.x, 1.0), Math.min(fire.windDir.y, 1.0))
}
}
scale: Qt.vector3d(0.4, 1.0, 0.4)
}
Node {
onSceneRotationChanged: {
smoke.rotation = sceneRotation.inverted()
}
Smoke {
id: smoke
visible: fire.isOn
size: 0.5
position: Qt.vector3d(0, 65, 0)
}
}
}
Node {
id: sketchfab_model
rotation: Qt.quaternion(1.94707e-07, 1, 0, 0)
scale: Qt.vector3d(1, 1, 1)
position: Qt.vector3d(0, 25, 0)
Node {
Model {
source: "media/meshes/torch/object_1_mesh.mesh"
materials: [
torch_material
]
}
}
}
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Physics
import QtQuick3D.Xr
Node {
id: gripper
property alias hand: action.hand
property Node torchBody: null
XrInputAction {
id: action
actionId: [XrInputAction.SqueezeValue]
onValueChanged: {
if (gripper.torchBody) {
if (value > 0.5) {
gripper.torchBody.attachedTo = gripper
}else if (gripper.torchBody.attachedTo) {
gripper.torchBody.attachedTo = null
gripper.torchBody = null
}
}
}
}
TriggerBody {
scale: Qt.vector3d(0.03, 0.03, 0.03)
collisionShapes: [SphereShape{}]
onBodyEntered: (body)=>{
if (body.objectName === "Torch" &&
!gripper.torchBody) {
gripper.torchBody = body
}
}
onBodyExited: (body)=>{
if (body.objectName === "Torch" &&
gripper.torchBody &&
!gripper.torchBody.attachedTo) {
gripper.torchBody = null
}
}
Model {
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: gripper.torchBody ? "green" : "white"
}
}
}
}

View File

@ -0,0 +1,59 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
Item {
id: fader
property real value: 1
function blink(fadedOutLambda, fadedInLambda, duration) {
blinkAnimation.stop()
blinkAnimation.fadedOutLambda = fadedOutLambda
blinkAnimation.fadedInLambda = fadedInLambda
blinkAnimation.duration = duration
blinkAnimation.start()
}
SequentialAnimation {
id: blinkAnimation
property var fadedOutLambda
property var fadedInLambda
property int duration
NumberAnimation {
target: fader; property: "value";
easing.type: Easing.OutCubic
duration: blinkAnimation.duration
to: 0
}
ScriptAction {
script: {
if (blinkAnimation.fadedOutLambda &&
typeof blinkAnimation.fadedOutLambda === "function") {
let lambda = ()=>{} //to suppress the linter warning
lambda = blinkAnimation.fadedOutLambda
lambda();
blinkAnimation.fadedOutLambda = null;
}
}
}
NumberAnimation {
target: fader; property: "value";
to: 1
duration: blinkAnimation.duration
easing.type: Easing.InCubic
}
ScriptAction {
script: {
if (blinkAnimation.fadedInLambda &&
typeof blinkAnimation.fadedInLambda === "function") {
let lambda = ()=>{} //to suppress the linter warning
lambda = blinkAnimation.fadedInLambda
lambda();
blinkAnimation.fadedInLambda = null;
}
}
}
running: false
}
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<!--
https://developer.oculus.com/documentation/native/android/mobile-native-manifest/
https://developer.oculus.com/resources/publish-mobile-manifest/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.qtproject.example.xr_physicsbase_teleportation"
android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
<uses-permission android:name="org.khronos.openxr.permission.OPENXR"/>
<uses-permission android:name="org.khronos.openxr.permission.OPENXR_SYSTEM"/>
<uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1" />
<uses-feature android:glEsVersion="0x00030000" />
<application android:name="org.qtproject.qt.android.bindings.QtApplication"
android:label="Quick3DXr Physics-base teleportation demo"
android:requestLegacyExternalStorage="true" android:allowNativeHeapPointerTagging="false">
<meta-data android:name="com.oculus.intent.category.VR" android:value="vr_only"/>
<meta-data android:name="com.oculus.supportedDevices" android:value="all" />
<activity android:name="org.qtproject.qt.android.bindings.QtActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
android:launchMode="singleTask"
android:resizeableActivity="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="com.oculus.intent.category.VR"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="xr_physicsbase_teleportation"/>
</activity>
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.qtprovider"
android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/qtprovider_paths"/>
</provider>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@ -0,0 +1,39 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\title Qt Quick 3D - XR Physics-base teleportation demo
\examplecategory {3D}
\ingroup qtquickdemos
\example demos/xr_physicsbase_teleportation
\brief Demonstrates how to make physics-affected locomotion in Qt Quick 3D XR.
\meta {tag} {demo,quick,3d,xr}
\borderedimage xr_physicsbase_teleportation.jpg
\section1 Overview
This demo shows how to navigate and interact with objects in the virtual environment using physics-affected locomotion.
\section2 Controls
When you run the example, use the following controls for navigation.
\table
\header
\li
\li
\row
\li Rotation
\li Left and Right stick on the right controller
\row
\li Aim and Teleport
\li Forward stick on the right controller
\row
\li Interact with objects
\li Squeeze the right controller
\endtable
\include examples-run.qdocinc
\sa {QML Applications}
*/

View File

@ -0,0 +1,20 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/Main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

View File

@ -0,0 +1,11 @@
Model Information:
* title: Block Rock
* source: https://sketchfab.com/3d-models/block-rock-963974e36f474dc1b4e12d54ed46f643
* author: bilgehan.korkmaz (https://sketchfab.com/bilgehan.korkmaz)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Block Rock" (https://sketchfab.com/3d-models/block-rock-963974e36f474dc1b4e12d54ed46f643) by bilgehan.korkmaz (https://sketchfab.com/bilgehan.korkmaz) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" ?>
<InstanceTable>
<Instance position="905 0 905" eulerRotation="90 90 0"/>
<Instance position="905 95 905" eulerRotation="0 90 90"/>
<Instance position="905 0 1000" eulerRotation="360 180 0"/>
<Instance position="905 95 1000" eulerRotation="180 270 360"/>
<Instance position="905 0 1095" eulerRotation="270 180 0"/>
<Instance position="905 95 1095" eulerRotation="270 360 0"/>
<Instance position="1000 0 905" eulerRotation="360 180 270"/>
<Instance position="1000 95 905" eulerRotation="360 0 180"/>
<Instance position="1000 0 1000" eulerRotation="270 0 360"/>
<Instance position="1000 95 1000" eulerRotation="180 270 90"/>
<Instance position="1000 0 1095" eulerRotation="180 270 90"/>
<Instance position="1000 95 1095" eulerRotation="180 0 180"/>
<Instance position="1095 0 905" eulerRotation="180 360 360"/>
<Instance position="1095 95 905" eulerRotation="90 180 180"/>
<Instance position="1095 0 1000" eulerRotation="0 90 0"/>
<Instance position="1095 95 1000" eulerRotation="90 180 90"/>
<Instance position="1095 0 1095" eulerRotation="360 360 0"/>
<Instance position="1095 95 1095" eulerRotation="270 180 180"/>
<Instance position="905 0 -1095" eulerRotation="270 0 0"/>
<Instance position="905 95 -1095" eulerRotation="0 90 270"/>
<Instance position="905 0 -1000" eulerRotation="180 0 180"/>
<Instance position="905 95 -1000" eulerRotation="270 90 0"/>
<Instance position="905 0 -905" eulerRotation="360 180 270"/>
<Instance position="905 95 -905" eulerRotation="0 270 360"/>
<Instance position="1000 0 -1095" eulerRotation="0 270 360"/>
<Instance position="1000 95 -1095" eulerRotation="270 360 0"/>
<Instance position="1000 0 -1000" eulerRotation="0 90 0"/>
<Instance position="1000 95 -1000" eulerRotation="90 270 270"/>
<Instance position="1000 0 -905" eulerRotation="270 0 360"/>
<Instance position="1000 95 -905" eulerRotation="360 360 360"/>
<Instance position="1095 0 -1095" eulerRotation="360 360 90"/>
<Instance position="1095 95 -1095" eulerRotation="180 270 180"/>
<Instance position="1095 0 -1000" eulerRotation="360 0 180"/>
<Instance position="1095 95 -1000" eulerRotation="270 90 0"/>
<Instance position="1095 0 -905" eulerRotation="90 270 360"/>
<Instance position="1095 95 -905" eulerRotation="270 180 0"/>
<Instance position="-1095 0 905" eulerRotation="90 270 0"/>
<Instance position="-1095 95 905" eulerRotation="0 90 90"/>
<Instance position="-1095 0 1000" eulerRotation="270 360 0"/>
<Instance position="-1095 95 1000" eulerRotation="0 360 0"/>
<Instance position="-1095 0 1095" eulerRotation="180 90 270"/>
<Instance position="-1095 95 1095" eulerRotation="0 360 270"/>
<Instance position="-1000 0 905" eulerRotation="90 0 360"/>
<Instance position="-1000 95 905" eulerRotation="360 0 90"/>
<Instance position="-1000 0 1000" eulerRotation="90 0 360"/>
<Instance position="-1000 95 1000" eulerRotation="90 0 270"/>
<Instance position="-1000 0 1095" eulerRotation="180 270 270"/>
<Instance position="-1000 95 1095" eulerRotation="360 90 90"/>
<Instance position="-905 0 905" eulerRotation="0 0 180"/>
<Instance position="-905 95 905" eulerRotation="360 360 360"/>
<Instance position="-905 0 1000" eulerRotation="180 90 180"/>
<Instance position="-905 95 1000" eulerRotation="180 0 360"/>
<Instance position="-905 0 1095" eulerRotation="180 270 90"/>
<Instance position="-905 95 1095" eulerRotation="180 90 360"/>
<Instance position="-1095 0 -1095" eulerRotation="360 180 360"/>
<Instance position="-1095 95 -1095" eulerRotation="180 0 180"/>
<Instance position="-1095 0 -1000" eulerRotation="90 270 360"/>
<Instance position="-1095 95 -1000" eulerRotation="270 180 360"/>
<Instance position="-1095 0 -905" eulerRotation="180 0 360"/>
<Instance position="-1095 95 -905" eulerRotation="90 90 0"/>
<Instance position="-1000 0 -1095" eulerRotation="270 270 0"/>
<Instance position="-1000 95 -1095" eulerRotation="180 360 0"/>
<Instance position="-1000 0 -1000" eulerRotation="0 360 0"/>
<Instance position="-1000 95 -1000" eulerRotation="270 90 180"/>
<Instance position="-1000 0 -905" eulerRotation="0 270 0"/>
<Instance position="-1000 95 -905" eulerRotation="90 360 180"/>
<Instance position="-905 0 -1095" eulerRotation="180 0 270"/>
<Instance position="-905 95 -1095" eulerRotation="360 180 90"/>
<Instance position="-905 0 -1000" eulerRotation="0 0 180"/>
<Instance position="-905 95 -1000" eulerRotation="0 180 0"/>
<Instance position="-905 0 -905" eulerRotation="90 90 270"/>
<Instance position="-905 95 -905" eulerRotation="180 360 0"/>
</InstanceTable>

View File

@ -0,0 +1,11 @@
Model Information:
* title: metal decor torch
* source: https://sketchfab.com/3d-models/metal-decor-torch-a7d2f60c656942caac78e1a0e225bab7
* author: Rson (https://sketchfab.com/DimanRson)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "metal decor torch" (https://sketchfab.com/3d-models/metal-decor-torch-a7d2f60c656942caac78e1a0e225bab7) by Rson (https://sketchfab.com/DimanRson) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,11 @@
Model Information:
* title: Wooden Chair
* source: https://sketchfab.com/3d-models/wooden-chair-df4198bc5bc04371ac5e1361e7a02def
* author: J0Y (https://sketchfab.com/lloydrostek)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Wooden Chair" (https://sketchfab.com/3d-models/wooden-chair-df4198bc5bc04371ac5e1361e7a02def) by J0Y (https://sketchfab.com/lloydrostek) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,363 @@
<?xml version="1.0" encoding="UTF-8" ?>
<InstanceTable>
<Instance position="2004.8873291015625 -10.937222480773926 0" eulerRotation="1 22.710018157958984 1"/>
<Instance position="2001.0623779296875 -18.483291625976562 34.96502685546875" eulerRotation="1 213.89784240722656 1"/>
<Instance position="2003.4189453125 -6.337015628814697 70.04578399658203" eulerRotation="1 122.70886993408203 1"/>
<Instance position="2005.886962890625 -13.928656578063965 104.81822204589844" eulerRotation="1 345.52801513671875 1"/>
<Instance position="2000.7408447265625 -3.492644786834717 140.06785583496094" eulerRotation="1 248.79856872558594 1"/>
<Instance position="1995.140625 -2.352069139480591 175.0791778564453" eulerRotation="1 195.69921875 1"/>
<Instance position="1991.4720458984375 -14.565777778625488 209.6610565185547" eulerRotation="1 147.4871826171875 1"/>
<Instance position="1985.892822265625 -15.368762016296387 244.5719757080078" eulerRotation="1 59.90792465209961 1"/>
<Instance position="1984.7734375 -14.57715892791748 278.9331970214844" eulerRotation="1 36.493614196777344 1"/>
<Instance position="1978.51025390625 -6.401062965393066 314.030029296875" eulerRotation="1 169.3419952392578 1"/>
<Instance position="1979.115234375 -6.201999187469482 348.3721008300781" eulerRotation="1 317.70355224609375 1"/>
<Instance position="1972.56591796875 -6.192686557769775 383.49493408203125" eulerRotation="1 54.51922607421875 1"/>
<Instance position="1964.392333984375 -9.443605422973633 416.71270751953125" eulerRotation="1 304.3303527832031 1"/>
<Instance position="1956.4449462890625 -15.310738563537598 451.08685302734375" eulerRotation="1 58.11771011352539 1"/>
<Instance position="1947.3953857421875 -6.270330429077148 484.3056335449219" eulerRotation="1 339.177978515625 1"/>
<Instance position="1935.9405517578125 -10.093535423278809 517.658203125" eulerRotation="1 17.5137882232666 1"/>
<Instance position="1922.769775390625 -10.945923805236816 551.4695434570312" eulerRotation="1 97.75160217285156 1"/>
<Instance position="1917.977783203125 -12.347034454345703 585.1943969726562" eulerRotation="1 342.4668273925781 1"/>
<Instance position="1902.5645751953125 -2.7976465225219727 618.6470336914062" eulerRotation="1 353.30859375 1"/>
<Instance position="1891.5177001953125 -13.59543514251709 652.1239013671875" eulerRotation="1 259.9620666503906 1"/>
<Instance position="1880.9853515625 -12.026472091674805 686.222900390625" eulerRotation="1 178.8809814453125 1"/>
<Instance position="1874.344970703125 -9.696571350097656 718.7643432617188" eulerRotation="1 98.62101745605469 1"/>
<Instance position="1861.0140380859375 -1.767014503479004 749.4505615234375" eulerRotation="1 162.88169860839844 1"/>
<Instance position="1844.616943359375 -14.22244930267334 783.2409057617188" eulerRotation="1 45.74037551879883 1"/>
<Instance position="1835.539794921875 -18.692472457885742 813.7664794921875" eulerRotation="1 189.93374633789062 1"/>
<Instance position="1818.169189453125 -18.149581909179688 849.030517578125" eulerRotation="1 98.04228210449219 1"/>
<Instance position="1797.9176025390625 -8.721160888671875 879.89453125" eulerRotation="1 11.252962112426758 1"/>
<Instance position="1787.865966796875 -1.1705185174942017 908.4371337890625" eulerRotation="1 169.52386474609375 1"/>
<Instance position="1774.187255859375 -16.34847068786621 941.7260131835938" eulerRotation="1 32.228023529052734 1"/>
<Instance position="1757.465576171875 -10.108654975891113 971.8574829101562" eulerRotation="1 158.9573974609375 1"/>
<Instance position="1736.1597900390625 -17.40435791015625 1004.4082641601562" eulerRotation="1 338.1105041503906 1"/>
<Instance position="1717.5814208984375 -8.068078994750977 1034.5111083984375" eulerRotation="1 215.4677276611328 1"/>
<Instance position="1704.0897216796875 -3.9755568504333496 1064.9443359375" eulerRotation="1 263.74884033203125 1"/>
<Instance position="1679.455078125 -15.097962379455566 1092.789794921875" eulerRotation="1 302.7609558105469 1"/>
<Instance position="1658.364501953125 -15.27957534790039 1122.965576171875" eulerRotation="1 358.29278564453125 1"/>
<Instance position="1644.8720703125 -12.58370304107666 1152.800048828125" eulerRotation="1 298.3340148925781 1"/>
<Instance position="1623.366455078125 -17.516626358032227 1178.123046875" eulerRotation="1 284.9007873535156 1"/>
<Instance position="1599.68505859375 -1.6415961980819702 1205.429443359375" eulerRotation="1 112.5880126953125 1"/>
<Instance position="1581.89208984375 -14.961873054504395 1232.9052734375" eulerRotation="1 202.2023468017578 1"/>
<Instance position="1559.821044921875 -8.586908340454102 1259.4259033203125" eulerRotation="1 276.5146484375 1"/>
<Instance position="1537.6839599609375 -13.535550117492676 1286.399658203125" eulerRotation="1 283.3631591796875 1"/>
<Instance position="1511.4674072265625 -8.093660354614258 1312.8939208984375" eulerRotation="1 9.194034576416016 1"/>
<Instance position="1493.646728515625 -6.255752086639404 1338.47802734375" eulerRotation="1 156.5480194091797 1"/>
<Instance position="1465.16357421875 -11.870723724365234 1366.021728515625" eulerRotation="1 103.17485046386719 1"/>
<Instance position="1445.5164794921875 -2.4028546810150146 1393.2003173828125" eulerRotation="1 132.84378051757812 1"/>
<Instance position="1420.9783935546875 -19.534690856933594 1414.3162841796875" eulerRotation="1 16.248281478881836 1"/>
<Instance position="1389.674072265625 -8.970355033874512 1439.4312744140625" eulerRotation="1 102.9133529663086 1"/>
<Instance position="1370.1890869140625 -16.172657012939453 1464.3284912109375" eulerRotation="1 176.181640625 1"/>
<Instance position="1341.0133056640625 -7.760373592376709 1490.642822265625" eulerRotation="1 189.13909912109375 1"/>
<Instance position="1315.426513671875 -17.870872497558594 1510.85986328125" eulerRotation="1 180.1317596435547 1"/>
<Instance position="1289.748779296875 -14.993217468261719 1536.00341796875" eulerRotation="1 314.01226806640625 1"/>
<Instance position="1262.0130615234375 -9.165276527404785 1559.332763671875" eulerRotation="1 56.306739807128906 1"/>
<Instance position="1231.7813720703125 -1.6970014572143555 1582.93603515625" eulerRotation="1 185.02767944335938 1"/>
<Instance position="1209.316650390625 -7.427068710327148 1598.1602783203125" eulerRotation="1 167.7611083984375 1"/>
<Instance position="1180.2049560546875 -16.310161590576172 1620.4334716796875" eulerRotation="1 274.17901611328125 1"/>
<Instance position="1148.3973388671875 -15.302572250366211 1640.8685302734375" eulerRotation="1 167.17636108398438 1"/>
<Instance position="1120.5699462890625 -18.448959350585938 1659.593017578125" eulerRotation="1 267.34942626953125 1"/>
<Instance position="1094.6829833984375 -8.323362350463867 1682.5787353515625" eulerRotation="1 51.11443328857422 1"/>
<Instance position="1062.432373046875 -10.460415840148926 1704.2344970703125" eulerRotation="1 209.64784240722656 1"/>
<Instance position="1031.604248046875 -2.2974259853363037 1719.96923828125" eulerRotation="1 54.367103576660156 1"/>
<Instance position="1004.9132080078125 -13.065818786621094 1735.8018798828125" eulerRotation="1 148.42332458496094 1"/>
<Instance position="970.597412109375 -4.7222113609313965 1757.21142578125" eulerRotation="1 322.183349609375 1"/>
<Instance position="943.62890625 -10.66843318939209 1772.6126708984375" eulerRotation="1 91.3207778930664 1"/>
<Instance position="909.1097412109375 -4.818757057189941 1784.9556884765625" eulerRotation="1 215.2249298095703 1"/>
<Instance position="876.9453125 -4.766798496246338 1798.06982421875" eulerRotation="1 67.02567291259766 1"/>
<Instance position="846.4754028320312 -2.8858776092529297 1815.5247802734375" eulerRotation="1 253.4959259033203 1"/>
<Instance position="817.3985595703125 -13.110901832580566 1828.5859375" eulerRotation="1 127.8003158569336 1"/>
<Instance position="785.2685546875 -16.969715118408203 1844.9984130859375" eulerRotation="1 344.8869323730469 1"/>
<Instance position="751.5182495117188 -11.69895076751709 1856.950927734375" eulerRotation="1 122.11788940429688 1"/>
<Instance position="720.166259765625 -12.296509742736816 1869.1422119140625" eulerRotation="1 176.57644653320312 1"/>
<Instance position="685.1106567382812 -2.691190242767334 1888.465087890625" eulerRotation="1 230.2069549560547 1"/>
<Instance position="652.9757080078125 -8.794905662536621 1894.0809326171875" eulerRotation="1 257.9208068847656 1"/>
<Instance position="619.66943359375 -17.119047164916992 1908.60400390625" eulerRotation="1 179.07376098632812 1"/>
<Instance position="586.8955688476562 -11.882834434509277 1914.993896484375" eulerRotation="1 96.29231262207031 1"/>
<Instance position="553.9318237304688 -5.027284622192383 1922.6392822265625" eulerRotation="1 101.8404312133789 1"/>
<Instance position="518.7230834960938 -7.559670448303223 1933.7862548828125" eulerRotation="1 14.74776840209961 1"/>
<Instance position="485.89434814453125 -19.839529037475586 1950.0928955078125" eulerRotation="1 194.4609375 1"/>
<Instance position="451.65472412109375 -14.67434310913086 1952.607666015625" eulerRotation="1 244.65097045898438 1"/>
<Instance position="417.2010803222656 -17.772493362426758 1962.872802734375" eulerRotation="1 17.642560958862305 1"/>
<Instance position="382.8194885253906 -17.761768341064453 1965.4981689453125" eulerRotation="1 278.5831604003906 1"/>
<Instance position="347.50445556640625 -2.1291027069091797 1970.9512939453125" eulerRotation="1 209.83575439453125 1"/>
<Instance position="313.5285339355469 -1.8441756963729858 1983.9383544921875" eulerRotation="1 35.843692779541016 1"/>
<Instance position="279.0982666015625 -13.804391860961914 1983.938720703125" eulerRotation="1 191.42369079589844 1"/>
<Instance position="243.9959716796875 -5.939338684082031 1988.570556640625" eulerRotation="1 329.6120300292969 1"/>
<Instance position="209.92059326171875 -18.744609832763672 1994.7919921875" eulerRotation="1 279.05133056640625 1"/>
<Instance position="174.47679138183594 -18.052085876464844 2000.697265625" eulerRotation="1 331.2702331542969 1"/>
<Instance position="139.53321838378906 -0.8500494956970215 2002.6387939453125" eulerRotation="1 109.57431030273438 1"/>
<Instance position="104.82368469238281 -12.72632884979248 2001.1490478515625" eulerRotation="1 257.6541442871094 1"/>
<Instance position="70.12149047851562 -12.469435691833496 1998.8172607421875" eulerRotation="1 289.3329772949219 1"/>
<Instance position="35.06015396118164 -12.488428115844727 2003.05810546875" eulerRotation="1 249.3823699951172 1"/>
<Instance position="1.2279645345263795e-13 -7.850288391113281 2004.1954345703125" eulerRotation="1 7.724409580230713 1"/>
<Instance position="-35.01461410522461 -1.5626990795135498 2007.4029541015625" eulerRotation="1 356.76837158203125 1"/>
<Instance position="-69.92202758789062 -14.763961791992188 2004.9443359375" eulerRotation="1 290.2225036621094 1"/>
<Instance position="-105.09069061279297 -8.050773620605469 1999.2891845703125" eulerRotation="1 112.98855590820312 1"/>
<Instance position="-139.5279541015625 -5.682704925537109 1998.326171875" eulerRotation="1 133.05015563964844 1"/>
<Instance position="-175.17784118652344 -16.9705867767334 1996.9688720703125" eulerRotation="1 150.5659637451172 1"/>
<Instance position="-209.62596130371094 -1.947021245956421 1998.3369140625" eulerRotation="1 349.7592468261719 1"/>
<Instance position="-244.36241149902344 -6.78826904296875 1991.6456298828125" eulerRotation="1 332.2086486816406 1"/>
<Instance position="-279.219482421875 -18.827198028564453 1985.050048828125" eulerRotation="1 79.54605865478516 1"/>
<Instance position="-314.1694030761719 -19.81075668334961 1983.933349609375" eulerRotation="1 188.17018127441406 1"/>
<Instance position="-348.5540466308594 -3.9271531105041504 1978.2005615234375" eulerRotation="1 33.57630920410156 1"/>
<Instance position="-382.46343994140625 -0.4010947048664093 1968.007568359375" eulerRotation="1 139.0752716064453 1"/>
<Instance position="-417.49029541015625 -9.739174842834473 1956.645751953125" eulerRotation="1 342.7809753417969 1"/>
<Instance position="-450.32855224609375 -13.532137870788574 1949.72900390625" eulerRotation="1 86.46353912353516 1"/>
<Instance position="-485.1539611816406 -0.17684949934482574 1941.9295654296875" eulerRotation="1 132.3712921142578 1"/>
<Instance position="-518.8695068359375 -19.624916076660156 1940.9017333984375" eulerRotation="1 277.502685546875 1"/>
<Instance position="-553.3504638671875 -16.01502799987793 1928.9403076171875" eulerRotation="1 158.8237762451172 1"/>
<Instance position="-587.6524658203125 -18.43729591369629 1918.29541015625" eulerRotation="1 288.6526184082031 1"/>
<Instance position="-619.8048706054688 -14.748957633972168 1907.764404296875" eulerRotation="1 339.83331298828125 1"/>
<Instance position="-651.8541259765625 -9.50455379486084 1897.419189453125" eulerRotation="1 282.107421875 1"/>
<Instance position="-686.1947021484375 -14.116842269897461 1879.9818115234375" eulerRotation="1 348.12469482421875 1"/>
<Instance position="-718.1250610351562 -0.5101636052131653 1867.302978515625" eulerRotation="1 140.93898010253906 1"/>
<Instance position="-751.1421508789062 -11.894282341003418 1856.6007080078125" eulerRotation="1 117.97637176513672 1"/>
<Instance position="-784.0859375 -9.12778091430664 1847.8338623046875" eulerRotation="1 20.78388023376465 1"/>
<Instance position="-815.5709228515625 -8.672213554382324 1833.8394775390625" eulerRotation="1 128.9021453857422 1"/>
<Instance position="-848.5034790039062 -3.328738212585449 1819.9898681640625" eulerRotation="1 261.5985412597656 1"/>
<Instance position="-876.9542846679688 -17.098567962646484 1799.9659423828125" eulerRotation="1 267.2855529785156 1"/>
<Instance position="-910.4312133789062 -9.504666328430176 1783.279052734375" eulerRotation="1 46.1609992980957 1"/>
<Instance position="-942.6138916015625 -14.198066711425781 1771.7484130859375" eulerRotation="1 33.02253341674805 1"/>
<Instance position="-974.43896484375 -5.249409198760986 1752.976318359375" eulerRotation="1 19.829532623291016 1"/>
<Instance position="-1001.595947265625 -9.87705135345459 1738.4268798828125" eulerRotation="1 105.25194549560547 1"/>
<Instance position="-1030.32568359375 -2.608034372329712 1717.3668212890625" eulerRotation="1 51.624671936035156 1"/>
<Instance position="-1060.511474609375 -8.30913257598877 1702.323974609375" eulerRotation="1 63.8110466003418 1"/>
<Instance position="-1090.642333984375 -17.161697387695312 1679.9803466796875" eulerRotation="1 301.4112854003906 1"/>
<Instance position="-1118.513427734375 -1.9619603157043457 1662.4075927734375" eulerRotation="1 86.6064453125 1"/>
<Instance position="-1148.50048828125 -14.392292976379395 1642.62548828125" eulerRotation="1 279.7842102050781 1"/>
<Instance position="-1176.80712890625 -4.694129467010498 1625.7132568359375" eulerRotation="1 221.4578857421875 1"/>
<Instance position="-1205.908203125 -17.157089233398438 1600.2135009765625" eulerRotation="1 237.57261657714844 1"/>
<Instance position="-1236.059814453125 -2.2185795307159424 1576.93505859375" eulerRotation="1 254.90768432617188 1"/>
<Instance position="-1263.56201171875 -4.670470714569092 1557.8917236328125" eulerRotation="1 274.2152404785156 1"/>
<Instance position="-1287.9625244140625 -9.219776153564453 1535.245849609375" eulerRotation="1 171.880859375 1"/>
<Instance position="-1314.0355224609375 -12.213530540466309 1509.9793701171875" eulerRotation="1 171.9212646484375 1"/>
<Instance position="-1343.5169677734375 -3.208033323287964 1492.9346923828125" eulerRotation="1 219.25682067871094 1"/>
<Instance position="-1367.960693359375 -16.978988647460938 1467.226806640625" eulerRotation="1 31.517696380615234 1"/>
<Instance position="-1390.2728271484375 -11.199563026428223 1444.5361328125" eulerRotation="1 139.8994140625 1"/>
<Instance position="-1417.5780029296875 -11.410419464111328 1419.520263671875" eulerRotation="1 83.54081726074219 1"/>
<Instance position="-1445.2313232421875 -4.787092208862305 1395.6751708984375" eulerRotation="1 163.38836669921875 1"/>
<Instance position="-1466.180908203125 -2.4119787216186523 1367.16015625" eulerRotation="1 163.93154907226562 1"/>
<Instance position="-1486.6885986328125 -14.214238166809082 1338.7879638671875" eulerRotation="1 189.97659301757812 1"/>
<Instance position="-1513.3048095703125 -18.161149978637695 1312.9698486328125" eulerRotation="1 95.46271514892578 1"/>
<Instance position="-1534.1405029296875 -16.856266021728516 1289.97705078125" eulerRotation="1 179.2611541748047 1"/>
<Instance position="-1558.5782470703125 -7.708557605743408 1264.777099609375" eulerRotation="1 44.41676330566406 1"/>
<Instance position="-1582.4708251953125 -5.18779182434082 1233.0032958984375" eulerRotation="1 240.5288543701172 1"/>
<Instance position="-1598.287109375 -3.889568567276001 1206.9783935546875" eulerRotation="1 245.80995178222656 1"/>
<Instance position="-1624.044677734375 -18.350210189819336 1176.46435546875" eulerRotation="1 290.4557189941406 1"/>
<Instance position="-1645.486083984375 -10.732856750488281 1150.2164306640625" eulerRotation="1 109.05123138427734 1"/>
<Instance position="-1665.435302734375 -0.680525004863739 1123.643798828125" eulerRotation="1 157.36473083496094 1"/>
<Instance position="-1681.1114501953125 -0.3302892744541168 1093.4803466796875" eulerRotation="1 129.54638671875 1"/>
<Instance position="-1698.211181640625 -8.384106636047363 1063.9312744140625" eulerRotation="1 95.05220031738281 1"/>
<Instance position="-1718.340087890625 -7.7179951667785645 1034.275390625" eulerRotation="1 255.2627410888672 1"/>
<Instance position="-1736.0316162109375 -15.00002670288086 1003.9577026367188" eulerRotation="1 241.78948974609375 1"/>
<Instance position="-1750.520751953125 -3.057766914367676 971.8738403320312" eulerRotation="1 228.05567932128906 1"/>
<Instance position="-1771.5762939453125 -5.35998010635376 939.88232421875" eulerRotation="1 2.104602336883545 1"/>
<Instance position="-1787.26318359375 -10.674132347106934 910.4493408203125" eulerRotation="1 208.357666015625 1"/>
<Instance position="-1799.9437255859375 -16.062301635742188 880.2859497070312" eulerRotation="1 88.738037109375 1"/>
<Instance position="-1819.7894287109375 -2.9114458560943604 847.2239990234375" eulerRotation="1 309.4671325683594 1"/>
<Instance position="-1831.12060546875 -9.961996078491211 816.1392822265625" eulerRotation="1 264.0062255859375 1"/>
<Instance position="-1847.92529296875 -5.978405475616455 783.0156860351562" eulerRotation="1 230.42066955566406 1"/>
<Instance position="-1858.4385986328125 -17.06477165222168 751.4879760742188" eulerRotation="1 192.29507446289062 1"/>
<Instance position="-1875.8948974609375 -19.97389793395996 716.7459106445312" eulerRotation="1 80.9563217163086 1"/>
<Instance position="-1881.82421875 -18.37840461730957 685.5946655273438" eulerRotation="1 229.7309112548828 1"/>
<Instance position="-1892.9091796875 -5.601089000701904 652.4141235351562" eulerRotation="1 171.8396453857422 1"/>
<Instance position="-1905.1541748046875 -13.414700508117676 618.2468872070312" eulerRotation="1 264.6466979980469 1"/>
<Instance position="-1914.0198974609375 -2.7390856742858887 587.4439086914062" eulerRotation="1 284.1000671386719 1"/>
<Instance position="-1930.5960693359375 -1.4159597158432007 553.1353149414062" eulerRotation="1 160.05621337890625 1"/>
<Instance position="-1936.76611328125 -4.033178806304932 517.9593505859375" eulerRotation="1 48.488460540771484 1"/>
<Instance position="-1946.2095947265625 -5.989327907562256 484.7184143066406" eulerRotation="1 106.77714538574219 1"/>
<Instance position="-1952.9222412109375 -2.0525481700897217 450.0308532714844" eulerRotation="1 221.1660614013672 1"/>
<Instance position="-1957.823486328125 -6.155316352844238 417.7075500488281" eulerRotation="1 139.728515625 1"/>
<Instance position="-1972.1785888671875 -11.007879257202148 382.41192626953125" eulerRotation="1 269.5816650390625 1"/>
<Instance position="-1974.430908203125 -9.655817031860352 348.1363525390625" eulerRotation="1 127.70319366455078 1"/>
<Instance position="-1983.17236328125 -0.10072386264801025 313.4450988769531" eulerRotation="1 101.39517211914062 1"/>
<Instance position="-1983.5911865234375 -18.90791130065918 279.5505676269531" eulerRotation="1 204.52670288085938 1"/>
<Instance position="-1992.7755126953125 -7.991392135620117 244.12718200683594" eulerRotation="1 160.4076385498047 1"/>
<Instance position="-1995.5084228515625 -16.791446685791016 209.188232421875" eulerRotation="1 190.69815063476562 1"/>
<Instance position="-1996.8016357421875 -7.726731300354004 174.91671752929688" eulerRotation="1 344.566162109375 1"/>
<Instance position="-2003.7664794921875 -12.106461524963379 140.07949829101562" eulerRotation="1 29.469446182250977 1"/>
<Instance position="-1998.349365234375 -15.263943672180176 104.92073822021484" eulerRotation="1 345.7972717285156 1"/>
<Instance position="-2001.4512939453125 -16.46323585510254 69.81430053710938" eulerRotation="1 259.53411865234375 1"/>
<Instance position="-2001.521240234375 -4.482601165771484 34.93195343017578" eulerRotation="1 243.00840759277344 1"/>
<Instance position="-2009.266357421875 -13.141471862792969 2.454816406573246e-13" eulerRotation="1 278.7698059082031 1"/>
<Instance position="-2004.1563720703125 -13.439399719238281 -35.06398010253906" eulerRotation="1 212.46209716796875 1"/>
<Instance position="-2002.0167236328125 -8.923271179199219 -70.12836456298828" eulerRotation="1 159.98448181152344 1"/>
<Instance position="-2003.1748046875 -12.248872756958008 -104.84382629394531" eulerRotation="1 127.98760223388672 1"/>
<Instance position="-2000.336181640625 -15.284089088439941 -139.64169311523438" eulerRotation="1 175.5594940185547 1"/>
<Instance position="-2001.2548828125 -5.062148571014404 -174.94313049316406" eulerRotation="1 271.3927917480469 1"/>
<Instance position="-1990.7537841796875 -12.951213836669922 -209.70489501953125" eulerRotation="1 164.48269653320312 1"/>
<Instance position="-1993.5174560546875 -14.66124153137207 -243.82083129882812" eulerRotation="1 184.701416015625 1"/>
<Instance position="-1987.065185546875 -5.9904465675354 -279.6904296875" eulerRotation="1 306.7141418457031 1"/>
<Instance position="-1984.1690673828125 -6.914464950561523 -314.1179504394531" eulerRotation="1 315.551025390625 1"/>
<Instance position="-1977.0308837890625 -12.399214744567871 -348.05224609375" eulerRotation="1 18.16429328918457 1"/>
<Instance position="-1963.6766357421875 -9.496023178100586 -382.8260803222656" eulerRotation="1 2.872962236404419 1"/>
<Instance position="-1963.494384765625 -8.868718147277832 -416.49188232421875" eulerRotation="1 221.72308349609375 1"/>
<Instance position="-1952.1708984375 -9.830825805664062 -450.51544189453125" eulerRotation="1 276.9450988769531 1"/>
<Instance position="-1947.4610595703125 -19.768606185913086 -484.7789611816406" eulerRotation="1 284.2572937011719 1"/>
<Instance position="-1934.48876953125 -5.00001335144043 -518.7393188476562" eulerRotation="1 137.27963256835938 1"/>
<Instance position="-1924.0257568359375 -4.7417402267456055 -553.2507934570312" eulerRotation="1 174.0843963623047 1"/>
<Instance position="-1915.1571044921875 -11.152419090270996 -586.3594360351562" eulerRotation="1 59.32475280761719 1"/>
<Instance position="-1904.8988037109375 -10.690223693847656 -618.5136108398438" eulerRotation="1 39.01955032348633 1"/>
<Instance position="-1897.0643310546875 -16.803804397583008 -653.4027099609375" eulerRotation="1 328.1426086425781 1"/>
<Instance position="-1879.9615478515625 -11.425705909729004 -686.2826538085938" eulerRotation="1 355.4687194824219 1"/>
<Instance position="-1871.6824951171875 -5.190011024475098 -719.3113403320312" eulerRotation="1 108.28848266601562 1"/>
<Instance position="-1859.680419921875 -1.5151265859603882 -750.4236450195312" eulerRotation="1 59.29494094848633 1"/>
<Instance position="-1841.5428466796875 -11.7880859375 -781.9485473632812" eulerRotation="1 161.91783142089844 1"/>
<Instance position="-1834.56787109375 -8.237434387207031 -815.3328857421875" eulerRotation="1 94.23674011230469 1"/>
<Instance position="-1817.9283447265625 -3.3359172344207764 -849.0576171875" eulerRotation="1 270.15777587890625 1"/>
<Instance position="-1799.113037109375 -2.0047121047973633 -880.3156127929688" eulerRotation="1 161.06019592285156 1"/>
<Instance position="-1786.5013427734375 -18.671865463256836 -909.1008911132812" eulerRotation="1 350.837646484375 1"/>
<Instance position="-1771.726806640625 -14.71026611328125 -941.6649169921875" eulerRotation="1 102.10147094726562 1"/>
<Instance position="-1751.4227294921875 -17.12139892578125 -971.716552734375" eulerRotation="1 139.01963806152344 1"/>
<Instance position="-1738.406982421875 -14.3962984085083 -1000.76025390625" eulerRotation="1 296.9557189941406 1"/>
<Instance position="-1716.90673828125 -10.413886070251465 -1030.64697265625" eulerRotation="1 220.55111694335938 1"/>
<Instance position="-1702.4283447265625 -17.70528793334961 -1061.7230224609375" eulerRotation="1 131.71865844726562 1"/>
<Instance position="-1684.7000732421875 -8.057792663574219 -1091.401611328125" eulerRotation="1 217.71630859375 1"/>
<Instance position="-1666.341796875 -9.378607749938965 -1119.0919189453125" eulerRotation="1 202.25619506835938 1"/>
<Instance position="-1644.162353515625 -4.631957530975342 -1152.87548828125" eulerRotation="1 268.24981689453125 1"/>
<Instance position="-1625.0059814453125 -12.63991928100586 -1178.331787109375" eulerRotation="1 63.20541000366211 1"/>
<Instance position="-1604.60302734375 -2.7942328453063965 -1205.240966796875" eulerRotation="1 103.60079956054688 1"/>
<Instance position="-1576.4879150390625 -18.236492156982422 -1232.0052490234375" eulerRotation="1 176.41082763671875 1"/>
<Instance position="-1556.1968994140625 -12.786321640014648 -1263.52099609375" eulerRotation="1 240.933349609375 1"/>
<Instance position="-1532.37744140625 -17.855510711669922 -1285.860595703125" eulerRotation="1 1.8936984539031982 1"/>
<Instance position="-1516.5543212890625 -3.0842947959899902 -1314.2135009765625" eulerRotation="1 248.02883911132812 1"/>
<Instance position="-1487.716064453125 -11.310312271118164 -1343.16259765625" eulerRotation="1 243.2762908935547 1"/>
<Instance position="-1463.24853515625 -14.221684455871582 -1367.090576171875" eulerRotation="1 179.48721313476562 1"/>
<Instance position="-1443.5482177734375 -18.806066513061523 -1390.1651611328125" eulerRotation="1 314.0834045410156 1"/>
<Instance position="-1414.6785888671875 -4.14377498626709 -1417.6544189453125" eulerRotation="1 28.030563354492188 1"/>
<Instance position="-1394.646728515625 -16.358510971069336 -1444.05712890625" eulerRotation="1 106.91492462158203 1"/>
<Instance position="-1368.038818359375 -8.436572074890137 -1465.982177734375" eulerRotation="1 56.97417449951172 1"/>
<Instance position="-1340.9949951171875 -10.778153419494629 -1489.8720703125" eulerRotation="1 113.46786499023438 1"/>
<Instance position="-1318.578857421875 -15.975537300109863 -1512.7076416015625" eulerRotation="1 151.71717834472656 1"/>
<Instance position="-1286.5496826171875 -11.441811561584473 -1532.4903564453125" eulerRotation="1 226.3960723876953 1"/>
<Instance position="-1261.5745849609375 -12.316543579101562 -1554.595703125" eulerRotation="1 298.1336669921875 1"/>
<Instance position="-1234.084716796875 -15.911791801452637 -1577.22705078125" eulerRotation="1 58.21437072753906 1"/>
<Instance position="-1209.584228515625 -2.725451946258545 -1601.00439453125" eulerRotation="1 293.7241516113281 1"/>
<Instance position="-1179.802001953125 -18.81833267211914 -1621.598876953125" eulerRotation="1 271.19000244140625 1"/>
<Instance position="-1150.4920654296875 -7.289712905883789 -1642.20849609375" eulerRotation="1 359.7353210449219 1"/>
<Instance position="-1122.7265625 -19.40886116027832 -1665.7220458984375" eulerRotation="1 353.2297668457031 1"/>
<Instance position="-1094.7109375 -2.743457794189453 -1682.4495849609375" eulerRotation="1 255.56719970703125 1"/>
<Instance position="-1060.4766845703125 -11.069350242614746 -1703.438720703125" eulerRotation="1 323.637939453125 1"/>
<Instance position="-1033.7220458984375 -9.37379264831543 -1718.208251953125" eulerRotation="1 325.240966796875 1"/>
<Instance position="-1001.4641723632812 -0.9201908707618713 -1734.0230712890625" eulerRotation="1 91.32838439941406 1"/>
<Instance position="-970.646484375 -6.680348873138428 -1754.2138671875" eulerRotation="1 182.1010284423828 1"/>
<Instance position="-941.4216918945312 -14.292679786682129 -1770.9385986328125" eulerRotation="1 307.1168212890625 1"/>
<Instance position="-911.5994873046875 -11.531937599182129 -1787.800537109375" eulerRotation="1 338.96026611328125 1"/>
<Instance position="-880.7520751953125 -3.099764108657837 -1798.1572265625" eulerRotation="1 174.8548126220703 1"/>
<Instance position="-846.3110961914062 -4.134286403656006 -1820.5418701171875" eulerRotation="1 55.40789031982422 1"/>
<Instance position="-814.5604858398438 -19.73225975036621 -1828.1414794921875" eulerRotation="1 74.1323013305664 1"/>
<Instance position="-784.6931762695312 -4.816412448883057 -1841.4942626953125" eulerRotation="1 76.2762680053711 1"/>
<Instance position="-751.4957885742188 -12.403891563415527 -1859.55908203125" eulerRotation="1 64.75605773925781 1"/>
<Instance position="-718.65380859375 -17.480335235595703 -1873.4385986328125" eulerRotation="1 96.45355987548828 1"/>
<Instance position="-686.6392822265625 -13.475086212158203 -1883.1324462890625" eulerRotation="1 55.609432220458984 1"/>
<Instance position="-654.1631469726562 -0.729341447353363 -1895.986572265625" eulerRotation="1 63.22945785522461 1"/>
<Instance position="-621.0201416015625 -18.356101989746094 -1909.9893798828125" eulerRotation="1 345.03594970703125 1"/>
<Instance position="-587.1718139648438 -1.511946201324463 -1921.6461181640625" eulerRotation="1 265.04156494140625 1"/>
<Instance position="-552.0844116210938 -18.863880157470703 -1931.2471923828125" eulerRotation="1 125.81796264648438 1"/>
<Instance position="-517.790283203125 -18.01422691345215 -1941.0963134765625" eulerRotation="1 310.9696960449219 1"/>
<Instance position="-484.2770690917969 -5.968751907348633 -1943.114013671875" eulerRotation="1 188.9571990966797 1"/>
<Instance position="-450.03863525390625 -13.299260139465332 -1953.0374755859375" eulerRotation="1 194.68861389160156 1"/>
<Instance position="-416.3640441894531 -3.565490961074829 -1965.9739990234375" eulerRotation="1 214.8862762451172 1"/>
<Instance position="-383.3658447265625 -11.734761238098145 -1970.2728271484375" eulerRotation="1 66.7164535522461 1"/>
<Instance position="-348.573974609375 -12.129134178161621 -1971.373779296875" eulerRotation="1 258.5540466308594 1"/>
<Instance position="-314.25909423828125 -13.656097412109375 -1978.5841064453125" eulerRotation="1 208.75323486328125 1"/>
<Instance position="-278.7254943847656 -4.0467705726623535 -1980.5909423828125" eulerRotation="1 329.8789978027344 1"/>
<Instance position="-244.22506713867188 -12.783992767333984 -1989.6395263671875" eulerRotation="1 18.134626388549805 1"/>
<Instance position="-209.7477264404297 -4.620805740356445 -1996.787841796875" eulerRotation="1 152.78700256347656 1"/>
<Instance position="-174.9020538330078 -18.942358016967773 -2000.394775390625" eulerRotation="1 86.7840576171875 1"/>
<Instance position="-139.88619995117188 -8.65797233581543 -1995.43212890625" eulerRotation="1 64.6023178100586 1"/>
<Instance position="-105.1338882446289 -4.516824722290039 -2006.13134765625" eulerRotation="1 284.5784912109375 1"/>
<Instance position="-70.089111328125 -18.42557716369629 -1998.8905029296875" eulerRotation="1 53.16244888305664 1"/>
<Instance position="-35.06217956542969 -1.3189935684204102 -2009.68115234375" eulerRotation="1 132.35044860839844 1"/>
<Instance position="-3.6872108556511296e-13 -17.341299057006836 -2002.7803955078125" eulerRotation="1 60.6529541015625 1"/>
<Instance position="35.031612396240234 -14.691126823425293 -2004.3724365234375" eulerRotation="1 187.48036193847656 1"/>
<Instance position="70.13565063476562 -7.967684745788574 -2005.8785400390625" eulerRotation="1 25.190052032470703 1"/>
<Instance position="105.05680084228516 -5.551372528076172 -2006.0340576171875" eulerRotation="1 130.63626098632812 1"/>
<Instance position="140.11631774902344 -17.20992088317871 -2004.3944091796875" eulerRotation="1 186.5386962890625 1"/>
<Instance position="174.67413330078125 -17.54553985595703 -1996.3543701171875" eulerRotation="1 319.6963806152344 1"/>
<Instance position="209.33334350585938 -2.1321005821228027 -1996.50927734375" eulerRotation="1 198.30520629882812 1"/>
<Instance position="243.905029296875 -14.665665626525879 -1994.8570556640625" eulerRotation="1 225.09732055664062 1"/>
<Instance position="279.6468505859375 -18.77557945251465 -1981.50048828125" eulerRotation="1 80.32858276367188 1"/>
<Instance position="313.6286926269531 -16.152847290039062 -1982.895751953125" eulerRotation="1 264.5630187988281 1"/>
<Instance position="347.9537048339844 -4.804656505584717 -1975.819580078125" eulerRotation="1 113.21031188964844 1"/>
<Instance position="383.3778381347656 -11.244460105895996 -1971.6790771484375" eulerRotation="1 275.63018798828125 1"/>
<Instance position="417.7118225097656 -5.87256383895874 -1960.7100830078125" eulerRotation="1 152.6545867919922 1"/>
<Instance position="450.5282897949219 -7.625755786895752 -1954.6710205078125" eulerRotation="1 62.98479461669922 1"/>
<Instance position="485.2425537109375 -4.501126766204834 -1944.1536865234375" eulerRotation="1 47.30873489379883 1"/>
<Instance position="518.5518188476562 -18.19874382019043 -1938.0938720703125" eulerRotation="1 300.24639892578125 1"/>
<Instance position="551.8706665039062 -5.385530471801758 -1925.0693359375" eulerRotation="1 310.0689392089844 1"/>
<Instance position="586.4218139648438 -9.688385009765625 -1919.8846435546875" eulerRotation="1 205.05496215820312 1"/>
<Instance position="619.181884765625 -8.485156059265137 -1909.654052734375" eulerRotation="1 42.04899597167969 1"/>
<Instance position="651.9381103515625 -17.930906295776367 -1893.264404296875" eulerRotation="1 323.6153869628906 1"/>
<Instance position="685.2921752929688 -5.66049337387085 -1885.906005859375" eulerRotation="1 72.25147247314453 1"/>
<Instance position="720.16552734375 -18.041336059570312 -1871.3011474609375" eulerRotation="1 176.16546630859375 1"/>
<Instance position="751.7390747070312 -0.7405952215194702 -1862.32177734375" eulerRotation="1 355.3892517089844 1"/>
<Instance position="783.2059936523438 -0.4607406556606293 -1845.160400390625" eulerRotation="1 201.54542541503906 1"/>
<Instance position="816.33740234375 -13.419639587402344 -1834.2137451171875" eulerRotation="1 211.36749267578125 1"/>
<Instance position="847.2423706054688 -14.272143363952637 -1816.74609375" eulerRotation="1 218.50428771972656 1"/>
<Instance position="877.0690307617188 -15.827258110046387 -1805.4228515625" eulerRotation="1 274.04949951171875 1"/>
<Instance position="911.43505859375 -18.68731689453125 -1786.76611328125" eulerRotation="1 115.94364166259766 1"/>
<Instance position="943.4183959960938 -16.357255935668945 -1769.2855224609375" eulerRotation="1 195.30113220214844 1"/>
<Instance position="973.52490234375 -10.242668151855469 -1750.889404296875" eulerRotation="1 58.104618072509766 1"/>
<Instance position="1004.5244750976562 -4.255053997039795 -1737.412353515625" eulerRotation="1 192.09181213378906 1"/>
<Instance position="1031.45703125 -13.785272598266602 -1718.3121337890625" eulerRotation="1 228.03611755371094 1"/>
<Instance position="1060.3175048828125 -16.261558532714844 -1700.6009521484375" eulerRotation="1 253.26150512695312 1"/>
<Instance position="1092.1375732421875 -8.118303298950195 -1677.43359375" eulerRotation="1 266.88226318359375 1"/>
<Instance position="1122.7005615234375 -18.532329559326172 -1661.9954833984375" eulerRotation="1 104.28538513183594 1"/>
<Instance position="1148.5279541015625 -12.763901710510254 -1645.6131591796875" eulerRotation="1 36.134483337402344 1"/>
<Instance position="1177.4189453125 -6.145010471343994 -1621.556396484375" eulerRotation="1 359.17510986328125 1"/>
<Instance position="1205.0968017578125 -16.118610382080078 -1598.762451171875" eulerRotation="1 185.81715393066406 1"/>
<Instance position="1234.5008544921875 -19.78626251220703 -1582.08642578125" eulerRotation="1 193.65084838867188 1"/>
<Instance position="1263.4530029296875 -6.836394309997559 -1560.3953857421875" eulerRotation="1 86.96308135986328 1"/>
<Instance position="1287.266845703125 -8.848514556884766 -1539.3701171875" eulerRotation="1 102.39668273925781 1"/>
<Instance position="1313.912841796875 -17.749040603637695 -1511.8741455078125" eulerRotation="1 218.27333068847656 1"/>
<Instance position="1344.5177001953125 -5.183916091918945 -1491.8544921875" eulerRotation="1 183.22206115722656 1"/>
<Instance position="1367.247802734375 -6.9044575691223145 -1464.200439453125" eulerRotation="1 228.52764892578125 1"/>
<Instance position="1390.0103759765625 -1.7290536165237427 -1442.2955322265625" eulerRotation="1 1.5914075374603271 1"/>
<Instance position="1420.5504150390625 -7.6085686683654785 -1415.6707763671875" eulerRotation="1 44.54063034057617 1"/>
<Instance position="1442.9124755859375 -19.953298568725586 -1391.919677734375" eulerRotation="1 307.31787109375 1"/>
<Instance position="1463.930419921875 -17.70060920715332 -1367.2421875" eulerRotation="1 17.46074867248535 1"/>
<Instance position="1493.1900634765625 -19.00769805908203 -1344.8011474609375" eulerRotation="1 68.855712890625 1"/>
<Instance position="1510.8447265625 -2.642169952392578 -1318.461669921875" eulerRotation="1 309.2993469238281 1"/>
<Instance position="1532.480712890625 -11.640501976013184 -1290.895263671875" eulerRotation="1 348.35650634765625 1"/>
<Instance position="1556.3837890625 -18.242631912231445 -1261.70361328125" eulerRotation="1 145.60958862304688 1"/>
<Instance position="1583.267578125 -13.142260551452637 -1236.0911865234375" eulerRotation="1 223.08197021484375 1"/>
<Instance position="1600.0426025390625 -7.550002098083496 -1206.993896484375" eulerRotation="1 271.6318664550781 1"/>
<Instance position="1621.58203125 -14.300189971923828 -1180.932861328125" eulerRotation="1 280.3489074707031 1"/>
<Instance position="1641.7144775390625 -6.511833667755127 -1152.218505859375" eulerRotation="1 23.08333396911621 1"/>
<Instance position="1660.680908203125 -14.095251083374023 -1120.6759033203125" eulerRotation="1 29.17145347595215 1"/>
<Instance position="1683.76318359375 -3.5831451416015625 -1093.8065185546875" eulerRotation="1 179.60557556152344 1"/>
<Instance position="1700.884765625 -7.994508266448975 -1062.186767578125" eulerRotation="1 31.253154754638672 1"/>
<Instance position="1722.808349609375 -11.941800117492676 -1035.1436767578125" eulerRotation="1 201.44039916992188 1"/>
<Instance position="1738.8712158203125 -1.7687619924545288 -1004.3989868164062" eulerRotation="1 102.6419906616211 1"/>
<Instance position="1755.9930419921875 -6.940460205078125 -971.4095458984375" eulerRotation="1 11.778501510620117 1"/>
<Instance position="1771.798828125 -0.2849941551685333 -941.1878051757812" eulerRotation="1 86.17729949951172 1"/>
<Instance position="1786.52392578125 -7.749936103820801 -911.8903198242188" eulerRotation="1 17.833229064941406 1"/>
<Instance position="1805.0137939453125 -6.456761360168457 -879.7488403320312" eulerRotation="1 213.6852569580078 1"/>
<Instance position="1818.5609130859375 -17.31022834777832 -846.8479614257812" eulerRotation="1 181.7125701904297 1"/>
<Instance position="1830.12060546875 -7.2076215744018555 -815.1956176757812" eulerRotation="1 37.679447174072266 1"/>
<Instance position="1846.958984375 -6.9531402587890625 -784.77197265625" eulerRotation="1 1.9489531517028809 1"/>
<Instance position="1854.4366455078125 -1.0874830484390259 -750.908447265625" eulerRotation="1 244.2303924560547 1"/>
<Instance position="1872.307373046875 -16.302719116210938 -718.208251953125" eulerRotation="1 307.915283203125 1"/>
<Instance position="1880.9879150390625 -17.23141860961914 -687.4153442382812" eulerRotation="1 169.14407348632812 1"/>
<Instance position="1891.995361328125 -11.203681945800781 -651.6134643554688" eulerRotation="1 38.832664489746094 1"/>
<Instance position="1903.0843505859375 -10.085371971130371 -619.69580078125" eulerRotation="1 134.38330078125 1"/>
<Instance position="1916.6533203125 -15.021976470947266 -585.2586669921875" eulerRotation="1 245.35386657714844 1"/>
<Instance position="1930.8193359375 -12.403164863586426 -551.7462768554688" eulerRotation="1 329.3010559082031 1"/>
<Instance position="1937.5543212890625 -6.293075084686279 -517.7960205078125" eulerRotation="1 303.533447265625 1"/>
<Instance position="1947.496337890625 -2.1369588375091553 -485.4500732421875" eulerRotation="1 81.32564544677734 1"/>
<Instance position="1953.711181640625 -18.072473526000977 -451.32904052734375" eulerRotation="1 24.16411018371582 1"/>
<Instance position="1958.0208740234375 -4.2005181312561035 -416.9647216796875" eulerRotation="1 334.09393310546875 1"/>
<Instance position="1969.864013671875 -4.674450397491455 -382.24969482421875" eulerRotation="1 103.5193099975586 1"/>
<Instance position="1970.267822265625 -19.126436233520508 -347.63592529296875" eulerRotation="1 266.40472412109375 1"/>
<Instance position="1979.4716796875 -15.964591026306152 -314.0959167480469" eulerRotation="1 46.1056022644043 1"/>
<Instance position="1988.4625244140625 -8.389565467834473 -278.55584716796875" eulerRotation="1 20.60913848876953 1"/>
<Instance position="1988.53125 -10.117165565490723 -244.71896362304688" eulerRotation="1 125.62110137939453 1"/>
<Instance position="1989.4163818359375 -1.3781391382217407 -209.68435668945312" eulerRotation="1 325.1085510253906 1"/>
<Instance position="1997.8037109375 -4.895318508148193 -175.04437255859375" eulerRotation="1 269.1058349609375 1"/>
<Instance position="2003.1951904296875 -5.676908016204834 -139.97183227539062" eulerRotation="1 354.6174011230469 1"/>
<Instance position="1998.53955078125 -6.315550327301025 -105.0665283203125" eulerRotation="1 1.1396117210388184 1"/>
<Instance position="2003.791259765625 -6.604065895080566 -69.95491027832031" eulerRotation="1 37.06053924560547 1"/>
<Instance position="2008.607421875 -18.343290328979492 -34.94842529296875" eulerRotation="1 227.8921356201172 1"/>
</InstanceTable>

View File

@ -0,0 +1,11 @@
Model Information:
* title: wood billet
* source: https://sketchfab.com/3d-models/wood-billet-9ba273cc850f497f8ffbd127bdd69c28
* author: falk lochmann (https://sketchfab.com/falk)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "wood billet" (https://sketchfab.com/3d-models/wood-billet-9ba273cc850f497f8ffbd127bdd69c28) by falk lochmann (https://sketchfab.com/falk) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<InstanceTable>
<Instance position="1000 220 1000"/>
<Instance position="1000 220 -1000"/>
<Instance position="-1000 220 1000"/>
<Instance position="-1000 220 -1000"/>
<Instance position="0 225 520"/>
</InstanceTable>

View File

@ -0,0 +1,11 @@
Model Information:
* title: Wood Table
* source: https://sketchfab.com/3d-models/wood-table-ce6977c9de1d43048838e4802e21f7d4
* author: toAflame (https://sketchfab.com/toAflame)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Wood Table" (https://sketchfab.com/3d-models/wood-table-ce6977c9de1d43048838e4802e21f7d4) by toAflame (https://sketchfab.com/toAflame) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,11 @@
Model Information:
* title: Manor Torch
* source: https://sketchfab.com/3d-models/manor-torch-09ad1f3d3256404d85f30a738e38db68
* author: RomarovArt (https://sketchfab.com/RomarArt)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Manor Torch" (https://sketchfab.com/3d-models/manor-torch-09ad1f3d3256404d85f30a738e38db68) by RomarovArt (https://sketchfab.com/RomarArt) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@ -0,0 +1,12 @@
// Copyright (C) 2024 The Qt Company Ltd.*
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
void MAIN()
{
vec2 tc = texcoord;
tc.y = 1.0 - tc.y;
vec3 base = texture(fireTexture, tc).xyz * color.xyz;
FRAGCOLOR = vec4(base.xyz, 1.0);
}

View File

@ -0,0 +1,76 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
VARYING vec4 vcolor;
float random(vec2 uv, float seed) {
return fract(sin(dot(uv.xy, vec2(12.9898 + seed, 78.233 + seed))) * 43758.5453 + seed);
}
mat3 rotateX(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
1.0, 0.0, 0.0,
0.0, c, -s,
0.0, s, c
);
}
mat3 rotateY(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, 0.0, s,
0.0, 1.0, 0.0,
-s, 0.0, c
);
}
mat3 rotateZ(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, -s, 0.0,
s, c, 0.0,
0.0, 0.0, 1.0
);
}
void MAIN()
{
texcoord = UV0;
vec3 pos = VERTEX;
vcolor = COLOR;
float tur = texture(turbulence, vcolor.zw + fract(time * windDir)).x;
float randx = random(vcolor.zw, 0);
float randy = random(vcolor.zw, 3.3545);
pos.y *= mix(0.5, 1.0, randx);
pos.xz *= min(texcoord.y * 5. + baseSize, 1.0);
vec2 displace = vec2(randx * 2.0 - 1.0, randy * 2.0 - 1.0);
vec2 windDirStrength = windstrength * 0.6 * windDir;
vec2 windDirStrengthNoise = windDirStrength * tur;
vec2 wind = displace * 0.3 + windDirStrength;
mat3 rotX = rotateX(texcoord.y * windDirStrengthNoise.x +
texcoord.y * wind.x +
windDirStrength.x * 0.3);
mat3 rotZ = rotateZ(texcoord.y * windDirStrengthNoise.y +
texcoord.y * wind.y +
windDirStrength.y * 0.3);
vec3 direction = normalize(CAMERA_POSITION - vec3(pos.x, 0.0, pos.z));
mat3 rotY = rotateY(3.1415 * vcolor.x);
mat3 rotationMatrix = rotZ * rotX * rotY;
pos = rotationMatrix * pos;
POSITION = MODELVIEWPROJECTION_MATRIX * vec4(pos, 1.0);
}

View File

@ -0,0 +1,24 @@
// Copyright (C) 2024 The Qt Company Ltd.*
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
VARYING vec4 vcolor;
VARYING vec3 vViewVec;
void MAIN()
{
vec2 tc = texcoord;
vec3 base = qt_sRGBToLinear(texture(grass_base, tc).xyz);
float noise = texture(perlin, vcolor.zw).x;
float invert = sign(dot(NORMAL, vViewVec));
NORMAL *= invert;
TANGENT *= invert;
BINORMAL *= invert;
ROUGHNESS = 1.;
METALNESS = 0;
OCCLUSION_AMOUNT = (smoothstep(0, 0.4, tc.y) + 0.1) * (1.0 - noise + 0.2);
BASE_COLOR = vec4(base * baseColor.xyz, 1.0);
}

View File

@ -0,0 +1,106 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
VARYING vec4 vcolor;
VARYING vec3 vViewVec;
float random(vec2 uv, float seed) {
return fract(sin(dot(uv.xy, vec2(12.9898 + seed, 78.233 + seed))) * 43758.5453 + seed);
}
mat3 rotateX(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
1.0, 0.0, 0.0,
0.0, c, -s,
0.0, s, c
);
}
mat3 rotateY(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, 0.0, s,
0.0, 1.0, 0.0,
-s, 0.0, c
);
}
mat3 rotateZ(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, -s, 0.0,
s, c, 0.0,
0.0, 0.0, 1.0
);
}
void MAIN()
{
texcoord = UV0;
vec3 pos = VERTEX;
vcolor = COLOR;
float tur = texture(turbulence, vcolor.zw + fract(time * windDir)).x;
float noise = texture(perlin, vcolor.zw).x;
pos.xz -= vcolor.xy;
float randx = random(vcolor.zw, 0);
float randy = random(vcolor.zw, 3.3545);
float mid = mix(0.9, 0.3, randx);
float ramp = 1.0 - max(smoothstep(mid, 1.02, texcoord.y),
smoothstep(mid, -0.3, texcoord.y));
pos.y *= noise;
pos.xz *= ramp;
pos.xz *= mix(0.3, 1.0, randx);
vec2 displace = vec2(randx * 2.0 - 1.0, randy * 2.0 - 1.0);
vec2 windDirStrength = windstrength * 0.4 * windDir;
vec2 windDirStrengthNoise = windDirStrength * tur;
vec2 wind = displace * 0.3 + windDirStrength;
mat3 rotX = rotateX(texcoord.y * windDirStrengthNoise.x +
windDirStrengthNoise.x +
texcoord.y * wind.x +
windDirStrength.x);
mat3 rotZ = rotateZ(texcoord.y * windDirStrengthNoise.y +
windDirStrengthNoise.y +
texcoord.y * wind.y +
windDirStrength.y);
vec3 PrePos = pos;
PrePos.xz += displace * 1.0;
PrePos.xz += vcolor.xy;
PrePos = (MODEL_MATRIX * vec4(PrePos, 1.0)).xyz;
vec3 direction = normalize(CAMERA_POSITION - vec3(PrePos.x, 0.0, PrePos.z));
mat3 rotY = rotateY(-atan(direction.x, direction.z));
mat3 rotationMatrix = rotZ * rotX * rotY;
vec3 centerPos = rotationMatrix * vec3(0.0, pos.y + 1.0, 0.0);
pos = rotationMatrix * pos;
vec3 tangent = normalize(centerPos);
vec3 binormal = cross(tangent, vec3(0., 1.0, 0.));
vec3 normal = cross(binormal, tangent);
pos.xz += displace * 1.0;
pos.xz += vcolor.xy;
TANGENT = tangent;
BINORMAL = binormal;
NORMAL = normal;
VERTEX = pos;
vViewVec = CAMERA_POSITION - (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
COLOR = vec4(1);
}

View File

@ -0,0 +1,7 @@
// Copyright (C) 2024 The Qt Company Ltd.*
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void MAIN()
{
FRAGCOLOR = vec4(1.0);
}

View File

@ -0,0 +1,9 @@
// Copyright (C) 2024 The Qt Company Ltd.*
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void MAIN()
{
vec3 pos = VERTEX;
pos.y += 1000000;
POSITION = vec4(pos, 1.0);
}

View File

@ -0,0 +1,12 @@
// Copyright (C) 2024 The Qt Company Ltd.*
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
void MAIN()
{
float val = clamp(pow(1.0 - texcoord.y, 20.) * mix(30., 5., sin(time)), 0., 1.0);
if (val < 0.01)
discard;
FRAGCOLOR = vec4(mix(vec3(0.), indicatorColor, val), val);
}

View File

@ -0,0 +1,10 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec2 texcoord;
void MAIN()
{
texcoord = UV0;
POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Some files were not shown because too many files have changed in this diff Show More