Beispiel #1
0
void BufferStoreIsoscelesTriangle(GG::GL2DVertexBuffer& buffer, const GG::Pt& ul, const GG::Pt& lr, ShapeOrientation orientation) {
    double x1_, y1_, x2_, y2_, x3_, y3_;
    FindIsoscelesTriangleVertices(ul, lr, orientation, x1_, y1_, x2_, y2_, x3_, y3_);
    buffer.store(x1_,   y1_);
    buffer.store(x2_,   y2_);
    buffer.store(x3_,   y3_);
}
Beispiel #2
0
    /// Fills \a buffer with the ends points for the lines that connect
    /// technologies in \a techs
    void FillArcBuffer(GG::GL2DVertexBuffer& buffer, const std::set<std::string>& techs) {
        for (std::set<std::string>::const_iterator it = techs.begin(); it != techs.end(); ++it) {

            const std::vector<TechTreeLayout::Edge*> edges = m_layout.GetOutEdges(*it);
            //prerequisite edge
            for (std::vector<TechTreeLayout::Edge*>::const_iterator edge = edges.begin();
                 edge != edges.end(); edge++)
            {
                std::vector<std::pair<double, double> > points;
                const std::string& from = (*edge)->GetTechFrom();
                const std::string& to   = (*edge)->GetTechTo();
                // Do not show lines leading to techs
                // we are not showing
                if (techs.find(to) == techs.end()) {
                    continue;
                }
                // Remember what edges we are showing so
                // we can eventually highlight them
                m_edges_to_show[from].insert(to);
                if (!GetTech(from) || !GetTech(to)) {
                    ErrorLogger() << "TechTreeArcs::FillArcBuffer missing arc endpoint tech " << from << "->" << to;
                    continue;
                }
                (*edge)->ReadPoints(points);
                // To be able to draw all the lines in one call,
                // we will draw the with GL_LINES, which means all
                // vertices except the first and the last must occur twice
                for (unsigned i = 0; i < points.size() - 1; ++i){
                    buffer.store(points[i].first, points[i].second);
                    buffer.store(points[i+1].first, points[i+1].second);
                }
            }
        }
        buffer.createServerBuffer();
    }
