Ранее в посте со схожим названием я описал свой способ подгрузки блоков ландшафта. чуть позже выяснилось, что не все так гладко, как хотелось бы. К сожалению, далеко не сразу москх додумывается до более полного использования возможностей им же изобретенного алгоритма.
Выяснилось, рнаботать-то подгрузка ландшафта работает, вот только идет лютая, хотя и кратковременная просадка логики - аж до 70 процентов и имеет место быть "мигание" террайна. В предыдущем посте я уже писал о путях решения проблемы. Выяснилось, что ни один из них не нужен, поскольку есть еще один - более простой и быстрый. Сначала приведу текст переименования террайна и выправления координат центра для каждого его блока.
import bpy
#print('xxx') # пoтому что камасутра чистой воды
scene = bpy.context.scene
listCoord = [-49,-47,-45,-43,-41,-39,-37,-35,-33,-31,-29,-27,-25,-23,-21,-19,-17,-15,-13,-11,-9,-7,-5,-3,-1,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49]
listIndex = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49]
blockX = 0
blockY = 0
cursorX = 0
cursorY = 0
for obj in scene.objects:
if '.' in obj.name: # у тебя должно быть другое имя
obj.select = True
X, Y, Z = obj.location
obj.data.name = obj.name
bpy.ops.object.origin_set(type = 'ORIGIN_GEOMETRY', center = 'MEDIAN')
for coordX in listCoord:
if (coordX-1)*10000 < X < (coordX+1)*10000:
blockX = listCoord.index(coordX)
scene.cursor_location[0] = coordX*10000
for coordY in listCoord:
if (coordY-1)*10000 < Y < (coordY+1)*10000:
blockY = listCoord.index(coordY)
scene.cursor_location[1] = coordY*10000
scene.cursor_location[2] = 0.0
bpy.ops.object.origin_set(type = 'ORIGIN_CURSOR')
newName = str(blockX) + '_' + str(blockY)
obj.name = newName
obj.data.name = obj.name
print(obj)
obj.select = False
Смысл всего этогог заключается в том, что каждый блок получает конкретное название, состоящее из слова "блок" и индекса квадрата, в котором он находится. в коде, думаю, ясно, как формируются индексы квадратов по Х и Y. Такое же название получает и меш блока. Теперь не надо создавать текстовый файл с длиннющим списком названий блоков, и их координатами. КООРДИНАТЫ каждого блока ВШИТЫ в его имя. с определенной поправкой, правда. У меня нет блоков с отрицательными значениями типа -35 или -2. Все индексы блоков заключены в интервале от 0 до 49.
А теперь приведем код подгрузки блоков ландшафта в новом варианте. Он пока еще не полон, осталось ввести список блоков района боевых действий для наземки, чтобы та не теряла опору под собой. Я не буду приводить "шапку" и окончание класса для экономии места
listCoord = [-49,-47,-45,-43,-41,-39,-37,-35,-33,-31,-29,-27,-25,-23,-21,-19,-17,-15,-13,-11,-9,-7,-5,-3,-1,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49]
listIndex = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49]
#Камера ТВ-прицела - вычисление нужного квадрата ее местонахождения
targetTV = scene.objects["CameraWorld"]
targetTVquadroX = int((int(targetTV.worldPosition[0]/1000)+ 490)/20)
targetTVquadroY = int((int(targetTV.worldPosition[1]/1000)+ 490)/20)
#Индексы "догружаемых" в сцену блоков - для этой камеры хватит и 9
targetTVblockX = str(listIndex.index(targetTVquadroX))
targetTVblockY = str(listIndex.index(targetTVquadroY))
targetTVblockX0 = str(listIndex.index(targetTVquadroX+1))
targetTVblockY0 = str(listIndex.index(targetTVquadroY+1))
targetTVblockX1 = str(listIndex.index(targetTVquadroX-1))
targetTVblockY1 = str(listIndex.index(targetTVquadroY-1))
#Жестко зафиксированный список для 9 блоков - "догружаемых" к камере ТВ-прицела
targetTVtempIndex = [('block_' + targetTVblockX + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY1 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX + '_' + targetTVblockY1 + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY1 + '_')]
for block in targetTVtempIndex:
if block not in scene.objects:
blockTerrain = scene.addObject(block, self)
blockTerrain.worldPosition[2] = 0.0
blockX = blockTerrain.name.split('_')[1]
blockY = blockTerrain.name.split('_')[2]
blockTerrain.worldPosition[0] = int(blockX)*20000 - 490000
blockTerrain.worldPosition[1] = int(blockY)*20000 - 490000
#Вычисление нужного квадрата, центрального блока ландшафта под камерой, целочисленные значения
#20 - размер блока в км, 490 - поправка сдвиг влево и вниз на "начало отсчета" от левого нижнего угла
#1000 - чтобы было меньше возни, отбрасываем метры, нас интересуют целые числа в диапазоне от 0 до 49
activeCam = scene.active_camera
quadroX = int((int(activeCam.worldPosition[0]/1000)+ 490)/20)
quadroY = int((int(activeCam.worldPosition[1]/1000)+ 490)/20)
#Вычисление индексов "огружаемых" блоков к камере игрока на ЛА - 25 блоков
blockX = str(listIndex.index(quadroX))
blockY = str(listIndex.index(quadroY))
blockX0 = str(listIndex.index(quadroX+1))
blockY0 = str(listIndex.index(quadroY+1))
blockX1 = str(listIndex.index(quadroX-1))
blockY1 = str(listIndex.index(quadroY-1))
blockX2 = str(listIndex.index(quadroX+2))
blockY2 = str(listIndex.index(quadroY+2))
blockX3 = str(listIndex.index(quadroX-2))
blockY3 = str(listIndex.index(quadroY-2))
#Жестко зафиксированный список для 25 блоков - "догружаемых" к камере игрока на ЛА
tempIndex = [('block_' + blockX + '_' + blockY + '_'),
('block_' + blockX0 + '_' + blockY0 + '_'),
('block_' + blockX1 + '_' + blockY1 + '_'),
('block_' + blockX1 + '_' + blockY + '_'),
('block_' + blockX + '_' + blockY1 + '_'),
('block_' + blockX0 + '_' + blockY + '_'),
('block_' + blockX + '_' + blockY0 + '_'),
('block_' + blockX1 + '_' + blockY0 + '_'),
('block_' + blockX0 + '_' + blockY1 + '_'),
('block_' + blockX2 + '_' + blockY + '_'),
('block_' + blockX2 + '_' + blockY0 + '_'),
('block_' + blockX2 + '_' + blockY1 + '_'),
('block_' + blockX2 + '_' + blockY2 + '_'),
('block_' + blockX2 + '_' + blockY3 + '_'),
('block_' + blockX3 + '_' + blockY + '_'),
('block_' + blockX3 + '_' + blockY0 + '_'),
('block_' + blockX3 + '_' + blockY1 + '_'),
('block_' + blockX3 + '_' + blockY2 + '_'),
('block_' + blockX3 + '_' + blockY3 + '_'),
('block_' + blockX0 + '_' + blockY2 + '_'),
('block_' + blockX1 + '_' + blockY2 + '_'),
('block_' + blockX + '_' + blockY2 + '_'),
('block_' + blockX0 + '_' + blockY3 + '_'),
('block_' + blockX1 + '_' + blockY3 + '_'),
('block_' + blockX + '_' + blockY3 + '_')]
for block in tempIndex:
if block not in scene.objects:
blockTerrain = scene.addObject(block, self)
blockTerrain.worldPosition[2] = 0.0
blockX = blockTerrain.name.split('_')[1]
blockY = blockTerrain.name.split('_')[2]
blockTerrain.worldPosition[0] = int(blockX)*20000 - 490000
blockTerrain.worldPosition[1] = int(blockY)*20000 - 490000
#Проверка на наличие лишних блоков и их уборка
for terrain in scene.objects:
if 'block_' in terrain.name:
if terrain.name not in tempIndex:
if terrain.name not in targetTVtempIndex:
terrain.endObject()
Суть в том, что есть два жестко фиксированных списка - один для камеры игрока на ЛА и вообще активной камеры в игре. Он рассчитан на 25 блоков, чтобы не было "пустот" на горипзонте (скорости-то большие). Второй список рассчитан на 9 блоков и нужен он для камеры ТВ прицела, передающей изображение на мониторы в кабине. Вроде бы он и лишний, но в то же время могут произойти такие события, когда он понадобится. Обратите внимание на длинные списки переменных для вычисления индексов сопутствующих блоков. Названия, наверное, не вполне удачные, а списки имен блоков я сделал "напрямую", без циклов и перебора значений в списке. Зато это работает и ничто не мешает в будущем это дело изменить. Как вычисляются координаты блоков по Х и Y, исходя из их имен, думаю, тоже понятно. Там просто вводится поправка по причине отсутствия отрицательных значений - так сложилось.
в конце идет проверка на наличие лишних блоков и их удаление. Перед тем, как задействовать этот алгоритм я пытался действовать через замену мешей террайна. Однако он кушал лишние 10 процентов логики, потому что объектов в сцене было ну очень много. При проверке работоспособности данного скрипта выяснилось, что кушает он меньше процента при частоте обновления раз в секунду (против 70 процентов при частоте обновления раз в три секунды). Зарекусь пока говорить о полной и безоговорочной победе, чтоб не сглазить - об этом можно будет уверенно сказать при работающих миссиях и кампаниях. Тем не менее, это явный шаг вперед, по сравнению с предыдущими вариантами. И да, ландшафт имеет 640 килополиков в сумме, вылетов БГЕ пока не отмечено, игровой процесс пока кушает 4 процента.
Картинок пока не будет - поскольку изменения были внутренние, а не внешние.
Теперь необходимо переходить к созданию меню с возможностью выбора оружия и редактирования миссий и кампаний. К тому же меню еще и будет завязано на выбор района БД, погоды и 2декораций", типа городов и авиабаз.
В заключение о декрациях. что-то мне не улыбается добавлять построчно каждый объект на тот же аэродром при его вызове. Гораздо проще сделать вызов группы объектов - ВПП и ее потомков - ангаров, башен и прочего. И произвести замену мешей. Опять будут задействованы имена объектов с "отсечением" лишнего типа _021. И вообще сильно мне полюбилось менять меши, да. Недавно тестил новые эффекты взрывов с помощью замены мешей-кадров, а не вызова плейнов-объектов, как раньше. выяснилось что две сотни одновременных взрывов кушают всего-то 5 процентов логики. Для движка это большое облегчение. Чуть позже напишу и об этом.
Выяснилось, рнаботать-то подгрузка ландшафта работает, вот только идет лютая, хотя и кратковременная просадка логики - аж до 70 процентов и имеет место быть "мигание" террайна. В предыдущем посте я уже писал о путях решения проблемы. Выяснилось, что ни один из них не нужен, поскольку есть еще один - более простой и быстрый. Сначала приведу текст переименования террайна и выправления координат центра для каждого его блока.
import bpy
#print('xxx') # пoтому что камасутра чистой воды
scene = bpy.context.scene
listCoord = [-49,-47,-45,-43,-41,-39,-37,-35,-33,-31,-29,-27,-25,-23,-21,-19,-17,-15,-13,-11,-9,-7,-5,-3,-1,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49]
listIndex = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49]
blockX = 0
blockY = 0
cursorX = 0
cursorY = 0
for obj in scene.objects:
if '.' in obj.name: # у тебя должно быть другое имя
obj.select = True
X, Y, Z = obj.location
obj.data.name = obj.name
bpy.ops.object.origin_set(type = 'ORIGIN_GEOMETRY', center = 'MEDIAN')
for coordX in listCoord:
if (coordX-1)*10000 < X < (coordX+1)*10000:
blockX = listCoord.index(coordX)
scene.cursor_location[0] = coordX*10000
for coordY in listCoord:
if (coordY-1)*10000 < Y < (coordY+1)*10000:
blockY = listCoord.index(coordY)
scene.cursor_location[1] = coordY*10000
scene.cursor_location[2] = 0.0
bpy.ops.object.origin_set(type = 'ORIGIN_CURSOR')
newName = str(blockX) + '_' + str(blockY)
obj.name = newName
obj.data.name = obj.name
print(obj)
obj.select = False
Смысл всего этогог заключается в том, что каждый блок получает конкретное название, состоящее из слова "блок" и индекса квадрата, в котором он находится. в коде, думаю, ясно, как формируются индексы квадратов по Х и Y. Такое же название получает и меш блока. Теперь не надо создавать текстовый файл с длиннющим списком названий блоков, и их координатами. КООРДИНАТЫ каждого блока ВШИТЫ в его имя. с определенной поправкой, правда. У меня нет блоков с отрицательными значениями типа -35 или -2. Все индексы блоков заключены в интервале от 0 до 49.
А теперь приведем код подгрузки блоков ландшафта в новом варианте. Он пока еще не полон, осталось ввести список блоков района боевых действий для наземки, чтобы та не теряла опору под собой. Я не буду приводить "шапку" и окончание класса для экономии места
listCoord = [-49,-47,-45,-43,-41,-39,-37,-35,-33,-31,-29,-27,-25,-23,-21,-19,-17,-15,-13,-11,-9,-7,-5,-3,-1,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49]
listIndex = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49]
#Камера ТВ-прицела - вычисление нужного квадрата ее местонахождения
targetTV = scene.objects["CameraWorld"]
targetTVquadroX = int((int(targetTV.worldPosition[0]/1000)+ 490)/20)
targetTVquadroY = int((int(targetTV.worldPosition[1]/1000)+ 490)/20)
#Индексы "догружаемых" в сцену блоков - для этой камеры хватит и 9
targetTVblockX = str(listIndex.index(targetTVquadroX))
targetTVblockY = str(listIndex.index(targetTVquadroY))
targetTVblockX0 = str(listIndex.index(targetTVquadroX+1))
targetTVblockY0 = str(listIndex.index(targetTVquadroY+1))
targetTVblockX1 = str(listIndex.index(targetTVquadroX-1))
targetTVblockY1 = str(listIndex.index(targetTVquadroY-1))
#Жестко зафиксированный список для 9 блоков - "догружаемых" к камере ТВ-прицела
targetTVtempIndex = [('block_' + targetTVblockX + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY1 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX + '_' + targetTVblockY1 + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY + '_'),
('block_' + targetTVblockX + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX1 + '_' + targetTVblockY0 + '_'),
('block_' + targetTVblockX0 + '_' + targetTVblockY1 + '_')]
for block in targetTVtempIndex:
if block not in scene.objects:
blockTerrain = scene.addObject(block, self)
blockTerrain.worldPosition[2] = 0.0
blockX = blockTerrain.name.split('_')[1]
blockY = blockTerrain.name.split('_')[2]
blockTerrain.worldPosition[0] = int(blockX)*20000 - 490000
blockTerrain.worldPosition[1] = int(blockY)*20000 - 490000
#Вычисление нужного квадрата, центрального блока ландшафта под камерой, целочисленные значения
#20 - размер блока в км, 490 - поправка сдвиг влево и вниз на "начало отсчета" от левого нижнего угла
#1000 - чтобы было меньше возни, отбрасываем метры, нас интересуют целые числа в диапазоне от 0 до 49
activeCam = scene.active_camera
quadroX = int((int(activeCam.worldPosition[0]/1000)+ 490)/20)
quadroY = int((int(activeCam.worldPosition[1]/1000)+ 490)/20)
#Вычисление индексов "огружаемых" блоков к камере игрока на ЛА - 25 блоков
blockX = str(listIndex.index(quadroX))
blockY = str(listIndex.index(quadroY))
blockX0 = str(listIndex.index(quadroX+1))
blockY0 = str(listIndex.index(quadroY+1))
blockX1 = str(listIndex.index(quadroX-1))
blockY1 = str(listIndex.index(quadroY-1))
blockX2 = str(listIndex.index(quadroX+2))
blockY2 = str(listIndex.index(quadroY+2))
blockX3 = str(listIndex.index(quadroX-2))
blockY3 = str(listIndex.index(quadroY-2))
#Жестко зафиксированный список для 25 блоков - "догружаемых" к камере игрока на ЛА
tempIndex = [('block_' + blockX + '_' + blockY + '_'),
('block_' + blockX0 + '_' + blockY0 + '_'),
('block_' + blockX1 + '_' + blockY1 + '_'),
('block_' + blockX1 + '_' + blockY + '_'),
('block_' + blockX + '_' + blockY1 + '_'),
('block_' + blockX0 + '_' + blockY + '_'),
('block_' + blockX + '_' + blockY0 + '_'),
('block_' + blockX1 + '_' + blockY0 + '_'),
('block_' + blockX0 + '_' + blockY1 + '_'),
('block_' + blockX2 + '_' + blockY + '_'),
('block_' + blockX2 + '_' + blockY0 + '_'),
('block_' + blockX2 + '_' + blockY1 + '_'),
('block_' + blockX2 + '_' + blockY2 + '_'),
('block_' + blockX2 + '_' + blockY3 + '_'),
('block_' + blockX3 + '_' + blockY + '_'),
('block_' + blockX3 + '_' + blockY0 + '_'),
('block_' + blockX3 + '_' + blockY1 + '_'),
('block_' + blockX3 + '_' + blockY2 + '_'),
('block_' + blockX3 + '_' + blockY3 + '_'),
('block_' + blockX0 + '_' + blockY2 + '_'),
('block_' + blockX1 + '_' + blockY2 + '_'),
('block_' + blockX + '_' + blockY2 + '_'),
('block_' + blockX0 + '_' + blockY3 + '_'),
('block_' + blockX1 + '_' + blockY3 + '_'),
('block_' + blockX + '_' + blockY3 + '_')]
for block in tempIndex:
if block not in scene.objects:
blockTerrain = scene.addObject(block, self)
blockTerrain.worldPosition[2] = 0.0
blockX = blockTerrain.name.split('_')[1]
blockY = blockTerrain.name.split('_')[2]
blockTerrain.worldPosition[0] = int(blockX)*20000 - 490000
blockTerrain.worldPosition[1] = int(blockY)*20000 - 490000
#Проверка на наличие лишних блоков и их уборка
for terrain in scene.objects:
if 'block_' in terrain.name:
if terrain.name not in tempIndex:
if terrain.name not in targetTVtempIndex:
terrain.endObject()
Суть в том, что есть два жестко фиксированных списка - один для камеры игрока на ЛА и вообще активной камеры в игре. Он рассчитан на 25 блоков, чтобы не было "пустот" на горипзонте (скорости-то большие). Второй список рассчитан на 9 блоков и нужен он для камеры ТВ прицела, передающей изображение на мониторы в кабине. Вроде бы он и лишний, но в то же время могут произойти такие события, когда он понадобится. Обратите внимание на длинные списки переменных для вычисления индексов сопутствующих блоков. Названия, наверное, не вполне удачные, а списки имен блоков я сделал "напрямую", без циклов и перебора значений в списке. Зато это работает и ничто не мешает в будущем это дело изменить. Как вычисляются координаты блоков по Х и Y, исходя из их имен, думаю, тоже понятно. Там просто вводится поправка по причине отсутствия отрицательных значений - так сложилось.
в конце идет проверка на наличие лишних блоков и их удаление. Перед тем, как задействовать этот алгоритм я пытался действовать через замену мешей террайна. Однако он кушал лишние 10 процентов логики, потому что объектов в сцене было ну очень много. При проверке работоспособности данного скрипта выяснилось, что кушает он меньше процента при частоте обновления раз в секунду (против 70 процентов при частоте обновления раз в три секунды). Зарекусь пока говорить о полной и безоговорочной победе, чтоб не сглазить - об этом можно будет уверенно сказать при работающих миссиях и кампаниях. Тем не менее, это явный шаг вперед, по сравнению с предыдущими вариантами. И да, ландшафт имеет 640 килополиков в сумме, вылетов БГЕ пока не отмечено, игровой процесс пока кушает 4 процента.
Картинок пока не будет - поскольку изменения были внутренние, а не внешние.
Теперь необходимо переходить к созданию меню с возможностью выбора оружия и редактирования миссий и кампаний. К тому же меню еще и будет завязано на выбор района БД, погоды и 2декораций", типа городов и авиабаз.
В заключение о декрациях. что-то мне не улыбается добавлять построчно каждый объект на тот же аэродром при его вызове. Гораздо проще сделать вызов группы объектов - ВПП и ее потомков - ангаров, башен и прочего. И произвести замену мешей. Опять будут задействованы имена объектов с "отсечением" лишнего типа _021. И вообще сильно мне полюбилось менять меши, да. Недавно тестил новые эффекты взрывов с помощью замены мешей-кадров, а не вызова плейнов-объектов, как раньше. выяснилось что две сотни одновременных взрывов кушают всего-то 5 процентов логики. Для движка это большое облегчение. Чуть позже напишу и об этом.
Комментариев нет:
Отправить комментарий