Tilemap rendering
|
|
soos | Дата: Среда, 22.06.2011, 15:39 | Сообщение # 31 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Quote (ninth) Кста, как вариант, ты можешь при получении данных формировать временный egg файл и грузить его как обычную модель. Это будет несколько проще чем мусолить внутреннюю структуру в рантайме, т.к. формат egg достаточно подробно описан и в принципе не сложен. Через одно место конечно, но попробовать стоит.
Quote (ninth) А ты его что каждый кадр обновляешь? О_о Нет.
Code node = GeomNode('gnode') for x in xrange(0,100): for z in xrange(0,100): gvd = GeomVertexData('name', GeomVertexFormat.getV3t2(), Geom.UHStatic) vertex = GeomVertexWriter(gvd, 'vertex') texcoord = GeomVertexWriter(gvd, 'texcoord') vertex.addData3f(x, 0, z) texcoord.addData2f(0, 0) vertex.addData3f(x, 0, z+1) texcoord.addData2f(0, 1) vertex.addData3f(x+1, 0, z+1) texcoord.addData2f(1, 1) vertex.addData3f(x+1, 0, z) texcoord.addData2f(1, 0) prim = GeomTriangles(Geom.UHStatic) prim.addVertices(0, 2, 1) prim.addVertices(0, 3, 2) geom = Geom(gvd) geom.addPrimitive(prim) node.addGeom(geom) terrain = render.attachNewNode(node) terrain.setRenderModeWireframe() run() Вот это рендерится на 10-12 fps
Quote (ninth) здесь пример удаления текстуры с полигона Гляну, попробую добавить текстуру.
Quote (serg-kkz) полигоны по отдельности рендерятся дольше, чем если они относяться к одному обьекту Как это? Полигоны можно рендерить по отдельности?
|
|
| |
ninth | Дата: Среда, 22.06.2011, 16:12 | Сообщение # 32 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Добавь перед run() terrain.flattenMedium() или terrain.flattenStrong()
Оптимизируется довольно долго перед запуском.
До оптимизации:
1 total nodes (including 0 instances); 0 LODNodes. 0 transforms; 100% of nodes have some render attribute. 10000 Geoms, with 10000 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 Geo mNodes. 40000 vertices, 0 normals, 0 colors, 40000 texture coordinates. GeomVertexData arrays occupy 782K memory. GeomPrimitive arrays occupy 118K memory. 9999 GeomPrimitive arrays are redundant, wasting 118K. 20000 triangles: 0 of these are on 0 tristrips. 20000 of these are independent triangles. 0 textures, estimated minimum 0K texture memory required.
После:
1 total nodes (including 0 instances); 0 LODNodes. 0 transforms; 0% of nodes have some render attribute. 1 Geoms, with 1 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 GeomNodes. 40000 vertices, 0 normals, 0 colors, 40000 texture coordinates. GeomVertexData arrays occupy 782K memory. GeomPrimitive arrays occupy 118K memory. 20000 triangles: 0 of these are on 0 tristrips. 20000 of these are independent triangles. 0 textures, estimated minimum 0K texture memory required.
Почувствуй разницу ) 10000 Geoms и 1 Geoms Зато разница в FPS видна невооружённым глазом ) И причина тоже )
|
|
| |
serg-kkz | Дата: Среда, 22.06.2011, 16:33 | Сообщение # 33 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Quote (soos) Как это? Полигоны можно рендерить по отдельности?
Я другое имел ввиду.
ninth уже ответил Quote (ninth) Почувствуй разницу ) 10000 Geoms и 1 Geoms
ООП -
|
|
| |
soos | Дата: Среда, 22.06.2011, 16:55 | Сообщение # 34 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Понятное дело, что flatten...() объединит все геомы, но суть не в том. Сейчас для меня главный вопрос в том, как повесить на отдельный полигон текстуру? Устал гуглить уже, но ничего не нашёл. :( Модель в egg файле - это набор вершин и полигонов, причём у каждого полигона есть текстура. Мне не понятно как это выглядит с точки зрения структур панды, потому что (как я понял) панда цепляет текстуру только к NodePath.
|
|
| |
serg-kkz | Дата: Среда, 22.06.2011, 17:05 | Сообщение # 35 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| NodePath это просто сылка, через которую панда цепляет текстурку на обьект на который она ссылается, а как цеплять её для панды описано в egg файле в соотвествующих тегах. Попробуй в примере multitexture
Code <Polygon> { <TRef> { 2.png } <MRef> { Material } <Normal> {0.000000 -1.000000 0.000000} <VertexRef> { 0 1 2 3 <Ref> { Plane }} } <Polygon> { <TRef> { 3.png } <MRef> { Material } <Normal> {0.000000 -1.000000 0.000000} <VertexRef> { 8 9 10 11 <Ref> { Plane }}
В строках <VertexRef> {<Ref> { Plane }} поменять номера вертексов например: 8 9 10 11 на 1 2 3 4 а, 1 2 3 4 на 8 9 10 11. Для наглядности. Позже я попробую написать генирируемый egg.
Впрочем если заранее определиться с размером полигона и количеством квадратов например 25*25 то можно сделать типа полигон-слот при генирации обекта где в строках имена текстур можно ипользовать переменные имени нужного тайла.
ООП -
Сообщение отредактировал serg-kkz - Среда, 22.06.2011, 17:36 |
|
| |
soos | Дата: Среда, 22.06.2011, 17:34 | Сообщение # 36 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Генерировать egg чтобы потом его же парсить и генерировать из него модель - это какой то изврат по-моему. Правильнее найти способ генерировать модель без избыточности. Я сделал в итоге генерацию и пришёл к тому с чего начал - сложный объект который упрощается flatten'ом :( Должен быть способ генерить эту модель изначально правильно. Порыскаю ещё. Вся суть flatten'а лишь в том, что он все геомы и их ноды объединяет в один.
Code ================================= BEFORE ======== 20004 total nodes (including 0 instances); 0 LODNodes. 1 transforms; 49% of nodes have some render attribute. 10000 Geoms, with 10000 GeomVertexDatas and 1 GeomVertexFormats, appear on 10000 GeomNodes. 40000 vertices, 0 normals, 0 colors, 40000 texture coordinates. GeomVertexData arrays occupy 782K memory. GeomPrimitive arrays occupy 118K memory. 9999 GeomPrimitive arrays are redundant, wasting 118K. 20000 triangles: 0 of these are on 0 tristrips. 20000 of these are independent triangles. 3 textures, estimated minimum 12K texture memory required. Code ================================= AFTER ========= 5 total nodes (including 0 instances); 0 LODNodes. 0 transforms; 20% of nodes have some render attribute. 3 Geoms, with 1 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 GeomNodes. 40000 vertices, 0 normals, 0 colors, 40000 texture coordinates. GeomVertexData arrays occupy 782K memory. GeomPrimitive arrays occupy 118K memory. 20000 triangles: 0 of these are on 0 tristrips. 20000 of these are independent triangles. 3 textures, estimated minimum 12K texture memory required.
|
|
| |
serg-kkz | Дата: Среда, 22.06.2011, 17:45 | Сообщение # 37 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Quote (soos) Вся суть flatten'а лишь в том, что он все геомы и их ноды объединяет в один
soos ты вроде завел разговор про скорость рендера. Вот и вспомнили про flatten.
Quote (soos) Генерировать egg чтобы потом его же парсить и генерировать из него модель - это какой то изврат по-моему
soos ты вроде завел разговор про генерацию меша на лету. Вот и вспомнили про egg.
Про избыточность скажу что она ничтожна, ибо все 3d игры страдают такой фигнёй "Loading"
А парсить не надо(то есть писать свой загрузчик) , надо сохранит и всё , а парсить будет загрузчик панды.
ООП -
Сообщение отредактировал serg-kkz - Среда, 22.06.2011, 17:49 |
|
| |
ninth | Дата: Среда, 22.06.2011, 19:41 | Сообщение # 38 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Вот тебе переделанный код чтобы писть в 1 геом. По текстурам чуть позже попробую глянуть.
Code node = GeomNode('gnode') gvd = GeomVertexData('name', GeomVertexFormat.getV3t2(), Geom.UHStatic) geom = Geom(gvd) prim = GeomTriangles(Geom.UHStatic) vertex = GeomVertexWriter(gvd, 'vertex') texcoord = GeomVertexWriter(gvd, 'texcoord') i = 0 for x in xrange(0,100): for z in xrange(0,100): vertex.addData3f(x, 0, z) texcoord.addData2f(0, 0) vertex.addData3f(x, 0, z+1) texcoord.addData2f(0, 1) vertex.addData3f(x+1, 0, z+1) texcoord.addData2f(1, 1) vertex.addData3f(x+1, 0, z) texcoord.addData2f(1, 0) prim.addVertices(i*4, i*4 + 2, i*4 + 1) prim.addVertices(i*4, i*4 + 3, i*4 + 2) i += 1 prim.closePrimitive() geom.addPrimitive(prim) node.addGeom(geom) terrain = render.attachNewNode(node) terrain.setRenderModeWireframe() terrain.analyze() run()
|
|
| |
soos | Дата: Среда, 22.06.2011, 21:06 | Сообщение # 39 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Quote (ninth) Вот тебе переделанный код чтобы писть в 1 геом Спасибо. Я тоже до подобного кода дошёл. А вот с текстурами совсем никак. Сейчас буду смотреть исходники на предмет того как Loader загружает egg файл и линкует полигоны с текстурами.
|
|
| |
ninth | Дата: Четверг, 23.06.2011, 00:15 | Сообщение # 40 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Ок. Вот тебе полный пример генерация + текстурирование + скрин ) К коду положи текстурки которые я выкладывал с egg файлом с теми же именами (1.png 2.png 3.png) Если будешь копировать отсюда код - смотри - местный bb code уже пробелов навтыкал, например 'index' превратил в 'in dex' так что перепроверь. Code from pandac.PandaModules import * loadPrcFileData("editor-startup", "show-frame-rate-meter #t") import direct.directbase.DirectStart from random import randint
node = GeomNode('gnode') geoms = [] for i in xrange(3): gvd = GeomVertexData('name', GeomVertexFormat.getV3t2(), Geom.UHStatic) geom = Geom(gvd) prim = GeomTriangles(Geom.UHStatic) vertex = GeomVertexWriter(gvd, 'vertex') texcoord = GeomVertexWriter(gvd, 'texcoord') tex = loader.loadTexture('%i.png' % (i+1)) tex.setMagfilter(Texture.FTLinearMipmapLinear) tex.setMinfilter(Texture.FTLinearMipmapLinear) geoms.append({'geo m': geom, 'prim':prim, 'vertex':vertex, 'texcoord':texcoord, ' in dex':0, 'gvd':gvd, 'texture':tex})
for x in xrange(0,100): for z in xrange(0,100): t_img = randint(0,2) i = geoms[t_img]['index'] geoms[t_img]['vertex'].addData3f(x, 0, z) geoms[t_img]['texcoord'].addData2f(0, 0) geoms[t_img]['vertex'].addData3f(x, 0, z+1) geoms[t_img]['texcoord'].addData2f(0, 1) geoms[t_img]['vertex'].addData3f(x+1, 0, z+1) geoms[t_img]['texcoord'].addData2f(1, 1) geoms[t_img]['vertex'].addData3f(x+1, 0, z) geoms[t_img]['texcoord'].addData2f(1, 0) geoms[t_img]['prim'].addVertices(i*4, i*4 + 2, i*4 + 1) geoms[t_img]['prim'].addVertices(i*4, i*4 + 3, i*4 + 2) geoms[t_img]['index'] += 1
for i in xrange(3): geoms[i]['prim'].closePrimitive() geoms[i]['geom'].addPrimitive(geoms[i]['prim']) node.addGeom(geoms[i]['geom']) node.setGeomState(i, node.getGeomState(i).addAttrib(TextureAttrib.make(geoms[i]['texture'])))
terrain = render.attachNewNode(node) #terrain.setRenderModeWireframe() terrain.analyze()
run()
|
|
| |
soos | Дата: Четверг, 23.06.2011, 10:56 | Сообщение # 41 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Quote (ninth) Вот тебе полный пример генерация + текстурирование + скрин ) Большое человеческое спасибо! Можно двигаться дальше. Постараюсь прогресс в разработке освещать (в том или ином виде)
|
|
| |
serg-kkz | Дата: Воскресенье, 26.06.2011, 13:59 | Сообщение # 42 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Вот пример через "цензура"
Добавлено (24.06.2011, 22:35) --------------------------------------------- Кажется я обнаружил в своём коде кое какое недоразумение, попозже исправлю. Ведь egg моно забацать средствами панды, а не тупым склеиванием строк.
Добавлено (25.06.2011, 21:55) --------------------------------------------- оказалось создание egg средствами панды только нервы портить, классы глючат ни какой гибкости, например текстуру можно добавить через EggPolygon который создаёт и Polygon. Загрузка напрямую из EggData в рендер тоже не всё как надо, например 10000 поликов грузит как разные обьекты, хотя если сохранить в файл, и загрузить то будет всё как надо. То лучше уж клеить строки. Легко и просто.
Добавлено (26.06.2011, 13:59) --------------------------------------------- Вот исправил, не нужных действий меньше. Но всё таки скорость загрузки очень медленная. loadEggData тужится ~ 9 сек, переливание данных из виртуального файла в EggData ~2 сек, сама же генерация 0.2 - 10000 полигонов. Кстати egg сгенирированный методом склеиванием строк можно сохранить пандовским writeEgg то разметка синтаксиса будет оформлена в правильный вид.
ООП -
Сообщение отредактировал serg-kkz - Воскресенье, 26.06.2011, 14:17 |
|
| |
ninth | Дата: Понедельник, 27.06.2011, 00:47 | Сообщение # 43 |
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| В принципе, я думаю оба эти куска можно кинуть в "примеры кода".
|
|
| |
soos | Дата: Четверг, 30.06.2011, 19:13 | Сообщение # 44 |
Майор
Группа: Пользователи
Сообщений: 82
Награды: 1
Репутация: 0
Статус: Offline
| Обернул всё в класс: Code class tilemap(NodePath): def __init__(self, name='tilemap'): NodePath.__init__(self, name) self.terrain_node = GeomNode(name) self.attachNewNode(self.terrain_node) self.geoms = [] def add_tile_type(self, tex_file): gvd = GeomVertexData('gvd', GeomVertexFormat.getV3t2(), Geom.UHStatic) geom = Geom(gvd) prim = GeomTriangles(Geom.UHStatic) vertex = GeomVertexWriter(gvd, 'vertex') texcoord = GeomVertexWriter(gvd, 'texcoord') tex = loader.loadTexture(tex_file) tex.setMagfilter(Texture.FTLinearMipmapLinear) tex.setMinfilter(Texture.FTLinearMipmapLinear) rs = RenderState.make(TextureAttrib.make(tex)) self.terrain_node.addGeom(geom, rs) self.geoms.append({'geom':geom,'prim':prim,'vertex':vertex,'texcoord':texcoord,'index':0,'gvd':gvd,'texture':tex}) def add_tile(self, x, z, tile_type): i = self.geoms[tile_type]['index'] v = self.geoms[tile_type]['vertex'] t = self.geoms[tile_type]['texcoord'] p = self.geoms[tile_type]['prim'] v.addData3f(x, 0, z) t.addData2f(0, 0) v.addData3f(x, 0, z+1) t.addData2f(0, 1) v.addData3f(x+1, 0, z+1) t.addData2f(1, 1) v.addData3f(x+1, 0, z) t.addData2f(1, 0) p.addVertices(i*4, i*4 + 2, i*4 + 1) p.addVertices(i*4, i*4 + 3, i*4 + 2) self.geoms[tile_type]['index'] += 1 def bake(self): for i in xrange(0, len(self.geoms)): self.geoms[i]['prim'].closePrimitive() self.geoms[i]['geom'].addPrimitive(self.geoms[i]['prim'])
terrain = tilemap()
for i in xrange(0,3): terrain.add_tile_type('tile%i.png' % (i+1))
size = 100 for x in xrange(0,size): for z in xrange(0,size): terrain.add_tile(x, z, random.randint(0,2))
terrain.bake() terrain.reparentTo(render) terrain.setPos(-size/2,0,-size/2) terrain.analyze()
run()
Думаю как это оптимизировать и можно ли сделать динамическое добавление/удаление тайлов.
|
|
| |
serg-kkz | Дата: Четверг, 30.06.2011, 19:26 | Сообщение # 45 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Ты всё заткнул в иницилизацию, а надо в функцию над который ты будешь иметь контроль, попробуй для начала сделать генерацию по нажатию кнопки. Для поставленой задачи потребуютя координаты, по которым надо расчитать четыре точки и добавить их к геометрии и вызвать функцию.
Вот пример для расчёта:
x = 2 y = 3
Расчитывем координаты vertex'ов из которых будет строиться полигон(это пример если через egg, но может и здесь будет работать)
0 vertex = x-0.5, y-0.5 добавляем к геометрии - 1.5, 1,5 1 vertex = x+0.5, y-0.5 добавляем к геометрии - 2.5, 1.5 2 vertex = x+0.5, y+0.5 добавляем к геометрии - 2.5, 3.5 3 vertex = x-0.5, y+0.5 добавляем к геометрии - 1.5, 3.5
Примечание: это формула для квадрата 1*1
Для оптимизации переделый код чтоб только генерил один полигон без for'ов, ведь ты будешь в место этого вызывать функцию по событию, получил координаты - передал функции с вызовом её.
ООП -
Сообщение отредактировал serg-kkz - Четверг, 30.06.2011, 20:36 |
|
| |