TextureStage и Terrain
|
|
serg-kkz | Дата: Четверг, 21.08.2014, 12:26 | Сообщение # 31 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Цитата ninth ( ) Да с PIL вполне можно сгенерить с учётом вертикальности стенок. - как? Я только слой скал буду генерировать с помощью коллизий. Увы на ум больше ни чего не приходить, кроме как клацать по поверхности и определять ориентацию полигона. Думаю наработка в дальнейшем пригодиться для генерации флоры. Только в данный момент задумался над тем как определить "крутость полигона" вроде нашел закономерность в сумме или разнице X и Y у направления вектора нормали. В дальнейшем думаю таким же способом освещение сделать, путем обстрела лучем из позиции солнца по террейну.
ООП -
|
|
| |
ninth | Дата: Четверг, 21.08.2014, 17:06 | Сообщение # 32 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| А поверхность у тебя геомип на основе карты высот или моделька?
з.ы. А вертикальность можно определить скалярным произведением (оно же dotproduct) нормали на up-вектор. Vec3(0,1,0).dot(myNormal)
|
|
| |
serg-kkz | Дата: Четверг, 21.08.2014, 17:20 | Сообщение # 33 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| На основе карты высот, по ней три слоя песок, земля, трава. Скалы на основе коллизий, еще в разработке, но одна проблема ввела меня в ступор. Не получается без добавления в рендер декектить лучем поверхность.
Пример PIL.
Код # -*- coding: utf-8 -*- #!/usr/bin/python from PIL import Image import sys
relief = Image.open("data/default.png") # Карта высот mask = Image.new("RGBA", (512,512), (0,0,0,0)) # Создаем новый файл изображения, с 4-мя каналами. rgba = mask.split() # Разбиваем на каналы
red = rgba[0] # Переменная для красного канала green = rgba[1] # Переменная для зеленого канала blue = rgba[2] # Переменная для синего канала alfa = rgba[3] # Переменная для альфа канала
for y in range(512): for x in range(512): # Определяем уровень песка от 0 до 75 if 0 <= relief.getpixel((x, y)) < 75: red.putpixel((x, y), 255 ) # Определяем уровень травы от 75 до 120 if 74 < relief.getpixel((x, y)) < 80: green.putpixel((x, y), 255 ) # Определяем уровень скал от 75 до 170 if 79 < relief.getpixel((x, y)) < 140: blue.putpixel((x, y), 255 ) # Определяем уровень снега от 170 до 255 if 139 < relief.getpixel((x, y)) < 255: alfa.putpixel((x, y), 255 )
im = Image.merge("RGBA", (red,green,blue,alfa)) # Собираем слои im.save("data/default_d.png") # И сохраняем
ООП -
Сообщение отредактировал serg-kkz - Четверг, 21.08.2014, 19:07 |
|
| |
serg-kkz | Дата: Четверг, 21.08.2014, 17:47 | Сообщение # 34 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| В дальнейшем думаю полность все рисовать с помощью коллизий, так можно будет полностью обработать всю карту. Так как я планирую сделать открытый мир, состоящий из тайлов мешей.
ООП -
|
|
| |
ninth | Дата: Пятница, 22.08.2014, 08:09 | Сообщение # 35 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Для геомип есть вариант получать нормаль без коллизий myGeoMipTerrain.getNormal(x,y) x,y - координаты пикселей карты высот
|
|
| |
serg-kkz | Дата: Вторник, 26.08.2014, 02:32 | Сообщение # 36 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Цитата ninth ( ) Для геомип есть вариант получать нормаль без коллизий myGeoMipTerrain.getNormal(x,y) x,y - координаты пикселей карты высот
О, это намного быстрее чем шарить лучем.
Правда ждал не того. Как то странно все это работает. Скалярное произведение местами выводит 0.0 в массиве. Хотя этого быть не должно теоретически.
ООП -
|
|
| |
ninth | Дата: Вторник, 26.08.2014, 08:57 | Сообщение # 37 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Скрин ничё так. А в дебаг вывести "неправильные" вектора на которых 0 получается?
|
|
| |
serg-kkz | Дата: Вторник, 26.08.2014, 10:33 | Сообщение # 38 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Цитата ninth ( ) Скрин ничё так. А в дебаг вывести "неправильные" вектора на которых 0 получается?
Я не соображу как это сделать? Могу только визуально проследить.
Да скрин хорош, но если в целом посмотреть, то получается как будь-то проталины от солнца, видно относительно одной оси определяется наклонность
И на скрине видно что некоторые точки больше горизонту ближе чем к вертикали.
ООП -
|
|
| |
ninth | Дата: Вторник, 26.08.2014, 10:51 | Сообщение # 39 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Ммм... результат можно записать в чёрно-белую текстуру чтобы визуально определить. И знаешь что, проверь-ка у тебя вектора нормализуются перед скалярным произведением? Оно корректно работает только на нормализованных векторах.
|
|
| |
serg-kkz | Дата: Вторник, 26.08.2014, 10:56 | Сообщение # 40 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Код def scan1(self, task): for x in range(512): for y in range(512): n = self.terrain.getNormal(x,y) print Vec3(0,1,0).dot(n) if 0.001 < Vec3(0,1,0).dot(n) < 0.01: self.red.putpixel((x, y), 0 ) self.green.putpixel((x, y), 0 ) self.blue.putpixel((x, y), 0 ) self.alfa.putpixel((x, y), 255 )
Таким макаром это работает, и вот что выдает.
ООП -
|
|
| |
ninth | Дата: Вторник, 26.08.2014, 11:25 | Сообщение # 41 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Попробуй так Код n = self.terrain.getNormal(x,y) n.normalize() dot = abs(Vec3(0,1,0).dot(n))
И ещё, это всё с учётом, что у тебя Y - вертикальная ось. Если вертикаль - Z, то вектор-то должен быть Vec3(0,0,1). Естественно, всё в координатах террайна. Кстати, террайн по вертикальной оси масштабирован перед проверкой нормали?
|
|
| |
serg-kkz | Дата: Вторник, 26.08.2014, 11:52 | Сообщение # 42 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Цитата ninth ( ) Кстати, террайн по вертикальной оси масштабирован перед проверкой нормали?
Код self.terrain = GeoMipTerrain("Terrain") self.terrain.setHeightfield(Filename('data/land01-map.png')) self.terrain.setBlockSize(32) self.terrain.setFactor(100) #self.terrain.setFocalPoint(base.camera) self.terrain.getRoot().reparentTo(render) self.terrain.getRoot().setPos(0, 0, -500) self.terrain.getRoot().setSz(200) self.terrain.generate()
Что-то мне алгебра надоела, вообщем как ноду задать положение пологона, вращение меня интересует. Сделаю по тупому, расположу нод, прицеплю два узла друг над другом(вертикально), и по их разнице в x и y буду считать. Логика если координаты ближе к совпадению, то значит горизонт, чем больше разница, вертикаль.
ООП -
|
|
| |
ninth | Дата: Вторник, 26.08.2014, 13:10 | Сообщение # 43 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Можешь мне целиком скинуть с ресурсами? Гляну.
|
|
| |
serg-kkz | Дата: Вторник, 26.08.2014, 13:21 | Сообщение # 44 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Вот, с нормалью разобрался. Думаю нужно будет применить какие нибудь фильтры, чтоб убрать полосы.
Запускай генератор, потом просмотр.
ООП -
Сообщение отредактировал serg-kkz - Вторник, 26.08.2014, 13:36 |
|
| |
ninth | Дата: Вторник, 26.08.2014, 16:07 | Сообщение # 45 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Альтернативная версия. Здесь полосы будут чуть сглажены. Изначально маска создаётся с заполненным синим каналом (трава) Код self.mask = Image.new("RGBA", (512,512), (0,0,255,0)) # Создаем новый файл изображения, с 4-мя каналами.
генерация камня Код def scan1(self, task): for x in range(512): for y in range(512): n = self.terrain.getNormal(x,y) n = Vec3(n.x*150, n.y*150, n.z) # 150 - масштаб террайна по высоте n.normalize() dot = abs(Vec3(0,0,1).dot(n)) r,g,b,a = self.mask.getpixel((x,y)) a = 255 - min(255, int(255 * dot ** 4 * 1.5)) # последние два коэффициента влияют на вертикальность и яркость прорисовки камней r = max(0, r-a) g = max(0, g-a) b = max(0, b-a) self.mask.putpixel((x, y), (r,g,b,a)) self.mask.save("data/default_d.png") sys.exit()
|
|
| |