Пример #1
0
static inline bool qSameDirection(const QVector3D &a , const QVector3D &b)
{
    bool res = false;
    if (!a.isNull() && !b.isNull())
    {
        float dot = QVector3D::dotProduct(a, b);
        res = qFskCompare((qreal)dot, a.length() * b.length());
    }
    return res;
}
Пример #2
0
static bool qCalculateNormal(int i, int j, int k, QGeometryData &p, QVector3D *vec = 0)
{
    QVector3D norm;
    QVector3D *n = &norm;
    if (vec)
        n = vec;
    bool nullTriangle = false;
    *n = QVector3D::crossProduct(p.vertexAt(j) - p.vertexAt(i),
                                   p.vertexAt(k) - p.vertexAt(j));
    if (qFskIsNull(n->x()))
        n->setX(0.0f);
    if (qFskIsNull(n->y()))
        n->setY(0.0f);
    if (qFskIsNull(n->z()))
        n->setZ(0.0f);
    if (n->isNull())
    {
        nullTriangle = true;
    }
    else
    {
        setNormals(i, j, k, p, *n);
    }
    return nullTriangle;
}
Пример #3
0
/*!
    Returns the distance that this vertex is from a line defined
    by \a point and the unit vector \a direction.

    If \a direction is a null vector, then it does not define a line.
    In that case, the distance from \a point to this vertex is returned.

    \sa distanceToPlane()
*/
qreal QVector3D::distanceToLine
(const QVector3D& point, const QVector3D& direction) const
{
    if (direction.isNull())
        return (*this - point).length();
    QVector3D p = point + dotProduct(*this - point, direction) * direction;
    return (*this - p).length();
}
Пример #4
0
void QMesh::addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &an, const QVector3D &bn, const QVector3D &cn)
{
    QVector3D anorm = an.isNull() ? QVector3D::normal(a, b, c) : an;
    QVector3D bnorm = bn.isNull() ? QVector3D::normal(a, b, c) : bn;
    QVector3D cnorm = cn.isNull() ? QVector3D::normal(a, b, c) : cn;

    if (sm == Smooth) {
        geom->appendSmooth(a, anorm, initv);
        geom->appendSmooth(b, bnorm, initv);
        geom->appendSmooth(c, cnorm, initv);
    } else {
        geom->appendFaceted(a, anorm);
        geom->appendFaceted(b, bnorm);
        geom->appendFaceted(c, cnorm);
    }

    count += 3;
}
Пример #5
0
/*!
    \internal
*/
void QGraphicsRotation3D::applyTo(QMatrix4x4 *matrix) const
{
    qreal angle = this->angle();
    QVector3D axis = this->axis();
    QVector3D origin = this->origin();

    if (angle == 0. || axis.isNull())
        return;

    matrix->translate(origin);
    matrix->rotate(angle, axis.x(), axis.y(), axis.z());
    matrix->translate(-origin);
}
Пример #6
0
void tst_QGLBuilder::addQuadRandom()
{
    QFETCH(int, size);
    QFETCH(int, type);

    int n = qSqrt(size);
    size = n * n;
    QVector3DArray data;
    data.reserve(size);
    for (int i = 0; i < size; ++i)
    {
        // make sure (in face of randomness) we get a planar quad
        QVector3D origin = randVector();
        QVector3D a;
        while (a.isNull())
            a = randVector();
        QVector3D b;
        while (b.isNull())
            b = randVector();
        data.append(origin, a, a+b, b);
    }
    addQuadBenchMarks(data, type);
}
Пример #7
0
void GLGameModel::pointInDirection(QVector3D d)
{
    if(d.isNull())
    {
        setAngleY(0.0);
        return;
    }

    // roate the object to point in direction
    // we only rotate in the x-z plane
    float cos_y = d.normalized().z();
    setAngleY(360.0 * qAcos(cos_y) / (2*M_PI));

    //qDebug() << "pointing to" << d << "with angles" << angleX << angleY << angleZ;
}
Пример #8
0
void Patch::addTri( const QVector3D &a, const QVector3D &b, const QVector3D &c,
                    const QVector3D &n )
{
    QVector3D norm = n.isNull() ? QVector3D::normal( a, b, c ) : n;
    if (sm == Smooth) {
        geom->appendSmooth( a, norm, initv );
        geom->appendSmooth( b, norm, initv );
        geom->appendSmooth( c, norm, initv );
    } else {
        geom->appendFaceted( a, norm );
        geom->appendFaceted( b, norm );
        geom->appendFaceted( c, norm );
    }
    count += 3;
}
Пример #9
0
/*!
    Adds to this section a polygonal face made of triangular sub-faces,
    defined by \a face.  The 0'th vertex is used for the center, while
    the subsequent vertices form the perimeter of the face, which must
    at minimum be a triangle.

    If \a face has less than four vertices this function exits without
    doing anything.

    This function provides functionality similar to the OpenGL mode GL_POLYGON,
    except it divides the face into sub-faces around a \b{central point}.
    The center and perimeter vertices must lie in the same plane (unlike
    triangle fan).  If they do not normals will be incorrectly calculated.

    \image triangulated-face.png

    Here the sub-faces are shown divided by green lines.  Note how this
    function handles some re-entrant (non-convex) polygons, whereas
    addTriangleFan will not support such polygons.

    If required, the center point can be calculated using the center() function
    of QGeometryData:

    \code
    QGeometryData face;
    face.appendVertex(perimeter.center()); // perimeter is a QGeometryData
    face.appendVertices(perimeter);
    builder.addTriangulatedFace(face);
    \endcode

    N sub-faces are generated where \c{N == face.count() - 2}.

    Each triangular sub-face consists of the center; followed by the \c{i'th}
    and \c{((i + 1) % N)'th} vertex.  The last face generated then is
    \c{(center, face[N - 1], face[0]}, the closing face.  Note that the closing
    face is automatically created, unlike addTriangleFan().

    If no normals are supplied in the vertices of \a face, normals are
    calculated as per addTriangle().  One normal is calculated, since a
    face's vertices lie in the same plane.

    Degenerate triangles are skipped in the same way as addTriangles().

    \sa addTriangleFan(), addTriangles()
*/
void QGLBuilder::addTriangulatedFace(const QGeometryData &face)
{
    if (face.count() < 4)
        return;
    QGeometryData f;
    f.appendGeometry(face);
    int cnt = f.count();
    bool calcNormal = !f.hasField(QGL::Normal);
    if (calcNormal)
    {
        QVector3DArray nm(cnt);
        f.appendNormalArray(nm);
    }
    bool skip = false;
    QVector3D norm;
    int k = 0;
    for (int i = 1; i < cnt; ++i)
    {
        int n = i + 1;
        if (n == cnt)
            n = 1;
        if (calcNormal)
        {
            skip = qCalculateNormal(0, i, n, f);
            if (norm.isNull() && !skip)
            {
                norm = f.normalAt(0);
                for (int i = 0; i < cnt; ++i)
                    f.normal(i) = norm;
            }
        }
        if (!skip)
            dptr->addTriangle(0, i, n, f, k);
    }
    dptr->currentNode->setCount(dptr->currentNode->count() + k);
}
Пример #10
0
void Plane3D::setNormal(const QVector3D &normal)
{
    m_vecNormal = normal.isNull() ? normal : normal.normalized();
}
Пример #11
0
// Compute the normal at a specific point in the patch.
// The s and t values vary between 0 and 1.
QVector3D QGLBezierPatch::normal(qreal s, qreal t) const
{
    qreal a[4];
    qreal b[4];
    qreal tx, ty, tz;
    qreal sx, sy, sz;

    // Compute the derivative of the surface in t.
    a[0] = b0(s);
    a[1] = b1(s);
    a[2] = b2(s);
    a[3] = b3(s);
    b[0] = db0(t);
    b[1] = db1(t);
    b[2] = db2(t);
    b[3] = db3(t);
    tx = 0.0f;
    ty = 0.0f;
    tz = 0.0f;
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            tx += a[i] * points[j * 4 + i].x() * b[j];
            ty += a[i] * points[j * 4 + i].y() * b[j];
            tz += a[i] * points[j * 4 + i].z() * b[j];
        }
    }

    // Compute the derivative of the surface in s.
    a[0] = db0(s);
    a[1] = db1(s);
    a[2] = db2(s);
    a[3] = db3(s);
    b[0] = b0(t);
    b[1] = b1(t);
    b[2] = b2(t);
    b[3] = b3(t);
    sx = 0.0f;
    sy = 0.0f;
    sz = 0.0f;
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            sx += a[i] * points[j * 4 + i].x() * b[j];
            sy += a[i] * points[j * 4 + i].y() * b[j];
            sz += a[i] * points[j * 4 + i].z() * b[j];
        }
    }

    // The normal is the cross-product of the two derivatives,
    // normalized to a unit vector.
    QVector3D n = QVector3D::normal(QVector3D(sx, sy, sz), QVector3D(tx, ty, tz));
    if (n.isNull()) {
        // A zero normal may occur if one of the patch edges is zero-length.
        // We correct for this by substituting an overall patch normal that
        // we compute from two of the sides that are not zero in length.
        QVector3D sides[4];
        QVector3D vectors[2];
        sides[0] = points[3] - points[0];
        sides[1] = points[15] - points[3];
        sides[2] = points[12] - points[15];
        sides[3] = points[0] - points[12];
        int i = 0;
        int j = 0;
        vectors[0] = QVector3D(1.0f, 0.0f, 0.0f);
        vectors[1] = QVector3D(0.0f, 1.0f, 0.0f);
        while (i < 2 && j < 4) {
            if (sides[j].isNull())
                ++j;
            else
                vectors[i++] = sides[j++];
        }
        n = QVector3D::normal(vectors[0], vectors[1]);
    }
    return n;
}