Вот скриншот того, что я делаю. В настоящее время я застрял в рисовании изогнутых границ в этом прямоугольнике.
Моим первым решением было: нарисовать четверть круга за прямоугольником, но если я отрегулирую непрозрачность фигуры, как вы можете видеть, четверть круга будет показан.
Я знаю, что это довольно просто для вас, ребята, но я не очень силен в математике.
Я попытался повторно использовать вычисленные края дуги и добавить размер границы, но в результате получил вот это.
Я также думаю о кривых Безье как о замене, но я думаю, что более эффективно просто повторно использовать вычисленные вершины и добавлять все недостающие. Кроме того, я не знаю, как вычислять изогнутые точки кривых Безье, а нахождение правильного количества t
было бы очень затратным с вычислительной точки зрения, поэтому я не реализую это.
Вот код, как я рисую внутренний круг, разделенный на четыре части, и я думаю, что могу просто использовать его повторно.
void drawArc(int x, int y,
int startAngle, int endAngle,
uint32_t radiusX, uint32_t radiusY,
int border_x, int border_y,
const rgb color,
const rgb bcX, const rgb bcY,
uint8_t opacity)
{
if (radiusX <= 0 || radiusY <= 0) return;
static constexpr float DTR = 3.14159 / 180;
float cx, cy;
int step;
static std::vector<float> verts;
static std::vector<uint8_t> colors;
if (startAngle < endAngle)
{
step = +1;
++ endAngle;
} else
{
step = -1;
-- endAngle;
}
verts.clear();
colors.clear();
verts.push_back(x);
verts.push_back(y);
colors.push_back(color[R]);
colors.push_back(color[G]);
colors.push_back(color[B]);
colors.push_back(opacity);
while (startAngle != endAngle)
{
cx = cos(DTR * startAngle) * radiusX;
cy = sin(DTR * startAngle) * radiusY;
verts.push_back(x + cx);
verts.push_back(y - cy);
colors.push_back(color[R]);
colors.push_back(color[G]);
colors.push_back(color[B]);
colors.push_back(opacity);
startAngle += step;
}
drawElements(GL_POLYGON, sizeof(arcIndices) / sizeof(arcIndices[0]), GL_FLOAT,
&verts[0], &colors[0], &arcIndices[0]);
if (border_x != 0 || border_y != 0)
{
//remove (x, y)
verts.erase(verts.begin(), verts.begin() + 2);
// float px, py;
//
// px = *(verts.begin() + 0);
// py = *(verts.begin() + 1);
//
// glPointSize(5);
//
// glBegin(GL_POINTS);
//
// glColor3ub(0,0,255);
// glVertex2i(px, py);
//
// px = *(verts.end() - 2);
// py = *(verts.end() - 1);
//
// glColor3ub(255,0,0);
// glVertex2i(px , py);
// glEnd();
//attempting to reuse the edges
//I think the last vertices are opposed
//that's why I got a crossed out lines??
for (int i = 0;i <= 90; ++i)
{
verts.push_back(verts[i + 0] + border_x);
verts.push_back(verts[i + 1] + border_y);
colors.push_back(bcX[R]);
colors.push_back(bcX[G]);
colors.push_back(bcX[B]);
colors.push_back(opacity);
}
//91 = steps from 0-90 degree revolution
//182 = 91 * 2
unsigned int index[182 + 91 * 2];
for (int i = 0;i < 182 + 91 * 2; ++i)
index[i] = i;
drawElements(GL_LINE_LOOP, verts.size() / 2, GL_FLOAT,
&verts[0], &colors[0], &index[0]);
}
}
Изменить:
Разве я не могу просто повторно использовать предварительно вычисленные (x, y) раньше?
Извините за слишком много изображений
Красные точки предварительно рассчитаны (x, y), о которых я говорю, и просто добавляют к этому следующую дугу.
Я собираюсь визуализировать многие из них, поэтому мне нужно как можно эффективнее (без слишком большого использования функций триго).
Обновление:
И вот результат, который я получил от использования stencil buffer
, как предложил Andon M. Coleman:
Кстати, как видите, я пытаюсь эмулировать свой собственный пользовательский интерфейс с помощью OpenGL: D