22#include <Qt3DRender/QCamera> 
   23#include <Qt3DRender/QGeometryRenderer> 
   25#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
   26#include <Qt3DRender/QAttribute> 
   27#include <Qt3DRender/QBuffer> 
   28#include <Qt3DRender/QGeometry> 
   33#include <Qt3DCore/QAttribute> 
   34#include <Qt3DCore/QBuffer> 
   35#include <Qt3DCore/QGeometry> 
   52    : m_direction( 0.0f, 0.0f, 1.0f )
 
   56  Ray3D::Ray3D( QVector3D origin, QVector3D direction, 
float distance )
 
   58    , m_direction( direction )
 
   59    , m_distance( distance )
 
   62  QVector3D Ray3D::origin()
 const 
   67  void Ray3D::setOrigin( QVector3D value )
 
   72  QVector3D Ray3D::direction()
 const 
   77  void Ray3D::setDirection( QVector3D value )
 
   85  float Ray3D::distance()
 const 
   90  void Ray3D::setDistance( 
float distance )
 
   92    m_distance = distance;
 
   95  QVector3D Ray3D::point( 
float t )
 const 
   97    return m_origin + t * m_direction;
 
  100  Ray3D &Ray3D::transform( 
const QMatrix4x4 &matrix )
 
  102    m_origin = matrix * m_origin;
 
  103    m_direction = matrix.mapVector( m_direction );
 
  108  Ray3D Ray3D::transformed( 
const QMatrix4x4 &matrix )
 const 
  110    return Ray3D( matrix * m_origin, matrix.mapVector( m_direction ) );
 
  113  bool Ray3D::operator==( 
const Ray3D &other )
 const 
  115    return m_origin == other.origin() && m_direction == other.direction();
 
  118  bool Ray3D::operator!=( 
const Ray3D &other )
 const 
  120    return !( *
this == other );
 
  123  bool Ray3D::contains( QVector3D point )
 const 
  125    const QVector3D ppVec( point - m_origin );
 
  126    if ( ppVec.isNull() ) 
 
  128    const float dot = QVector3D::dotProduct( ppVec, m_direction );
 
  129    if ( qFuzzyIsNull( dot ) )
 
  131    return qFuzzyCompare( dot * dot, ppVec.lengthSquared() * m_direction.lengthSquared() );
 
  134  bool Ray3D::contains( 
const Ray3D &ray )
 const 
  136    const float dot = QVector3D::dotProduct( m_direction, ray.direction() );
 
  137    if ( !qFuzzyCompare( dot * dot, m_direction.lengthSquared() * ray.direction().lengthSquared() ) )
 
  139    return contains( ray.origin() );
 
  142  float Ray3D::projectedDistance( QVector3D point )
 const 
  144    Q_ASSERT( !m_direction.isNull() );
 
  146    return QVector3D::dotProduct( point - m_origin, m_direction ) /
 
  147           m_direction.lengthSquared();
 
  150  QVector3D Ray3D::project( QVector3D vector )
 const 
  152    const QVector3D norm = m_direction.normalized();
 
  153    return QVector3D::dotProduct( vector, norm ) * norm;
 
  157  float Ray3D::distance( QVector3D point )
 const 
  159    const float t = projectedDistance( point );
 
  160    return ( point - ( m_origin + t * m_direction ) ).length();
 
  163  QDebug 
operator<<( QDebug dbg, 
const Ray3D &ray )
 
  165    const QDebugStateSaver saver( dbg );
 
  166    dbg.nospace() << 
"QRay3D(origin(" 
  167                  << ray.origin().x() << 
", " << ray.origin().y() << 
", " 
  168                  << ray.origin().z() << 
") - direction(" 
  169                  << ray.direction().x() << 
", " << ray.direction().y() << 
", " 
  170                  << ray.direction().z() << 
