1 /* 2 * DQt - D bindings for the Qt Toolkit 3 * 4 * GNU Lesser General Public License Usage 5 * This file may be used under the terms of the GNU Lesser 6 * General Public License version 3 as published by the Free Software 7 * Foundation and appearing in the file LICENSE.LGPL3 included in the 8 * packaging of this file. Please review the following information to 9 * ensure the GNU Lesser General Public License version 3 requirements 10 * will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 11 */ 12 module qt.gui.vector3d; 13 extern(C++): 14 15 import qt.config; 16 import qt.helpers; 17 version(QT_NO_VECTOR2D){}else 18 version(QT_NO_VECTOR3D){}else 19 import qt.gui.vector2d; 20 version(QT_NO_VECTOR3D){}else 21 version(QT_NO_VECTOR4D){}else 22 import qt.gui.vector4d; 23 version(QT_NO_VECTOR3D){}else 24 { 25 import qt.core.metatype; 26 import qt.core.namespace; 27 import qt.core.point; 28 import qt.core.rect; 29 import qt.core.typeinfo; 30 import qt.core.variant; 31 } 32 33 version(QT_NO_VECTOR3D) 34 { 35 extern(C++, class) struct QVector3D; 36 } 37 version(QT_NO_VECTOR3D){}else 38 { 39 40 /// Binding for C++ class [QVector3D](https://doc.qt.io/qt-6/qvector3d.html). 41 @Q_PRIMITIVE_TYPE extern(C++, class) struct QVector3D 42 { 43 public: 44 /+pragma(inline, true) this()/+ noexcept+/ 45 { 46 this.v = [0.0f, 0.0f, 0.0f]; 47 }+/ 48 /+ explicit +/this(/+ Qt:: +/qt.core.namespace.Initialization)/+ noexcept+/ {} 49 this(float xpos, float ypos, float zpos)/+ noexcept+/ 50 { 51 this.v = [xpos, ypos, zpos]; 52 } 53 54 /+ explicit +/pragma(inline, true) this(QPoint point)/+ noexcept+/ 55 { 56 this.v = [float(point.x()), float(point.y()), 0.0f]; 57 } 58 /+ explicit +/pragma(inline, true) this(QPointF point)/+ noexcept+/ 59 { 60 this.v = [float(point.x()), float(point.y()), 0.0f]; 61 } 62 /+ #ifndef QT_NO_VECTOR2D +/ 63 version(QT_NO_VECTOR2D){}else 64 { 65 /+ /+ explicit +/pragma(inline, true) this(QVector2D vector)/+ noexcept+/ 66 { 67 this.v = [vector[0], vector[1], 0.0f]; 68 } 69 pragma(inline, true) this(QVector2D vector, float zpos)/+ noexcept+/ 70 { 71 this.v = [vector[0], vector[1], zpos]; 72 } +/ 73 } 74 /+ #endif 75 #ifndef QT_NO_VECTOR4D +/ 76 version(QT_NO_VECTOR4D){}else 77 { 78 /+ /+ explicit +/pragma(inline, true) this(QVector4D vector)/+ noexcept+/ 79 { 80 this.v = [vector[0], vector[1], vector[2]]; 81 } +/ 82 } 83 /+ #endif +/ 84 85 pragma(inline, true) bool isNull() const/+ noexcept+/ 86 { 87 import qt.core.global; 88 89 return qIsNull(v[0]) && qIsNull(v[1]) && qIsNull(v[2]); 90 } 91 92 pragma(inline, true) float x() const/+ noexcept+/ { return v[0]; } 93 pragma(inline, true) float y() const/+ noexcept+/ { return v[1]; } 94 pragma(inline, true) float z() const/+ noexcept+/ { return v[2]; } 95 96 pragma(inline, true) void setX(float aX)/+ noexcept+/ { v[0] = aX; } 97 pragma(inline, true) void setY(float aY)/+ noexcept+/ { v[1] = aY; } 98 pragma(inline, true) void setZ(float aZ)/+ noexcept+/ { v[2] = aZ; } 99 100 /+pragma(inline, true) ref float operator [](int i) 101 { 102 import qt.core.global; 103 104 (mixin(Q_ASSERT(q{uint(i) < 3u}))); 105 return v[i]; 106 }+/ 107 /+pragma(inline, true) float operator [](int i) const 108 { 109 import qt.core.global; 110 111 (mixin(Q_ASSERT(q{uint(i) < 3u}))); 112 return v[i]; 113 }+/ 114 115 /+ /+ [[nodiscard]] +/ pragma(inline, true) float length() const/+ noexcept+/ 116 { 117 return qHypot(v[0], v[1], v[2]); 118 } 119 /+ [[nodiscard]] +/ pragma(inline, true) float lengthSquared() const/+ noexcept+/ 120 { 121 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; 122 } 123 124 /+ [[nodiscard]] +/ pragma(inline, true) QVector3D normalized() const/+ noexcept+/ 125 { 126 import qt.core.global; 127 128 const(float) len = length(); 129 return qFuzzyIsNull(len - 1.0f) ? this : qFuzzyIsNull(len) ? QVector3D() 130 : QVector3D(v[0] / len, v[1] / len, v[2] / len); 131 } 132 pragma(inline, true) void normalize()/+ noexcept+/ 133 { 134 import qt.core.global; 135 136 const(float) len = length(); 137 if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) 138 return; 139 140 v[0] /= len; 141 v[1] /= len; 142 v[2] /= len; 143 } +/ 144 145 /+pragma(inline, true) ref QVector3D operator +=(QVector3D vector)/+ noexcept+/ 146 { 147 v[0] += vector.v[0]; 148 v[1] += vector.v[1]; 149 v[2] += vector.v[2]; 150 return this; 151 }+/ 152 /+pragma(inline, true) ref QVector3D operator -=(QVector3D vector)/+ noexcept+/ 153 { 154 v[0] -= vector.v[0]; 155 v[1] -= vector.v[1]; 156 v[2] -= vector.v[2]; 157 return this; 158 }+/ 159 /+pragma(inline, true) ref QVector3D operator *=(float factor)/+ noexcept+/ 160 { 161 v[0] *= factor; 162 v[1] *= factor; 163 v[2] *= factor; 164 return this; 165 }+/ 166 /+pragma(inline, true) ref QVector3D operator *=(QVector3D vector)/+ noexcept+/ 167 { 168 v[0] *= vector.v[0]; 169 v[1] *= vector.v[1]; 170 v[2] *= vector.v[2]; 171 return this; 172 }+/ 173 /+pragma(inline, true) ref QVector3D operator /=(float divisor) 174 { 175 import qt.core.global; 176 177 (mixin(Q_ASSERT(q{divisor < 0 || divisor > 0}))); 178 v[0] /= divisor; 179 v[1] /= divisor; 180 v[2] /= divisor; 181 return this; 182 }+/ 183 /+pragma(inline, true) ref QVector3D operator /=(QVector3D vector) 184 { 185 import qt.core.global; 186 187 (mixin(Q_ASSERT(q{vector.v[0] > 0 || vector.v[0] < 0}))); 188 (mixin(Q_ASSERT(q{vector.v[1] > 0 || vector.v[1] < 0}))); 189 (mixin(Q_ASSERT(q{vector.v[2] > 0 || vector.v[2] < 0}))); 190 v[0] /= vector.v[0]; 191 v[1] /= vector.v[1]; 192 v[2] /= vector.v[2]; 193 return this; 194 }+/ 195 196 /+ [[nodiscard]] +/ pragma(inline, true) static float dotProduct(QVector3D v1, QVector3D v2)/+ noexcept+/ 197 { 198 return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2]; 199 } 200 /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D crossProduct(QVector3D v1, QVector3D v2)/+ noexcept+/ 201 { 202 return QVector3D(v1.v[1] * v2.v[2] - v1.v[2] * v2.v[1], 203 v1.v[2] * v2.v[0] - v1.v[0] * v2.v[2], 204 v1.v[0] * v2.v[1] - v1.v[1] * v2.v[0]); 205 } 206 207 /+ /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D normal(QVector3D v1, QVector3D v2)/+ noexcept+/ 208 { 209 return crossProduct(v1, v2).normalized(); 210 } 211 /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D normal(QVector3D v1, QVector3D v2, QVector3D v3)/+ noexcept+/ 212 { 213 return crossProduct((v2 - v1), (v3 - v1)).normalized(); 214 } +/ 215 216 /+ Q_GUI_EXPORT +/ QVector3D project(ref const(QMatrix4x4) modelView, ref const(QMatrix4x4) projection, ref const(QRect) viewport) const; 217 /+ Q_GUI_EXPORT +/ QVector3D unproject(ref const(QMatrix4x4) modelView, ref const(QMatrix4x4) projection, ref const(QRect) viewport) const; 218 219 /+ QT_WARNING_PUSH 220 QT_WARNING_DISABLE_FLOAT_COMPARE +/ 221 /+ constexpr friend inline bool operator==(QVector3D v1, QVector3D v2) noexcept 222 { 223 return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2]; 224 } +/ 225 226 /+ constexpr friend inline bool operator!=(QVector3D v1, QVector3D v2) noexcept 227 { 228 return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2]; 229 } +/ 230 /+ QT_WARNING_POP +/ 231 /+ pragma(inline, true) float distanceToPoint(QVector3D point) const/+ noexcept+/ 232 { 233 return (this - point).length(); 234 } 235 pragma(inline, true) float distanceToPlane(QVector3D plane, QVector3D normal) const/+ noexcept+/ 236 { 237 return dotProduct(this - plane, normal); 238 } 239 pragma(inline, true) float distanceToPlane(QVector3D plane1, QVector3D plane2, QVector3D plane3) const/+ noexcept+/ 240 { 241 QVector3D n = normal(plane2 - plane1, plane3 - plane1); 242 return dotProduct(this - plane1, n); 243 } 244 pragma(inline, true) float distanceToLine(QVector3D point, QVector3D direction) const/+ noexcept+/ 245 { 246 if (direction.isNull()) 247 return (this - point).length(); 248 QVector3D p = cast(QVector3D)(point + dotProduct(this - point, direction) * direction); 249 return (this - p).length(); 250 } +/ 251 252 253 /+ constexpr friend inline QVector3D operator+(QVector3D v1, QVector3D v2) noexcept 254 { 255 return QVector3D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2]); 256 } +/ 257 258 /+ constexpr friend inline QVector3D operator-(QVector3D v1, QVector3D v2) noexcept 259 { 260 return QVector3D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2]); 261 } +/ 262 263 /+ constexpr friend inline QVector3D operator*(float factor, QVector3D vector) noexcept 264 { 265 return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor); 266 } +/ 267 268 /+ constexpr friend inline QVector3D operator*(QVector3D vector, float factor) noexcept 269 { 270 return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor); 271 } +/ 272 273 /+ constexpr friend inline QVector3D operator*(QVector3D v1, QVector3D v2) noexcept 274 { 275 return QVector3D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2]); 276 } +/ 277 278 /+ constexpr friend inline QVector3D operator-(QVector3D vector) noexcept 279 { 280 return QVector3D(-vector.v[0], -vector.v[1], -vector.v[2]); 281 } +/ 282 283 /+ constexpr friend inline QVector3D operator/(QVector3D vector, float divisor) 284 { 285 Q_ASSERT(divisor < 0 || divisor > 0); 286 return QVector3D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor); 287 } +/ 288 289 /+ constexpr friend inline QVector3D operator/(QVector3D vector, QVector3D divisor) 290 { 291 Q_ASSERT(divisor.v[0] > 0 || divisor.v[0] < 0); 292 Q_ASSERT(divisor.v[1] > 0 || divisor.v[1] < 0); 293 Q_ASSERT(divisor.v[2] > 0 || divisor.v[2] < 0); 294 return QVector3D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1], 295 vector.v[2] / divisor.v[2]); 296 } +/ 297 298 /+ friend Q_GUI_EXPORT bool qFuzzyCompare(QVector3D v1, QVector3D v2) noexcept; +/ 299 300 /+ #ifndef QT_NO_VECTOR2D +/ 301 version(QT_NO_VECTOR2D){}else 302 { 303 pragma(inline, true) QVector2D toVector2D() const/+ noexcept+/ 304 { 305 return QVector2D(v[0], v[1]); 306 } 307 } 308 /+ #endif 309 #ifndef QT_NO_VECTOR4D +/ 310 version(QT_NO_VECTOR4D){}else 311 { 312 pragma(inline, true) QVector4D toVector4D() const/+ noexcept+/ 313 { 314 return QVector4D(v[0], v[1], v[2], 0.0f); 315 } 316 } 317 /+ #endif +/ 318 319 pragma(inline, true) QPoint toPoint() const/+ noexcept+/ 320 { 321 import qt.core.global; 322 323 return QPoint(qRound(v[0]), qRound(v[1])); 324 } 325 pragma(inline, true) QPointF toPointF() const/+ noexcept+/ 326 { 327 import qt.core.global; 328 329 return QPointF(qreal(v[0]), qreal(v[1])); 330 } 331 332 /+/+ Q_GUI_EXPORT +/ auto opCast(T : QVariant)() const;+/ 333 334 private: 335 float[3] v = [0.0f, 0.0f, 0.0f]; 336 337 /+ friend class QVector2D; +/ 338 /+ friend class QVector4D; +/ 339 static if(!defined!"QT_NO_MATRIX4X4") 340 { 341 /+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix); +/ 342 /+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector); +/ 343 } 344 345 /+ template <std::size_t I, 346 typename V, 347 std::enable_if_t<(I < 3), bool> = true, 348 std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector3D>, bool> = true> +/ 349 /+ friend constexpr decltype(auto) get(V &&vec) noexcept 350 { 351 static if (I == 0) 352 return (std::forward<V>(vec).v[0]); 353 else static if (I == 1) 354 return (std::forward<V>(vec).v[1]); 355 else static if (I == 2) 356 return (std::forward<V>(vec).v[2]); 357 } +/ 358 mixin(CREATE_CONVENIENCE_WRAPPERS); 359 } 360 } 361