Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование в широком смысле слова > Алгоритмика

Алгоритмика Об алгоритмах вообще; методы, обсуждения способов решения

Ответ
 
Опции темы
Старый 18.05.2012, 21:58   #1
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Наложение текстуры на меш в любом месте, игнорируя UV-швы

Собственно сабж
Есть текстура персонажа, развороченная по UV на манер

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

Много гуглил по этому поводу. Была например идея попиксельного проэцирования плоскости с текстурой на меш. Но идея прогорела из-за некорректного растяжения накладываемого изображения на выпуклые и впуклые части модели.

Есть мысль как-то заюзать две UV-сетки для "смазывания" граней между UV-швами, но пока не придумал как именно.

Еще нагуглил про http://3dyuriki.com/2010/09/24/ptex-...nyh-koordinat/ по идее то что нужно (можно рисовать прямо поверх 3д модели что угодно), но увы современными игровыми 3д-движками пока что не поддерживаемо

Может быть кто-нить сталкивался с проблемой и находил решение?
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо Amatsu за это полезное сообщение:
Harter (18.05.2012), Mr_F_ (21.05.2012)
Старый 21.05.2012, 08:06   #2
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Решил часть задачи (надеюсь что решил). Сейчас встал вопрос - есть ли быстрый способ на юнити заблюрить (размыть) текстуру? Не приметь к ней шейдер, а именно изменить саму текстуру, как в фотошопе, а точнее размыть все ее пиксели. Пока не начал изобретать велосипед - может кто сталкивался с готовым решением? Повторюсь - важна скорость применения этого эффекта к текстуре

И второй вопрос, так же на всякий случай - как определить быстро грани меша? То есть у меня допустим есть полигональная плоскость (не квад, а состоящая из множества полигонов некая рандомная фигура), надо на ней найти вертексы на границах этой плоскости
(Offline)
 
Ответить с цитированием
Старый 21.05.2012, 10:00   #3
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

1. А может просто взять mip уровень другой с этой же текстуры?
2. Тут быстро не очень получится... вероятно для начала надо будет объединить вершины, имеющие одинаковые позиции(границы разрывов на UV), потом найти вершины, которые соединяются с другими вершинами не парно (т.е. грань должна быть одна, соединяющая конкретные две вершины).
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Amatsu (21.05.2012)
Старый 25.05.2012, 19:53   #4
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы


http://gyazo.com/a70870e260eacdbd5c4...png?1337957184
В общем, нашел я границы развернутого на плоскости меша (красные точки). Сейчас ломаю голову над методом определения нормалей (красные стрелки), исходящих из этих вершин во внешнее от меша пространство. Если найду эти нормали, смогу периметр меша сделать "толще". Простой скейл из центра не подходит, так как геометрия может быть не только выпуклой, но и "впуклой". Может кто знает ссылку на подобный метод, или хотя бы название подобного дейсвия?
(Offline)
 
Ответить с цитированием
Старый 26.05.2012, 10:03   #5
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Нормаль в вершине, это сумма нормалей ребер, которые образует эта вершина. Достаточно для каждого ребра посчитать нормаль, а для вершин их сумму и нормализовать. А посчитать нормаль к ребру можно например поворотом ребра на 90 градусов.
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Amatsu (26.05.2012)
Старый 26.05.2012, 10:06   #6
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Я уже где-то в этом направлении копаю Пока что вопрос стоит в оптимизации кода
(Offline)
 
Ответить с цитированием
Старый 26.05.2012, 23:15   #7
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Кажется мне, что тут надо не сдвигать по нормалям, а делать extrude для ребер...
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Старый 27.05.2012, 06:24   #8
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Сообщение от pax Посмотреть сообщение
Кажется мне, что тут надо не сдвигать по нормалям, а делать extrude для ребер...
Я конкретно такой команды не нашел ) А поиски по этому слову в интернете выдают описание процесса создание объемного меша по его 2д профилю. Так что не то

UPDATE
Все, решил задачу

У меня теперь вопрос - кто-нить сталкивался с "квадратизацией" развертки? То есть у меня допустим есть меш человеческой ноги. Я разрезаю ее вдоль и разворачиваю как цилиндр. Она развернется как-то так А мне нужно привести ее к форме квадрата, не просто сместив к квадратной форме границы, но и все вертексы внутри развертки соответствующе

Последний раз редактировалось Amatsu, 27.05.2012 в 09:10.
(Offline)
 
Ответить с цитированием
Старый 27.05.2012, 13:20   #9
ARA
ТЫ ЧООО?
 
Аватар для ARA
 
