void ShaderRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { double x, y, z; x = screen.x; y = kOriginalHeight - screen.y; z = 0.9f; const Math::Vector2d tl = _viewport.getTopLeft(); x = 2 * double(x - tl.getX()) / _viewport.getWidth() - 1.0f; y = 2 * double(y - tl.getY()) / _viewport.getHeight() - 1.0f; z = 2 * z - 1.0f; // Screen coords to 3D coords Math::Vector4d point = Math::Vector4d(x, y, z, 1.0f); point = _mvpMatrix * point; // 3D coords to polar coords Math::Vector3d v = Math::Vector3d(point.x(), point.y(), point.z()); v.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(v.x(), v.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(v.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void BaseRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { // Screen coords to 3D coords Math::Vector3d obj; Math::gluMathUnProject(Math::Vector3d(screen.x, _system->getHeight() - screen.y, 0.9f), _mvpMatrix, frameViewport(), obj); // 3D coords to polar coords obj.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void TinyGLRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { // Screen coords to 3D coords Math::Vector3d obj; Math::gluMathUnProject<float, int>(Math::Vector3d(screen.x, kOriginalHeight - screen.y, 0.9), _cubeModelViewMatrix, _cubeProjectionMatrix, _cubeViewport, obj); // 3D coords to polar coords obj.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void Renderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { double x, y, z; // Screen coords to 3D coords gluUnProject(screen.x, kOriginalHeight - screen.y, 0.9, _cubeModelViewMatrix, _cubeProjectionMatrix, (GLint *)_cubeViewport, &x, &y, &z); // 3D coords to polar coords Math::Vector3d v = Math::Vector3d(x, y, z); v.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(v.x(), v.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(v.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
bool Actor::handleCollisionWith(Actor *actor, CollisionMode mode, Math::Vector3d *vec) const { if (actor->_collisionMode == CollisionOff) { return false; } Model *model1 = getCurrentCostume()->getModel(); Model *model2 = actor->getCurrentCostume()->getModel(); Math::Vector3d p1 = _pos + model1->_insertOffset; Math::Vector3d p2 = actor->_pos + model2->_insertOffset; float size1 = model1->_radius * _collisionScale; float size2 = model2->_radius * actor->_collisionScale; CollisionMode mode1 = mode; CollisionMode mode2 = actor->_collisionMode; if (mode1 == CollisionSphere && mode2 == CollisionSphere) { Math::Vector3d pos = p1 + *vec; float distance = (pos - p2).getMagnitude(); if (distance < size1 + size2) { // Move the destination point so that its distance from the // center of the circle is size1+size2. Math::Vector3d v = pos - p2; v.normalize(); v *= size1 + size2; *vec = v + p2 - p1; collisionHandlerCallback(actor); return true; } } else if (mode1 == CollisionBox && mode2 == CollisionBox) { warning("Collision between box and box not implemented!"); return false; } else { Math::Rect2d rect; Math::Vector3d bboxPos; Math::Vector3d size; float scale; Math::Vector3d pos; Math::Vector3d circlePos; Math::Angle yaw; Math::Vector2d circle; float radius; if (mode1 == CollisionBox) { pos = p1 + *vec; bboxPos = pos + model1->_bboxPos; size = model1->_bboxSize; scale = _collisionScale; yaw = _yaw; circle.setX(p2.x()); circle.setY(p2.y()); circlePos = p2; radius = size2; } else { pos = p2; bboxPos = p2 + model2->_bboxPos; size = model2->_bboxSize; scale = actor->_collisionScale; yaw = actor->_yaw; circle.setX(p1.x() + vec->x()); circle.setY(p1.y() + vec->y()); circlePos = p1; radius = size1; } rect._topLeft = Math::Vector2d(bboxPos.x(), bboxPos.y() + size.y()); rect._topRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y() + size.y()); rect._bottomLeft = Math::Vector2d(bboxPos.x(), bboxPos.y()); rect._bottomRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y()); rect.scale(scale); rect.rotateAround(Math::Vector2d(pos.x(), pos.y()), yaw); if (rect.intersectsCircle(circle, radius)) { Math::Vector2d center = rect.getCenter(); // Draw a line from the center of the rect to the place the character // would go to. Math::Vector2d v = circle - center; v.normalize(); Math::Segment2d edge; // That line intersects (usually) an edge rect.getIntersection(center, v, &edge); // Take the perpendicular of that edge Math::Line2d perpendicular = edge.getPerpendicular(circle); Math::Vector3d point; Math::Vector2d p; // If that perpendicular intersects the edge if (edge.intersectsLine(perpendicular, &p)) { Math::Vector2d direction = perpendicular.getDirection(); direction.normalize(); // Move from the intersection until we are at a safe distance Math::Vector2d point1(p - direction * radius); Math::Vector2d point2(p + direction * radius); if (center.getDistanceTo(point1) < center.getDistanceTo(point2)) { point = point2.toVector3d(); } else { point = point1.toVector3d(); } } else { //if not we're around a corner // Find the nearest vertex of the rect Math::Vector2d vertex = rect.getTopLeft(); float distance = vertex.getDistanceTo(circle); Math::Vector2d other = rect.getTopRight(); float otherDist = other.getDistanceTo(circle); if (otherDist < distance) { distance = otherDist; vertex = other; } other = rect.getBottomLeft(); otherDist = other.getDistanceTo(circle); if (otherDist < distance) { distance = otherDist; vertex = other; } other = rect.getBottomRight(); if (other.getDistanceTo(circle) < distance) { vertex = other; } // and move on a circle around it Math::Vector2d dst = circle - vertex; dst.normalize(); dst = dst * radius; point = (vertex + dst).toVector3d(); } float z = vec->z(); *vec = point - circlePos; vec->z() = z; collisionHandlerCallback(actor); return true; } } return false; }