Задать вопрос
Dyikot
@Dyikot

Как правильно посчитать UV координаты из локальных нормальных?

Пытаюсь нарисовать прямогульник с закругленными углами. Без текстуры все работает.

9adfea301d2a8a7f01f47cf7b31ac92a.PNG

Алгоритм преобразования в UV следующий:
1) Для 9 точек дуги 90 градусов рассчитаны нормальные координаты.
static constexpr FPoint Coordinates[] =
{
	{ 1.000000f,  0.000000f}, { 0.980785f,  0.195090f}, { 0.923880f,  0.382683f},
	{ 0.831470f,  0.555570f}, { 0.707107f,  0.707107f}, { 0.555570f,  0.831470f},
	{ 0.382683f,  0.923880f}, { 0.195090f,  0.980785f}, { 0.000000f,  1.000000f},
};

2) Так как друга лишь 1/4, то я умножаю на 0.5 каждую компоненту.
3) Перевод в нужный квадрант и по необходимости поворот.

// Center
vertices[i++] = createVertex(rect.x + rect.w / 2.0f, rect.y + rect.h / 2.0f, FPoint(0.5, 0.5));

// Top-left
{
	float x = rect.x + radius;
	float y = rect.y + radius;

	for(size_t j = 0; j < arcPoints.size(); j++)
	{
		auto& p = arcPoints[j];
		const float px = x - p.x;
		const float py = y - p.y;
		const float u =	0.5f - Arc::Coordinates[j].x * 0.5f;
		const float v = 0.5f - Arc::Coordinates[j].y * 0.5f;

		vertices[i++] = createVertex(px, py, FPoint(u, v));
	}
}

// Top-right
{
	float x = rect.x + rect.w - radius;
	float y = rect.y + radius;

	for(int j = arcPoints.size() - 1; j >= 0; j--)
	{
		auto& p = arcPoints[j];
		const float px = x + p.x;
		const float py = y - p.y;
		const float u = 0.5f + Arc::Coordinates[j].x * 0.5f;
		const float v = 0.5f - Arc::Coordinates[j].y * 0.5f;

		vertices[i++] = createVertex(px, py, FPoint(u, v));
	}
}

// Bottom-right
{
	float x = rect.x + rect.w - radius;
	float y = rect.y + rect.h - radius;

	for(size_t j = 0; j < arcPoints.size(); j++)
	{
		auto& p = arcPoints[j];
		const float px = x + p.x;
		const float py = y + p.y;
		const float u = 0.5f + Arc::Coordinates[j].x * 0.5f;
		const float v = 0.5f + Arc::Coordinates[j].y * 0.5f;

		vertices[i++] = createVertex(px, py, FPoint(u, v));
	}
}

// Bottom-left
{
	float x = rect.x + radius;
	float y = rect.y + rect.h - radius;

	for(int j = arcPoints.size() - 1; j >= 0; j--)
	{
		auto& p = arcPoints[j];
		const float px = x - p.x;
		const float py = y + p.y;
		const float u = 0.5f - Arc::Coordinates[j].x * 0.5f;
		const float v = 0.5f + Arc::Coordinates[j].y * 0.5f;

		vertices[i++] = createVertex(px, py, FPoint(u, v));
	}
}


Но получается что-то странное.
48cb2d01fe3ec71bb221c813034d0bde.PNG

При этом с эллипсом таких проблем нет:
vertices[0] = createVertex(x, y, FPoint(0.5f, 0.5f));

for(size_t i = 0; i < EllipseNormalizedSize; i++)
{
	float nx = EllipseNormalized[i].x;
	float ny = EllipseNormalized[i].y;
	float u = (nx + 1.0f) * 0.5f;
	float v = (ny + 1.0f) * 0.5f;

	vertices[i + 1] = createVertex(x + radiusX * nx, y + radiusY * ny, FPoint(u, v));
}

9ca781c09f6c2cc4ad112a6ccea75e3a.PNG
  • Вопрос задан
  • 157 просмотров
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик на C++
    12 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++
    9 месяцев
    Далее
  • Академия Эдюсон
    Разработчик игр на Unreal Engine + ИИ
    9 месяцев
    Далее
Решения вопроса 1
opium
@opium
Просто люблю качественно работать
UV нужно считать из реальной позиции вершины в прямоугольнике, а не из нормалей дуги. Замени во всех 4 квадрантах:

const float u = (px - rect.x) / rect.w;
const float v = (py - rect.y) / rect.h;


Нормали дуги описывают направление от центра угла, не положение пикселя в текстуре. Эллипс работал потому что там нормали покрывают весь круг и центрированы в 0,0 — поэтому формула (n+1)*0.5 давала правильный результат. Тут же каждый угол живёт в своём квадранте.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы