Russian Qt Forum
Ноябрь 23, 2024, 07:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Алгоритм наложения тайлов на сферу (проекция меркатора)  (Прочитано 22010 раз)
spirits25
Гость
« Ответ #15 : Март 13, 2013, 16:12 »

Да. У меня декартовые координаты сферы (переведённые из сферических координат) от -1 до 1. А текстурные координаты от 0 до 1.

Я для каждого тайла (текстуры) строю часть сферы (именно поэтому у меня на полюсах дырки, так как в меркаторе там нет ничего).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Март 13, 2013, 17:10 »

Да. У меня декартовые координаты сферы (переведённые из сферических координат) от -1 до 1.
Та как будто OpenGL понимает вертекс и в полярных координатах! Улыбающийся Ясно что x, y, z

А текстурные координаты от 0 до 1.
Я для каждого тайла (текстуры) строю часть сферы (именно поэтому у меня на полюсах дырки, так как в меркаторе там нет ничего).
Строите часть сферы (все углы в радианах)

Код
C++ (Qt)
struct UV {
qreal u, v;
};
 
UV GetUV( qreal angleU, qreal angleV )
{
 UV uv;
 uv.u = angleU / (M_PI * 2);
 uv.v = angleV / (M_PI / 2) + 0.5;
 return uv;
}
 
void BuildSpherePart(
                         qreal startU, qreal stepU, qreal int numU,   // широта (0..2*PI)
                         qreal startV, qreal stepV, qreal int numV,   // долгота (-PI/2 .. +PI/2)
                         // ... др параметры
{
// находим диапазон
  UV minUV = GetUV(startU, startV);
  UV maxUV = GetUV(startU + stepU * (numU - 1), startV + stepV * (numV - 1));
  minUV.v = Mercator2SphereAnalytic(minUV.v);  
  maxUV.v = Mercator2SphereAnalytic(maxUV.v);  
 
// вычисляем UV координаты для сферы
 for (int i =  0; i < numU; ++i)
  for (int j =  0; j < numV; ++j) {
 
    qreal angleU = startU + stepU * i;
    qreal angleV = startV + stepV * j;
 
   // добавляем вертекс
    qreal y = sin(angleV);
    qreal len = sqrt(1 - y * y);
    qreal x = cos(angleU) * len;
    qreal z = sin(angleU) * len;
    prim.appendVertex(QPoint3D(x, y, z) * radius);
 
   // получаем сферические UV
    UV uv = GetUV(angleU, angleV);
 
   // получаем V меркатора
    uv.v = Mercator2SphereAnalytic(maxUV.v);  
 
  // нормируем UV
    uv.u = (uv.u - minUV.u) / (maxUV.u - minUV.u);
    uv.v = (uv.c - minUV.v) / (maxUV.v - minUV.v);
    prim.appendTexCoord(QVector2D(UV.u, UV.v));
 }
}
}
« Последнее редактирование: Март 13, 2013, 17:16 от Igors » Записан
spirits25
Гость
« Ответ #17 : Март 21, 2013, 11:29 »

Строите часть сферы (все углы в радианах)

Сделал по вашему примеру. Сфера строится правильно, но вот текстура накладывается неверно.

Немного изменил код, так как в нём были неточности, и соответственно подстроил под мой случай, получилось:
Код:
QGLSceneNode* Earth::BuildSpherePart(qreal startU, qreal stepU, int numU,   // широта (0..2*PI)
                     qreal startV, qreal stepV, int numV   // долгота (-PI/2 .. +PI/2)
                    )
{
// находим диапазон
    UV minUV = GetUV(startU, startV);
    UV maxUV = GetUV(startU + stepU * (numU - 1), startV + stepV * (numV - 1));
    minUV.v = Mercator2SphereAnalytic(minUV.v);
    maxUV.v = Mercator2SphereAnalytic(maxUV.v);

    QGLBuilder tempBuilder;
    QGeometryData prim;

// вычисляем UV координаты для сферы
    for (int i =  0; i < numU; ++i)
    {
        for (int j =  0; j < numV; ++j)
        {
            qreal angleU = startU + stepU * i;
            qreal angleV = startV + stepV * j;

            // добавляем вертекс
            qreal y = sin(angleV);
            qreal len = sqrt(1 - y * y);
            qreal x = cos(angleU) * len;
            qreal z = sin(angleU) * len;
            prim.appendVertex(QVector3D(x, y, z) * a);
            prim.appendNormal(QVector3D(x, y, z) * a);

            // получаем сферические UV
            UV uv = GetUV(angleU, angleV);

            // получаем V меркатора
            uv.v = Mercator2SphereAnalytic(maxUV.v);

            // нормируем UV
            uv.u = (uv.u - minUV.u) / (maxUV.u - minUV.u);
            uv.v = (uv.v - minUV.v) / (maxUV.v - minUV.v);

            prim.appendTexCoord(QVector2D(uv.u, uv.v));
        }
            tempBuilder.addQuadStrip(prim);
            prim.clear();
    }
    return tempBuilder.finalizedSceneNode();
}

