Russian Qt Forum

Qt => OpenGL => Тема начата: spirits25 от Октябрь 30, 2012, 16:38



Название: [РЕШЕНО] QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Октябрь 30, 2012, 16:38
Доброе время суток.
Я создаю произвольный объект QGLSceneNode
Код:

QGeometryData prim;

//наполняю вертексами, нормалями и текстурными координатами.
prim.appendVertex(...);
prim.appendNormal(...);
prim.appendTexCoord(...);

//добавляю в QGLBuilder объект
builder.addQuadStrip(prim);

//получаю свой объект QGLSceneNode
return builder.finalizedSceneNode();

Вопрос:
1) как наложить новую текстуру на этот же объект QGLSceneNode, но не на весь, а на часть его (задав новые текстурные координаты??)?
2) как изменить текстурные координаты уже существующего объекта QGLSceneNode? или просто заменить старую текстуру на новую?

Если кто знает, можете минимальный пример показать? хотя и подсказкам буду рад=)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Октябрь 31, 2012, 13:33
Судя по доке текстурные координаты (UV) доступны (texCoords(At). Другое дело откуда Вы их возьмете (т.е. на что менять). Они должны быть кем-то созданы (напр в спец редакторе), это не так просто. Если у Вас есть наборы UV - то просто заряжайте их QGL::TextureCoord0, QGL::TextureCoord1, а потом указывайте текстурам какие юзать.

Вообще текстура имеет параметры наложения (масштаб и др), обычно их меняют (а не UV). Наложение на часть сводится к изменению параметров текстуры и указанию нужного clamp'а. Ну можно использовать имедж с альфа-каналом чтобы покрыть часть.

Ну и по-хорошему UV - это 3 значения (а не 2). Это мне у них не понравилось


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Октябрь 31, 2012, 14:26
Судя по доке текстурные координаты (UV) доступны (texCoords(At). Другое дело откуда Вы их возьмете (т.е. на что менять). Они должны быть кем-то созданы (напр в спец редакторе), это не так просто. Если у Вас есть наборы UV - то просто заряжайте их QGL::TextureCoord0, QGL::TextureCoord1, а потом указывайте текстурам какие юзать.

Вообще текстура имеет параметры наложения (масштаб и др), обычно их меняют (а не UV). Наложение на часть сводится к изменению параметров текстуры и указанию нужного clamp'а. Ну можно использовать имедж с альфа-каналом чтобы покрыть часть.

Ну и по-хорошему UV - это 3 значения (а не 2). Это мне у них не понравилось

Можете дать ссылку на документацию? и это Qt3D или OpenGL?


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Октябрь 31, 2012, 14:37
Можете дать ссылку на документацию? и это Qt3D или OpenGL?
Как изменить текстурные координаты

QVector2D & QGeometryData::texCoord

Как наложить часть текстуры

QGLTexture2D::setVerticalWrap
QGLTexture2D::HorizontalWrap
QGLTexture2D::setSize


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Октябрь 31, 2012, 14:54
Как изменить текстурные координаты

QVector2D & QGeometryData::texCoord

Как наложить часть текстуры

QGLTexture2D::setVerticalWrap
QGLTexture2D::HorizontalWrap
QGLTexture2D::setSize

Подскажите ещё:
1) вот у меня есть сфера, созданная с помощью QGLSphere. То есть чтобы так наложить произвольно текстуру QGLSphere не подойдёт? необходимо рисовать сферу самому?

2) Сферу нарисовать не проблема но у меня получится очень много QGeometryData. Необходимо будет хранить их все, например, в массиве с доступом по координатам?

3) вместо QGLMaterial нужно использовать QGLTexture2D?

Спасибо.


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Октябрь 31, 2012, 15:39
Подскажите ещё:
Хотя я еще не видел Qt3D "живьем", общие принципы везде одинаковы. Материал - это набор параметров который полностью определяет внешний вид объекта. Материал может иметь хоть 100 текстур (по крайней мере в теории), и не только текстур, а много еще чего. Можете Вы добавить QGLSphere как нод сцены. Нод имеет материал, материал может иметь текстуру. Плюс QGLSphere имеет UV - значит можете


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 01, 2012, 11:09
Или я не понял, или мы друг друга не поняли. мне нужно не часть текстуры на сферу, а всю текстуру на часть сферы. То есть мой вопрос сводится к тому, как при наложении текстуры указать к каким координатам на сфере привязать её границы? мне нужно, чтобы не вся сфера была обтянута текстурой, а только часть её. причём после создания самой сферы, чтобы можно было так наложить. Можете мне с этой "стороны" помочь?=)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 01, 2012, 12:17
1) подготовить имедж в центре которого уменьшенный исходный а по краям черная альфа - он сам ее и обрежет