Beispiel #3
0
void BufferStoreAngledCornerRectangleVertices(GG::GL2DVertexBuffer& buffer, const GG::Pt& ul, const GG::Pt& lr,
                                              int angle_offset, bool upper_left_angled,
                                              bool lower_right_angled, bool connect_bottom_line)
{
    // these are listed in CCW order
    if (connect_bottom_line)
        buffer.store(Value(ul.x),                   Value(lr.y));

    if (lower_right_angled) {
        buffer.store(Value(lr.x) - angle_offset - 3,Value(lr.y));   // don't know why, but - 3 here and the next line seem to make things symmetric top-left and bottom-right
        buffer.store(Value(lr.x),                   Value(lr.y) - angle_offset - 3);
    } else {
        buffer.store(Value(lr.x),                   Value(lr.y));
    }

    buffer.store(Value(lr.x),                       Value(ul.y));

    if (upper_left_angled) {
        buffer.store(Value(ul.x) + angle_offset,    Value(ul.y));
        buffer.store(Value(ul.x),                   Value(ul.y) + angle_offset);
    } else {
        buffer.store(Value(ul.x),                   Value(ul.y));
    }

    buffer.store(Value(ul.x),                       Value(lr.y));
}
Beispiel #4
0
void BufferStorePartlyRoundedRectVertices(GG::GL2DVertexBuffer& buffer, const GG::Pt& ul,
                                          const GG::Pt& lr, int radius, bool ur_round,
                                          bool ul_round, bool ll_round, bool lr_round)
{
    const double PI = 3.141594;

    buffer.store(lr.x, ul.y + radius);

    if (ur_round)
        BufferStoreCircleArcVertices(buffer, GG::Pt(lr.x - 2 * radius, ul.y),
                                     GG::Pt(lr.x, ul.y + 2 * radius), 0.0, PI / 2.0, false);
    else
        buffer.store(lr.x, ul.y);

    if (ul_round)
        BufferStoreCircleArcVertices(buffer, ul, GG::Pt(ul.x + 2 * radius, ul.y + 2 * radius),
                                     PI / 2.0, PI, false);
    else
        buffer.store(ul.x, ul.y);

    if (ll_round)
        BufferStoreCircleArcVertices(buffer, GG::Pt(ul.x, lr.y - 2 * radius),
                                     GG::Pt(ul.x + 2 * radius, lr.y),
                                     PI, 3.0 * PI / 2.0, false);
    else
        buffer.store(ul.x, lr.y);

    if (lr_round)
        BufferStoreCircleArcVertices(buffer, GG::Pt(lr.x - 2 * radius, lr.y - 2 * radius),
                                     lr, 3.0 * PI / 2.0, 0.0, false);
    else
        buffer.store(lr.x, lr.y);

    buffer.store(lr.x, ul.y + radius);
}
    void DrawArrow(GG::Pt begin, GG::Pt end) {
        double head_width = 5.0;
        // A vector (math) of the arrow we wish to draw
        GG::Pt direction = end - begin;
        double length = sqrt(1.0*(Value(direction.x)*Value(direction.x) +
                                  Value(direction.y)*Value(direction.y)));
        if (length == 0) {
            return;
        }

        // The point in the main line of the arrow,
        // paraller to which the head ends
        //          \.
        //           \.
        // --------h-->
        //           /.
        //          /.
        // h is at the handle
        GG::Pt handle;
        // How much to move off the handle to get to
        // the end point of one of the head lines
        GG::X delta_x;
        GG::Y delta_y;

        if (direction.x != 0 && direction.y != 0) {
            // In a skewed arrow we need
            // a bit of geometry to figure out the head
            double x = Value(direction.x);
            double y = Value(direction.y);
            double normalizer = head_width / sqrt(1 + x*x / (y*y));
            delta_x = GG::X(normalizer);
            delta_y = GG::Y(- x / y * normalizer);

            handle = end - GG::Pt((head_width / length) * direction.x, (head_width / length) * direction.y);
        } else if (direction.x == 0) {
            // Vertical arrow
            handle = end;
            handle.y -= boost::math::sign(Value(direction.y))*GG::Y(head_width);
            delta_x = GG::X(head_width);
            delta_y = GG::Y0;
        } else {
            //horizontal arrow
            handle = end;
            handle.x -= boost::math::sign(Value(direction.x)) * GG::X(head_width);
            delta_x = GG::X0;
            delta_y = GG::Y(head_width);
        }

        GG::Pt left_head = handle;
        GG::Pt right_head = handle;

        left_head.x += delta_x;
        left_head.y += delta_y;
        // The other line is on the opposite side of the handle
        right_head.x -=  delta_x;
        right_head.y -= delta_y;

        GG::glColor(GG::CLR_WHITE);
        glLineWidth(2);
        glDisable(GL_TEXTURE_2D);

        GG::GL2DVertexBuffer verts;
        verts.reserve(6);
        verts.store(Value(begin.x),     Value(begin.y));
        verts.store(Value(end.x),       Value(end.y));
        verts.store(Value(end.x),       Value(end.y));
        verts.store(Value(left_head.x), Value(left_head.y));
        verts.store(Value(end.x),       Value(end.y));
        verts.store(Value(right_head.x),Value(right_head.y));
        verts.activate();

        glDrawArrays(GL_LINES, 0, verts.size());

        glEnable(GL_TEXTURE_2D);
    }