Во вложении прикрепил скриншот сферы. Видимо текстуры накладываются вдоль меридиан, сейчас буду разбираться почему так.
Записан
spirits25
Гость
« Ответ #18 : Март 21, 2013, 11:32 »

Если же не делать prim.clear(); то получается не менее интересное наложение
Записан
spirits25
Гость
« Ответ #19 : Март 21, 2013, 11:42 »


Код
C++ (Qt)
struct UV {
qreal u, v;
};
 
UV GetUV( qreal angleU, qreal angleV )
{
 UV uv;
 uv.u = angleU / (M_PI * 2);
 uv.v = angleV / (M_PI / 2) + 0.5;
 return uv;
}

Для расчёта uv.v точно не
Код:
uv.v = angleV / (M_PI) + 0.5;
нужно? там ведь диапазон PI составляет?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Март 21, 2013, 19:13 »

Для расчёта uv.v точно не
Код:
uv.v = angleV / (M_PI) + 0.5;
нужно? там ведь диапазон PI составляет?
Совершенно верно, делить надо на PI, это я насвистел  Улыбающийся

У Вас типичная ситуация - ничего сложного, но трудно отладить, хз где ошибка. Советую делать шаг за шагом.

1) Закомментите все вызовы меркатора, возьмите сферическую текстуру и постройте с ней полную сферу
2) Отладьте кусочки - опять-таки пока на сфере
3) Включите меркатор и с ним постройте всю сферу
4) Ну и в конце-концов...
Записан
spirits25
Гость
« Ответ #21 : Апрель 08, 2013, 18:01 »

никак я не справлюсь с этим. У вас нормально работает наложение с этим кодом?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Апрель 08, 2013, 18:12 »

никак я не справлюсь с этим. У вас нормально работает наложение с этим кодом?
Что-то Вы просыпаетесь раз в 2 недели  Улыбающийся Нет, это конкретно не тестировал, но "наложить текстуру на часть" делал часто. На сферу у Вас все норм ?
Записан
spirits25
Гость
« Ответ #23 : Апрель 08, 2013, 18:18 »

никак я не справлюсь с этим. У вас нормально работает наложение с этим кодом?
Что-то Вы просыпаетесь раз в 2 недели  Улыбающийся Нет, это конкретно не тестировал, но "наложить текстуру на часть" делал часто. На сферу у Вас все норм ?
Мне пришлось отвлечься на другую программу.
Мне вот что из вашего кода удалось сделать (см. вложение, скриншот для 4-х тайлов - 2х2).

