MutableMatrix44D SphericalPlanet::singleDrag(const Vector3D& finalRay) const
{
  // test if initialPoint is valid
  if (_initialPoint.isNan()) return MutableMatrix44D::invalid();

  // compute final point
  const Vector3D origin = _origin.asVector3D();
  MutableVector3D finalPoint = closestIntersection(origin, finalRay).asMutableVector3D();
  if (finalPoint.isNan()) {
    //printf ("--invalid final point in drag!!\n");
    finalPoint = closestPointToSphere(origin, finalRay).asMutableVector3D();
  }

  // compute the rotation axis
  const Vector3D rotationAxis = _initialPoint.cross(finalPoint).asVector3D();

  // compute the angle
  double sinus = rotationAxis.length()/_initialPoint.length()/finalPoint.length();
  const Angle rotationDelta = Angle::fromRadians(-IMathUtils::instance()->asin(sinus));
  if (rotationDelta.isNan()) return MutableMatrix44D::invalid();

  // save params for possible inertial animations
  _lastDragAxis = rotationAxis.asMutableVector3D();
  double radians = rotationDelta._radians;
  _lastDragRadiansStep = radians - _lastDragRadians;
  _lastDragRadians = radians;
  _validSingleDrag = true;

  // return rotation matrix
  return MutableMatrix44D::createRotationMatrix(rotationDelta, rotationAxis);
}
void SphericalPlanet::beginDoubleDrag(const Vector3D& origin,
                                      const Vector3D& centerRay,
                                      const Vector3D& initialRay0,
                                      const Vector3D& initialRay1) const
{
  _origin = origin.asMutableVector3D();
  _centerRay = centerRay.asMutableVector3D();
  _initialPoint0 = closestIntersection(origin, initialRay0).asMutableVector3D();
  _initialPoint1 = closestIntersection(origin, initialRay1).asMutableVector3D();
  _angleBetweenInitialPoints = _initialPoint0.angleBetween(_initialPoint1)._degrees;
  _centerPoint = closestIntersection(origin, centerRay).asMutableVector3D();
  _angleBetweenInitialRays = initialRay0.angleBetween(initialRay1)._degrees;

  // middle point in 3D
  Geodetic2D g0 = toGeodetic2D(_initialPoint0.asVector3D());
  Geodetic2D g1 = toGeodetic2D(_initialPoint1.asVector3D());
  Geodetic2D g  = getMidPoint(g0, g1);
  _initialPoint = toCartesian(g).asMutableVector3D();
}
Effect* SphericalPlanet::createDoubleTapEffect(const Vector3D& origin,
                                               const Vector3D& centerRay,
                                               const Vector3D& tapRay) const
{
  const Vector3D initialPoint = closestIntersection(origin, tapRay);
  if (initialPoint.isNan()) return NULL;

  // compute central point of view
  const Vector3D centerPoint = closestIntersection(origin, centerRay);

  // compute drag parameters
  const IMathUtils* mu = IMathUtils::instance();
  const Vector3D axis = initialPoint.cross(centerPoint);
  const Angle angle   = Angle::fromRadians(- mu->asin(axis.length()/initialPoint.length()/centerPoint.length()));

  // compute zoom factor
  const double height   = toGeodetic3D(origin)._height;
  const double distance = height * 0.6;

  // create effect
  return new DoubleTapRotationEffect(TimeInterval::fromSeconds(0.75), axis, angle, distance);
}
Beispiel #4
0
IntersectionData KDTree::searchNode(KDNode *node, const ray &viewRay, double tmin, double tmax, int curAxis) {
    assert(tmin <= tmax);
    assert(curAxis >= 0 && curAxis < 3);
    if(node->is_leaf) {
        return closestIntersection(node->objects, viewRay);
    }

    int nextAxis = (curAxis + 1) % 3;
    double tSplit = (node->split_pos - viewRay.orig(curAxis)) / viewRay.dir(curAxis);
    KDNode *nearNode, *farNode;
    if(viewRay.orig(curAxis) < node->split_pos) {
        nearNode = node->left;
        farNode = node->right;
    } else {
        nearNode = node->right;
        farNode = node->left;
    }


    if(tSplit > tmax) {
        return searchNode(nearNode, viewRay, tmin, tmax, nextAxis);
    } else if (tSplit < tmin) {
        if(tSplit > 0)
            return searchNode(farNode, viewRay, tmin, tmax, nextAxis);
        else if(tSplit < 0)
            return searchNode(nearNode, viewRay, tmin, tmax, nextAxis);
        else {
            if(viewRay.dir(curAxis) < 0)
                return searchNode(node->left, viewRay, tmin, tmax, nextAxis);
            else
                return searchNode(node->right, viewRay, tmin, tmax, nextAxis);
        }
    } else {
        if(tSplit > 0) {
            IntersectionData test = searchNode(nearNode, viewRay, tmin, tSplit, nextAxis);
            if(test.obj != NULL && test.time < tSplit + EPSILON)
                return test;
            else
                return searchNode(farNode, viewRay, tSplit, tmax, nextAxis);
        } else {
            return searchNode(nearNode, viewRay, tSplit, tmax, nextAxis);
        }
    }
}
MutableMatrix44D SphericalPlanet::doubleDrag(const Vector3D& finalRay0,
                                             const Vector3D& finalRay1) const
{
  // test if initialPoints are valid
  if (_initialPoint0.isNan() || _initialPoint1.isNan())
    return MutableMatrix44D::invalid();

  // init params
  const IMathUtils* mu = IMathUtils::instance();
  MutableVector3D positionCamera = _origin;
  const double finalRaysAngle = finalRay0.angleBetween(finalRay1)._degrees;
  const double factor = finalRaysAngle / _angleBetweenInitialRays;
  double dAccum=0, angle0, angle1;
  double distance = _origin.sub(_centerPoint).length();

  // compute estimated camera translation: step 0
  double d = distance*(factor-1)/factor;
  MutableMatrix44D translation = MutableMatrix44D::createTranslationMatrix(_centerRay.asVector3D().normalized().times(d));
  positionCamera = positionCamera.transformedBy(translation, 1.0);
  dAccum += d;
  {
    const Vector3D point0 = closestIntersection(positionCamera.asVector3D(), finalRay0);
    const Vector3D point1 = closestIntersection(positionCamera.asVector3D(), finalRay1);
    angle0 = point0.angleBetween(point1)._degrees;
    if (ISNAN(angle0)) return MutableMatrix44D::invalid();
  }

  // compute estimated camera translation: step 1
  d = mu->abs((distance-d)*0.3);
  if (angle0 < _angleBetweenInitialPoints) d*=-1;
  translation = MutableMatrix44D::createTranslationMatrix(_centerRay.asVector3D().normalized().times(d));
  positionCamera = positionCamera.transformedBy(translation, 1.0);
  dAccum += d;
  {
    const Vector3D point0 = closestIntersection(positionCamera.asVector3D(), finalRay0);
    const Vector3D point1 = closestIntersection(positionCamera.asVector3D(), finalRay1);
    angle1 = point0.angleBetween(point1)._degrees;
    if (ISNAN(angle1)) return MutableMatrix44D::invalid();
  }

  // compute estimated camera translation: steps 2..n until convergence
  //int iter=0;
  double precision = mu->pow(10, mu->log10(distance)-8.0);
  double angle_n1=angle0, angle_n=angle1;
  while (mu->abs(angle_n-_angleBetweenInitialPoints) > precision) {
    // iter++;
    if ((angle_n1-angle_n)/(angle_n-_angleBetweenInitialPoints) < 0) d*=-0.5;
    translation = MutableMatrix44D::createTranslationMatrix(_centerRay.asVector3D().normalized().times(d));
    positionCamera = positionCamera.transformedBy(translation, 1.0);
    dAccum += d;
    angle_n1 = angle_n;
    {
      const Vector3D point0 = closestIntersection(positionCamera.asVector3D(), finalRay0);
      const Vector3D point1 = closestIntersection(positionCamera.asVector3D(), finalRay1);
      angle_n = point0.angleBetween(point1)._degrees;
      if (ISNAN(angle_n)) return MutableMatrix44D::invalid();
    }
  }
  //if (iter>2) printf("-----------  iteraciones=%d  precision=%f angulo final=%.4f  distancia final=%.1f\n", iter, precision, angle_n, dAccum);

  // start to compound matrix
  MutableMatrix44D matrix = MutableMatrix44D::identity();
  positionCamera = _origin;
  MutableVector3D viewDirection = _centerRay;
  MutableVector3D ray0 = finalRay0.asMutableVector3D();
  MutableVector3D ray1 = finalRay1.asMutableVector3D();

  // drag from initialPoint to centerPoint
  {
    Vector3D initialPoint = _initialPoint.asVector3D();
    const Vector3D rotationAxis = initialPoint.cross(_centerPoint.asVector3D());
    const Angle rotationDelta = Angle::fromRadians( - mu->acos(_initialPoint.normalized().dot(_centerPoint.normalized())) );
    if (rotationDelta.isNan()) return MutableMatrix44D::invalid();
    MutableMatrix44D rotation = MutableMatrix44D::createRotationMatrix(rotationDelta, rotationAxis);
    positionCamera = positionCamera.transformedBy(rotation, 1.0);
    viewDirection = viewDirection.transformedBy(rotation, 0.0);
    ray0 = ray0.transformedBy(rotation, 0.0);
    ray1 = ray1.transformedBy(rotation, 0.0);
    matrix = rotation.multiply(matrix);
  }

  // move the camera forward
  {
    MutableMatrix44D translation2 = MutableMatrix44D::createTranslationMatrix(viewDirection.asVector3D().normalized().times(dAccum));
    positionCamera = positionCamera.transformedBy(translation2, 1.0);
    matrix = translation2.multiply(matrix);
  }

  // compute 3D point of view center
  Vector3D centerPoint2 = closestIntersection(positionCamera.asVector3D(), viewDirection.asVector3D());

  // compute middle point in 3D
  Vector3D P0 = closestIntersection(positionCamera.asVector3D(), ray0.asVector3D());
  Vector3D P1 = closestIntersection(positionCamera.asVector3D(), ray1.asVector3D());
  Geodetic2D g = getMidPoint(toGeodetic2D(P0), toGeodetic2D(P1));
  Vector3D finalPoint = toCartesian(g);

  // drag globe from centerPoint to finalPoint
  {
    const Vector3D rotationAxis = centerPoint2.cross(finalPoint);
    const Angle rotationDelta = Angle::fromRadians( - mu->acos(centerPoint2.normalized().dot(finalPoint.normalized())) );
    if (rotationDelta.isNan()) return MutableMatrix44D::invalid();
    MutableMatrix44D rotation = MutableMatrix44D::createRotationMatrix(rotationDelta, rotationAxis);
    positionCamera = positionCamera.transformedBy(rotation, 1.0);
    viewDirection = viewDirection.transformedBy(rotation, 0.0);
    ray0 = ray0.transformedBy(rotation, 0.0);
    ray1 = ray1.transformedBy(rotation, 0.0);
    matrix = rotation.multiply(matrix);
  }

  // camera rotation
  {
    Vector3D normal = geodeticSurfaceNormal(centerPoint2);
    Vector3D v0     = _initialPoint0.asVector3D().sub(centerPoint2).projectionInPlane(normal);
    Vector3D p0     = closestIntersection(positionCamera.asVector3D(), ray0.asVector3D());
    Vector3D v1     = p0.sub(centerPoint2).projectionInPlane(normal);
    double angle    = v0.angleBetween(v1)._degrees;
    double sign     = v1.cross(v0).dot(normal);
    if (sign<0) angle = -angle;
    MutableMatrix44D rotation = MutableMatrix44D::createGeneralRotationMatrix(Angle::fromDegrees(angle), normal, centerPoint2);
    matrix = rotation.multiply(matrix);
  }

  return matrix;
}
void SphericalPlanet::beginSingleDrag(const Vector3D& origin, const Vector3D& initialRay) const
{
  _origin = origin.asMutableVector3D();
  _initialPoint = closestIntersection(origin, initialRay).asMutableVector3D();
  _validSingleDrag = false;
}
Beispiel #7
0
void Vision::run()
{
    _drawPoints.clear();
    _light.clear();

    if(getSource().x < 0 || getSource().x > _mp->getMapSize().x) return;
    if(getSource().y < 0 || getSource().y > _mp->getMapSize().y) return;

    float fov = Tools::deg2rad(_fov);
    float half_fov = fov / 2;

    float min_fov = Tools::normalizeRad(_heading - half_fov);
    float max_fov = Tools::normalizeRad(_heading + half_fov);

    /* Ray minf; */
    /* minf.start = getSource(); */
    /* minf.end.x = (int)minf.start.x + _raylineMax * std::cos(min_fov); */
    /* minf.end.y = (int)minf.start.y + _raylineMax * std::sin(min_fov); */
    /* DrawTools::drawLine(minf.start, minf.end, sf::Color::Blue, _window); */

    /* Ray maxf; */
    /* maxf.start = getSource(); */
    /* maxf.end.x = (int)maxf.start.x + _raylineMax * std::cos(max_fov); */
    /* maxf.end.y = (int)maxf.start.y + _raylineMax * std::sin(max_fov); */
    /* DrawTools::drawLine(maxf.start, maxf.end, sf::Color::Blue, _window); */

    std::vector<float> _angles;

    _angles.push_back(min_fov);
    _angles.push_back(max_fov);

    for(Wall* wall : _mp->getWalls())
    {
        for(std::size_t i = 0; i < 4; i++)
        {
            float a = std::atan2(wall->points[i].y - getSource().y, wall->points[i].x - getSource().x);

            if(!Tools::radiansBetween(a, min_fov, max_fov)) continue;

            _angles.push_back(Tools::normalizeRad(a) - 0.0001);
            _angles.push_back(Tools::normalizeRad(a));
            _angles.push_back(Tools::normalizeRad(a) + 0.0001);
        }
    }

    std::unique(_angles.begin(), _angles.end());
    std::sort(_angles.begin(), _angles.end());
    auto it = std::find(_angles.begin(), _angles.end(), min_fov);
    std::rotate(_angles.begin(), it, _angles.end());

    Ray ray;
    ray.start = getSource();

    Point intersection;
    for(float angle : _angles)
    {
        ray.end.x = (int)ray.start.x + _raylineMax * std::cos(angle);
        ray.end.y = (int)ray.start.y + _raylineMax * std::sin(angle);

        Point closestIntersection(-1000,-1000);
        for(Wall* wall : _mp->getWalls())
        {
            for(std::size_t i = 0; i < 4; i++)
            {
                if(Tools::getIntersection(ray, wall->segments[i], intersection))
                {
                    if(Tools::distance(intersection, ray.start) < Tools::distance(closestIntersection, ray.start))
                        closestIntersection = intersection;
                }
            }
        }

        _drawPoints.push_back(closestIntersection);
    }

    sf::Vertex tripoint;
    tripoint.position = sf::Vector2f(getSource().x, getSource().y);
    tripoint.color = _colour;
    _light.append(tripoint);

    for(Point& p : _drawPoints)
    {
        tripoint.position = sf::Vector2f(p.x, p.y);
        _light.append(tripoint);
    }

}