forked from qt-creator/qt-creator
QmlDesigner: Update light gizmos
Directional light model was made constant size, as it doesn't have actual physical presence. Spot light cone now shows the cone angle correctly and the length of the cone is calculated so that 5% of the brightness reaches the center of the cone bottom. Area light rectangle matches the area of the light. Point light mesh changed to three perpendicular circles. Same formula for size of the circles used as for spotlight length. All light types share a common brightness indicator arrow. Task-number: QDS-2037 Change-Id: I534dbcda9cfa2a7768c2537868ba83818979b250 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
55
share/qtcreator/qml/qmlpuppet/mockfiles/AdjustableArrow.qml
Normal file
55
share/qtcreator/qml/qmlpuppet/mockfiles/AdjustableArrow.qml
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.15
|
||||
import LineGeometry 1.0
|
||||
|
||||
Arrow {
|
||||
id: arrowRoot
|
||||
|
||||
property real length: 10
|
||||
|
||||
source: ""
|
||||
|
||||
Model {
|
||||
geometry: LineGeometry {
|
||||
id: lineGeometry
|
||||
name: "Edit 3D ScalableArrow"
|
||||
startPos: Qt.vector3d(0, 0, 0)
|
||||
endPos: Qt.vector3d(0, 1, 0)
|
||||
}
|
||||
materials: [ arrowRoot.material ]
|
||||
scale: Qt.vector3d(1, arrowRoot.length, 1)
|
||||
}
|
||||
|
||||
Model {
|
||||
id: arrowHead
|
||||
source: "#Cone"
|
||||
materials: [ arrowRoot.material ]
|
||||
y: arrowRoot.length
|
||||
scale: Qt.vector3d(0.02, 0.035, 0.02)
|
||||
}
|
||||
}
|
@@ -25,7 +25,6 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.15
|
||||
import MouseArea3D 1.0
|
||||
|
||||
DirectionalDraggable {
|
||||
id: arrow
|
||||
|
@@ -36,6 +36,7 @@ Model {
|
||||
property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
|
||||
property bool active: false
|
||||
property MouseArea3D dragHelper: null
|
||||
property alias material: material
|
||||
|
||||
readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
|
||||
|
||||
@@ -47,12 +48,14 @@ Model {
|
||||
signal dragged(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance)
|
||||
signal released(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance)
|
||||
|
||||
materials: DefaultMaterial {
|
||||
DefaultMaterial {
|
||||
id: material
|
||||
emissiveColor: "white"
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
}
|
||||
|
||||
materials: [ material ]
|
||||
|
||||
function handlePressed(mouseArea, planePos)
|
||||
{
|
||||
if (!targetNode)
|
||||
|
@@ -54,7 +54,7 @@ Item {
|
||||
property Node selectedNode: null // This is non-null only in single selection case
|
||||
property var selectedNodes: [] // All selected nodes
|
||||
|
||||
property var lightGizmos: []
|
||||
property var lightIconGizmos: []
|
||||
property var cameraGizmos: []
|
||||
property var selectionBoxes: []
|
||||
property rect viewPortRect: Qt.rect(0, 0, 1000, 1000)
|
||||
@@ -278,29 +278,25 @@ Item {
|
||||
function addLightGizmo(scene, obj)
|
||||
{
|
||||
// Insert into first available gizmo
|
||||
for (var i = 0; i < lightGizmos.length; ++i) {
|
||||
if (!lightGizmos[i].targetNode) {
|
||||
lightGizmos[i].scene = scene;
|
||||
lightGizmos[i].targetNode = obj;
|
||||
for (var i = 0; i < lightIconGizmos.length; ++i) {
|
||||
if (!lightIconGizmos[i].targetNode) {
|
||||
lightIconGizmos[i].scene = scene;
|
||||
lightIconGizmos[i].targetNode = obj;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No free gizmos available, create a new one
|
||||
var gizmoComponent = Qt.createComponent("LightGizmo.qml");
|
||||
var modelComponent = Qt.createComponent("LightModel.qml");
|
||||
if (gizmoComponent.status === Component.Ready && modelComponent.status === Component.Ready) {
|
||||
var geometryName = _generalHelper.generateUniqueName("LightGeometry");
|
||||
var model = modelComponent.createObject(overlayScene, {"geometryName": geometryName});
|
||||
var gizmoComponent = Qt.createComponent("LightIconGizmo.qml");
|
||||
if (gizmoComponent.status === Component.Ready) {
|
||||
var gizmo = gizmoComponent.createObject(overlayView,
|
||||
{"view3D": overlayView, "targetNode": obj,
|
||||
"selectedNodes": selectedNodes, "scene": scene,
|
||||
"activeScene": activeScene});
|
||||
lightGizmos[lightGizmos.length] = gizmo;
|
||||
lightIconGizmos[lightIconGizmos.length] = gizmo;
|
||||
gizmo.clicked.connect(handleObjectClicked);
|
||||
gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;});
|
||||
gizmo.activeScene = Qt.binding(function() {return activeScene;});
|
||||
gizmo.connectModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,10 +334,10 @@ Item {
|
||||
|
||||
function releaseLightGizmo(obj)
|
||||
{
|
||||
for (var i = 0; i < lightGizmos.length; ++i) {
|
||||
if (lightGizmos[i].targetNode === obj) {
|
||||
lightGizmos[i].scene = null;
|
||||
lightGizmos[i].targetNode = null;
|
||||
for (var i = 0; i < lightIconGizmos.length; ++i) {
|
||||
if (lightIconGizmos[i].targetNode === obj) {
|
||||
lightIconGizmos[i].scene = null;
|
||||
lightIconGizmos[i].targetNode = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -360,9 +356,9 @@ Item {
|
||||
|
||||
function updateLightGizmoScene(scene, obj)
|
||||
{
|
||||
for (var i = 0; i < lightGizmos.length; ++i) {
|
||||
if (lightGizmos[i].targetNode === obj) {
|
||||
lightGizmos[i].scene = scene;
|
||||
for (var i = 0; i < lightIconGizmos.length; ++i) {
|
||||
if (lightIconGizmos[i].targetNode === obj) {
|
||||
lightIconGizmos[i].scene = scene;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -455,6 +451,13 @@ Item {
|
||||
onRotateChange: viewRoot.changeObjectProperty(viewRoot.selectedNode, "eulerRotation")
|
||||
}
|
||||
|
||||
LightGizmo {
|
||||
id: lightGizmo
|
||||
targetNode: viewRoot.selectedNode
|
||||
view3D: overlayView
|
||||
dragHelper: gizmoDragHelper
|
||||
}
|
||||
|
||||
AutoScaleHelper {
|
||||
id: autoScale
|
||||
view3D: overlayView
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -25,45 +25,138 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.15
|
||||
import MouseArea3D 1.0
|
||||
import LightGeometry 1.0
|
||||
|
||||
IconGizmo {
|
||||
Node {
|
||||
id: lightGizmo
|
||||
|
||||
property Model lightModel: null
|
||||
property color overlayColor: targetNode ? targetNode.color : "transparent"
|
||||
|
||||
iconSource: targetNode
|
||||
? targetNode instanceof DirectionalLight
|
||||
? "image://IconGizmoImageProvider/directional.png:" + overlayColor
|
||||
: targetNode instanceof AreaLight
|
||||
? "image://IconGizmoImageProvider/area.png:" + overlayColor
|
||||
: targetNode instanceof PointLight
|
||||
? "image://IconGizmoImageProvider/point.png:" + overlayColor
|
||||
: "image://IconGizmoImageProvider/spot.png:" + overlayColor
|
||||
: "image://IconGizmoImageProvider/point.png:" + overlayColor
|
||||
|
||||
function connectModel(model)
|
||||
{
|
||||
lightModel = model;
|
||||
|
||||
model.selected = selected;
|
||||
model.selected = Qt.binding(function() {return selected;});
|
||||
|
||||
model.scene = scene;
|
||||
model.scene = Qt.binding(function() {return scene;});
|
||||
|
||||
model.targetNode = targetNode;
|
||||
model.targetNode = Qt.binding(function() {return targetNode;});
|
||||
|
||||
model.color = lightGizmo.overlayColor;
|
||||
model.color = Qt.binding(function() {return lightGizmo.overlayColor;});
|
||||
|
||||
model.visible = visible;
|
||||
model.visible = Qt.binding(function() {return visible;});
|
||||
property View3D view3D
|
||||
property Node targetNode: null
|
||||
property MouseArea3D dragHelper: null
|
||||
property color color: Qt.rgba(1, 1, 0, 1)
|
||||
property real brightnessScale: targetNode ? Math.max(1.0, 1.0 + targetNode.brightness) : 100
|
||||
property real fadeScale: {
|
||||
// Value indicates area where intensity is above certain percent of total brightness.
|
||||
if (lightGizmo.targetNode instanceof SpotLight || lightGizmo.targetNode instanceof PointLight) {
|
||||
var l = targetNode.linearFade;
|
||||
var q = targetNode.quadraticFade;
|
||||
var c = targetNode.constantFade;
|
||||
var d = 20; // divisor to target intensity value. E.g. 20 = 1/20 = 5%
|
||||
if (l === 0 && q === 0)
|
||||
l = 1;
|
||||
// Solved from equation in shader:
|
||||
// 1 / d = 1 / (c + (l + q * dist) * dist);
|
||||
if (q === 0)
|
||||
return 100 * Math.max(((d - c) / l), 1);
|
||||
else
|
||||
return 100 * ((Math.sqrt(4 * q * (d - c) + (l * l)) - l) / (2 * q));
|
||||
} else {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
onActiveSceneChanged: {
|
||||
if (lightModel && activeScene == scene)
|
||||
lightModel.updateGeometry();
|
||||
position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
|
||||
visible: lightGizmo.targetNode instanceof SpotLight
|
||||
|| lightGizmo.targetNode instanceof AreaLight
|
||||
|| lightGizmo.targetNode instanceof DirectionalLight
|
||||
|| lightGizmo.targetNode instanceof PointLight
|
||||
|
||||
AutoScaleHelper {
|
||||
id: autoScale
|
||||
view3D: lightGizmo.view3D
|
||||
}
|
||||
|
||||
Node {
|
||||
rotation: !lightGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
|
||||
: lightGizmo.targetNode.sceneRotation
|
||||
|
||||
LightModel {
|
||||
id: spotModel
|
||||
|
||||
property real coneScale: visible
|
||||
? lightGizmo.fadeScale * Math.tan(Math.PI * targetNode.coneAngle / 180)
|
||||
: 1
|
||||
|
||||
geometryName: "Edit 3D SpotLight"
|
||||
geometryType: LightGeometry.Spot
|
||||
color: lightGizmo.color
|
||||
visible: lightGizmo.targetNode instanceof SpotLight
|
||||
scale: Qt.vector3d(coneScale, coneScale, lightGizmo.fadeScale)
|
||||
}
|
||||
Node {
|
||||
visible: lightGizmo.targetNode instanceof SpotLight
|
||||
SpotLightHandle {
|
||||
id: sphereHandle1
|
||||
view3D: lightGizmo.view3D
|
||||
material: lightMaterial
|
||||
position: Qt.vector3d(0, spotModel.scale.y, -spotModel.scale.z)
|
||||
}
|
||||
SpotLightHandle {
|
||||
id: sphereHandle2
|
||||
view3D: lightGizmo.view3D
|
||||
material: lightMaterial
|
||||
position: Qt.vector3d(spotModel.scale.x, 0, -spotModel.scale.z)
|
||||
}
|
||||
SpotLightHandle {
|
||||
id: sphereHandle3
|
||||
view3D: lightGizmo.view3D
|
||||
material: lightMaterial
|
||||
position: Qt.vector3d(0, -spotModel.scale.y, -spotModel.scale.z)
|
||||
}
|
||||
SpotLightHandle {
|
||||
id: sphereHandle4
|
||||
view3D: lightGizmo.view3D
|
||||
material: lightMaterial
|
||||
position: Qt.vector3d(-spotModel.scale.x, 0, -spotModel.scale.z)
|
||||
}
|
||||
}
|
||||
|
||||
LightModel {
|
||||
id: areaModel
|
||||
geometryName: "Edit 3D AreaLight"
|
||||
geometryType: LightGeometry.Area
|
||||
color: lightGizmo.color
|
||||
visible: lightGizmo.targetNode instanceof AreaLight
|
||||
scale: visible ? Qt.vector3d(lightGizmo.targetNode.width / 2,
|
||||
lightGizmo.targetNode.height / 2, 1)
|
||||
.times(lightGizmo.targetNode.scale)
|
||||
: Qt.vector3d(1, 1, 1)
|
||||
}
|
||||
LightModel {
|
||||
id: directionalModel
|
||||
geometryName: "Edit 3D DirLight"
|
||||
geometryType: LightGeometry.Directional
|
||||
color: lightGizmo.color
|
||||
visible: lightGizmo.targetNode instanceof DirectionalLight
|
||||
scale: autoScale.getScale(Qt.vector3d(50, 50, 50))
|
||||
}
|
||||
LightModel {
|
||||
id: pointModel
|
||||
geometryName: "Edit 3D PointLight"
|
||||
geometryType: LightGeometry.Point
|
||||
color: lightGizmo.color
|
||||
visible: lightGizmo.targetNode instanceof PointLight
|
||||
scale: Qt.vector3d(lightGizmo.fadeScale, lightGizmo.fadeScale, lightGizmo.fadeScale)
|
||||
}
|
||||
|
||||
AdjustableArrow {
|
||||
id: primaryArrow
|
||||
eulerRotation: Qt.vector3d(-90, 0, 0)
|
||||
targetNode: lightGizmo.targetNode
|
||||
color: lightGizmo.color
|
||||
view3D: lightGizmo.view3D
|
||||
active: false
|
||||
dragHelper: lightGizmo.dragHelper
|
||||
scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
|
||||
length: lightGizmo.brightnessScale / 10
|
||||
}
|
||||
|
||||
DefaultMaterial {
|
||||
id: lightMaterial
|
||||
emissiveColor: lightGizmo.color
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
cullMode: Material.NoCulling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
share/qtcreator/qml/qmlpuppet/mockfiles/LightIconGizmo.qml
Normal file
43
share/qtcreator/qml/qmlpuppet/mockfiles/LightIconGizmo.qml
Normal file
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.15
|
||||
|
||||
IconGizmo {
|
||||
id: lightIconGizmo
|
||||
|
||||
property color overlayColor: targetNode ? targetNode.color : "transparent"
|
||||
|
||||
iconSource: targetNode
|
||||
? targetNode instanceof DirectionalLight
|
||||
? "image://IconGizmoImageProvider/directional.png:" + overlayColor
|
||||
: targetNode instanceof AreaLight
|
||||
? "image://IconGizmoImageProvider/area.png:" + overlayColor
|
||||
: targetNode instanceof PointLight
|
||||
? "image://IconGizmoImageProvider/point.png:" + overlayColor
|
||||
: "image://IconGizmoImageProvider/spot.png:" + overlayColor
|
||||
: "image://IconGizmoImageProvider/point.png:" + overlayColor
|
||||
}
|
@@ -30,11 +30,8 @@ import LightGeometry 1.0
|
||||
Model {
|
||||
id: lightModel
|
||||
|
||||
property string geometryName
|
||||
property alias geometryName: lightGeometry.name // Name must be unique for each geometry
|
||||
property Node targetNode: null
|
||||
property Node scene: null
|
||||
property bool selected: false
|
||||
property alias geometryType: lightGeometry.lightType
|
||||
property color color
|
||||
|
||||
function updateGeometry()
|
||||
@@ -42,15 +39,13 @@ Model {
|
||||
lightGeometry.update();
|
||||
}
|
||||
|
||||
position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
|
||||
rotation: targetNode ? targetNode.sceneRotation : Qt.quaternion(1, 0, 0, 0)
|
||||
scale: Qt.vector3d(50, 50, 50)
|
||||
|
||||
geometry: lightGeometry
|
||||
materials: [
|
||||
DefaultMaterial {
|
||||
id: defaultMaterial
|
||||
emissiveColor: lightModel.selected ? lightModel.color : "#555555"
|
||||
emissiveColor: lightModel.color
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
cullMode: Material.NoCulling
|
||||
}
|
||||
@@ -58,6 +53,5 @@ Model {
|
||||
|
||||
LightGeometry {
|
||||
id: lightGeometry
|
||||
light: lightModel.scene && lightModel.targetNode ? lightModel.targetNode : null
|
||||
}
|
||||
}
|
||||
|
45
share/qtcreator/qml/qmlpuppet/mockfiles/SpotLightHandle.qml
Normal file
45
share/qtcreator/qml/qmlpuppet/mockfiles/SpotLightHandle.qml
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.15
|
||||
|
||||
Node {
|
||||
id: handleRoot
|
||||
|
||||
property DefaultMaterial material
|
||||
property View3D view3D
|
||||
|
||||
Model {
|
||||
scale: autoScale.getScale(Qt.vector3d(0.1, 0.1, 0.1))
|
||||
source: "#Sphere"
|
||||
materials: [ handleRoot.material ]
|
||||
}
|
||||
|
||||
AutoScaleHelper {
|
||||
id: autoScale
|
||||
view3D: handleRoot.view3D
|
||||
}
|
||||
}
|
@@ -29,10 +29,6 @@
|
||||
|
||||
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
|
||||
#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
|
||||
#include <QtQuick3D/private/qquick3darealight_p.h>
|
||||
#include <QtQuick3D/private/qquick3ddirectionallight_p.h>
|
||||
#include <QtQuick3D/private/qquick3dpointlight_p.h>
|
||||
#include <QtQuick3D/private/qquick3dspotlight_p.h>
|
||||
#include <QtCore/qmath.h>
|
||||
|
||||
#include <limits>
|
||||
@@ -49,25 +45,25 @@ LightGeometry::~LightGeometry()
|
||||
{
|
||||
}
|
||||
|
||||
QQuick3DAbstractLight *QmlDesigner::Internal::LightGeometry::light() const
|
||||
LightGeometry::LightType LightGeometry::lightType() const
|
||||
{
|
||||
return m_light;
|
||||
return m_lightType;
|
||||
}
|
||||
|
||||
void QmlDesigner::Internal::LightGeometry::setLight(QQuick3DAbstractLight *light)
|
||||
void LightGeometry::setLightType(LightGeometry::LightType lightType)
|
||||
{
|
||||
if (m_light == light)
|
||||
if (m_lightType == lightType)
|
||||
return;
|
||||
|
||||
m_light = light;
|
||||
m_lightType = lightType;
|
||||
|
||||
emit lightChanged();
|
||||
emit lightTypeChanged();
|
||||
update();
|
||||
}
|
||||
|
||||
QSSGRenderGraphObject *LightGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
|
||||
{
|
||||
if (!m_light)
|
||||
if (m_lightType == LightType::Invalid)
|
||||
return node;
|
||||
|
||||
node = QQuick3DGeometry::updateSpatialNode(node);
|
||||
@@ -99,28 +95,26 @@ void LightGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData
|
||||
{
|
||||
int vertexSize = 0;
|
||||
int indexSize = 0;
|
||||
const int dirSegments = 12; // Segment lines in directional light circle
|
||||
const int spotArc = 6; // Segment lines per cone line in spotlight arc
|
||||
const int spotCone = 4; // Lines in spotlight cone
|
||||
const int pointLightDensity = 5;
|
||||
const int arc = 12; // Segment lines per cone line in spot/directional light arc
|
||||
const int dirLines = 4; // Directional lines in spot/directional light
|
||||
const quint16 segments = arc * dirLines;
|
||||
const double segment = M_PI * 2. / double(segments);
|
||||
|
||||
if (qobject_cast<QQuick3DAreaLight *>(m_light)) {
|
||||
// Area light model is a rectangle with perpendicular lines on corners
|
||||
vertexSize = int(sizeof(float)) * 3 * 8;
|
||||
indexSize = int(sizeof(quint16)) * 8 * 2;
|
||||
} else if (qobject_cast<QQuick3DDirectionalLight *>(m_light)) {
|
||||
if (m_lightType == LightType::Area) {
|
||||
// Area light model is a rectangle
|
||||
vertexSize = int(sizeof(float)) * 3 * 4;
|
||||
indexSize = int(sizeof(quint16)) * 4 * 2;
|
||||
} else if (m_lightType == LightType::Directional) {
|
||||
// Directional light model is a circle with perpendicular lines on circumference vertices
|
||||
vertexSize = int(sizeof(float)) * 3 * dirSegments * 2;
|
||||
indexSize = int(sizeof(quint16)) * dirSegments * 2 * 2;
|
||||
} else if (qobject_cast<QQuick3DPointLight *>(m_light)) {
|
||||
// Point light model is a set of lines radiating from central point.
|
||||
// We reserve more than we need so we don't have to calculate the actual need here,
|
||||
// and resize later when we know the exact count.
|
||||
vertexSize = int(sizeof(float)) * 3 * pointLightDensity * pointLightDensity * 4;
|
||||
indexSize = int(sizeof(quint16)) * pointLightDensity * pointLightDensity * 4;
|
||||
} else if (qobject_cast<QQuick3DSpotLight *>(m_light)) {
|
||||
vertexSize = int(sizeof(float)) * 3 * (spotArc * spotCone + 1);
|
||||
indexSize = int(sizeof(quint16)) * (spotArc + 1) * spotCone * 2;
|
||||
vertexSize = int(sizeof(float)) * 3 * (segments + dirLines);
|
||||
indexSize = int(sizeof(quint16)) * (segments + dirLines) * 2;
|
||||
} else if (m_lightType == LightType::Point) {
|
||||
// Point light model is a set of three perpendicular circles
|
||||
vertexSize = int(sizeof(float)) * 3 * segments * 3;
|
||||
indexSize = int(sizeof(quint16)) * segments * 2 * 3;
|
||||
} else if (m_lightType == LightType::Spot) {
|
||||
vertexSize = int(sizeof(float)) * 3 * (segments + 1);
|
||||
indexSize = int(sizeof(quint16)) * (segments + dirLines) * 2;
|
||||
}
|
||||
vertexData.resize(vertexSize);
|
||||
indexData.resize(indexSize);
|
||||
@@ -128,89 +122,56 @@ void LightGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData
|
||||
auto dataPtr = reinterpret_cast<float *>(vertexData.data());
|
||||
auto indexPtr = reinterpret_cast<quint16 *>(indexData.data());
|
||||
|
||||
if (qobject_cast<QQuick3DAreaLight *>(m_light)) {
|
||||
auto createCircle = [&](quint16 startIndex, float zVal, int xIdx, int yIdx, int zIdx) {
|
||||
for (quint16 i = 0; i < segments; ++i) {
|
||||
float x = float(qCos(i * segment));
|
||||
float y = float(qSin(i * segment));
|
||||
auto vecPtr = reinterpret_cast<QVector3D *>(dataPtr);
|
||||
(*vecPtr)[xIdx] = x;
|
||||
(*vecPtr)[yIdx] = y;
|
||||
(*vecPtr)[zIdx] = zVal;
|
||||
dataPtr += 3;
|
||||
*indexPtr++ = startIndex + i; *indexPtr++ = startIndex + i + 1;
|
||||
}
|
||||
// Adjust the final index to complete the circle
|
||||
*(indexPtr - 1) = startIndex;
|
||||
};
|
||||
|
||||
if (m_lightType == LightType::Area) {
|
||||
*dataPtr++ = -1.f; *dataPtr++ = 1.f; *dataPtr++ = 0.f;
|
||||
*dataPtr++ = -1.f; *dataPtr++ = -1.f; *dataPtr++ = 0.f;
|
||||
*dataPtr++ = 1.f; *dataPtr++ = -1.f; *dataPtr++ = 0.f;
|
||||
*dataPtr++ = 1.f; *dataPtr++ = 1.f; *dataPtr++ = 0.f;
|
||||
|
||||
*dataPtr++ = -1.f; *dataPtr++ = 1.f; *dataPtr++ = -1.f;
|
||||
*dataPtr++ = -1.f; *dataPtr++ = -1.f; *dataPtr++ = -1.f;
|
||||
*dataPtr++ = 1.f; *dataPtr++ = -1.f; *dataPtr++ = -1.f;
|
||||
*dataPtr++ = 1.f; *dataPtr++ = 1.f; *dataPtr++ = -1.f;
|
||||
|
||||
*indexPtr++ = 0; *indexPtr++ = 1;
|
||||
*indexPtr++ = 1; *indexPtr++ = 2;
|
||||
*indexPtr++ = 2; *indexPtr++ = 3;
|
||||
*indexPtr++ = 3; *indexPtr++ = 0;
|
||||
} else if (m_lightType == LightType::Directional) {
|
||||
createCircle(0, 0.f, 0, 1, 2);
|
||||
|
||||
*indexPtr++ = 0; *indexPtr++ = 4;
|
||||
*indexPtr++ = 1; *indexPtr++ = 5;
|
||||
*indexPtr++ = 2; *indexPtr++ = 6;
|
||||
*indexPtr++ = 3; *indexPtr++ = 7;
|
||||
} else if (qobject_cast<QQuick3DDirectionalLight *>(m_light)) {
|
||||
const double segment = M_PI * 2. / double(dirSegments);
|
||||
for (quint16 i = 0; i < dirSegments; ++i) {
|
||||
float x = float(qCos(i * segment));
|
||||
float y = float(qSin(i * segment));
|
||||
*dataPtr++ = x; *dataPtr++ = y; *dataPtr++ = 0.f;
|
||||
*dataPtr++ = x; *dataPtr++ = y; *dataPtr++ = -1.f;
|
||||
const quint16 base = i * 2;
|
||||
*indexPtr++ = base; *indexPtr++ = base + 1;
|
||||
*indexPtr++ = base; *indexPtr++ = base + 2;
|
||||
// Dir lines
|
||||
for (quint16 i = 0; i < dirLines; ++i) {
|
||||
auto circlePtr = reinterpret_cast<float *>(vertexData.data()) + (3 * arc * i);
|
||||
*dataPtr++ = *circlePtr; *dataPtr++ = *(circlePtr + 1); *dataPtr++ = -3.f;
|
||||
*indexPtr++ = i * arc;
|
||||
*indexPtr++ = i + segments;
|
||||
}
|
||||
// Adjust the final index to complete the circle
|
||||
*(--indexPtr) = 0;
|
||||
} else if (qobject_cast<QQuick3DPointLight *>(m_light)) {
|
||||
const double innerRad = .3;
|
||||
vertexSize = 0;
|
||||
indexSize = 0;
|
||||
int vertexIndex = 0;
|
||||
for (quint16 i = 0; i < pointLightDensity; ++i) {
|
||||
double latAngle = (((.9 / (pointLightDensity - 1)) * i) + .05) * M_PI;
|
||||
quint16 longPoints = pointLightDensity * 2 * qSin(latAngle);
|
||||
latAngle -= M_PI_2;
|
||||
const double longSegment = M_PI * 2. / double(longPoints);
|
||||
for (quint16 j = 0; j < longPoints; ++j) {
|
||||
double longAngle = longSegment * j;
|
||||
float q = float(qCos(latAngle));
|
||||
float x = float(qCos(longAngle) * q);
|
||||
float y = float(qSin(latAngle));
|
||||
float z = float(qSin(longAngle) * q);
|
||||
|
||||
*dataPtr++ = x * innerRad; *dataPtr++ = y * innerRad; *dataPtr++ = z * innerRad;
|
||||
*dataPtr++ = x; *dataPtr++ = y; *dataPtr++ = z;
|
||||
*indexPtr++ = vertexIndex; *indexPtr++ = vertexIndex + 1;
|
||||
|
||||
vertexIndex += 2;
|
||||
vertexSize += 6 * sizeof(float);
|
||||
indexSize += 2 * sizeof(quint16);
|
||||
}
|
||||
}
|
||||
vertexData.resize(vertexSize);
|
||||
indexData.resize(indexSize);
|
||||
} else if (qobject_cast<QQuick3DSpotLight *>(m_light)) {
|
||||
const quint16 segments = spotArc * spotCone;
|
||||
const double segment = M_PI * 2. / double(segments);
|
||||
|
||||
// Circle
|
||||
for (quint16 i = 0; i < segments; ++i) {
|
||||
float x = float(qCos(i * segment));
|
||||
float y = float(qSin(i * segment));
|
||||
*dataPtr++ = x; *dataPtr++ = y; *dataPtr++ = -2.f;
|
||||
*indexPtr++ = i; *indexPtr++ = i + 1;
|
||||
}
|
||||
// Adjust the final index to complete the circle
|
||||
*(indexPtr - 1) = 0;
|
||||
} else if (m_lightType == LightType::Point) {
|
||||
createCircle(0, 0.f, 0, 1, 2);
|
||||
createCircle(segments, 0.f, 2, 0, 1);
|
||||
createCircle(segments * 2, 0.f, 1, 2, 0);
|
||||
} else if (m_lightType == LightType::Spot) {
|
||||
createCircle(0, -1.f, 0, 1, 2);
|
||||
|
||||
// Cone tip
|
||||
*dataPtr++ = 0.f; *dataPtr++ = 0.f; *dataPtr++ = 0.f;
|
||||
quint16 tipIndex = segments;
|
||||
|
||||
// Cone lines
|
||||
for (quint16 i = 0; i < spotCone; ++i) {
|
||||
for (quint16 i = 0; i < dirLines; ++i) {
|
||||
*indexPtr++ = tipIndex;
|
||||
*indexPtr++ = i * spotArc;
|
||||
*indexPtr++ = i * arc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#ifdef QUICK3D_MODULE
|
||||
|
||||
#include <QtQuick3D/private/qquick3dgeometry_p.h>
|
||||
#include <QtQuick3D/private/qquick3dabstractlight_p.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
@@ -36,19 +35,28 @@ namespace Internal {
|
||||
class LightGeometry : public QQuick3DGeometry
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QQuick3DAbstractLight *light READ light WRITE setLight NOTIFY lightChanged)
|
||||
Q_PROPERTY(LightType lightType READ lightType WRITE setLightType NOTIFY lightTypeChanged)
|
||||
|
||||
public:
|
||||
enum class LightType {
|
||||
Invalid,
|
||||
Spot,
|
||||
Area,
|
||||
Directional,
|
||||
Point
|
||||
};
|
||||
Q_ENUM(LightType)
|
||||
|
||||
LightGeometry();
|
||||
~LightGeometry() override;
|
||||
|
||||
QQuick3DAbstractLight *light() const;
|
||||
LightType lightType() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setLight(QQuick3DAbstractLight *light);
|
||||
void setLightType(LightType lightType);
|
||||
|
||||
Q_SIGNALS:
|
||||
void lightChanged();
|
||||
void lightTypeChanged();
|
||||
|
||||
protected:
|
||||
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
|
||||
@@ -56,7 +64,7 @@ protected:
|
||||
private:
|
||||
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
|
||||
QVector3D &minBounds, QVector3D &maxBounds);
|
||||
QQuick3DAbstractLight *m_light = nullptr;
|
||||
LightType m_lightType = LightType::Invalid;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,10 @@
|
||||
<file>mockfiles/CameraFrustum.qml</file>
|
||||
<file>mockfiles/CameraGizmo.qml</file>
|
||||
<file>mockfiles/LightModel.qml</file>
|
||||
<file>mockfiles/LightIconGizmo.qml</file>
|
||||
<file>mockfiles/LightGizmo.qml</file>
|
||||
<file>mockfiles/SpotLightHandle.qml</file>
|
||||
<file>mockfiles/AdjustableArrow.qml</file>
|
||||
<file>mockfiles/IconGizmo.qml</file>
|
||||
<file>mockfiles/Overlay2D.qml</file>
|
||||
<file>mockfiles/HelperGrid.qml</file>
|
||||
|
Reference in New Issue
Block a user