"))";
 
  193  ray( 
double xO, 
double yO, 
double zO, 
double xD, 
double yD, 
double zD )
 
  195    origin[0] = xO; origin[1] = yO; origin[2] = zO;
 
  196    dir[0] = xD; dir[1] = yD; dir[2] = zD;
 
  197    dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
 
  199  ray( 
const QgsRayCastingUtils::Ray3D &r )
 
  202    origin[0] = r.origin().x(); origin[1] = r.origin().y(); origin[2] = r.origin().z();
 
  203    dir[0] = r.direction().x(); dir[1] = r.direction().y(); dir[2] = r.direction().z();
 
  204    dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
 
  214bool intersection( 
const box &b, 
const ray &r )
 
  216  double t1 = ( b.min[0] - r.origin[0] ) * r.dir_inv[0];
 
  217  double t2 = ( b.max[0] - r.origin[0] ) * r.dir_inv[0];
 
  219  double tmin = std::min( t1, t2 );
 
  220  double tmax = std::max( t1, t2 );
 
  222  for ( 
int i = 1; i < 3; ++i )
 
  224    t1 = ( b.min[i] - r.origin[i] ) * r.dir_inv[i];
 
  225    t2 = ( b.max[i] - r.origin[i] ) * r.dir_inv[i];
 
  227    tmin = std::max( tmin, std::min( std::min( t1, t2 ), tmax ) );
 
  228    tmax = std::min( tmax, std::max( std::max( t1, t2 ), tmin ) );
 
  231  return tmax > std::max( tmin, 0.0 );
 
  238  bool rayBoxIntersection( 
const Ray3D &r, 
const QgsAABB &aabb )
 
  243    if ( b.min[0] == b.max[0] ) b.max[0] += 0.1;
 
  244    if ( b.min[1] == b.max[1] ) b.max[1] += 0.1;
 
  245    if ( b.min[2] == b.max[2] ) b.max[2] += 0.1;
 
  247    return intersection( b, ray( r ) );
 
  252  bool rayTriangleIntersection( 
const Ray3D &ray,
 
  262    const QVector3D ab = b - a;
 
  263    const QVector3D ac = 
c - a;
 
  264    const QVector3D qp = ( ray.origin() - ray.point( ray.distance() ) );
 
  266    const QVector3D n = QVector3D::crossProduct( ab, ac );
 
  267    const float d = QVector3D::dotProduct( qp, n );
 
  269    if ( d <= 0.0f || std::isnan( d ) )
 
  272    const QVector3D ap = ray.origin() - a;
 
  273    t = QVector3D::dotProduct( ap, n );
 
  275    if ( t < 0.0f || t > d )
 
  278    const QVector3D e = QVector3D::crossProduct( qp, ap );
 
  279    uvw.setY( QVector3D::dotProduct( ac, e ) );
 
  281    if ( uvw.y() < 0.0f || uvw.y() > d )
 
  284    uvw.setZ( -QVector3D::dotProduct( ab, e ) );
 
  286    if ( uvw.z() < 0.0f || uvw.y() + uvw.z() > d )
 
  289    const float ood = 1.0f / d;
 
  291    uvw.setY( uvw.y() * ood );
 
  292    uvw.setZ( uvw.z() * ood );
 
  293    uvw.setX( 1.0f - uvw.y() - uvw.z() );
 
  298  bool rayMeshIntersection( Qt3DRender::QGeometryRenderer *geometryRenderer,
 
  299                            const QgsRayCastingUtils::Ray3D &r,
 
  300                            const QMatrix4x4 &worldTransform,
 
  304    if ( geometryRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles )
 
  306      QgsDebugError( QString( 
"Unsupported primitive type for intersection: " ).arg( geometryRenderer->primitiveType() ) );
 
  309    if ( geometryRenderer->instanceCount() != 1 || geometryRenderer->indexOffset() != 0 || geometryRenderer->indexBufferByteOffset() != 0 || geometryRenderer->firstVertex() != 0 || geometryRenderer->firstInstance() != 0 )
 
  311      QgsDebugError( QString( 
"Unsupported geometry renderer for intersection." ) );
 
  321      if ( attr->name() == Qt3DQAttribute::defaultPositionAttributeName() )
 
  325      else if ( attr->attributeType() == Qt3DQAttribute::IndexAttribute )
 
  337    if ( positionAttr->vertexBaseType() != Qt3DQAttribute::Float || positionAttr->vertexSize() != 3 )
 
  339      QgsDebugError( QString( 
"Unsupported position attribute: base type %1, vertex size %2" ). arg( positionAttr->vertexBaseType() ).arg( positionAttr->vertexSize() ) );
 
  343    const QByteArray vertexBuf = positionAttr->buffer()->data();
 
  344    const char *vertexPtr = vertexBuf.constData();
 
  345    vertexPtr += positionAttr->byteOffset();
 
  346    int vertexByteStride = positionAttr->byteStride() == 0 ? 3 * 
sizeof( float ) : positionAttr->byteStride();
 
  348    const uchar *indexPtrUChar = 
nullptr;
 
  349    const ushort *indexPtrUShort = 
nullptr;
 
  350    const uint *indexPtrUInt = 
nullptr;
 
  353      if ( indexAttr->byteStride() != 0 || indexAttr->vertexSize() != 1 )
 
  355        QgsDebugError( QString( 
"Unsupported index attribute: stride %1, vertex size %2" ).arg( indexAttr->byteStride() ).arg( indexAttr->vertexSize() ) );
 
  359      const QByteArray indexBuf = indexAttr->buffer()->data();
 
  360      if ( indexAttr->vertexBaseType() == Qt3DQAttribute::UnsignedByte )
 
  362        indexPtrUChar = 
reinterpret_cast<const uchar *
>( indexBuf.constData() + indexAttr->byteOffset() );
 
  364      else if ( indexAttr->vertexBaseType() == Qt3DQAttribute::UnsignedShort )
 
  366        indexPtrUShort = 
reinterpret_cast<const ushort *
>( indexBuf.constData() + indexAttr->byteOffset() );
 
  368      else if ( indexAttr->vertexBaseType() == Qt3DQAttribute::UnsignedInt )
 
  370        indexPtrUInt = 
reinterpret_cast<const uint *
>( indexBuf.constData() + indexAttr->byteOffset() );
 
  374        QgsDebugError( QString( 
"Unsupported index attribute: base type %1" ).arg( indexAttr->vertexBaseType() ) );
 
  379    int vertexCount = geometryRenderer->vertexCount();
 
  380    if ( vertexCount == 0 && indexAttr )
 
  382      vertexCount = indexAttr->count();
 
  384    if ( vertexCount == 0 )
 
  386      vertexCount = positionAttr->count();
 
  389    QVector3D intersectionPt, minIntersectionPt;
 
  390    float minDistance = -1;
 
  392    for ( 
int i = 0; i < vertexCount; i += 3 )
 
  394      int v0index = 0, v1index = 0, v2index = 0;
 
  401      else if ( indexPtrUShort )
 
  403        v0index = indexPtrUShort[i];
 
  404        v1index = indexPtrUShort[i + 1];
 
  405        v2index = indexPtrUShort[i + 2];
 
  407      else if ( indexPtrUChar )
 
  409        v0index = indexPtrUChar[i];
 
  410        v1index = indexPtrUChar[i + 1];
 
  411        v2index = indexPtrUChar[i + 2];
 
  413      else if ( indexPtrUInt )
 
  415        v0index = indexPtrUInt[i];
 
  416        v1index = indexPtrUInt[i + 1];
 
  417        v2index = indexPtrUInt[i + 2];
 
  422      const float *v0ptr = 
reinterpret_cast<const float *
>( vertexPtr + v0index * vertexByteStride );
 
  423      const float *v1ptr = 
reinterpret_cast<const float *
>( vertexPtr + v1index * vertexByteStride );
 
  424      const float *v2ptr = 
reinterpret_cast<const float *
>( vertexPtr + v2index * vertexByteStride );
 
  426      const QVector3D a( v0ptr[0], v0ptr[1], v0ptr[2] );
 
  427      const QVector3D b( v1ptr[0], v1ptr[1], v1ptr[2] );
 
  428      const QVector3D 
c( v2ptr[0], v2ptr[1], v2ptr[2] );
 
  433      const QVector3D tA = worldTransform * a;
 
  434      const QVector3D tB = worldTransform * b;
 
  435      const QVector3D tC = worldTransform * 
c;
 
  443      if ( QgsRayCastingUtils::rayTriangleIntersection( r, tA, tB, tC, uvw, t ) ||
 
  444           QgsRayCastingUtils::rayTriangleIntersection( r, tA, tC, tB, uvw, t ) )
 
  446        intersectionPt = r.point( t * r.distance() );
 
  447        const float distance = r.projectedDistance( intersectionPt );
 
  450        if ( minDistance == -1 || distance < minDistance )
 
  452          triangleIndex = 
static_cast<int>( i / 3 );
 
  453          minDistance = distance;
 
  454          minIntersectionPt = intersectionPt;
 
  459    if ( minDistance != -1 )
 
  461      intPt = minIntersectionPt;
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
Qt3DCore::QAttribute Qt3DQAttribute
 
Qt3DCore::QGeometry Qt3DQGeometry
 
QDataStream & operator<<(QDataStream &out, const QgsFeature &feature)
Writes the feature to stream out. QGIS version compatibility is not guaranteed.
 
#define QgsDebugError(str)
 
Qt3DCore::QAttribute Qt3DQAttribute
 
Qt3DCore::QBuffer Qt3DQBuffer
 
Qt3DCore::QGeometry Qt3DQGeometry