/*! Finds the \a minimum_t and \a maximum_t values where \a ray intersects this sphere. Returns true if intersections were found; or false if there is no intersection. If \a minimum_t and \a maximum_t are set to the same value, then \a ray touches the surface of the sphere at a single point. If the t values are negative, then the intersection occurs before the ray's origin point in the reverse direction of the ray. The \a minimum_t and \a maximum_t values can be passed to QRay3D::point() to determine the actual intersection points, as shown in the following example: \code qreal minimum_t, maximum_t; if (sphere.intersection(ray, &minimum_t, &maximum_t)) { qDebug() << "intersections at" << ray.point(minimum_t) << "and" << ray.point(maximum_t); } \endcode \sa intersects(), QRay3D::point() */ bool QSphere3D::intersection(const QRay3D &ray, qreal *minimum_t, qreal *maximum_t) const { QVector3D centerToOrigin = ray.origin() - m_center; qreal term1 = ray.direction().lengthSquared(); qreal term2 = 2.0f * QVector3D::dotProduct(centerToOrigin, ray.direction()); qreal term3 = centerToOrigin.lengthSquared() - m_radius * m_radius; qreal det = term2 * term2 - (4.0f * term1 * term3); if (term1 == 0.0f || det < 0.0f) { *minimum_t = qSNaN(); *maximum_t = qSNaN(); return false; } else if (det == 0.0f) { *minimum_t = *maximum_t = -term2 / (2.0f * term1); } else { qreal sqrtDet = qSqrt(det); qreal t1 = (-term2 - sqrtDet) / (2.0f * term1); qreal t2 = (-term2 + sqrtDet) / (2.0f * term1); if (t1 < t2) { *minimum_t = t1; *maximum_t = t2; } else { *minimum_t = t2; *maximum_t = t1; } } return true; }
cv::Vec3f AreaLight::getIntensity(QVector3D direction) const { float c = QVector3D::dotProduct(direction.normalized(), normal.normalized()) / direction.lengthSquared() * normal.length(); assert(!isnan(c)); if(c < 0) c = 0; return c * intensity; }
/*! \since 5.5 Returns the shortest arc quaternion to rotate from the direction described by the vector \a from to the direction described by the vector \a to. \sa fromDirection() */ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to) { // Based on Stan Melax's article in Game Programming Gems const QVector3D v0(from.normalized()); const QVector3D v1(to.normalized()); float d = QVector3D::dotProduct(v0, v1) + 1.0f; // if dest vector is close to the inverse of source vector, ANY axis of rotation is valid if (qFuzzyIsNull(d)) { QVector3D axis = QVector3D::crossProduct(QVector3D(1.0f, 0.0f, 0.0f), v0); if (qFuzzyIsNull(axis.lengthSquared())) axis = QVector3D::crossProduct(QVector3D(0.0f, 1.0f, 0.0f), v0); axis.normalize(); // same as QQuaternion::fromAxisAndAngle(axis, 180.0f) return QQuaternion(0.0f, axis.x(), axis.y(), axis.z()); } d = std::sqrt(2.0f * d); const QVector3D axis(QVector3D::crossProduct(v0, v1) / d); return QQuaternion(d * 0.5f, axis).normalized(); }
/** * @brief gives Quaternion to transform between 2 vectors * @param v1 first vector * @param v2 second vector * @return Quaternion * * based on http://stackoverflow.com/a/11741520 */ Quaternion Quaternion::between(const QVector3D &v1, const QVector3D &v2) { float kCosTheta = QVector3D::dotProduct(v1, v2); float k = sqrt(v1.lengthSquared() * v2.lengthSquared()); if (kCosTheta / k == -1) { // 180 degree rotation around any orthogonal vector QVector3D other = (abs(QVector3D::dotProduct(v1, QVector3D(1, 0, 0))) < 1.0) ? QVector3D(1, 0, 0) : QVector3D(0, 1, 0); return Quaternion(QQuaternion::fromAxisAndAngle((QVector3D::crossProduct(v1, other).normalized()), 180)); } return Quaternion(kCosTheta + k, QVector3D::crossProduct(v1, v2)).normalized(); }
void Material::fresnelDielectric(const QVector3D &d, const QVector3D &normal, float ni, float nt, QVector<QPair<float, QVector3D> > &rays) { QVector3D n = normal; float ndd = QVector3D::dotProduct(n, d); if (ndd > -Config::Epsilon && ndd < Config::Epsilon) { return ; } if (ndd > 0) { n *= -1; ndd *= -1; } QVector3D r = d - 2.0f * ndd * n; r.normalize(); QVector3D z = (d - ndd * n) * ni / nt; float z2 = z.lengthSquared(); if (z2 >= 1.0f) { rays.append(QPair<float, QVector3D>(1.0f, r)); return ; } QVector3D t = z - qSqrt(1.0f - z2) * n; t.normalize(); float ndt = QVector3D::dotProduct(n, t); float rPar = (nt * ndd - ni * ndt) / (nt * ndd + ni * ndt); float rPerp = (ni * ndd - nt * ndt) / (ni * ndd + nt * ndt); float fr = 0.5f * (rPar * rPar + rPerp * rPerp); rays.append(QPair<float, QVector3D>(fr, r)); rays.append(QPair<float, QVector3D>(1.0f - fr, t)); }
static double squaredDistanceToAABB(const QVector3D& point, const AxisAlignedBox& box) { const QVector3D center = (box.Max() + box.Min()) / 2; const QVector3D half_sz = (box.Max() - box.Min()) / 2; const QVector3D vec(max(0.0, fabs(center.x() - point.x()) - half_sz.x()), max(0.0, fabs(center.y() - point.y()) - half_sz.y()), max(0.0, fabs(center.z() - point.z()) - half_sz.z())); return vec.lengthSquared(); }
void SpringMesh::integrate(int algorithm /*= 0*/) { // Apply internal force and integrate for (auto vertex : mesh->vertSet) { if (fixedPoint.find(vertex->index) != fixedPoint.end()) { continue; } //cout << vertex->in_force.length() << endl; vertex->vel += vertex->in_force * timestep; vertex->pos += 0.5 * (vertex->pre_vel + vertex->vel) * timestep; /*cout << (vertex->in_force * timestep).length() << endl; vector<QVector3D> K0, K1, K2, K3, K4; K0.push_back(vertex->pre_pos); K0.push_back(vertex->pre_vel); K1.push_back(vertex->in_force * timestep); K1.push_back(vertex->in_force); K1 = stateMul(K1, timestep); //K2 = statePlus(K0, K1, 1, 0.5); K2 = stateMul(stateDeriv(K0, statePlus(K0, K1, 1, 0.5)), timestep); K3 = stateMul(stateDeriv(K0, statePlus(K0, K2, 1, 0.5)), timestep); K4 = stateMul(stateDeriv(K0, statePlus(K0, K3)), timestep); K0 = statePlus(K0, statePlus(statePlus(K1, K2, 1, 2), statePlus(K3, K4, 2, 1)) , 1, 1.0 / 6.0); vertex->pos = K0.front(); vertex->vel = K0.back();*/ if ((vertex->pos - sphere_pos).length() < sphere_r) //&& (vertex->pre_pos - sphere_pos).length() > sphere_r) { QVector3D v10 = (vertex->pre_pos - vertex->pos).normalized(); QVector3D cv0 = sphere_pos - vertex->pre_pos; QVector3D h = cv0 - (cv0 * v10) * v10; QVector3D hitp = sphere_pos + h + sqrt(sphere_r * sphere_r - h.lengthSquared()) * v10; QVector3D n = (hitp - sphere_pos).normalized(); /*vertex->pos = hitp + n * 0.01;// +vertex->pos - ((vertex->pos - hitp) * n) * n;*/ vertex->vel = vertex->pre_vel - 2 * (vertex->pre_vel * n) * n; vertex->pos = vertex->pre_pos; //vertex->vel = 0.5 * (vertex->vel + vertex->pre_vel) * friction; } if (vertex->pos.y() < plane_height) { vertex->vel.setY(-vertex->vel.y()); vertex->vel *= friction; vertex->pos.setY(plane_height * 2 - vertex->pos.y()); } } }
float NavigationMath::distanceToClosestPoint( const QVector3D & eye , const QVector3D & center , const QVector3D & point) { const QVector3D ray(center - eye); const QVector3D b(point - eye); const float m = ray.lengthSquared(); // magnitude of ray const float theta = QVector3D::dotProduct(b, ray); if(m == 0.0) return 0.0; return theta / m; // distance from camera to closest point c; }
void View::mouseMoveEvent(QMouseEvent *event) { if(m_isTouchEvent) return; const qreal c_mouseFactor = 0.2; QPoint newPos = event->pos(); if((event->buttons() & Qt::LeftButton) && (event->modifiers() & Qt::ControlModifier)) { QPoint center(width()/2, height()/2); QLineF oldLine( center, m_mousePos); QLineF newLine( center, newPos); qreal angle = oldLine.angleTo(newLine); if(angle > 180.0) angle = angle - 360.0; setRoll( roll() + angle*c_mouseFactor*2 ); } else if(event->buttons() & Qt::LeftButton) { QVector3D diffRotate = QVector3D(newPos.y() - m_mousePos.y(), 0, newPos.x() - m_mousePos.x()) * c_mouseFactor; setRotate( rotate() + diffRotate ); const qreal c_treshold = 15.0; const qreal c_speedFactor = 0.5; if(diffRotate.lengthSquared() > c_treshold) camera()->setAnimatedRotation( -diffRotate*c_speedFactor ); else camera()->setAnimatedRotation( QVector3D() ); } else if((event->buttons() & Qt::MidButton) && isFreeMode()) { QVector3D diffShift = c_mouseFactor* QVector3D(newPos.x() - m_mousePos.x(), newPos.y() - m_mousePos.y(), 0 );//newPos.x() - m_mousePos.x()) * c_mouseFactor; shift(diffShift); } m_mousePos = newPos; }
QT_BEGIN_NAMESPACE /*! \class QSphere3D \brief The QSphere3D class represents a mathematical sphere in 3D space. \since 4.8 \ingroup qt3d \ingroup qt3d::math QSphere3D can be used to represent the bounding regions of objects in a 3D scene so that they can be easily culled if they are out of view. It can also be used to assist with collision testing. \sa QBox3D */ /*! \fn QSphere3D::QSphere3D() Constructs a default sphere with a center() of (0, 0, 0) and radius() of 1. */ /*! \fn QSphere3D::QSphere3D(const QVector3D ¢er, qreal radius) Constructs a sphere with the specified \a center and \a radius. */ /*! \fn QVector3D QSphere3D::center() const Returns the center of this sphere. \sa setCenter(), radius() */ /*! \fn void QSphere3D::setCenter(const QVector3D ¢er) Sets the \a center of this sphere. \sa center(), setRadius() */ /*! \fn qreal QSphere3D::radius() const Returns the radius of this sphere. \sa setRadius(), center() */ /*! \fn void QSphere3D::setRadius(qreal radius) Sets the \a radius of this sphere. \sa radius(), setCenter() */ /*! \fn bool QSphere3D::contains(const QVector3D &point) const Returns true if \a point is contained within the bounds of this sphere; false otherwise. */ /*! Returns true if this sphere intersects \a ray; false otherwise. \sa intersection() */ bool QSphere3D::intersects(const QRay3D &ray) const { QVector3D centerToOrigin = ray.origin() - m_center; qreal term1 = ray.direction().lengthSquared(); qreal term2 = 2.0f * QVector3D::dotProduct(centerToOrigin, ray.direction()); qreal term3 = centerToOrigin.lengthSquared() - m_radius * m_radius; qreal det = term2 * term2 - (4.0f * term1 * term3); return term1 != 0.0f && det >= 0.0f; }
QVector3D Connections::proj(QVector3D a, QVector3D b, QVector3D p) { QVector3D ba = b-a; QVector3D pa = p-a; return a + ba*QVector3D::dotProduct(ba,pa) / ba.lengthSquared(); }