2) изменить текстурные координаты - я бы попробовал сначала тупенько поделить/умножить на 2 и посмотреть что получится. Надо только установить wrap'ы чтобы текстура не тайлилась

3) наверное есть лучший способ/сервис - но я его пока не нашел


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 01, 2012, 12:33
1) подготовить имедж в центре которого уменьшенный исходный а по краям черная альфа - он сам ее и обрежет

2) изменить текстурные координаты - я бы попробовал сначала тупенько поделить/умножить на 2 и посмотреть что получится. Надо только установить wrap'ы чтобы текстура не тайлилась

3) наверное есть лучший способ/сервис - но я его пока не нашел

Спасибо. Второй совет наиболее подходящий. Только я не могу этого сделать=)
Я не могу поменять отдельно текстурные координаты в созданном объекте
Код:
QGeometryData prim;

//наполняю вертексами, нормалями и текстурными координатами.
prim.appendVertex(...);
prim.appendNormal(...);
prim.appendTexCoord(...);

//добавляю в QGLBuilder объект
builder.addQuadStrip(prim);

//получаю свой объект QGLSceneNode
return builder.finalizedSceneNode();
, так как QGeometryData помещается в builder "builder.addQuadStrip" и я не могу достать и изменить эти координаты из уже готового объекта.

В общем мне нужно собрать текстуру сферы - Планеты из 8 или 16 кусков, но заранее неизвестно какие это куски и сколько их=) и при этом при определённом действии они могут сменить друг друга. Вот такая проблема=)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 02, 2012, 14:38
Я не могу поменять отдельно текстурные координаты в созданном объекте
Чего это? Вот я вижу методы get/set

QGeometryData QGLSceneNode::geometry () const
QGeometryData QGLSceneNode::setGeometry ()


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 02, 2012, 15:44
Я не могу поменять отдельно текстурные координаты в созданном объекте
Чего это? Вот я вижу методы get/set

QGeometryData QGLSceneNode::geometry () const
QGeometryData QGLSceneNode::setGeometry ()


пробовал, первоначально заданные текстурные координаты таким способом не изменяются.. не знаю почему, но получаю через geometry (), создаю новую переменную, присваиваю из старой вертексы и нормали, а текстурные координаты новые задаю.. устанавливаю новую через setGeometry, но ничего не меняется=(


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 07, 2012, 11:58
В общем придумал, как сделать. но вот возник другой вопрос. Текстурные координаты для наложения одной прямоугольной текстуры на всю сферу у меня есть. А вот как вычислить текстурные координаты для наложения квадратной текстуры? может есть у кого эти вычисления, например, для http://tile.openstreetmap.org/0/0/0.png ?
(http://tile.openstreetmap.org/0/0/0.png)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 07, 2012, 14:46
Обычно меняют картинку, всей сфере нужен имедж 2:1, можно просто растянуть (QGLTexture2D::setSize). 

 


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 07, 2012, 15:47
Обычно меняют картинку, всей сфере нужен имедж 2:1, можно просто растянуть (QGLTexture2D::setSize). 

стандартный размер, установка
tex->setSize(QSize(256, 512));
и установка
tex->setSize(QSize(512, 256));
вообще ничем не отличаются. всё как то странно вытянуто, антарктида раз в 20 по площади больше, чем австралия. Африка по ширине больше, чем по высоте..


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 07, 2012, 17:56
стандартный размер, установка
tex->setSize(QSize(256, 512));
и установка
tex->setSize(QSize(512, 256));
вообще ничем не отличаются.
Значит делаете когда текстура уже загружена в OpenGL. Можно сразу сделать QImage::scaled,
Перед вызовом glTexImage2D размер установленный setSize сравнивается с размером исходного. Если не равны - QImage::scaled и OpenGL получит смасштабленный имедж

всё как то странно вытянуто, антарктида раз в 20 по площади больше, чем австралия. Африка по ширине больше, чем по высоте..
Так работает сферическая карта, с квадратной картинкой это нормально


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 08, 2012, 10:30
Думаю, так не пройдёт. Нужно из проекции меркатора в сферическую пересчитать, простое растяжение тут не поможет.


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 08, 2012, 11:34
Думаю, так не пройдёт. Нужно из проекции меркатора в сферическую пересчитать, простое растяжение тут не поможет.
Проверил и убедился что Вы правы :) Немного посмотрел что такое меркаторская, по-моему всего-навсего Вам надо возвести V (y текстуры) в квадрат. Во всяком случае это легко проверить

Edit: нет, просто в квадрат неправильно. Должно быть совсем просто, щас придет мысля  :)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 08, 2012, 14:00
Вот тут http://forum.openstreetmap.org/viewtopic.php?pid=288636 мне подсказали, но я до конца всё равно не разобрался..
Как перевести из проекции меркатора в сферическую?


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 08, 2012, 14:48
Код ниже рабочий, у меня земля с Вашей текстурой смотрится прилично
ВАЖНО: предполагается что входной параметр iTY (y текстуры) уже посчитан для сферической карты и находится в пределах [0..1]
Код
C++ (Qt)
#include <QtGUI>
#include <math.h>
#include <vector>
 
