Войти
ПрограммированиеФорумГрафика

Как свернуть простое изображение и разделить на 6 квадратов?

Страницы: 1 2 3 Следующая »
#0
17:32, 4 ноя 2015

Использую Qt с OpenGL, решил нарисовать землю в 3D.
Есть куб, преобразованный в сферу:
cube | Как свернуть простое изображение и разделить на 6 квадратов?
И есть изображение поверхности земли
worldMap | Как свернуть простое изображение и разделить на 6 квадратов?
Как его преобразовать (свернуть верхнюю и нижнюю часть в квадрат) и разбить на 6 квадратов для дальнейшего наложения?
Находил сторонние программы (на space engine например), но не нашел нигде как именно сделать... очень интересно как математически сжать, как отсечь лишние пиксели при свертывании и т.п.

#1
17:41, 4 ноя 2015

Тебе нужно развертку сферы преобразовать в cube map. Гугли.

#2
19:04, 4 ноя 2015

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

#3
23:23, 4 ноя 2015

slevin
Так вроде очевидно.

Сначала выяснить, которая картографическая проекция здесь. На глаз, похоже на:
https://ru.wikipedia.org/wiki/Равнопромежуточная_проекция

Ну и работать в 3-мерных координатах.

Проекция:
\(\vec{F}(u,v)= \begin{bmatrix} \sin (\pi v) \cos (2 \pi u) \\ \sin (\pi v) \sin (2 \pi u) \\ \cos (\pi v) \end{bmatrix} ,\, u,\,v \in [0;1].\)
(u,v) - (текстурные) координаты на карте
Соответственно \(2 \pi (u-0.5)\) - долгота, \(\pi (v-0.5)\) - широта (обе - в радианах), ось Земли - вдоль Oz.

Обратная функция:
\(F^{-1}_u=u( \begin{bmatrix} x \\ y \\ z \end{bmatrix} )=\mathrm{atan2}\,(y,x)\)
\(F^{-1}_v=v( \begin{bmatrix} x \\ y \\ z \end{bmatrix} )=\mathrm{atan2}\,(\sqrt{x^2+y^2},z)\)
Это всё стандартнейшие вещи:
https://ru.wikipedia.org/wiki/Сферическая_система_координат#.D0.9… D.D0.B0.D1.82

Для cubemap есть 6 сторон. Как именно там выбраны направеления координат - тоже надо выяснить.
Скорее всего https://www.opengl.org/registry/specs/ARB/texture_cube_map.txt :

      major axis
      direction     target                             sc     tc    ma
      ----------    -------------------------------    ---    ---   ---
       +rx          TEXTURE_CUBE_MAP_POSITIVE_X_ARB    -rz    -ry   rx
       -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_ARB    +rz    -ry   rx
       +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_ARB    +rx    +rz   ry
       -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB    +rx    -rz   ry
       +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_ARB    +rx    -ry   rz
       -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB    -rx    -ry   rz

Тогда, для одной из сторон (+x):
\(\vec{G}(u,v)=\frac{ \begin{bmatrix} +1 \\ 1 - 2 v \\ 1 - 2 u \\ \end{bmatrix}} {\sqrt{1+(1 - 2 u)^2+(1 - 2 v)^2}}\)