Beispiel #6
0
void BufferStoreCircleArcVertices(GG::GL2DVertexBuffer& buffer, const GG::Pt& ul, const GG::Pt& lr,
                                  double theta1, double theta2, bool filled_shape, int num_slices, bool fan)
{
    int wd = Value(lr.x - ul.x), ht = Value(lr.y - ul.y);
    double center_x = Value(ul.x + wd / 2.0);
    double center_y = Value(ul.y + ht / 2.0);
    double r = std::min(wd / 2.0, ht / 2.0);
    const double PI = 3.141594;

    // correct theta* values to range [0, 2pi)
    if (theta1 < 0)
        theta1 += (int(-theta1 / (2 * PI)) + 1) * 2 * PI;
    else if (theta1 >= 2 * PI)
        theta1 -= int(theta1 / (2 * PI)) * 2 * PI;
    if (theta2 < 0)
        theta2 += (int(-theta2 / (2 * PI)) + 1) * 2 * PI;
    else if (theta2 >= 2 * PI)
        theta2 -= int(theta2 / (2 * PI)) * 2 * PI;

    int SLICES = 50;
    if (num_slices <= 0)
        SLICES = std::min(std::max(12, 3 + std::max(wd, ht)), 50);  // this is a good guess at how much to tesselate the circle coordinates (50 segments max)
    else
        SLICES = num_slices;
    const double   HORZ_THETA = (2 * PI) / SLICES;

    static std::map<int, std::vector<double>> unit_circle_coords;
    std::vector<double>& unit_vertices = unit_circle_coords[SLICES];
    bool calc_vertices = unit_vertices.size() == 0;
    if (calc_vertices) {
        unit_vertices.resize(2 * (SLICES + 1), 0.0);
        double theta = 0.0f;
        for (int j = 0; j <= SLICES; theta += HORZ_THETA, ++j) { // calculate x,y values for each point on a unit circle divided into SLICES arcs
            unit_vertices[j*2] = std::cos(-theta);
            unit_vertices[j*2+1] = std::sin(-theta);
        }
    }
    int first_slice_idx = int(theta1 / HORZ_THETA + 1);
    int last_slice_idx = int(theta2 / HORZ_THETA - 1);
    if (theta1 >= theta2)
        last_slice_idx += SLICES;

    if (fan) {  // store a triangle fan vertex list, specifying each vertex just once

        if (filled_shape)   // specify the central vertex first, to act as the pivot vertex for the fan
            buffer.store(static_cast<GLfloat>(center_x),    static_cast<GLfloat>(center_y));
        // if not filled_shape, assumes a previously-specified vertex in the buffer will act as the pivot for the fan

        // point on circle at angle theta1
        double theta1_x = std::cos(-theta1), theta1_y = std::sin(-theta1);
        buffer.store(static_cast<GLfloat>(center_x + theta1_x * r), static_cast<GLfloat>(center_y + theta1_y * r));

        // angles in between theta1 and theta2, if any
        for (int i = first_slice_idx; i <= last_slice_idx + 1; ++i) {
            int X = (i > SLICES ? (i - SLICES) : i) * 2, Y = X + 1;
            buffer.store(static_cast<GLfloat>(center_x + unit_vertices[X] * r), static_cast<GLfloat>(center_y + unit_vertices[Y] * r));
        }

        // theta2
        double theta2_x = std::cos(-theta2), theta2_y = std::sin(-theta2);
        buffer.store(static_cast<GLfloat>(center_x + theta2_x * r), static_cast<GLfloat>(center_y + theta2_y * r));

    } else {    // (not a fan) store a list of complete lines / triangles
        // if storing a filled_shape, the first point in each triangle should be the centre of the arc
        std::pair<GLfloat, GLfloat> first_point = {static_cast<GLfloat>(center_x), static_cast<GLfloat>(center_y)};
        // (not used for non-filled-shape)

        // angles in between theta1 and theta2, if any
        for (int i = first_slice_idx - 1; i <= last_slice_idx; ++i) {
            if (filled_shape) {
                buffer.store(first_point.first, first_point.second);
                // list of triangles: need two more vertices on the arc per starting vertex
            }
            // else: list of lines, with two vertices each

            int X = (i > SLICES ? (i - SLICES) : i) * 2;
            int Y = X + 1;
            buffer.store(static_cast<GLfloat>(center_x + unit_vertices[X] * r), static_cast<GLfloat>(center_y + unit_vertices[Y] * r));

            int next_i = i + 1;
            X = (next_i > SLICES ? (next_i - SLICES) : next_i) * 2;
            Y = X + 1;
            buffer.store(static_cast<GLfloat>(center_x + unit_vertices[X] * r), static_cast<GLfloat>(center_y + unit_vertices[Y] * r));
        }

        // theta2
        if (filled_shape) {
            buffer.store(first_point.first, first_point.second);
        }

        int i = last_slice_idx + 1;
        int X = (i > SLICES ? (i - SLICES) : i) * 2;
        int Y = X + 1;
        buffer.store(static_cast<GLfloat>(center_x + unit_vertices[X] * r), static_cast<GLfloat>(center_y + unit_vertices[Y] * r));

        double theta2_x = std::cos(-theta2), theta2_y = std::sin(-theta2);
        buffer.store(static_cast<GLfloat>(center_x + theta2_x * r), static_cast<GLfloat>(center_y + theta2_y * r));
    }
}
Beispiel #7
0
void BufferStoreRectangle(GG::GL2DVertexBuffer& buffer,
                          const GG::Rect& area,
                          const GG::Rect& border_thickness)
{
        GG::X inner_x1(area.ul.x + border_thickness.ul.x);
        GG::Y inner_y1(area.ul.y + border_thickness.ul.y);
        GG::X inner_x2(area.lr.x - border_thickness.lr.x);
        GG::Y inner_y2(area.lr.y - border_thickness.lr.y);

        buffer.reserve(14);
        buffer.store(inner_x2, inner_y1);
        buffer.store(area.lr.x, area.ul.y);
        buffer.store(inner_x1, inner_y1);
        buffer.store(area.ul.x, area.ul.y);
        buffer.store(inner_x1, inner_y2);
        buffer.store(area.ul.x, area.lr.y);
        buffer.store(inner_x2, inner_y2);
        buffer.store(area.lr.x, area.lr.y);
        buffer.store(inner_x2, inner_y1);
        buffer.store(area.lr.x, area.ul.y);

        buffer.store(inner_x2, inner_y1);
        buffer.store(inner_x1, inner_y1);
        buffer.store(inner_x1, inner_y2);
        buffer.store(inner_x2, inner_y2);
}