1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
import numpy as np
from PySide6.QtCore import Property, Signal
from PySide6.QtGui import QVector3D
from PySide6.QtQml import QmlElement
from PySide6.QtQuick3D import QQuick3DGeometry
QML_IMPORT_NAME = "ExampleTriangleGeometry"
QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
class ExampleTriangleGeometry(QQuick3DGeometry):
normalsChanged = Signal()
normalXYChanged = Signal()
uvChanged = Signal()
uvAdjustChanged = Signal()
def __init__(self, parent=None):
QQuick3DGeometry.__init__(self, parent)
self._hasNormals = False
self._normalXY = 0.0
self._hasUV = False
self._uvAdjust = 0.0
self.updateData()
@Property(bool, notify=normalsChanged)
def normals(self):
return self._hasNormals
@normals.setter
def normals(self, enable):
if self._hasNormals == enable:
return
self._hasNormals = enable
self.normalsChanged.emit()
self.updateData()
self.update()
@Property(float, notify=normalXYChanged)
def normalXY(self):
return self._normalXY
@normalXY.setter
def normalXY(self, xy):
if self._normalXY == xy:
return
self._normalXY = xy
self.normalXYChanged.emit()
self.updateData()
self.update()
@Property(bool, notify=uvChanged)
def uv(self):
return self._hasUV
@uv.setter
def uv(self, enable):
if self._hasUV == enable:
return
self._hasUV = enable
self.uvChanged.emit()
self.updateData()
self.update()
@Property(float, notify=uvAdjustChanged)
def uvAdjust(self):
return self._uvAdjust
@uvAdjust.setter
def uvAdjust(self, f):
if self._uvAdjust == f:
return
self._uvAdjust = f
self.uvAdjustChanged.emit()
self.updateData()
self.update()
def updateData(self):
self.clear()
stride = 3
if self._hasNormals:
stride += 3
if self._hasUV:
stride += 2
# We use numpy arrays to handle the vertex data,
# but still we need to consider the 'sizeof(float)'
# from C to set the Stride, and Attributes for the
# underlying Qt methods
FLOAT_SIZE = 4
vertexData = np.zeros(3 * stride, dtype=np.float32)
# a triangle, front face = counter-clockwise
p = 0
vertexData[p] = -1.0
p += 1
vertexData[p] = -1.0
p += 1
vertexData[p] = 0.0
p += 1
if self._hasNormals:
vertexData[p] = self._normalXY
p += 1
vertexData[p] = self._normalXY
p += 1
vertexData[p] = 1.0
p += 1
if self._hasUV:
vertexData[p] = 0.0 + self._uvAdjust
p += 1
vertexData[p] = 0.0 + self._uvAdjust
p += 1
vertexData[p] = 1.0
p += 1
vertexData[p] = -1.0
p += 1
vertexData[p] = 0.0
p += 1
if self._hasNormals:
vertexData[p] = self._normalXY
p += 1
vertexData[p] = self._normalXY
p += 1
vertexData[p] = 1.0
p += 1
if self._hasUV:
vertexData[p] = 1.0 - self._uvAdjust
p += 1
vertexData[p] = 0.0 + self._uvAdjust
p += 1
vertexData[p] = 0.0
p += 1
vertexData[p] = 1.0
p += 1
vertexData[p] = 0.0
p += 1
if self._hasNormals:
vertexData[p] = self._normalXY
p += 1
vertexData[p] = self._normalXY
p += 1
vertexData[p] = 1.0
p += 1
if self._hasUV:
vertexData[p] = 1.0 - self._uvAdjust
p += 1
vertexData[p] = 1.0 - self._uvAdjust
p += 1
self.setVertexData(vertexData.tobytes())
self.setStride(stride * FLOAT_SIZE)
self.setBounds(QVector3D(-1.0, -1.0, 0.0), QVector3D(+1.0, +1.0, 0.0))
self.setPrimitiveType(QQuick3DGeometry.PrimitiveType.Triangles)
self.addAttribute(
QQuick3DGeometry.Attribute.Semantic.PositionSemantic, 0,
QQuick3DGeometry.Attribute.ComponentType.F32Type
)
if self._hasNormals:
self.addAttribute(
QQuick3DGeometry.Attribute.Semantic.NormalSemantic,
3 * FLOAT_SIZE,
QQuick3DGeometry.Attribute.ComponentType.F32Type,
)
if self._hasUV:
self.addAttribute(
QQuick3DGeometry.Attribute.TexCoordSemantic,
6 * FLOAT_SIZE if self._hasNormals else 3 * FLOAT_SIZE,
QQuick3DGeometry.Attribute.F32Type,
)
|