Ну и соответственно, исходный пиксель для (u,v) этой стороны кубомапы находится в координатах (u',v') карты:
\(u'=F^{-1}_u(\vec{G}(u,v))\)
\(v'=F^{-1}_v(\vec{G}(u,v))\)

Ну и самплим их, с тем фильтром, который выберем.
Фильтровать в 2D или в 3D - отдельный вопрос.

Вроде так.

#4
9:50, 5 ноя 2015

Спасибо, правда не до конца понял...

кажется мой мозг остался в армии.

я так понимаю после u,v преобразования (так вроде наоборот 2п(u-0.5) - это широта) мы получим u,v map, которая по сути все еще плоская, дальше преобразовав в декартову приняв r=1 Изображение получим все 3 координаты, которые будут описывать сферу и можно рисовать я правильно понимаю?
Это будет так сказать текстура с координатами в виде сферы... А как порезать ее не на кубическую карту (откуда вы формулу кстати взяли?), а на 6 отдельный текстур? я не понимаю как получить из исходного большого изображения отдельный свернутый по верху квадрат......  с | Как свернуть простое изображение и разделить на 6 квадратов?
хотя если ранее получившуюся сферу преобразовать в обратную сторону к кубу, по сути должно получиться.
или есть более простой способ?

#5
10:34, 5 ноя 2015

это ты получил вектор сферы из координат долготы и широты. теперь осталось сделать обратное преобразование из вектора в выбранную систему - кубических координат.
только мне казалось что формула выглядит иначе (sin(0)=0)
x=cos(w)*cos(a)
y=cos(w)*sin(a)
z=sin(w)

Далее я использовал такую логику:
sin(45)=cos(45)=1/√2 это край текстур на сфере.
соотвественно выбор одной из 6 текстур происходит по условию

+ Показать

В данном случае UV получаются в диапазоне +-1.0. а BLOCK будет содержать номер стороны 0-5. (4 сервер, 5 юг)
v2=_pos*(1.0/max); - данное действие сразу дает координаты на описывающем сферу кубе спроецированного на нее, и на выполнение условий оно ни как не влияет.

#6
10:50, 5 ноя 2015

slevin
>так вроде наоборот 2п(u-0.5) - это широта
Широта - в \([-\frac{\pi}{2};\,+\frac{\pi}{2}]\) (С:90 - Ю:90), долгота - в \([-\pi;\,+\pi]\) (З:180 - В:180).

>откуда вы формулу кстати взяли?
G(u,v)? Из головы. Она очевидная же - проекция грани куба (ребром 2, т. е. \([-1;\,+1]^3\)) с центром по {u=0.5, v=0.5} на единичную сферу.

>получим все 3 координаты, которые будут описывать сферу и можно рисовать я правильно понимаю?
Да, если цели преобразовать в cube map не стоит, то можно рисовать так.

>хотя если ранее получившуюся сферу преобразовать в обратную сторону к кубу, по сути должно получиться.
Ну да, я по сути это и предложил.

>или есть более простой способ?
А хрен его знает. Это - первый, который пришёл в голову.

foxes
Такая формулировка в русской Википедии (в английской - несколько вариантов, но этот приводится как основной).
Там углы в [0;180] и [0;360] соответственно, возможно это сбивает с толку.
Как раз для текстурных координат - удобно.

#7
11:18, 5 ноя 2015

Забавно как то помню пришлось поспорить с одним новоиспеченным программистом-знатаком картографических систем координат, о том что сферической системы координат не существует. Даже ссылка в википедии его не убедила...
На самом деле тут все будет зависеть от воображения не лишенного математической логики.

slevin
Да кстати чтобы построить текстуру для какой либо из сторон, имея твою общую развертку, придется использовать обратную формулу. Я для нее получал координаты из UV таким образом:

if (block==0) {x=u-0.5; y=v-0.5; z=0.5;}
if (block==1) {x=0.5; y=v-0.5; z=0.5-u;}
if (block==2) {x=0.5-u; y=v-0.5; z=-0.5;}
if (block==3) {x=-0.5; y=v-0.5; z=u-0.5;}
if (block==4) {x=u-0.5; y=0.5; z=0.5-v;}
if (block==5) {x=0.5-u; y=-0.5; z=0.5-v;}
#8
11:39, 5 ноя 2015

спасибо! вечером посмотрю что из этого получится)

#9
11:08, 6 ноя 2015

Вобщем что то я совсем потерялся... Изображение в целом нормально собирается в сферу и рисуется (по точкам для наглядности)...

    
    glPointSize(15); // для наглядности побольше
    float scaleW = 360.f/sizeW; // устанавливаем соотношение между размером картинки и 360/180 градусами.
    float scaleH = 180.f/sizeH;
    glBegin(GL_POINTS);
    for(int i = 0; i < sizeW; i++) // sizeW и H это размеры изображения
        for(int j = 0; j < sizeH; j++)
        {
            float toRadi = i*scaleW*M_PI/180; // переходим к радианам
            float toRadj = j*scaleH*M_PI/180;
            float x = sin(toRadj)*cos(toRadi); // преобразуем точки плоского изображения в сферу
            float y = sin(toRadj)*sin(toRadi);
            float z = cos(toRadj);

            QRgb rgb = img1.pixel(i, j); //вытаскиваем цвет пикселя из картинки
            //   Установка цвета для пикселя (от 0 до 1)
            glColor3f((float)qRed(rgb)/255, (float)qGreen(rgb)/255, (float)qBlue(rgb)/255);

            if(cos(toRadj) > 1/sqrtf(2.0f)) // отрисовываем только верхнюю часть
                glVertex3f(x,y,z);
        }
    glEnd();

Зачем тогда нужно u,v преобразование и куда его тут прилепить?? (википедию про u,v читал....)
и основной вопрос как вместо сферы теперь нарисовать куб этой уже свернутой в сферу текстурой(ну или точками правильнее будет сказать)??

#10
12:12, 6 ноя 2015

Тада тада там, Пиииииууууу....

Ладно, давай попробуем по твоему, отрисовываем одну сторону куба точками:

    // sizeW и H это размеры изображения
    glPointSize(15); // для наглядности побольше
    float sizeCube= 100.0f;
    float scaleCube = 1.f/sizeCube; //
    glBegin(GL_POINTS);
    for(int i = 0; i < sizeCube; i++)
        for(int j = 0; j < sizeCube; j++)
        {
            // u*sizeW0 v*sizeH0 - координаты текстуры которая должна использоваться  
            float u=j* scaleCube;
            float v=i* scaleCube;
            float x = u-0.5; // преобразуем точки плоского изображения в сторону куба
            float y = v-0.5;
            float z = 0.5;
            float ilen=1.0f/sqrt(x*x+y*y+z*z);

            // atan должна давать результат в диапазоне [-pi : pi]
            // realX, realY - координаты текстуры которая у тебя есть.
            int realX=(atan2(x,y)*0.5/M_PI+0.5)*sizeW;
            int realY=(atan2(sqrt(x*x+y*y),z)/M_PI+0.5)*sizeH;

            QRgb rgb = img1.pixel(realX,realY); //вытаскиваем цвет пикселя из картинки
            imgCubeMap0.setPixel(u*sizeW0, v*sizeH0,rgb ); // задаем цвет пикселя для развертки cube одной из 6 сторон
            //   Установка цвета для пикселя (от 0 до 1)
            glColor3f((float)qRed(rgb)/255, (float)qGreen(rgb)/255, (float)qBlue(rgb)/255);
         
            glVertex3f(x*ilen,y*ilen,z*ilen);
        }
    glEnd();

как то так

#11
12:15, 6 ноя 2015

foxes

Марьё?

#12
13:04, 6 ноя 2015

nes

Ералаш

#13
13:22, 6 ноя 2015

здесь я так понял atan(y/x) и atan(sqrt(x*x+y*y)/z) ? чего то не хотит...

#14
13:24, 6 ноя 2015

думаю тут как у FordPerfect должен быть atan2.

Только правильнее было бы сначала создать текстуру для одной из сторон:

+ Показать

А потом уже использовать ее для отрисовки.

+ Показать

slevin
> Зачем тогда нужно u,v преобразование и куда его тут прилепить??
Понадобятся когда в место точек начнешь геометрию строить, и для каждой вершины задавать текстурные координаты.

для того чтобы изображение на экран вывести цветные чернила и бумага тоже не требуются.

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.