Регистрация: 26.02.2007
Сообщений: 3,369
Написано 2,020 полезных сообщений
(для 7,192 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

А мне нужно привести ее к форме квадрата, не просто сместив к квадратной форме границы, но и все вертексы внутри развертки соответствующе
2012 макс так умеет. UnwrapUVW -> функция развёртки Peel. Нужно врубить peel mode, отметить все крайние вертексы, как pin selected (они станут синенькими) и выровнять по краям. Всё, что внутри куска развёртки пропорционально распределится.
__________________
Вертекс в глаз или в пиксель раз?
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо ARA за это полезное сообщение:
Amatsu (27.05.2012), Mr_F_ (27.05.2012), Nex (27.05.2012)
Старый 27.05.2012, 13:47   #10
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Отлично, большое спасибо!

И да, если кому-то будет нужна помощь в построении подобной системы (нанесение текстуры в любую часть модели игнорируя швы ее развертки) - обращайтесь. Весь код предоставить не могу, но по отдельным местам помогу
(Offline)
 
Ответить с цитированием
Старый 27.05.2012, 13:55   #11
Mr_F_
Терабайт исходников
 
Аватар для Mr_F_
 
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений
(для 6,051 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

можешь вкратце описать алгоритм, к которому пришёл?
(Offline)
 
Ответить с цитированием
Старый 27.05.2012, 14:48   #12
Amatsu
Дэвелопер
 
Аватар для Amatsu
 
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений
(для 2,706 пользователей)
Ответ: Наложение текстуры на меш в любом месте, игнорируя UV-швы

Вкратце...
Я сейчас расскажу в случае связки C# + Unity3D

Ну, для начала на старте программы я обрабатываю развертку меша, на который буду накладывать текстуры вот этим методом
    static Vector2[] CorrectUV(Mesh mesh, float scale)
    {
        if (mesh != null)
        {
            var meshTriangles = mesh.triangles;
            var meshUV = mesh.uv;


            var borderNormals = new Vector2[meshUV.Length];
            var borderAngle = new float[meshUV.Length];


            for (var i = 0; i < meshTriangles.Length; i += 3)
            {
                var foundRib = new bool[3];
                for (var j = 0; j < meshTriangles.Length; j += 3)
                {
                    if (i == j) continue;
                    var foundVert = new bool[3];
                    for (var k = 0; k < 3; k++)
                    {
                        if (meshTriangles[i + k] == meshTriangles[j] || meshTriangles[i + k] == meshTriangles[j + 1] || meshTriangles[i + k] == meshTriangles[j + 2]) foundVert[k] = true;
                    }
                    if (foundVert[0] && foundVert[1]) foundRib[0] = true;
                    if (foundVert[1] && foundVert[2]) foundRib[1] = true;
                    if (foundVert[2] && foundVert[0]) foundRib[2] = true;
                }


                if (!foundRib[0])
                {
                    var normal = Perpendicular(meshUV[meshTriangles[i]], meshUV[meshTriangles[i + 1]], meshUV[meshTriangles[i + 2]]).normalized;
                    borderAngle[meshTriangles[i]] = Vector2.Angle(borderNormals[meshTriangles[i]], normal);
                    borderNormals[meshTriangles[i]] += normal;
                    borderAngle[meshTriangles[i + 1]] = Vector2.Angle(borderNormals[meshTriangles[i + 1]], normal);
                    borderNormals[meshTriangles[i + 1]] += normal;
                }
                if (!foundRib[1])
                {
                    var normal = Perpendicular(meshUV[meshTriangles[i + 1]], meshUV[meshTriangles[i + 2]], meshUV[meshTriangles[i]]).normalized;
                    borderAngle[meshTriangles[i + 1]] = Vector2.Angle(borderNormals[meshTriangles[i + 1]], normal);
                    borderNormals[meshTriangles[i + 1]] += normal;
                    borderAngle[meshTriangles[i + 2]] = Vector2.Angle(borderNormals[meshTriangles[i + 2]], normal);
                    borderNormals[meshTriangles[i + 2]] += normal;
                }
                if (!foundRib[2])
                {
                    var normal = Perpendicular(meshUV[meshTriangles[i + 2]], meshUV[meshTriangles[i]], meshUV[meshTriangles[i + 1]]).normalized;
                    borderAngle[meshTriangles[i + 2]] = Vector2.Angle(borderNormals[meshTriangles[i + 2]], normal);
                    borderNormals[meshTriangles[i + 2]] += normal;
                    borderAngle[meshTriangles[i]] = Vector2.Angle(borderNormals[meshTriangles[i]], normal);
                    borderNormals[meshTriangles[i]] += normal;
                }
            }

            var updatedUV = new Vector2[meshUV.Length];
            for (var i = 0; i < meshUV.Length; i++)
            {
                updatedUV[i] = meshUV[i] + borderNormals[i] * (0.5F + borderAngle[i] / 180F) * scale;
            }

            return updatedUV;
        }
        return null;
    }
В результате я получаю UV-развертку меша, грани которой расширены как я рисовал выше. Но эта UV-развертка представлена лишь как массив 2d-векторов, к исходному мешу я ее не применяю. Эта операция выполняется один раз на старте

Далее, я кликаю по мешу, нахожу точку клика, а так же вектор (например от точки клика до камеры или же беру нормаль клика). На "вершине" этого найденного вектора вешаю GameObject, заставляю его "смотреть" на точку клика. Назовем этот объект А

Затем делаю копию оригинального меша (внимание, не забудьте повесить на копию меша материал с шейдером, учитывающим вертексную альфу, шейдер представлен здесь ) и проецирую все координаты вертексов этой копии на плоскость, принадлежащую space'у А. То есть просто перевожу координаты вершин копии меша из мировых в координатную систему А, затем беру у этих вершин только X и Y составляющие, игнорируя Z, и записываю их в массив двухмерных векторов, который (массив) потом присваиваю UV-развертке копии исходного меша.

Затем я накладываю на копию меша текстуру с альфой, в clamp-режиме. Текстура накладывается на меш проекцией. Но чтобы она не размазывалась по всей поверхности, я делаю у копии меша повершинно три проверки. Сначала я проверяю дистанцию каждого вертекса копии меша относительно точки клика по исходному мешу. Если эта дистанция больше какого-то числа - я текущему вертексу вешаю цвет (1, 1, 1, 0) (то есть белый с нулевой альфой). Если же вертекс проходит проверку - я проверяю, что его угол между его нормалью и вектором клика (на конце которого мы повесили А) не больше, допустим, 90 градусов, если больше - так же ставлю вертексу нулевую альфу. Ну и если вертекс и эту проверку прошел - кидаю из А до него RayCast. Если луч не дошел до вертекса - правильно, вершину так же загоняем в нулевую альфу.

Тут может возникнуть вопрос, что при большом числе вертексом рейкасты могут замедлить проверку - не замедляют. Физиксовый рейкаст очень быстр

Все, наша текстура наложилась именно там, где вы кликнули и под тем углом, как вы захотели.

Теперь можно водя по поверхности исходного меша мышкой менять ему наложение (копировать заново меш не нужно, можно начать сразу с пункта установки в нужной точки объекта А и проэцирования в его координатную систему вершин копии меша)

Вторая фаза - запекание нашей текстуры из копии меша в текстуру оригинального меша.

Я передаю в соответствующий метод указатель на оригинальный меш, на нашу затекстуренную копию меша, а так же на тот массив 2d-векторов, представляющий собой "поправленную" UV-развертку оригинала.

Далее, я беру нашу поправленную UV-развертку (преимущество моего способа - эта развертка может быть практически любой). Затем я создаю новый меш, в который добавляю информацию о геометрии следующим образом:
каждый полигон из моей копии меша (захватив при этом координаты развертки этого полигона, которые мы нашли, когда накладывали текстуру на него) переносился на 2d-плоскость (плоскость естессно в 3д пространстве) в поправленные (!) UV-координаты соответствующего полигона из оригинального меша (мы ведь делали копию оригинального меша, так что число полигонов у нас совпадает и на меше, и на UV-развертке).

Этим хитрым способом мы переводим развертку копии меша (по сути разрезаем копию меша на полигоны и помещаем каждый из них в соответствующие координаты на UV) в UV-развертку оригинального меша.

Поле этого осталось лишь создать условия для рендера этой фигуры в текстуру для оригинального меша. Ставим перед полученной "сплюснутой" копией меша камеру, позади создаем из дух полигонов квад и натягиваем на него текстуру, которая у нас уже была на оригинальном меше (например текстуру тела, которую вы успели сделать герою в фотошопе по его UV-развертке), настраиваем камере ортографический рендер и ВУА ЛЯ
Полученную из рендера текстуру натягиваем на персонажа вместо той, что на нем была до этого.
Копию меша, камеру, квад, объект А и прочий мусор чистим.

Честно, я пытался рассказать доступно...
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо Amatsu за это полезное сообщение:
ARA (27.05.2012), Mr_F_ (27.05.2012), pax (27.05.2012)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 09:45.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com