Это я сделал, добавив ещё один вертекс сразу, то есть добавляя не каждый по цепочке, а сразу два из параллельных цепочек вертексов:
Код:
QGLSceneNode* Earth::BuildSpherePart(qreal startU, qreal stepU, int numU,   // широта (0..2*PI)
                     qreal startV, qreal stepV, int numV   // долгота (-PI/2 .. +PI/2)
                     // ... др параметры
                    )
{
// находим диапазон
    UV minUV = GetUV(startU, startV);
    UV maxUV = GetUV(startU + stepU * (numU - 1), startV + stepV * (numV - 1));
    minUV.v = Mercator2SphereAnalytic(minUV.v);
    maxUV.v = Mercator2SphereAnalytic(maxUV.v);

    QGLBuilder tempBuilder;
    QGeometryData prim;
// вычисляем UV координаты для сферы
    for (int i =  0; i <= numU; ++i)
    {
        prim.clear();
        for (int j =  0; j <= numV; ++j)
        {
            qreal angleU = startU + stepU * i;
            qreal angleV = startV + stepV * j;

            // добавляем вертекс
            qreal y = sin(angleV);
            qreal len = sqrt(1 - y * y);
            qreal x = cos(angleU) * len;
            qreal z = sin(angleU) * len;
            prim.appendVertex(QVector3D(x, y, z) * a);
            prim.appendNormal(QVector3D(x, y, z) * a);

            // получаем сферические UV
            UV uv = GetUV(angleU, angleV);

            // получаем V меркатора
            uv.v = Mercator2SphereAnalytic(maxUV.v);

            // нормируем UV
            uv.u = (uv.u - minUV.u) / (maxUV.u - minUV.u);
            uv.v = (uv.v - minUV.v) / (maxUV.v - minUV.v);

            prim.appendTexCoord(QVector2D(uv.u, uv.v));

            // second vertex
            angleU = startU + stepU * (i+1);
            angleV = startV + stepV * j;

            // добавляем вертекс
            y = sin(angleV);
            len = sqrt(1 - y * y);
            x = cos(angleU) * len;
            z = sin(angleU) * len;
            prim.appendVertex(QVector3D(x, y, z) * a);
            prim.appendNormal(QVector3D(x, y, z) * a);

            // получаем сферические UV
            uv = GetUV(angleU, angleV);

            // получаем V меркатора
            uv.v = Mercator2SphereAnalytic(maxUV.v);

            // нормируем UV
            uv.u = (uv.u - minUV.u) / (maxUV.u - minUV.u);
            uv.v = (uv.v - minUV.v) / (maxUV.v - minUV.v);

            prim.appendTexCoord(QVector2D(uv.u, uv.v));
        }
        tempBuilder.addQuadStrip(prim);
    }
    return tempBuilder.finalizedSceneNode();
}
« Последнее редактирование: Апрель 08, 2013, 18:21 от spirits25 » Записан
spirits25
Гость
« Ответ #24 : Апрель 08, 2013, 18:24 »

Нашёл, вместо
Код:
// получаем V меркатора
            uv.v = Mercator2SphereAnalytic(maxUV.v);
нужно
Код:
// получаем V меркатора
            uv.v = Mercator2SphereAnalytic(uv.v);
А слона то я и не заметил, самое простое и пропустил=)
Записан
spirits25
Гость
« Ответ #25 : Апрель 09, 2013, 11:46 »

Нет, это конкретно не тестировал, но "наложить текстуру на часть" делал часто. На сферу у Вас все норм ?

А можете ли Вы поделиться своим кодом, который у Вас работает?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Апрель 09, 2013, 15:35 »

А можете ли Вы поделиться своим кодом, который у Вас работает?
Ну вырезать его нереально. В принципе все то же самое - нормирование UV, просто др маппинги. Дайте небольшой проект - попробую помочь
Записан
spirits25
Гость
« Ответ #27 : Апрель 10, 2013, 12:17 »

Дайте небольшой проект - попробую помочь

Вот минимальное, что смог сделать. (переделал стандартный пример solarsystem)

PS. В директории /tmp должны лежать 4 файла http://tile.openstreetmap.org/1/0/0.png, http://tile.openstreetmap.org/1/0/1.png, http://tile.openstreetmap.org/1/1/0.png, http://tile.openstreetmap.org/1/1/1.png с именами 1-0-0.png 1-0-1.png 1-1-0.png и 1-1-1.png соответственно.

Спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Апрель 10, 2013, 15:22 »

Дайте небольшой проект - попробую помочь

Вот минимальное, что смог сделать. (переделал стандартный пример solarsystem)

PS. В директории /tmp должны лежать 4 файла http://tile.openstreetmap.org/1/0/0.png, http://tile.openstreetmap.org/1/0/1.png, http://tile.openstreetmap.org/1/1/0.png, http://tile.openstreetmap.org/1/1/1.png с именами 1-0-0.png 1-0-1.png 1-1-0.png и 1-1-1.png соответственно.

Спасибо.
Так а проект/исходники-то где?
Записан
spirits25
Гость
« Ответ #29 : Апрель 10, 2013, 16:32 »

сорри=) теперь здесь.
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.191 секунд. Запросов: 23.