double Mercant2Sphere( double iTY, const double maxAng = 85.0 )
{
static std::vector <double> vec;
if (!vec.size()) {
vec.push_back(0.0);
double unit = M_PI / 180;
for (double i = 1; i < maxAng; ++i)
vec.push_back(vec[i - 1] + unit / cos(i * unit));
 
// normalize
double scale = M_PI_2 / vec.back();
for (size_t i = 0; i < vec.size(); ++i)
vec[i] *= scale;
}
 
double angle = (iTY * 2 - 1) * M_PI_2; // texture V to angle
double angle_degree = fabs(angle) * 180 / M_PI;
int beg = (int) angle_degree;
double val;
if (beg >= (int) vec.size() - 1)
val = M_PI_2;
else {
double w = angle_degree - beg;
val = vec[beg] * (1.0 - w) + vec[beg + 1] * w;
}
if (angle < 0.0) val = -val;
return (1 + val / M_PI_2) * 0.5; // angle to texture V
}
 
int main( int argc, char **argv )
{
(void) argc;
(void) argv;
return 0;
}
 
Однозначного перевода просто не существует, все зависит от предела (ну вроде видел 85 градусов, их и поставил)

Дв, и в следующий раз говорите тип подготовленной текстуры, просто "квадратная" ни о чем не говорит (напр lightprobe тоже квадратная)


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 08, 2012, 15:09
Огромнейшее спасибо!=) Работает на отличненько=)
На будущее учту, но просто я поначалу сам разбирался и не сразу понял, что там именно меркатор. Но признаю, мог бы постараться и точнее объяснить=)

ЗЫ. Не дадите источник, где это нашли? или где информацию для написания этого.. в общем хотелось бы посмотреть там, может ещё что полезное найду=)
Спасибо.


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 08, 2012, 15:24
ЗЫ. Не дадите источник, где это нашли? или где информацию для написания этого.. в общем хотелось бы посмотреть там, может ещё что полезное найду=)
Не дам потому что нету, это самопальный велосипед  :) Можно сделать точнее (на том форуме есть формула для вычисления угла меркатора, я ее не знал). Ну численно посчитать тоже не ошибка. В любом случае нужно держать таблицу т.к. нормировка неизбежна.


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 08, 2012, 15:43
Не дам потому что нету, это самопальный велосипед  :) Можно сделать точнее (на том форуме есть формула для вычисления угла меркатора, я ее не знал). Ну численно посчитать тоже не ошибка. В любом случае нужно держать таблицу т.к. нормировка неизбежна.
То есть зная
Код:
inline double mercator(double x) {
    return 0.5*log((1.0+sin(x))/(1.0-sin(x)));
}
можно точнее?


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 08, 2012, 18:13
То есть зная
Код:
inline double mercator(double x) {
    return 0.5*log((1.0+sin(x))/(1.0-sin(x)));
}
можно точнее?
Ну да, x это ведь исходный "угол возвышения" в радианах, просто меняете 1 строку
Код:
// vec.push_back(vec[i - 1] + unit / cos(i * unit));
vec.push_back(mercator(i * unit));


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: spirits25 от Ноябрь 09, 2012, 11:48
вроде даже точнее получается=) спасибо.


Название: Re: QGLSceneNode текстуры (добавление или изменение)
Отправлено: Igors от Ноябрь 09, 2012, 12:08
Можно и без массива

Код
C++ (Qt)
const double defMercAngle = 85 * M_PI / 180;
const double defMercScale = M_PI_2 / mercator(defMercAngle);
 
double Mercant2SphereAnalytic( double iTY, const double scale = defMercScale, const double maxAng = defMercAngle )
{
double angle = (iTY * 2 - 1) * M_PI_2; // texture V to angle
       double angle2 = fabs(angle);
double val = (angle2 > maxAng) ? M_PI_2 : (mercator(angle2) * scale);
if (angle < 0.0) val = -val;
return (1 + val / M_PI_2) * 0.5; // angle to texture V
}