コード例 #1
0
ファイル: segmentgl.cpp プロジェクト: Sammalou/EUMETCastView
void SegmentGL::CalculateSegmentContour(QVector<GLfloat> *positions, float lat_first, float lon_first, float lat_last, float lon_last)
{
    QVector3D pos;

    double sinlatdiff = sin((lat_first-lat_last)/2);
    double sinlondiff = sin((lon_first-lon_last)/2);

    double sinpsi = sqrt(sinlatdiff * sinlatdiff + cos(lat_first)*cos(lat_last)*sinlondiff * sinlondiff);
    double delta = 2*asin(sinpsi);

    int nDelta = 10;
    double deltax = delta / (nDelta - 1);
    double lonpos, latpos, dlon, tc;

    tc = fmod(atan2(sin(lon_first-lon_last)*cos(lat_last), cos(lat_first)*sin(lat_last)-sin(lat_first)*cos(lat_last)*cos(lon_first-lon_last)) , 2 * PI);
    for (int pix = 0 ; pix < nDelta; pix++)
    {
        latpos = asin(sin(lat_first)*cos(deltax * pix)+cos(lat_first)*sin(deltax * pix)*cos(tc));
        dlon=atan2(sin(tc)*sin(deltax * pix)*cos(lat_first),cos(deltax * pix)-sin(lat_first)*sin(latpos));
        lonpos=fmod( lon_first-dlon + PI,2*PI )-PI;

        LonLat2PointRad(latpos, lonpos, &pos, 1.001f);

        positions->append(pos.x());
        positions->append(pos.y());
        positions->append(pos.z());
    }
}
コード例 #2
0
ファイル: Terrain.hpp プロジェクト: splatterlinge/Ununoctium
inline bool Terrain::getHeightAboveGround( const QVector3D & position, float & heightAboveGround ) const
{
	bool ret = getHeight( QPointF(position.x(),position.z()), heightAboveGround );
	if( ret )
		heightAboveGround = position.y() - heightAboveGround;
	return ret;
}
コード例 #3
0
ファイル: RayTracer.cpp プロジェクト: swighton/RayTracer
void RayTracer::RenderScene(Scene * scene, Camera * camera, QImage * buffer)
{
    buffer->fill(QColor(Qt::white).rgb());

    double fov   = camera->GetFOV();
    double fov_2 = fov / 2.0;

    double largestDim = std::max(camera->getXRes(), camera->getYRes());
    double cameraPlaneDist = 0.5 * largestDim * tan((90 - fov_2) * DEGREE_TO_RAD);

    // Assumes camera location is negative
    // TODO: Fix this assumption
    QVector3D cameraPlaneLocation = QVector3D(0, 0, camera->GetZPos() + cameraPlaneDist);

    int y_2 = camera->getYRes() / 2;
    int x_2 = camera->getXRes() / 2;

    QVector3D cp = QVector3D(0, 0, camera->GetZPos());

    for (int y = -y_2; y < y_2; ++y)
    {
        for (int x = - x_2; x < x_2; ++x)
        {
            // Compute the vector from the eye
            QVector3D rayDirection = QVector3D(x, y, cameraPlaneLocation.z());
            QVector3D color = TraceRay(scene, cp, rayDirection, 0);
            buffer->setPixel(x + x_2, y + y_2, qRgb(color.x() * 255, color.y()* 255, color.z() * 255));
        }
    }
}
コード例 #4
0
bool FrustumTest::isSphereInFrustum( QVector3D center, float radius ) const
{
	for( int p = 0; p < 6; p++ )
	if( mFrustum[p].x() * center.x() + mFrustum[p].y() * center.y() + mFrustum[p].z() * center.z() + mFrustum[p].w() <= -radius )
		return false;
	return true;
}
コード例 #5
0
ファイル: Terrain.hpp プロジェクト: splatterlinge/Ununoctium
inline QPoint Terrain::toMap( const QPointF & point ) const
{
	return QPoint(
		floorf( (point.x()-mOffset.x()) * mToMapFactor.width() ),
		floorf( (point.y()-mOffset.z()) * mToMapFactor.height() )
	);
}
コード例 #6
0
ファイル: arcball.cpp プロジェクト: Banus/CV-Playground
void EulerBall::mouseDragged(const QVector3D &currentPoint)
{
    QVector3D delta = currentPoint - v_down;

    phi_now = phi_down - 2.0 * atan(delta.x() / 2.0);
    theta_now = theta_down - 2.0 * atan(delta.y() / 2.0);
}
コード例 #7
0
ファイル: GLGameModel.cpp プロジェクト: rku/Settleboard
void GLGameModel::createFrame()
{
    glNewList(frameDisplayListID, GL_COMPILE);

    for(int i = 0; i < glModelFaces.size(); ++i)
    {
        GLModelFace face = glModelFaces.at(i);

        // draw the model
        glBegin(GL_POLYGON);

        for(int n = 0; n < face.vertexIds.size(); ++n)
        {
            int x = face.vertexIds.at(n);

            if(x < 0 || x >= vertices.size()) continue;

            QVector3D v = vertices.at(x);
            glVertex3f(v.x(), v.y(), v.z());
        }

        glEnd();
    }

    glEndList();
}
コード例 #8
0
/*!
    \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();
}
コード例 #9
0
void SimpleRoadGraph::_generateMeshVertices(ucore::TextureManager* textureManager) {
	ucore::RenderableQuadList* renderable = new ucore::RenderableQuadList(textureManager->get("data/textures/street.jpg"));

	roadGraphEdgeIter ei, eend;
	for (boost::tie(ei, eend) = boost::edges(myRoadGraph); ei != eend; ++ei) {
		SimpleRoadGraphEdge* edge = &myRoadGraph[*ei];

		QVector3D pt1 = myRoadGraph[boost::source(*ei, myRoadGraph)].getPt();
		QVector3D pt2 = myRoadGraph[boost::target(*ei, myRoadGraph)].getPt();

		QVector3D vec = pt2 - pt1;
		vec = QVector3D(-vec.y(), vec.x(), 0.0f);
		vec.normalize();

		QVector3D p0 = pt1 + vec * edge->getWidth() / 2.0f + QVector3D(0, 0, heightAboveGround);
		QVector3D p1 = pt1 - vec * edge->getWidth() / 2.0f + QVector3D(0, 0, heightAboveGround);
		QVector3D p2 = pt2 - vec * edge->getWidth() / 2.0f + QVector3D(0, 0, heightAboveGround);
		QVector3D p3 = pt2 + vec * edge->getWidth() / 2.0f + QVector3D(0, 0, heightAboveGround);
		QVector3D normal = ucore::Util::calculateNormal(p0, p1, p2);

		//renderable2->addQuad(p0, p1, p2, p3, normal, color);
		renderable->addQuad(p0, p1, p2, p3, normal, 0, 1, 0, 1);
	}

	renderables.push_back(renderable);
}
コード例 #10
0
void BulletComponent::update(float delta)
{
    EnemyComponent *enemy = target->getComponent<EnemyComponent>();

    if(enemy != nullptr) {
        destination = target->getPosition();
    }
    QVector3D dir = -(this->getEntity()->getPosition() - destination);
    if(dir.length() < 10) {
        if(enemy != nullptr) {
            enemy->takeDamage(damage);
            QVector3D v = getEntity()->getPosition();
            v.setX(v.x() / 768);
            v.setY(v.y() / 624);
            v.setZ(0);

            FMODManager::getInstance()->setCurrentEvent("event:/hit");
            FMODManager::getInstance()->setEventInstancePosition(v);
            FMODManager::getInstance()->setEventInstanceVolume(0.4);
            FMODManager::getInstance()->setParameterValue("pitch", 0.3 + (qrand() % 200) * 0.001);
            FMODManager::getInstance()->startEventInstance();
        }

        this->getEntity()->release();
    } else {
        dir.normalize();
        this->getEntity()->setPosition(this->getEntity()->getPosition() + dir * speed * delta);
    }
}
コード例 #11
0
Maillage Maillage::Rotation(const double matrice[3][3])
{
    QVector<QVector3D> geom2;
    QVector3D temp;
    for (int i = 0; i < geom.size(); ++i)
    {
         temp = geom.at(i);
         temp.setX(temp.x() * matrice[0][0] + temp.y() * matrice[0][1] + temp.z() * matrice[0][2]);
         temp.setY(temp.x() * matrice[2][0] + temp.y() * matrice[2][1] + temp.z() * matrice[2][2]);
         temp.setZ(temp.x() * matrice[1][0] + temp.y() * matrice[1][1] + temp.z() * matrice[1][2]);
         geom2.append(temp);
    }

    Maillage * sphere = new Maillage(geom2, topo, normales);
    return *sphere;
}
コード例 #12
0
ファイル: glwidget.cpp プロジェクト: satra/brainbundler
GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
    resize(800,800);

    QString filename = qApp->arguments().value(1,"");
    qDebug() << "arglength: " << qApp->arguments().length();
    if (filename == "artificial" || qApp->arguments().length() == 1) {
        qDebug() << "creating new artificial data";
        cons = new ArtificialConnections();

    } else if (arg("nodes")!=""){
        qDebug() << arg("nodes");
        cons = new Connections(arg("nodes"), arg("cons"));
    } else {
        qDebug() << filename;
        cons = new Connections(filename);
    }

    view = new GLfloat[16];
    stuffAlpha = 0.99;
    QVector3D size = cons->max-cons->min;
    float largest = qMax(size.x(),size.y());
    scale = (1/largest)*0.95;
    bg = 1;
    p1 = true;
    p2 = true;

    if (qApp->arguments().indexOf(QRegExp("-writefib"))!=-1) cons->writeBinaryVTK(filename+".fib");

    if (qApp->arguments().indexOf(QRegExp("-screenshot"))!=-1) screenshot(filename+".png");
    if (qApp->arguments().indexOf(QRegExp("-csv"))!=-1) cons->writeCSVs();
    setFocus();

}
コード例 #13
0
ファイル: disk2dROI.cpp プロジェクト: vingtsens/imbricable
QRectF Disk2dROI_QVecQVec3D::boundaryBox()
{
    QVector3D c = d_center->getValue();
    float r = d_radius->getValue();

    return QRectF(c.x()-r,c.y()-r,2*r,2*r);
}
コード例 #14
0
ファイル: model_renderer.cpp プロジェクト: ashuang/sceneview
void ModelRenderer::LoadModelGL() {
  Scene::Ptr scene = GetScene();

  // Clear out any previously loaded model.
  ClearModel();

  // Load the model as a scene graph resource.
  Scene::Ptr model = AssetImporter::ImportFile(GetResources(), model_fname_);

  if (!model) {
    return;
  }

  // Create a node in the main scene graph.
  node_ = scene->MakeGroup(GetBaseNode());

  // Instantiate the model as a child of the newly created node.
  scene->MakeGroupFromScene(node_, model);

  // Scale and translate the model so that it fits inside a unit cube
  // centered at the origin.
  const AxisAlignedBox& box = model->Root()->WorldBoundingBox();
  const QVector3D span = box.Max() - box.Min();
  const float max_span = std::max(std::max(span.x(), span.y()), span.z());
  const double scale_factor = 1.0 / max_span;
  node_->SetScale(QVector3D(scale_factor, scale_factor, scale_factor));
  node_->SetTranslation(-0.5 * scale_factor * (box.Max() + box.Min()));

  GetViewport()->ScheduleRedraw();
}
コード例 #15
0
ファイル: quiddiards.cpp プロジェクト: silencious/Quiddiards
void Quiddiards::drawBall(const Ball& ball){
	glPushMatrix();

	glTranslatef(ball.getX(), ball.getY(), ball.getZ());
	//transpose the matrix because qt uses row-major matrix while opengl use column major matrix
	glMultMatrixf(ball.getRotation().transposed().constData());


	switch (ball.getType()){
	case Ball::QUAFFLE:
		bindTexture("quaffle.jpg");
		break;
	case Ball::BLUDGER:
		bindTexture("bludger.jpg");
		break;
	case Ball::CUEBALL:
		bindTexture("cueball.jpg");
		break;
	case Ball::SNITCH:
		bindTexture("snitch.jpg");
		break;
	default:
		QVector3D color = ball.getColor();
		glColor3f(color.x(), color.y(), color.z());
		break;
	}

	gluSphere(quad, ball.getR(), 16, 16);
	releaseTexture();

	glPopMatrix();
}
コード例 #16
0
void Util_Move_Object_Class::calculIntervalle(QVector3D positionSource, QVector3D positionFinale, int time, Function::Type easingType){
    if (easingType == 0){
        for (int i = 0; i < time/16; i++){ // number of position to calcul
            intervalleTranslate.append(QVector3D((positionFinale.x() - positionSource.x())/time*16, (positionFinale.y()-positionSource.y())/time*16, (positionFinale.z()- positionSource.z())/time*16));
        }
    }
    else if(easingType == 1){

    }
    else if(easingType == 2){

    }
    else if(easingType == 3){

    }
}
コード例 #17
0
ファイル: quiddiards.cpp プロジェクト: silencious/Quiddiards
void Quiddiards::drawGround(){
	glPushMatrix();
	//glTranslatef(center.x(), center.y(), 0);
	int n = Ground::RESO - 1;
	bindTexture("ground.jpg");
	glDisable(GL_CULL_FACE);
	glBegin(GL_QUADS);
	for (int x = 0; x < n; x++){
		for (int y = 0; y < n; y++){
			QVector3D p00 = ground->at(x, y), p10 = ground->at(x + 1, y), p11 = ground->at(x + 1, y + 1), p01 = ground->at(x, y + 1);
			QVector3D n = QVector3D::crossProduct(p11 - p00, p01 - p10);
			glNormal3f(n.x(), n.y(), n.z());
			glTexCoord2f(0, 0);
			glVertex3f(p00.x(), p00.y(), p00.z());
			glTexCoord2f(1, 0);
			glVertex3f(p10.x(), p10.y(), p10.z());
			glTexCoord2f(1, 1);
			glVertex3f(p11.x(), p11.y(), p11.z());
			glTexCoord2f(0, 1);
			glVertex3f(p01.x(), p01.y(), p01.z());
		}
	}
	glEnd();
	glEnable(GL_CULL_FACE);
	releaseTexture();
	glPopMatrix();
}
コード例 #18
0
ファイル: rotatey_control.cpp プロジェクト: denji/antimony
void RotateYControl::drag(QVector3D c, QVector3D d)
{
    Q_UNUSED(c);
    dragValue("x", d.x());
    dragValue("_y", d.y());
    dragValue("z", d.z());
}
コード例 #19
0
ファイル: qglbuilder.cpp プロジェクト: Distrotech/qt3d
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;
}
コード例 #20
0
ファイル: box.cpp プロジェクト: ThomasGoerttler/Graphics
void Box::pinch(QVector3D v, float pinchPlateau)
{
    
    float heightY = m_overallObjectDimensions.y();
    v.setX(v.x() * ( 1.0 - (pinchPlateau * (heightY / 2 + v.y()) / heightY)));
    glVertex3fv(&v[0]);
}
コード例 #21
0
bool FrustumTest::isPointInFrustum( QVector3D point ) const
{
	for( int p = 0; p < 6; p++ )
		if( mFrustum[p].x() * point.x() + mFrustum[p].y() * point.y() + mFrustum[p].z() * point.z() + mFrustum[p].w() <= 0 )
			return false;
	return true;
}
コード例 #22
0
ファイル: loader.cpp プロジェクト: dmastrovito/braingl
bool Loader::loadASC( QVector3D offset )
{
    QString fn = m_fileName.path();

    LoaderFreesurfer* lf = new LoaderFreesurfer();

    if ( !lf->loadASC( fn ) )
    {
        qCritical() << "unable to load: " << fn;
        return false;
    }

    std::vector<float>* points = lf->getPoints();
    std::vector<int> triangles = lf->getTriangles();
    int numPoints = points->size() / 3;
    int numTriangles = triangles.size() / 3;

    TriangleMesh2* mesh = new TriangleMesh2( numPoints, numTriangles );
    for ( int i = 0; i < numPoints; ++i )
    {
        mesh->addVertex( points->at( i * 3 ) + offset.x(), points->at( i * 3 + 1 ) + offset.y(), points->at( i * 3 + 2 ) + offset.z() );
    }
    for ( int i = 0; i < numTriangles; ++i )
    {
        //TODO: Check orientation change (0,2,1)...
        mesh->addTriangle( triangles[i * 3], triangles[i * 3 + 2], triangles[i * 3 + 1] );
    }
    mesh->finalize();
    DatasetMesh* dataset = new DatasetMesh( mesh, fn );
    m_dataset.push_back( dataset );

    return true;
}
コード例 #23
0
ファイル: Terrain.hpp プロジェクト: splatterlinge/Ununoctium
inline QPointF Terrain::toMapF( const QPointF & point ) const
{
	return QPointF(
		(point.x()-(float)mOffset.x()) * mToMapFactor.width(),
		(point.y()-(float)mOffset.z()) * mToMapFactor.height()
	);
}
コード例 #24
0
VectorInputDialog::VectorInputDialog(QWidget *parent, QString title, QString text, QVector3D default_input) :
    QDialog(parent)
{
	_x = new QDoubleSpinBox(this);
	_y = new QDoubleSpinBox(this);
	_z = new QDoubleSpinBox(this);
	_x->setRange(-1000000, 1000000);
	_y->setRange(-1000000, 1000000);
	_z->setRange(-1000000, 1000000);
	_x->setValue(default_input.x());
	_y->setValue(default_input.y());
	_z->setValue(default_input.z());

	QLabel* label = new QLabel(this);
	label->setText(text);

	QGridLayout* layout = new QGridLayout(this);
	layout->addWidget(label, 0, 0, 1, 3);
	layout->addWidget(_x, 1 ,0);
	layout->addWidget(_y, 1 ,1);
	layout->addWidget(_z, 1 ,2);
	QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
	layout->addWidget(buttonBox, 2, 0, 1, 3, Qt::AlignCenter);
	setLayout(layout);

	connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
	connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));

	setWindowTitle(title);
}
コード例 #25
0
ファイル: Terrain.hpp プロジェクト: splatterlinge/Ununoctium
inline QPointF Terrain::fromMap( const QPoint & point ) const
{
	return QPointF(
		point.x()/mToMapFactor.width() + (float)mOffset.x(),
		point.y()/mToMapFactor.height() + (float)mOffset.z()
	);
}
コード例 #26
0
QVector3D CatmulRom::point_on_curve(QVector3D p0, QVector3D p1, QVector3D p2,
                                    QVector3D p3, float t)
{
    QVector3D result;

    float t0 = ((-t + 2.0f) * t - 1.0f) * t * 0.5f;
    float t1 = (((3.0f * t - 5.0f) * t) * t + 2.0f) * 0.5f;
    float t2 = ((-3.0f * t + 4.0f) * t + 1.0f) * t * 0.5f;
    float t3 = ((t - 1.0f) * t * t) * 0.5f;

    result.setX(p0.x() * t0 + p1.x() * t1 + p2.x() * t2 + p3.x() * t3);
    result.setY(p0.y() * t0 + p1.y() * t1 + p2.y() * t2 + p3.y() * t3);
    result.setZ(p0.z() * t0 + p1.z() * t1 + p2.z() * t2 + p3.z() * t3);

    return result;
}
コード例 #27
0
void TrajectoryWidthRenderer::paintImpl()
{
	updateSettings();

	glColor3f(color->getValue().redF(), color->getValue().greenF(),
		color->getValue().blueF());

	glLineWidth(0.1);
	QVector3D prev;
	foreach(auto current, data.vertices)
	{
		if((prev - current.first).length() > level->getValue())
		{
			//glEnd();
			//glLineWidth(0.3);
			//glBegin(GL_LINE_STRIP);
		}
		else
		{
			glLineWidth(scaleLineWidth(current.second));
			glBegin(GL_LINES);
			glVertex3f(current.first.x(), current.first.y(), current.first.z());
			glVertex3f(prev.x(), prev.y(), prev.z());
			glEnd();
		}
		prev = current.first;
	}

	glLineWidth(0);
	glEnd();
}
コード例 #28
0
ファイル: perlingenerator.cpp プロジェクト: glararan/QEditor
float PerlinGenerator::lattice(int ix, int iy, int iz, QVector3D& point)
{
    int _index   = index(ix, iy, iz);
    int gradient = _index * 3;

    return gradientTable[gradient] * point.x() + gradientTable[gradient + 1] * point.y() + gradientTable[gradient + 2] * point.z();
}
コード例 #29
0
void tst_QQuaternion::fromAxisAndAngle()
{
    QFETCH(float, x1);
    QFETCH(float, y1);
    QFETCH(float, z1);
    QFETCH(float, angle);

    // Use a straight-forward implementation of the algorithm at:
    // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
    // to calculate the answer we expect to get.
    QVector3D vector = QVector3D(x1, y1, z1).normalized();
    float sin_a = sinf((angle * M_PI / 180.0) / 2.0);
    float cos_a = cosf((angle * M_PI / 180.0) / 2.0);
    QQuaternion result(cos_a,
                       (vector.x() * sin_a),
                       (vector.y() * sin_a),
                       (vector.z() * sin_a));
    result = result.normalized();

    QQuaternion answer = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle);
    QVERIFY(qFuzzyCompare(answer.x(), result.x()));
    QVERIFY(qFuzzyCompare(answer.y(), result.y()));
    QVERIFY(qFuzzyCompare(answer.z(), result.z()));
    QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));

    answer = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle);
    QVERIFY(qFuzzyCompare(answer.x(), result.x()));
    QVERIFY(qFuzzyCompare(answer.y(), result.y()));
    QVERIFY(qFuzzyCompare(answer.z(), result.z()));
    QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));
}
コード例 #30
0
ファイル: fpmouse.cpp プロジェクト: felipeanchieta/foxhouse
void FPMouse::mouseMove(const QPointF &p)
{

	if (!trackingMouse)
		return;

	std::cerr << "Movendo mouse \n";

	QTime currentTime = QTime::currentTime();
	int msecs = lastTime.msecsTo(currentTime);
	if (msecs) {
		QVector3D vp = mousePosTo3D(p);
		QVector3D currentPos3D = QVector3D(vp.x(), vp.y(), 0);
		double lenSqr = currentPos3D.lengthSquared();

		if (lenSqr >= 1.0)
			currentPos3D.normalize();
		else
			currentPos3D.setZ(sqrt(1.0 - lenSqr));

/*      (lenSqr >= 1.0) ? currentPos3D.normalize() :
						  currentPos3D.setZ(sqrt(1.0 - lenSqr)); */

		axis = QVector3D::crossProduct(lastPos3D, currentPos3D);
		double angle = rad2deg * axis.length();
		velocity = angle / msecs;
		axis.normalize();
		rotation = QQuaternion::fromAxisAndAngle(axis, angle) * rotation;

		lastPos3D = currentPos3D;
		lastTime = currentTime;
	}
}