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:
Miikka Heikkinen
2020-05-04 17:42:22 +03:00
parent 4d23e6300f
commit a3e6e24427
11 changed files with 374 additions and 167 deletions

View 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)
}
}

View File

@@ -25,7 +25,6 @@
import QtQuick 2.0
import QtQuick3D 1.15
import MouseArea3D 1.0
DirectionalDraggable {
id: arrow

View File

@@ -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)

View File

@@ -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

View File

@@ -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;});
}
onActiveSceneChanged: {
if (lightModel && activeScene == scene)
lightModel.updateGeometry();
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;
}
}
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
}
}
}

View 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
}

View File

@@ -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
}
}

View 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
}
}

View File

@@ -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;
}
}

View File

@@ -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;
};
}

View File

@@ -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>