Revision control

Copy as Markdown

// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
import QtQuick3D
import QtQuick.Controls
import QtQuick.Layouts
import QtQml
import QtQuick3D.Helpers
import io.qt.tests.manual.dynamic3DTest
Window {
width: 1280
height: 720
visible: true
title: qsTr("Dynamic 3D Object Tester")
Node {
id: sceneRoot
PerspectiveCamera {
id: mainCamera
z: 600
}
Model {
id: mainSphere
source: "#Sphere"
materials: PrincipledMaterial {
id: sphereMaterial
baseColor: "blue"
}
function updateTexture() {
if (objectSpawner.textures.length > 0)
sphereMaterial.baseColorMap = objectSpawner.textures[objectSpawner.textures.length - 1];
else
sphereMaterial.baseColorMap = null
if (objectSpawner.dynamicTextures.length > 0) {
sphereMaterial.emissiveFactor = Qt.vector3d(1, 1, 1)
sphereMaterial.emissiveMap = objectSpawner.dynamicTextures[objectSpawner.dynamicTextures.length - 1]
} else {
sphereMaterial.emissiveMap = null
sphereMaterial.emissiveFactor = Qt.vector3d(0, 0, 0)
}
}
NumberAnimation on y {
from: 0
to: 50
duration: 10000
running: enableAnimationCheckbox.checked
loops: -1
}
}
Node {
id: objectSpawner
property real range: 300
property var directionLights: []
property var pointLights: []
property var spotLights: []
property var cameras: []
property var models: []
property var riggedModels: []
property var dynamicModels: []
property var dynamicGeometries: []
property var textures: []
property var dynamicTextures: []
property var qmlTextures: []
property var qmlSharedTextures: []
property var item2Ds: []
property int directionLightsCount: 0
property int pointLightsCount: 0
property int spotLightsCount: 0
property int camerasCount: 0
property int modelsCount: 0
property int riggedModelsCount: 0
property int dynamicModelsCount: 0
property int texturesCount: 0
property int dynamicTexturesCount: 0
property int qmlTexturesCount: 0
property int qmlSharedTexturesCount: 0
property int item2DsCount: 0
Component {
id: directionalLight
DirectionalLight {
ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
}
}
Component {
id: pointLight
PointLight {
ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
}
}
Component {
id: spotLight
SpotLight {
ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
}
}
Component {
id: camera
PerspectiveCamera {
}
}
Component {
id: model
Model {
property alias color: material.diffuseColor
//source: "#Cube"
materials: DefaultMaterial {
id: material
diffuseColor: "red"
}
}
}
Component {
id: riggedModel
RiggedFigure {
}
}
Component {
id: dynamicModel
Model {
property alias color: material.baseColor
materials: PrincipledMaterial {
lighting: PrincipledMaterial.NoLighting
id: material
baseColor: "red"
}
}
}
Component {
id: dynamicGeometry
GridGeometry {
property alias lines: gridGeometry.horizontalLines
property alias step: gridGeometry.horizontalStep
id: gridGeometry
verticalLines: horizontalLines
verticalStep: horizontalStep
}
}
Component {
id: texture
Texture {
}
}
Component {
id: dynamicTexture
Texture {
property alias height: gradientTexture.height
property alias width: gradientTexture.width
property alias startColor: gradientTexture.startColor
property alias endColor: gradientTexture.endColor
textureData: GradientTexture {
id: gradientTexture
}
}
}
Component {
id: qmlTexture
Model {
property alias color: sourceItemRect.color
property alias text: textLabel.text
source: "#Rectangle"
materials: PrincipledMaterial {
lighting: PrincipledMaterial.NoLighting
baseColorMap: Texture {
sourceItem: Rectangle {
id: sourceItemRect
width: 256
height: 256
color: "black"
Text {
id: textLabel
anchors.centerIn: parent
color: "white"
font.pointSize: 64
}
}
}
}
}
}
Component {
id: qmlTextureShared
Model {
property alias sharedItem: texture.sourceItem
source: "#Rectangle"
materials: PrincipledMaterial {
lighting: PrincipledMaterial.NoLighting
baseColorMap: Texture {
id: texture
}
}
}
}
Component {
id: item2D
Node {
property alias text: textLabel.text
Text {
id: textLabel
anchors.centerIn: parent
font.pointSize: 64
color: "black"
}
}
}
function getRandomVector3d(range) {
return Qt.vector3d((2 * Math.random() * range) - range,
(2 * Math.random() * range) - range,
(2 * Math.random() * range) - range)
}
function getRandomColor() {
return Qt.rgba(Math.random(),
Math.random(),
Math.random(),
1.0)
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * max) + min;
}
function getMeshSource() {
let sources = [
"random1.mesh",
"random2.mesh",
"random3.mesh",
"random4.mesh",
"#Cube",
"#Sphere",
"#Cone",
"#Cylinder"
]
let index = Math.floor(Math.random() * sources.length);
return sources[index]
}
function getRiggedMeshSource() {
let sources = [
"riggedfigure.mesh",
"riggedsimple.mesh"
]
let index = Math.floor(Math.random() * sources.length);
return sources[index]
}
function getImageSource() {
let sources = [
"noise1.jpg",
"noise2.jpg",
"noise3.jpg",
"noise4.jpg",
"noise5.jpg"
]
let index = Math.floor(Math.random() * sources.length);
return sources[index]
}
function addDirectionalLight() {
let position = getRandomVector3d(objectSpawner.range)
let rotation = getRandomVector3d(360)
let instance = directionalLight.createObject(objectSpawner, { "position": position, "eulerRotation": rotation})
directionLights.push(instance);
directionLightsCount++
}
function removeDirectionalLight() {
if (directionLights.length > 0) {
let instance = directionLights.pop();
instance.destroy();
directionLightsCount--
}
}
function addPointLight() {
let position = getRandomVector3d(objectSpawner.range)
let instance = pointLight.createObject(objectSpawner, { "position": position})
pointLights.push(instance);
pointLightsCount++
}
function removePointLight() {
if (pointLights.length > 0) {
let instance = pointLights.pop();
instance.destroy();
pointLightsCount--
}
}
function addSpotLight() {
let position = getRandomVector3d(objectSpawner.range)
let rotation = getRandomVector3d(360)
let instance = spotLight.createObject(objectSpawner, { "position": position, "eulerRotation": rotation})
spotLights.push(instance);
spotLightsCount++
}
function removeSpotLight() {
if (spotLights.length > 0) {
let instance = spotLights.pop();
instance.destroy();
spotLightsCount--
}
}
function addCamera() {
let position = getRandomVector3d(objectSpawner.range * 2)
let rotation = getRandomVector3d(360)
let instance = camera.createObject(objectSpawner, { "position": position, "eulerRotation": rotation})
cameras.push(instance);
instance.lookAt(Qt.vector3d(0, 0, 0))
view2.updateCamera();
camerasCount++
}
function removeCamera() {
if (cameras.length > 0) {
let instance = cameras.pop();
instance.destroy();
camerasCount--
}
view2.updateCamera();
}
function addModel() {
let position = getRandomVector3d(objectSpawner.range)
let rotation = getRandomVector3d(360)
let source = getMeshSource();
let color = getRandomColor();
let instance = model.createObject(objectSpawner, { "position": position, "eulerRotation": rotation, "color": color, "source": source})
models.push(instance);
modelsCount++
}
function removeModel() {
if (models.length > 0) {
let instance = models.pop();
instance.destroy();
modelsCount--
}
}
function addRiggedModel() {
let position = getRandomVector3d(objectSpawner.range)
let rotation = getRandomVector3d(360)
let instance = riggedModel.createObject(objectSpawner, { "position": position, "eulerRotation": rotation})
riggedModels.push(instance);
riggedModelsCount++
}
function removeRiggedModel() {
if (riggedModels.length > 0) {
let instance = riggedModels.pop();
instance.destroy();
riggedModelsCount--
}
}
function addDynamicModel() {
let position = getRandomVector3d(objectSpawner.range)
let rotation = getRandomVector3d(360)
let color = getRandomColor();
let lines = getRandomInt(100, 1000);
let steps = getRandomInt(1, 25);
let geometry = dynamicGeometry.createObject(objectSpawner, {"lines": lines, "step": steps})
dynamicGeometries.push(geometry)
let instance = dynamicModel.createObject(objectSpawner, {"position": position, "eulerRotation": rotation, "color": color, "geometry": geometry})
dynamicModels.push(instance)
dynamicModelsCount++
}
function removeDynamicModel() {
if (dynamicModels.length > 0) {
let instance = dynamicModels.pop();
instance.destroy();
// Reset the dynamicGeometries
for (var i = 0; i < dynamicModels.length; i++)
dynamicModels[i].geometry = dynamicGeometries[i]
let geometryInstance = dynamicGeometries.pop();
geometryInstance.destroy()
dynamicModelsCount--
}
}
function addTexture() {
let source = getImageSource()
let instance = texture.createObject(objectSpawner, {"source": source})
textures.push(instance);
texturesCount++
mainSphere.updateTexture()
}
function removeTexture() {
if (textures.length > 0) {
let instance = textures.pop();
instance.destroy();
texturesCount--
mainSphere.updateTexture()
}
}
function changeTextures() {
// reset the texture sources
textures.forEach(texture => texture.source = getImageSource())
}
function addDynamicTexture() {
let startColor = getRandomColor()
let endColor = getRandomColor()
let width = 2048
let height = 2048
let instance = dynamicTexture.createObject(objectSpawner, {"startColor": startColor, "endColor": endColor, "height": height, "width": width})
dynamicTextures.push(instance);
dynamicTexturesCount++
mainSphere.updateTexture()
}
function removeDynamicTexture() {
if (dynamicTextures.length > 0) {
let instance = dynamicTextures.pop();
instance.destroy();
dynamicTexturesCount--
mainSphere.updateTexture()
}
}
function addQmlTexture() {
let rectColor = getRandomColor()
let position = getRandomVector3d(objectSpawner.range * 2)
let labelText = qmlTexturesCount + 1
let instance = qmlTexture.createObject(objectSpawner, {"position": position, "color": rectColor, "text": labelText})
qmlTextures.push(instance)
qmlTexturesCount++
}
function removeQmlTexture() {
if (qmlTextures.length > 0) {
let instance = qmlTextures.pop()
instance.destroy()
qmlTexturesCount--
}
}
function addQmlSharedTexture() {
let position = getRandomVector3d(objectSpawner.range * 2)
let instance = qmlTextureShared.createObject(objectSpawner, {"sharedItem": sharedItem, "position": position})
qmlSharedTextures.push(instance)
qmlSharedTexturesCount++
}
function removeQmlSharedTexture() {
if (qmlSharedTextures.length > 0) {
let instance = qmlSharedTextures.pop()
instance.destroy()
qmlSharedTexturesCount--
}
}
function addItem2D() {
let position = getRandomVector3d(objectSpawner.range * 2)
let labelText = item2DsCount + 1
let instance = item2D.createObject(objectSpawner, {"position": position, "text":labelText})
item2Ds.push(instance);
item2DsCount++
}
function removeItem2D() {
if (item2Ds.length > 0) {
let instance = item2Ds.pop()
instance.destroy()
item2DsCount--
}
}
function changeModels() {
// reset the model sources
models.forEach(model => model.source = getMeshSource())
}
function changeDynamicModels() {
// reset the dynamic model sources
if (dynamicModels.length == 0)
return
var shuffleIndexs = Array.from({length: dynamicModels.length}, (x, i) => i);
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
shuffleIndexs = shuffle(shuffleIndexs);
for (var i = 0; i < dynamicModels.length; i++)
dynamicModels[i].geometry = dynamicGeometries[shuffleIndexs[i]]
}
}
}
Item {
id: viewsContainer
anchors.top: parent.top
anchors.right: controlsContainer.left
anchors.bottom: parent.bottom
anchors.left: parent.left
property var windowView: undefined
Image {
id: sharedItem
source: "noise1.jpg"
width: 256
height: 256
}
View3D {
id: view1
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
width: parent.width * 0.5
importScene: sceneRoot
camera: mainCamera
environment: SceneEnvironment {
clearColor: "green"
backgroundMode: SceneEnvironment.Color
}
}
View3D {
id: view2
anchors.top: parent.top
anchors.left: view1.right
anchors.bottom: parent.bottom
anchors.right: parent.right
importScene: sceneRoot
environment: SceneEnvironment {
clearColor: "pink"
backgroundMode: SceneEnvironment.Color
}
function updateCamera() {
if (objectSpawner.cameras.length > 0) {
var dynamicCamera = objectSpawner.cameras[objectSpawner.cameras.length - 1]
view2.camera = dynamicCamera
} else {
view2.camera = mainCamera
}
}
//camera: objectSpawner.cameras.length > 0 ? objectSpawner.cameras[objectSpawner.cameras.length - 1] : mainCamera
}
}
Component {
id: windowComponent
Window {
id: subWindow
visible: true
height: 400
width: 400
View3D {
id: view3
anchors.fill: parent
importScene: sceneRoot
environment: SceneEnvironment {
clearColor: "orange"
backgroundMode: SceneEnvironment.Color
}
}
}
}
Rectangle {
id: controlsContainer
width: 300
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "grey"
ColumnLayout {
CheckBox {
id: enableAnimationCheckbox
checked: false
text: "Enable Animation"
}
CheckBox {
id: enableWindowCheckbox
checked: false
text: "Enable Window View"
onCheckedChanged: {
if (checked) {
// Create Window component
viewsContainer.windowView = windowComponent.createObject(viewsContainer)
} else {
// Delete Window component
viewsContainer.windowView.destroy();
viewsContainer.windowView = undefined
}
}
}
RowLayout {
Label {
text: "Directional Light"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.directionLightsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addDirectionalLight()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeDirectionalLight()
}
}
}
RowLayout {
Label {
text: "Point Light"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.pointLightsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addPointLight()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removePointLight()
}
}
}
RowLayout {
Label {
text: "Spot Light"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.spotLightsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addSpotLight()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeSpotLight()
}
}
}
RowLayout {
Label {
text: "Camera"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.camerasCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addCamera()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeCamera()
}
}
}
RowLayout {
Label {
text: "Model"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.modelsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addModel()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeModel()
}
}
ToolButton {
text: "<->"
onClicked: {
objectSpawner.changeModels()
}
}
}
RowLayout {
Label {
text: "Rigged Model"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.riggedModelsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addRiggedModel()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeRiggedModel()
}
}
}
RowLayout {
Label {
text: "Dynamic Model"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.dynamicModelsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addDynamicModel()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeDynamicModel()
}
}
ToolButton {
text: "<->"
onClicked: {
objectSpawner.changeDynamicModels()
}
}
}
RowLayout {
Label {
text: "Texture"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.texturesCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addTexture()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeTexture()
}
}
ToolButton {
text: "<->"
onClicked: {
objectSpawner.changeTextures()
}
}
}
RowLayout {
Label {
text: "Dynamic Texture"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.dynamicTexturesCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addDynamicTexture()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeDynamicTexture()
}
}
}
RowLayout {
Label {
text: "QML Texture"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.qmlTexturesCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addQmlTexture()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeQmlTexture()
}
}
}
RowLayout {
Label {
text: "QML Texture (Shared)"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.qmlSharedTexturesCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addQmlSharedTexture()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeQmlSharedTexture()
}
}
}
RowLayout {
Label {
text: "Item 2D"
color: "white"
Layout.fillWidth: true
}
Label {
text: objectSpawner.item2DsCount
color: "white"
Layout.fillWidth: true
}
ToolButton {
text: "+"
onClicked: {
objectSpawner.addItem2D()
}
}
ToolButton {
text: "-"
onClicked: {
objectSpawner.removeItem2D()
}
}
}
}
}
}