/*! \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(); }
void PerspectiveProjection::setup(QVector3D position, QVector3D view, QVector3D up, qreal aspectRatio) { qreal hfov = qTan(m_fov * 0.5); m_origin = position; m_xVector = QVector3D::normal(up, view) * (hfov * aspectRatio * 2.0); m_yVector = -up.normalized() * (hfov * 2.0); m_corner = view.normalized() - (m_xVector * 0.5) - (m_yVector * 0.5); }
void Quiddiards::keyPressEvent(QKeyEvent *event){ switch (event->key()) { case Qt::Key_F2: actStart(); break; case Qt::Key_P: actPause(); break; case Qt::Key_Escape: case Qt::Key_Q: close(); break; case Qt::Key_Space: case Qt::Key_Enter: case Qt::Key_Return: break; case Qt::Key_W:{ /* forward cueball */ QVector3D n = -eye; n.setZ(0); n.normalize(); n += cueball.getVelocity(); if (n.length() > cueball.getSpeed()){ n = cueball.getSpeed()*n.normalized(); } cueball.setVelocity(n); break; } case Qt::Key_A: phi += 10; break; case Qt::Key_S:{ QVector3D n = eye; n.setZ(0); n.normalize(); n += cueball.getVelocity(); if (n.length() > cueball.getSpeed()){ n = cueball.getSpeed()*n.normalized(); } cueball.setVelocity(n); break; } case Qt::Key_D: phi -= 10; break; case Qt::Key_Tab: //camera = CAMERA((camera + 1) % 2); break; default: return; } update(); }
QVector3D Bird::limit(QVector3D vec, float limit) { QVector3D temp; if(vec.length() < limit) //if(vec.x() < limit && vec.y() < limit && vec.z() < limit ) { return vec; } else { /*if(vec.x() > limit ) { vec.setX(limit); } if(vec.y() > limit) { vec.setY(limit); } if(vec.z() > limit) { vec.setZ(limit); }*/ temp = vec.normalized(); //temp*= limit; return temp; } }
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; }
void Camera::setMotionAdjustment(const QVector3D& vector) { Q_D(Camera); if (d->motionAdjustment != vector) { d->motionAdjustment = vector; if (vector.x() == 0.0f && vector.y() == 0.0f) { // If the vector is centered, then don't perform any rotations. d->motionQuaternion = QQuaternion(); } else { // Determine the pan and tilt angles from the vector. QVector3D view = -vector.normalized(); if (view.z() < 0.0f) view = -view; qreal xangle = asin(view.x()) * 180.0f / M_PI; qreal yangle = asin(-view.y()) * 180.0f / M_PI; // Construct the pan and tilt quaternions. if (qFuzzyIsNull(xangle)) d->motionQuaternion = tilt(yangle); else if (qFuzzyIsNull(yangle)) d->motionQuaternion = pan(xangle); else d->motionQuaternion = tilt(yangle) * pan(xangle); } emit viewChanged(); } }
void GlobalShaderUniforms::setDirectionalLight(const QVector3D &vec) { QVector3D temp = vec.normalized(); if ( m_vecDirectionalLight == temp ) return; m_vecDirectionalLight = temp; m_bNeedsUpload = true; }
void GravityDemo::init() { Scene::Instance().addCamera(QVector3D(-3740.57, 0.225304, 2.12885), QVector3D(0.987211, 0.0453626, -0.152828)); Scene::Instance().getCurrentCamera()->farClip = 100000.0; Scene::Instance().getCurrentCamera()->updatePerspective(); float sunDistance = 1.496e+8; float moonDistance = 356400; sunDistance /= 4.0; moonDistance /= 4.0; SimPlanet * moon = new SimPlanet("Earth/MoonMap_2500x1250.jpg", QVector3D(-sunDistance,0,moonDistance), 1737.1); moon->mass = 7.3477e+22; QVector3D moonDir = QVector3D(moonDistance - sunDistance, 0, 0) - moon->position; // moon->velocity = 1022 * moonDir.normalized(); moon->velocity = 30 * moonDir.normalized(); planets.push_back(moon); SimPlanet * earth = new SimPlanet("earthmap1k.jpg", QVector3D(-sunDistance,0,0), 6371); earth->mass = 5.9736e+24; QVector3D earthDir = QVector3D(0, 0, -sunDistance) - earth->position; // moon->velocity = 1022 * moonDir.normalized(); earth->velocity = 3 * earthDir.normalized(); planets.push_back(earth); SimPlanet * sun = new SimPlanet("Planets/sun.jpg", QVector3D(0,0,0), 6.96342e+5); sun->mass = 1.9891e+30; planets.push_back(sun); foreach (SimPlanet * planet, planets) planet->init(); simulationTimer = new QTimer(); connect(simulationTimer, SIGNAL(timeout()), this, SLOT(simulatePlanets())); simulationTimer->start(0); Scene::Instance().initSkyShaderSphere("spheremaps/nasa-sky.jpg"); }
/*! Returns true if this triangle contains \a point; false otherwise. To contain the \a point means that: \list \li the point lies on the same plane as the triangle, and \li the point \list \li lies either wholly within the triangle, or \li lies on one of the sides, or \li coincides with one of the 3 vertices \endlist \endlist \sa intersects() */ bool QTriangle3D::contains(const QVector3D &point) const { // Check if the point is on the triangle's plane first. QVector3D normal = QVector3D::crossProduct(m_q - m_p, m_r - m_q); if (!qFuzzyIsNull(float(QVector3D::dotProduct(normal.normalized(), m_p - point)))) return false; // Compute the barycentric co-ordinates and use them to determine // if the point is within the triangle. return uvInTriangle(uv(point)); }
Connection::Connection( QVector3D fn, QVector3D diff, float v ) : fn( fn ), diff( diff ), v( v ) { QVector3D diffn = diff.normalized(); r=qAbs(diffn.x()); g=qAbs(diffn.y()); b=qAbs(diffn.z()); }
/*! Creates a normalized quaternion that corresponds to rotating through \a angle degrees about the specified 3D \a axis. \sa getAxisAndAngle() */ QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle) { // Algorithm from: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56 // We normalize the result just in case the values are close // to zero, as suggested in the above FAQ. float a = qDegreesToRadians(angle / 2.0f); float s = std::sin(a); float c = std::cos(a); QVector3D ax = axis.normalized(); return QQuaternion(c, ax.x() * s, ax.y() * s, ax.z() * s).normalized(); }
/*! Creates a normalized quaternion that corresponds to rotating through \a angle degrees about the specified 3D \a axis. */ QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, qreal angle) { // Algorithm from: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56 // We normalize the result just in case the values are close // to zero, as suggested in the above FAQ. qreal a = (angle / 2.0f) * M_PI / 180.0f; qreal s = qSin(a); qreal c = qCos(a); QVector3D ax = axis.normalized(); return QQuaternion(c, ax.x() * s, ax.y() * s, ax.z() * s).normalized(); }
void SS3DWidget::camMoveAroundCenter(const QVector3D& tt) { QVector3D xv = QVector3D::crossProduct((m_cam_center - m_cam_eye), m_cam_up).normalized(); QVector3D yv = QVector3D::crossProduct(xv, (m_cam_center - m_cam_eye)).normalized(); QVector3D xyTrans = xv * tt.x() + yv * tt.y(); double r = (m_cam_eye - m_cam_center).length() * (1 - 0.1 * tt.z()) / (m_cam_eye + xyTrans - m_cam_center).length(); QVector3D new_cam_eye = (m_cam_eye + xyTrans - m_cam_center) * r + m_cam_center; m_cam_up = yv.normalized(); if(!qFuzzyCompare((new_cam_eye - m_cam_center).normalized(), m_cam_up.normalized())) m_cam_eye = new_cam_eye; }
void QGLXCamera::setForward(QVector3D dir) { m_direction = dir.normalized(); m_verticalAngle = asin(m_direction.y()); m_horizontalAngle = acos(m_direction.z() / cos(m_verticalAngle)); m_right = QVector3D( sin(m_horizontalAngle - M_PI/2.0), 0, cos(m_horizontalAngle - M_PI/2.0) ).normalized(); m_compileViewMatrix(); }
void GLWidget::mouseMoveEvent(QMouseEvent *event) { if ((event->buttons() & Qt::RightButton) && dragging) { double xtrans = (event->pos().x() - lastPoint.x()) / 1000.0; double ytrans = -(event->pos().y() - lastPoint.y()) / 1000.0; //Qt y-coord is inverted QVector4D trans(xtrans, ytrans, 0, 1); QVector4D worldTrans = trans * camera->getCameraMatrix(); if(cameraActive) { this->camera->setpointOfInterest(scene->getMainBoat()->getPosition()); this->camera->translate(-worldTrans.x(), -worldTrans.y(), -worldTrans.z()); updateGL(); } else { emit translate(worldTrans.x(), worldTrans.y(), worldTrans.z()); } } // if ((event->buttons() & Qt::LeftButton) && dragging) { //Here we implement the trackball. Sample two points on the sphere and //calculate their angle to use as the rotation. //normalize to intervals [-1,1] double lastx = clampUnit(lastPoint.x() / (this->size().width() / 2.0) - 1.0); double lasty = clampUnit(-(lastPoint.y() / (this->size().height() / 2.0) - 1.0)); double newx = clampUnit(event->pos().x() / (this->size().width() / 2.0) - 1.0); double newy = clampUnit(-(event->pos().y() / (this->size().height() / 2.0) - 1.0)); //Project the two points into the sphere (or the hyperbolic plane) QVector3D v1(lastx, lasty, z(lastx, lasty)); v1.normalize(); QVector3D v2(newx, newy, z(newx, newy)); v2.normalize(); //Determine the normal of the generated plane through the center of the sphere QVector3D normal = QVector3D::crossProduct(v1, v2); double theta = acos(QVector3D::dotProduct(v1, v2)) / 3.0; //angle/2.0, because the quats double cover SO(3) QQuaternion newRot = QQuaternion(cos(theta/2.0), sin(theta/2.0) * normal.normalized()); QQuaternion cameraQuat = M4toQuat(camera->getCameraMatrix()); QQuaternion worldQuat = cameraQuat.conjugate() * newRot * cameraQuat; if(cameraActive) { this->camera->rotate(newRot); updateGL(); } else { emit rotate(&worldQuat); } // } }
cv::Vec3f BlinnMaterial::brdf(const HitRecord &hit, QVector3D direction) const { QVector3D normal = hit.getSurfaceNormal(); normal.normalize(); QVector3D wo = -hit.getRay().getDirection().normalized(); QVector3D wi = -direction.normalized(); if(signum(QVector3D::dotProduct(normal, wo)) != signum(QVector3D::dotProduct(normal, wi))) { return cv::Vec3f(); } if(QVector3D::dotProduct(normal, wo) < 0) normal *= -1; QVector3D wh = wi + wo; wh.normalize(); return kd * (1 / M_PI) + ks * D(wh, normal) * G(wi, wo, normal) / (4 * QVector3D::dotProduct(wo, normal) * QVector3D::dotProduct(wi, normal)); }
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; }
cv::Vec3f AreaLight::getIntensity(const HitRecord & hit, QVector3D &direction, const Intersectable &scene, const Sample &sample) const { QVector3D at = hit.getIntersectingPoint().toVector3DAffine(); QPointF p = sample.getSample(); QVector3D lightLocation = getLocation(p); direction = at - lightLocation; HitRecord shadowHit = scene.intersect(Ray(at, -direction.normalized(), EPSILON, direction.length() - EPSILON)); if(shadowHit.intersects() && &shadowHit.getMaterial() != this) { return cv::Vec3f(); } else { return getIntensity(direction); } }
/*! \since 5.5 Constructs the quaternion using specified forward direction \a direction and upward direction \a up. If the upward direction was not specified or the forward and upward vectors are collinear, a new orthonormal upward direction will be generated. \sa fromAxes(), rotationTo() */ QQuaternion QQuaternion::fromDirection(const QVector3D &direction, const QVector3D &up) { if (qFuzzyIsNull(direction.x()) && qFuzzyIsNull(direction.y()) && qFuzzyIsNull(direction.z())) return QQuaternion(); const QVector3D zAxis(direction.normalized()); QVector3D xAxis(QVector3D::crossProduct(up, zAxis)); if (qFuzzyIsNull(xAxis.lengthSquared())) { // collinear or invalid up vector; derive shortest arc to new direction return QQuaternion::rotationTo(QVector3D(0.0f, 0.0f, 1.0f), zAxis); } xAxis.normalize(); const QVector3D yAxis(QVector3D::crossProduct(zAxis, xAxis)); return QQuaternion::fromAxes(xAxis, yAxis, zAxis); }
//----------------------------------------------------------------------------------------- void TestTransformation::wheel(int delta) { if (CCamera* pCamera = m_pView->getCurrentCamera()) { QVector3D viewVector = pCamera->getEyePosition() - pCamera->getCenter(); real zoomMag = viewVector.length(); real zoomIncrement = -real(delta) / 100.; if (!qFuzzyIsNull(zoomIncrement)) { zoomMag += zoomIncrement; if (zoomMag < 1.) zoomMag = 1.; CRay viewLine(pCamera->getCenter(), viewVector.normalized()); pCamera->setEyePosition(viewLine.point(zoomMag)); } } }
void QGLXCamera::setView(QVector3D pos, QVector3D target, QVector3D m_up) { m_position = pos; m_direction = (target - pos).normalized(); this->m_up = m_up.normalized(); m_verticalAngle = asin(m_direction.y()); m_horizontalAngle = acos(m_direction.z() / cos(m_verticalAngle)); m_right = QVector3D( sin(m_horizontalAngle - M_PI/2.0), 0, cos(m_horizontalAngle - M_PI/2.0) ).normalized(); m_compileViewMatrix(); }
Path Renderer::createPath(const Ray& primaryRay, const Intersectable &scene, const Sample pathSamples[], cv::Vec3f alpha, int pathLength, float russianRoulettePdf, int russianRouletteStartIndex) { Path result; HitRecord hit = scene.intersect(primaryRay); for(int i = 0; i < pathLength; i++) { if(!hit.intersects()) return result; float pdf; cv::Vec3f brdf; QVector3D outDirection = hit.getMaterial().outDirection(hit, pathSamples[i], pdf, brdf); if(hit.getMaterial().emitsLight()) { result.alphaValues.push_back(alpha); result.hitRecords.push_back(hit); return result; } else if(hit.getMaterial().isSpecular()) { //Try not to terminate on refractive vertices if(i == pathLength - 1 && pathLength < MAX_DEPTH) pathLength++; } else { result.alphaValues.push_back(alpha); result.hitRecords.push_back(hit); if(pdf == 0 || alpha == cv::Vec3f()) return result; float cos = fabs(QVector3D::dotProduct(outDirection.normalized(), hit.getSurfaceNormal().normalized())); assert(cos >= 0 && !isnan(pdf)); assert(pdf > 0 && !isnan(pdf)); alpha = alpha.mul(brdf) * (cos / pdf); if(i > russianRouletteStartIndex) alpha *= (1 / russianRoulettePdf); } hit = scene.intersect(Ray(hit.getIntersectingPoint(), outDirection)); } return result; }
void QCamera::translate( const QVector3D& vLocal, CameraTranslationOption option ) { QVector3D viewVector = viewCenter() - position(); // From "camera" position to view center // Calculate the amount to move by in world coordinates QVector3D vWorld; if ( !qFuzzyIsNull( vLocal.x() ) ) { // Calculate the vector for the local x axis QVector3D x = QVector3D::crossProduct(viewVector, upVector()).normalized(); vWorld += vLocal.x() * x; } if ( !qFuzzyIsNull( vLocal.y() ) ) vWorld += vLocal.y() * upVector(); if ( !qFuzzyIsNull( vLocal.z() ) ) vWorld += vLocal.z() * viewVector.normalized(); // Update the camera position using the calculated world vector setPosition(position() + vWorld); // May be also update the view center coordinates if ( option == TranslateViewCenter ) setViewCenter(viewCenter() + vWorld); // Refresh the camera -> view center vector viewVector = viewCenter() - position(); // Calculate a new up vector. We do this by: // 1) Calculate a new local x-direction vector from the cross product of the new // camera to view center vector and the old up vector. // 2) The local x vector is the normal to the plane in which the new up vector // must lay. So we can take the cross product of this normal and the new // x vector. The new normal vector forms the last part of the orthonormal basis QVector3D x = QVector3D::crossProduct(viewVector, upVector()).normalized(); setUpVector(QVector3D::crossProduct(x, viewVector).normalized()); }
QVector3D NavigationMath::cameraWithPointInView( const QVector3D & eye , const QVector3D & center , const QVector3D & up , const float fovy , const float aspect , const QVector3D & point) { const QVector3D ray(center - eye); const QVector3D n(ray.normalized()); // retrieve u and v for orthonormal basis const QVector3D v(QVector3D::crossProduct(n, up).normalized()); const QVector3D u(QVector3D::crossProduct(v, n).normalized()); // get both field of view vectors const float vFov(rad(fovy)); //const float hFov(2.0 * atan(tan(vFov * 0.5) * aspect)); // closest point c const QVector3D c = eye + ray * distanceToClosestPoint(eye, center, point); // project bc = t to u and v using scalar projection const QVector3D t = point - c; const float uPart = abs(QVector3D::dotProduct(t, u)); const float vPart = abs(QVector3D::dotProduct(t, v)) / aspect; // retrieve max distance to camera with required fov for the bigger part const float p = qMax<float>(uPart, vPart); // required distance from c to new camera position const float a = p / tan(vFov * 0.5); return c - a * n; }
QVector3D HdrImage::lightDir() const { if (!_data) { qWarning() << "Hdr not loaded" << __DEBUG_INFO__; return QVector3D(1, 0, 0); } int n = size().width()*size().height(); int maxId = 0; float max = 0; switch (_format) { case Format_RGB32F: { Rgb32F *rgb32f = reinterpret_cast<Rgb32F*>(_data); for (int i=0; i<n; i++) { float sum = rgb32f[i].r+rgb32f[i].g+rgb32f[i].b; if (sum>max) { max = sum; maxId = i; } } break; } case Format_RGBE8: default: { Rgba8 *rgba8 = reinterpret_cast<Rgba8*>(_data); Rgb32F rgb32f; for (int i=0; i<n; i++) { rgbeToFloat(rgba8[i], rgb32f); float sum = rgb32f.r+rgb32f.g+rgb32f.b; if (sum>max) { max = sum; maxId = i; } } break; } } QVector3D light; int section = maxId/(n/6); int pix = maxId - section*n/6; float x = pix % size().width(); float y = pix / size().width(); x /= size().width(); y /= size().height()/6; switch (section) { case 0: // -x light = {-1, x, 1-y}; break; case 1: // +x light = {1, x, 1-y}; break; case 2: // -y light = {x, 1, 1-y}; break; case 3: // +y light = {x, -1, 1-y}; break; case 4: // -z light = {x, 1-y, 1}; break; case 5: // +z light = {x, 1-y, -1}; break; } return light.normalized(); }
Ray::Ray(const QVector3D &o, const QVector3D &d) : origin(o) , direction(d.normalized()) { }
float MathUtil::GetAngleBetweenRadians(const QVector3D & v1, const QVector3D & v2) { return acosf(QVector3D::dotProduct(v1.normalized(), v2.normalized())); }
float NavigationMath::angle( const QVector3D & a , const QVector3D & b) { return acos(QVector3D::dotProduct(a.normalized(), b.normalized())); }
QQuaternion QCamera::tiltRotation(float angle) const { QVector3D viewVector = viewCenter() - position(); QVector3D xBasis = QVector3D::crossProduct(upVector(), viewVector.normalized()).normalized(); return QQuaternion::fromAxisAndAngle( xBasis, -angle ); }
void Camera::setUp(QVector3D const& _up) { up_ = _up.normalized(); }