... решение по коррекции траектории - делать расчёт точки соприкосновения (через вектора) или попытаться использовать точку, которая формируется во время коллизии при соприкосновении колеса с землёй, но там есть свои проблемы (поскольку будут соприкасаться левая или правая сторона колеса) ...Вектора вряд ли мне сейчас будут по зубам, а вот соприкосновение левой или правой стороной колеса попробую устранить за счёт ликвидации угла наклона колеса. Николай, я очень доволен твоей помощью, спасибо большое. Очень рад знакомству.
... у меня был проект на плоскости с треками и следом ( https://sungreen.github.io/projects/veterbot/veterbot.html ), но рассчитывал всё через в скриптах ...Здорово. Ещё бы позёмка развевала след, было бы вообще супер, а так она выглядит здесь лишней.
... и отложил идею делать на неровной поверхности из-за усложнения расчётов ...
... поэтому у меня интерес к этой теме тоже есть ...
... поясни цель задачи, это курсовик? может стоит условия поменять ...Нет. Любопытство. Желание попробовать свои силы в самостоятельном изучении чего-то нового, незнакомого. А, условия и так самые примитивные.
if not 'objs' in own: # если нет списка добавляемых следов
print("25 not 'objs' in own = ", not 'objs' in own)
own['objs'] = [] # создать список добавляемых следов
longSleda = 0 # назначаю параметр переменной
print("29 longSleda = ", longSleda) # проверка
elif own['objs'] == []: # если список уже создан
print("31 not 'objs' in own = ", not 'objs' in own
own['objs'].append(sled) # добавить след в список
longSleda += spd # наращиваю длину следа
print("34 longSleda = ", longSleda) # проверкка
if longSleda >= 0.4:
print("36 longSleda = ", longSleda)
sled = scn.addObject(inobjs[sled]) # добавить след в сцену
sled.worldPosition.x = pos.x #расположить след в точке столкновения
sled.worldPosition.y = pos.y #расположить след в точке столкновения
sled.worldPosition.z = pos.z - 1 #расположить след в точке столкновения, с заданным отступом
print("41 sled.worldPosition = ", sled.worldPosition) #
own['objs'] = [] # очистить список следов
longSleda = 0
25 not 'objs' in own = TrueКак долго переменные живут, только в одном кадре, или я в чём-то другом ошибаюсь?
29 longSleda = 0
=
31 not 'objs' in own = False
Python script error - object 'Koleso', controller 'Python':
Traceback (most recent call last):
File "Text", line 33, in <module>
NameError: name 'longSleda' is not defined
Как долго переменные живут, только в одном кадре, или я в чём-то другом ошибаюсь?Куском чего является этот твой код?
... рекомендовал бы использовать Module Mode против Script Mode, преимущества описаны здесь https://wiki.blender.org/index.php/Doc:/Tutorials/Game_Engine/ScriptMode_vs_ModuleMode ...Постараюсь освоить и модули. Blender меня заинтересовал своими возможностями "не программируя делать программы" - ведь я не программист и имею самые начальные понятия в этом деле. Затем заинтересовавшись BGE, увидел любопытную возможность воздействия на происходящие процессы, но тут потребовалось создавать скрипты. "Скрипнув зубами", освоил самые простые возможности. Теперь мне предлагается освоить модули...
... собственно Module Mode - полноценная программа внутри Blender с соответствующими областями видимости переменных, в том числе и global ...
Куском чего является этот твой код?Да, по сути, ответом на вызов появления следа за колесом в ответ на его перемещение.
Если это внутри какой-либо функции, то все её локальные переменные живут только внутри одного вызова.Я благодарен за пояснения. Вроде всё очевидно, однако сам это учесть не смог.
Если нужно длительное хранение значения, то это должна быть либо глобальная переменная (для её изменения внутри функции применяется ключевое слово globals), либо она должна быть членом некоего большого объекта (тогда уже он должен быть глобальной переменной) - это может быть экземпляр класса, или, например, словарь.
Николай, что у меня получилось видно на рисунке Sled 3.jpg.
... и отложил идею делать на неровной поверхности из-за усложнения расчётов ...
... поэтому у меня интерес к этой теме тоже есть ...
... у меня был проект на плоскости с треками и следом ( https://sungreen.github.io/projects/veterbot/veterbot.html ), но рассчитывал всё через в скриптах ...Гоняю и гоняю я этот вездеход, и всё больше и больше мне он нравится.
... и отложил идею делать на неровной поверхности из-за усложнения расчётов ...
... поэтому у меня интерес к этой теме тоже есть ...
import bge
from mathutils import Vector# из модуля mathutils импортировать Vector
def init():
global sc
global wl
global sl
global gr
print("Init app\n\n\n")
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
wl = sc.objects['wheel']
gr = sc.objects['ground']
gr.collisionCallbacks.append(callback)
def callback(object, point, normal):
ob = sc.addObject(sl)
a = wl.getAxisVect(Vector((0,0,1)))
ob.worldPosition = object.worldPosition+Vector((0,0,-1))
ob.alignAxisToVect(a,0,1)
import bge
from mathutils import Vector# из модуля mathutils импортировать Vector
z = Vector((0,0,1))
def init():
global sc
global wl
global sl
global gr
print("Init app\n\n\n")
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
wl = sc.objects['wheel']
gr = sc.objects['ground']
gr.collisionCallbacks.append(callback)
def callback(object, point, normal):
ob = sc.addObject(sl)
a = wl.getAxisVect(z)
ob.worldPosition = object.worldPosition-z
ob.alignAxisToVect(a,0,1)
>> Ладно, помоги хоть найти ответы на более простые вопросы, которые уже мною заданы.Николай, паники-то нет никакой. Всё дело в том, что я действительно не программист. Могу создать цикл, могу провести проверку условий, и, по результатам проверки что-то предпринять. Тонкости типа классов, их отличие, структуры и т.д. мне практически неведомы. Я полагал, что возможности Blender снивелируют дефицит знаний и опыта в программировании. В какой-то мере это так и случилось. Однако есть не менее серьёзное препятствие – я зачастую не могу правильно изложить свои затруднения. Опять же из-за малых знаний.
... только без паники, повторите вкратце суть вопросов ...
... так или иначе постараемся найти на них решение ... >> Очень похоже что я рано в эти дебри свой нос сунул.
... в чем предмет опасения? ...
... посмотри функцию alignAxisToVect, если у тебя есть нормаль к поверхности, то попробуй выровнять след по ней ...
https://docs.blender.org/api/blender_python_api_2_77_0/bge.types.KX_GameObject.html?highlight=alignaxistovect#bge.types.KX_GameObject.alignAxisToVectВыравнивание оси игрового объекта по мировому вектору.
http://bgepython.tutorialsforblender3d.com/GameObject/alignAxisToVect
import bge
from mathutils import Vector# из модуля mathutils импортировать Vector
z = Vector((0,0,1))
def init():
global sc
global wl
global sl
global gr
print("Init app\n\n\n")
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
wl = sc.objects['wheel']
gr = sc.objects['ground']
gr.collisionCallbacks.append(callback)
def callback(object, point, normal):
ob = sc.addObject(sl)
a = wl.getAxisVect(z)
ob.alignAxisToVect(a,0,1)
a = ob.getAxisVect(z)
ob.worldPosition = object.worldPosition
obj,point,normal = ob.rayCast(ob.worldPosition-a*2)
if obj:
print(point)
ob.worldPosition = point+a*0.03
ob.alignAxisToVect(normal,2,1)
from bge import logic as L # из модуля bge импортировать logic как L
from mathutils import Vector# из модуля mathutils импортировать Vector
cont = L.getCurrentController()# получить активный контроллер
own = cont.owner # получить объект Koleso - владелец контроллера
pos = own.worldPosition # получить позицию колеса
print("6 pos = ", pos) #
scn = own.scene # получить активную сцену Scene
inobjs = scn.objectsInactive # получить неактивный объект [Plane]
print("9 inobjs = ", inobjs) #
#вычисление скорости движения объекта
sm = own.get("oldPos", pos) - pos
print("12 sm = ", sm) #
spd = (sm.x ** 2 + sm.y ** 2) ** 0.5
own["oldPos"] = pos.copy() # .copy() - копирует вектор
print("15 own[oldPos] = ", own["oldPos"], " spd = ",spd) #
###########настройки#############
sled = 'Plane' # имя объекта-следа, он находится на скрытом слое
speed = 0.01 #скорость, требуемая для активации
################################
if sled in inobjs and spd >= speed: #если есть объект-след на скрытом слое, а скорость больше или равна указанной
sled = scn.addObject(inobjs[sled]) # добавить след в сцену
a = own.getAxisVect(Vector((0,0,1)))
sled.alignAxisToVect(a,0,1)
a = sled.getAxisVect(Vector((0,0,1)))
sled.worldPosition = own.worldPosition
obj,point,normal = sled.rayCast(sled.worldPosition-a*2)
if obj:
sled.worldPosition = point+a*0.03
sled.alignAxisToVect(normal,2,1)
print("25 sled.worldPosition = ", sled.worldPosition) #
print(" = ")
>> Насколько я понял, нормаль поверхности в точке соприкосновения ведь не определена, а, следовательно, пока преждевременно след располагать на поверхности?Открыл ссылку… Здорово, но абсолютно непонятно… В объектном программировании я ноль.
... ответ не однозначен (для меня) - значение точки соприкосновения и нормали формируется во время обратного вызова при обработке коллизии https://docs.blender.org/api/2.79/bge.types.KX_GameObject.html?highlight=collisioncallbacks#bge.types.KX_GameObject.collisionCallbacks ...
... насколько это значения тебя устроят?! сомневаюсь что полностью ...
>> Выравнивание оси игрового объекта по мировому вектору.В твоей ссылке http://bgepython.tutorialsforblender3d.com/GameObject/alignAxisToVect в сообщении от 29 Марта 2018, 13:30:42.
>> alignAxisToVect(vect, axis, fac – скобка не закрыта из-за опечатки?
... где приведён такой текст? ...
>> vect – в моём случае (0.0, 0.0, -1.0)? Отрицательное направление оси ZПогоди гнать, Николай с векторными операциями.
... обрати внимание на этот топик http://blender-3d.ru/forum/index.php/topic,326.msg4308.html#msg4308 ...
... тебя не должно это пугать ...
... если у тебя есть z = Vector(0,0,1) , то чтобы получить Vector(0,0,-1) нужно просто использовать -z ...
... в целом в коде у тебя векторные операции будут выглядеть как a = b+c ...
>> Всё дело в том, что я действительно не программист.Инженер-технолог в цехе холодной обработки металла на опытном производстве.
... какой вид деятельности? если не секрет ...
... страх, негативный опыт, отрицательная практика или бытовое отвращение к этой категории?Только незнание и отсутствие навыка. Поздно заинтересовался 3D графикой – собственно вынужденно заинтересовался.
... пиши больше мелких вопросов и типа "делаю это, не получается" ...Пытаюсь, но не всегда получается.
... и выкладывай больше кода и промежуточные модели, это значительно ускоряет решение проблем ...
... http://bgepython.tutorialsforblender3d.com/ - попробуй использовать те примеры, которые уже решены и хорошо себя показали, и в части этой позитивной практики можешь комбинировать элементы этих решений в своих целях ...Я так и поступаю. На указанный сайт как попал не помню, может полгода назад, может больше и сразу же его «загнал» в папку «Избранные». Помог он мне знатно.
>> Строка b.normalize() позволяет определить нормаль для вектора b?Зашибись. Так что это тогда?
... нет ...
>> Мне необходима нормаль к части поверхности (плоскости) в определённой точке.Была у меня такая попытка – видел описание rayCast.
... для этого есть rayCast - от объекта исходит луч в сторону поверхности, в ответ получаешь точку соприкосновения и нормаль ...
import math # импортировать модуль math
from bge import logic as L # из модуля bge импортировать logic как L
from mathutils import Vector# из модуля mathutils импортировать Vector
from mathutils import Euler # импортировать функцию Euler из модуля mathutils
cont = L.getCurrentController()# получить активный контроллер
own = cont.owner # получить объект Koleso - владелец контроллера
pos = own.worldPosition # получить позицию колеса
print("8 pos = ", pos) #
scn = own.scene # получить активную сцену Scene
inobjs = scn.objectsInactive # получить неактивный объект [Plane]
# print("11 inobjs = ", inobjs) #
#вычисление скорости движения объекта
puty = own.get("oldPos", pos) - pos # вектор разности между предыдущей и текущей позицией следа
# print("14 puty = ", puty) #
spd = (puty.x ** 2 + puty.y ** 2) ** 0.5 # пройденный путь колесом
own["oldPos"] = pos.copy() # .copy() - копирует вектор
print("17 spd = ",spd) #
###########настройки#############
sled = 'Plane' # имя объекта-следа, он находится на скрытом слое
speed = 0.01 # скорость, требуемая для активации
vect = 0, 0, 1 # вектор луча
dist = 2.1 # длина луча
################################
print("25 pos = ", pos)
print("26 own.getAxisVect(vect) = ", own.getAxisVect(vect))
obj, hit, norm = own.rayCast(pos + own.getAxisVect(vect) * dist)
print("28 obj = ", obj, " hit = ",hit, " norm = ",norm) #
>> Поздно заинтересовался 3D графикой – собственно вынужденно заинтересовался.Просто есть проблемы с абстрактным восприятием. Для понимания работы оснастки со сложными траекториями движения нескольких точек. Я просто теряю ориентацию – необходимо иметь возможность наглядной демонстрации, что и в каких ситуациях происходит. BGE, как помощник с возможностью управления в текущем моменте, для этой цели, должен стать незаменимым. По крайней мере, я надеюсь на это.
... ранее задавал вопрос "зачем это нужно, какая цель преследуется" ...
... поясни всё-таки зачем тебе 3D, возможно что так будет легче подобрать решение, ты же технолог должен понимать что и в 3D есть разные технологические приёмы, используемые оснастки ...
[quote author=Николай Николаев link=topic=2090.msg29485#msg29485 date=1522472304][/quote]
[color=green]Николай, в этой строке что за переменная получается?[/color]
a = own.getAxisVect(Vector((0,0,1)))
[color=green]Вектор выравнивания по оси Х? В чём смысл?[/color]
sled.alignAxisToVect(a,0,1)
a = sled.getAxisVect(Vector((0,0,1)))
sled.worldPosition = own.worldPosition
obj,point,normal = sled.rayCast(sled.worldPosition-a*2) [color=green]- что это за значение "-a*2", в чём его смысл?[/color]
if obj:
sled.worldPosition = point+a*0.03 [color=green]- а это значение "a*0.03" получено методом "научного тыка"? Работает сразу по трём осям?[/color]
sled.alignAxisToVect(normal,2,1)
print("25 sled.worldPosition = ", sled.worldPosition) #
print(" = ")
a = own.getAxisVect(Vector((0,0,1)))
sled.alignAxisToVect(a,0,1)
sled.worldPosition = own.worldPosition
a = sled.getAxisVect(Vector((0,0,1)))
obj,point,normal = sled.rayCast(sled.worldPosition-a*2)
sled.worldPosition = point+a*0.03
Галопом по европам. С физикой лучше ознакомился, в особенности с жидкостями, с арматурой - по-хуже, с ограничениями - можно сказать совсем плохо. Интересовали частицы - имею некоторое представление. Намечал разобраться со следами, через текстурирование, затем через взаимодействия сеток и уж потом колесо должно покатиться по луже разбрызгивая брызги по сторонам. Если ничто отвлекать не будет, и, повезёт, сумею найти видеоурок или необходимые статьи, то, несмотря на отсутствие официальной возможности работы BGE с частицами, надеюсь добиться своего. Недавно попалась статья на глаза о частицах в BGE, но разбираться пока не пытался.
...
... а как у тебя с арматурной анимацией в Blender, с Physics и Rigid Body без BGE пробовал?
https://docs.blender.org/manual/ru/dev/physics/index.html#physics-types
https://docs.blender.org/manual/en/dev/physics/rigid_body/index.html
...
>>> a = own.getAxisVect(Vector((0,0,1))) Вектор выравнивания по оси Х? В чём смысл?Интересно девки пляшут… Давай поэтапно.
>>> obj,point,normal = sled.rayCast(sled.worldPosition-a*2) - что это за значение "-a*2", в чём его смысл?
>>> sled.worldPosition = point+a*0.03 - а это значение "a*0.03" получено методом "научного тыка"? Работает сразу по трём осям?
... представь, что происходит во время движения колеса с осями Z и Y - они вращаются вокруг оси X, а ось X перпендикулярна плоскости,в которой вращается колесо и эта плоскость вертикальна к поверхности (с небольшим наклоном) ...
... то есть базироваться по другим осям кроме X смысла нет ...Кодa = own.getAxisVect(Vector((0,0,1)))
sled.alignAxisToVect(a,0,1)
sled.worldPosition = own.worldPosition
>> я не спорю с тобой – я уточняю правильность своего понимания.Извини Николай, но думаю лучше не отвлекаться на другие последовательности, пока в этой есть непонятки.
... у меня нет стопроцентной уверенности, код, который представил, результат экспериментов на понимание ...
... возможно что есть решение в другой последовательности, думаю вместе разберёмся ...
... давай вместе порассуждаем ...Это я понял, к тому же это рассуждения уже о макроуровне. Нет, он, конечно тоже интересен, но для случая создания колеи следа – изменение сетки.
... на левой картинке - колесо и две точки касания, А - точка касания середины колеса (допустим поверхность под таким наклоном) и B - точка касания, которую отдаёт обратный вызов коллизии (нарисованный след в ней выглядит нелепо, поскольку точки могут быть и слева и справа) ...
... на правой картинке тоже не очевидно куда пускать луч для определения точки соприкосновения (вниз или ?) ...
... внизу моё представление о скольжении куба и качении шара по наклонной плоскости ...Куб скользит – без вопросов. Шар катится с вращением осей вокруг оси Х почему? С моими «тараканами» это как-то не увязывается. Я всегда думал, что оси координат неизменны, и изменяются только значения для объектов.
... после того как выровняли след по X получаем от него вектор, который направлен по Z (причём это не глобальный Z, а именно Z локальный с учётом наклона следа, то есть плоскость, в которой лежит след перпендикулярна плоскости в которой вращается колеса) и стреляем в этом направлении в сторону поверхности на два расстояния длины этого вектора и по направлению этого вектора ...Вопрос: «длина вектора 1 и радиус вектора 1» - разве это не одно и то же?
... по идее нужно стрелять на радиус колеса с небольшим запасом, но суть в том что длина вектора 1 и радиус вектора 1, то две длины вектора это двойной запас ...
Вектор «а» имеет положительное направление по оси Z, потому и минусуем?Код... в идеале и с математической стороны можно просто переместить след в point, но тогда во время его отрисовки он будет перекрываться поверхностью, то есть его следует поднять на минимально приемлемое расстояние над поверхностью ...a = sled.getAxisVect(Vector((0,0,1)))
obj,point,normal = sled.rayCast(sled.worldPosition-a*2)
... но поднимать его нужно не по оси Z, а по направлению нормали к поверхности, а это вектор "a" ...
И, всё же. Крутизна склона может быть разной, а потому, если не рассчитывать её фактическое значение в точке, то остаётся подбор коэффициента?Код>> получено методом "научного тыка"sled.worldPosition = point+a*0.03
... 0.03 получено скорее методом "экспертная оценка", если бы след гарантированно попадал только в один полигон поверхности, то можно было бы использовать минимально вменяемое значение 0.001, но в твоём случае это бы съело часть следа неровностью смежных полигонов поверхности ...
>> Вектор «а» имеет положительное направление по оси Z, потому и минусуем?Не понял. Я про строку:
... вектор «а» он в большинстве случаев смотрит примерно вверх, а нужно пустить луч вниз к поверхности ...
... мне через 20 минут коптильню снимать ...Хм, так у меня ничего не горит... Запросто подождать могу.
>> Можешь поделиться своими соображениями, которыми пользовался создавая след за своим вездеходом?А, я, хотел переспросить, что за мувик такой, я должен был посмотреть.
... а ты смотрел мувик в конце этого поста http://blender-3d.ru/forum/index.php/topic,2090.msg29474.html#msg29474 это и есть мои соображения на твой вопрос ...
import bge
from mathutils import Vector# из модуля mathutils импортировать Vector
z = Vector((0,0,1))
def init(): # объявление глбальных переменных
global sc # сцены
global wl # колеса
global sl # следа
global gr # поверхности
print("Init app\n\n\n") # назначение глбальных переменных
sc = bge.logic.getCurrentScene() # сцены
sl = sc.objectsInactive['sled'] # следа
wl = sc.objects['wheel'] # колеса
gr = sc.objects['ground'] # поверхности
gr.collisionCallbacks.append(callback) # вызов процедуры callback ???
def callback(object, point, normal):
ob = sc.addObject(sl) # добавить объект следа в сцену
a = wl.getAxisVect(z) # вектор луча исходящий от колеса
ob.worldPosition = object.worldPosition-z # позицию следа установить от позиции колеса за вычетом вектора луча
ob.alignAxisToVect(a,0,1) # выверить след согласно вектору исходящего от колеса
import bge
from mathutils import Vector# из модуля mathutils импортировать Vector
z = Vector((0,0,1))
def init():
bge.logic.getCurrentScene().objects['ground'].collisionCallbacks.append(callback)
def callback(object, point, normal):
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
ob = sc.addObject(sl)
a = object.getAxisVect(z)
ob.alignAxisToVect(a,0,1)
a = ob.getAxisVect(z)
ob.worldPosition = object.worldPosition
obj,point,normal = ob.rayCast(ob.worldPosition-a*2)
if obj:
print(point)
ob.worldPosition = point+a*0.03
ob.alignAxisToVect(normal,2,1)
>> gr.collisionCallbacks.append(callback) # вызов процедуры callback ???Ну и морока… Как это понять не вызов, а добавление вызова? Где тот список вызовов, в который добавляется, чем и как вызывается из него, в какой строке?
... нет, в данном случае происходит добавление вызова функции когда случается коллизия ...
... то есть callback не вызывается в этой строке, а добавляется в список и когда на поыверхность что-то падает, то вызывается из этого списка с указанием объекта, точки и нормали соприкосновения ...
... сама же обработка вызовов скрыта внутри bge (это внутренняя логика) ...Ну, и как тут разберёшься? Поневоле приходишь к мысли, тупо использовать строки как формулы в сопромате, с подстановкой своих данных.
https://docs.blender.org/api/2.79/bge.types.KX_GameObject.html?highlight=collisioncallbacks#bge.types.KX_GameObject.collisionCallbacks
... у меня был проект на плоскости с треками и следом ( https://sungreen.github.io/projects/veterbot/veterbot.html ), но рассчитывал всё через в скриптах ...Николай, сейчас роясь в своих архивах набрёл на скопированный мною текст. Ссылку, откуда скопировал, к сожалению не сохранил. Может чем интересна будет тебе.
... и отложил идею делать на неровной поверхности из-за усложнения расчётов ...
... поэтому у меня интерес к этой теме тоже есть ...
сейчас роясь в своих архивах набрёл на скопированный мною текст. Ссылку, откуда скопировал, к сожалению не сохранил.Книга называется "Написание скриптов для Blender 2.49", я её в 2010 году переводил: http://striver00.ru/files/Scripting_Blender_2.49_ru.pdf
Теперь-то ссылку сохранил. Просто хотелось хоть чем-то помочь Николаю.Цитироватьсейчас роясь в своих архивах набрёл на скопированный мною текст. Ссылку, откуда скопировал, к сожалению не сохранил.Книга называется "Написание скриптов для Blender 2.49", я её в 2010 году переводил: http://striver00.ru/files/Scripting_Blender_2.49_ru.pdf
Книга называется "Написание скриптов для Blender 2.49", я её в 2010 году переводил: http://striver00.ru/files/Scripting_Blender_2.49_ru.pdfStriver, отсюда делаю вывод:
def callback(object, point, normal):Николай, в строке в скобках получаемые параметры или передаваемые в функцию? Я так понял что это получаемые в результате работы функции.
Есть знание английскогоВот тут не угадал. Много лет себя пинками под зад заставляю переводить всякую хрень, в надежде, что в голове что-то останется, но эффект минимален.
продублирую свою просьбу-вопрос: в современном BGE возможно создание подобного следа?К сожалению в BGE я не ориентируюсь, от слова "совсем".
Что-то, да остаётся, просто человек так устроен, что не доволен достигнутым.ЦитироватьЕсть знание английскогоВот тут не угадал. Много лет себя пинками под зад заставляю переводить всякую хрень, в надежде, что в голове что-то останется, но эффект минимален.
Но, всё-таки сделаю предположение о том что в bge это невозможно, т.к. при формировании следа скрипт манипулирует координатами отдельных вершин. Раньше я не слышал, что в BGE это допустимо в реальном времени.Мне попадался как-то ролик, в котором грузовик буксует образуя колею и летящие от колёс комки грязи, но мне помнится, или так показалось, что там было упоминание о 3D Max'е. Может я что и путаю, давно это было.
Мне попадался как-то ролик, в котором грузовик буксует образуя колею и летящие от колёс комки грязи, но мне помнится, или так показалось, что там было упоминание о 3D Max'е.Т.е. это заранее отрендеренный ролик. Ну так книжка, которую я упомянул, в основном про это, про моделирование и создание анимации. Это и для современных версий Блендера можно переписать.
Я, вообще-то, считал Blender более продвинутым чем Max.У Блендера игровой движок хотя бы есть, но естественно, со своими ограничениями. А про наличие игрового движка в 3D Max'е я не слышал. "Продвинутость" - понятие относительное и субъективное...
Нет. Очень похоже на запись с экрана, потому как голос за экраном комментировал свои оплошности, и происходило маневрирование авто согласно комментариев.ЦитироватьМне попадался как-то ролик, в котором грузовик буксует образуя колею и летящие от колёс комки грязи, но мне помнится, или так показалось, что там было упоминание о 3D Max'е.Т.е. это заранее отрендеренный ролик. Ну так книжка, которую я упомянул, в основном про это, про моделирование и создание анимации. Это и для современных версий Блендера можно переписать.
import bge
import random
def init():
print("Init module\n\n\n")
def order():
sc = bge.logic.getCurrentScene()
ob = sc.objects['Plane']
ms = ob.meshes[0]
v = random.randint(0,ms.getVertexArrayLength(0))
vs = ms.getVertex(0,v)
vs.z += random.random()/2
vs.color = [random.random(),random.random(),random.random(),random.random()]
#46Ладно, со временем разберусь.
... есть игровая логика, когда ты нажимаешь P то запускается игровой движок с этой логикой, в этой логике указано что у тебя установлены коллизии на объекты и если они срабатывают то выполнение программы прерывается и выполняется callback вызов указанной функции ...
... то есть при загрузке модуля функции определяемые заголовком def не выполняются, они выполняются когда происходит какое-либо событие или выполняется условие в игровой логике ...
#51Что такое «идёт определение функции»? Не подскажешь где об этом можно прочитать на нормальном русском языке, а не в электронном переводе?
... этой строке идёт определение функции (def, define), то есть сама функция не выполняется, но определяется её вызов и содержание ...
... далее по тексту можно вызвать код этой функции многократно ...
И, ещё. Просматривая готовые файлы, попадаются такие фрагменты:Это GLSL https://ru.wikipedia.org/wiki/OpenGL_Shading_Language
VertexShader = """
varying vec4 fragPos;
varying float timer;
void main()
{
vec3 pos = vec3(gl_Vertex);
fragPos = ftransform();
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
}
"""
Текст в тройных кавычках и сами кавычки в текстовом редакторе Blender'а отображаются в красном цвете. Что это означает и как эти строки обрабатывает Python?
>> удастся создать след на сетке поверхности, может найдёшь способ его показать?Мой ответ « Ответ #44 : 01 Апреля 2018, 18:44:13 »:
... поясни суть вопроса, непонятно же - что и где требуется показать ...
Николай, суть вопроса, возможно ли создание подобного описанному следу в BGE?»Цитироватьсейчас роясь в своих архивах набрёл на скопированный мною текст. Ссылку, откуда скопировал, к сожалению не сохранил.Книга называется "Написание скриптов для Blender 2.49", я её в 2010 году переводил: http://striver00.ru/files/Scripting_Blender_2.49_ru.pdf
... исходя из описания, такое делать можно ...Коль надумаешь попробовать, поделишься соображениями (наработками)?
>> ведь я её не пропускаю к образованию следа, или он образуется дублем ещё откуда-то?Понятно, освобожусь немного и посмотрю внимательнее.
... на самом деле ты не делаешь этого, посмотри где добавляется след (ob = sc.addObject(sl)), а где ты его не пропускаешь ...
... то есть у тебя след в сцену добавляется без условно, а изменение его положения происходит по условию ...
ps ещё можно обработчик коллизии цеплять не на поверхность, а к колесу, тогда у сферы не будет этого вызова и следовательно не будет формироваться след ...
>> ведь я её не пропускаю к образованию следа, или он образуется дублем ещё откуда-то?Всё-таки забавно, я ведь считал, что след добавляется в список объектов сцены ob. Точка вставки объекта sled в сцену пока не определена, так куда в этом случае вставка производится?
... на самом деле ты не делаешь этого, посмотри где добавляется след (ob = sc.addObject(sl)), а где ты его не пропускаешь ...
... то есть у тебя след в сцену добавляется без условно, а изменение его положения происходит по условию ...
ps ещё можно обработчик коллизии цеплять не на поверхность, а к колесу, тогда у сферы не будет этого вызова и следовательно не будет формироваться след ...Николай, я пытался применять к колёсам – взгляни в редактор логики в данном мною файле на блоки с активными колёсами. Неправильный подход к отбору объектов, за которыми должен быть след, сбил меня, и я отказался от этой затеи разъединив связи между блоками.
... поясню свой вопрос ...Николай, так два колеса имеют совершенно разные координаты местонахождения. Так почему коллизия одного колеса дублируется вызовом коллизии второго?
... ты соединил сенсор с контроллером, который должен вызывать функцию init модуля app ...
... ты сделал это для двух колес, поэтому у тебя при старте дважды вызывается функция init ...
... в функции init идёт назначение обратного вызова callback для коллизии по поверхности ...
... и теперь таких обратных вызова назначено два ...
... отсюда ответ на твой вопрос "за счёт чего" ...
... то есть ты не сделал назначение обратных вызовов для колес, а сделал двойной вызов функции init в которой назначается обратный вызов для поверхности ...
>> Так почему коллизия одного колеса дублируется вызовом коллизии второго?Сенсор Всегда будирует через контроллер модуль app.init, работу которого я свою очередь и пытаюсь выведать у тебя, ведь в нём есть какая-то закономерность которую можно изложить словами. На мои комментарии ты почему-то не обращаешь внимания и свои не даёшь. Воду в ступе непонятно зачем толчём, только и всего.
... покажи код (или цепочку рассуждений) который подтверждает, что у колеса (колёс) назначена обработка коллизий ...
... просто напиши почему ты считаешь, что у колеса есть вызов обработки коллизий и где это происходит ...
>> Сенсор Всегда будирует через контроллер модуль app.initНиколай, я не понял вопрос. Да потому что именно сенсор "Всегда" объекта wheel каждый кадр, не ожидая событий, через контроллер будирует модуль app.init
... поясни почему Всегда? ...
Сенсор Always без параметров, срабатывает только один раз при запуске BGE. Я так понял, это и нужно для инициализации...... да, именно так и происходит, не в каждом "кадре", а только один раз для инициализации ...
Ну, и почему же?Сенсор Always без параметров, срабатывает только один раз при запуске BGE. Я так понял, это и нужно для инициализации...... да, именно так и происходит, не в каждом "кадре", а только один раз для инициализации ...
... тогда следующий вопрос - если инициализация только один раз почему в консоль постоянно выводятся сообщения? ...
Я вижу другое, два обращения - две инициализации, но несмотря на то что обращения идут от разных объектов, инициализации идут дважды одного и того же объекта. Ну, просто зашибись...Сенсор Always без параметров, срабатывает только один раз при запуске BGE. Я так понял, это и нужно для инициализации...... да, именно так и происходит, не в каждом "кадре", а только один раз для инициализации ...
... тогда следующий вопрос - если инициализация только один раз почему в консоль постоянно выводятся сообщения? ...
... не зацикливайся на "инициализации" ...Погоди Николай. Отменил вызов в одном из колёс. Всё устаканилось, идёт одна инициализация и последовательная обработка объектов. Если в сцене полторы тысячи объектов, а необходимо отслеживать один, то модуль будет все полторы тысячи отслеживать потому что строка
... суть не в ней, а в том что ты сам назначил два вызова функции init модуля app ...
... более того, число формально в вызов этой функции не передаётся никакой объект, то есть говорить о том что идёт инициализация дважды одного и того же объекта не уместно ...
... происходит вызов два раза функции init модуля app и эти два вызова ты сам прописал через логику bge (а на самом деле этого не требовалось) ...
... попробуй изложить текстом последовательность того что должно происходить в твоей программе ...
... в этом модуле (по факту текстовый файл с определением функций) определена функция init (название может быть любым другим), в которой выполняется строка bge.logic.getCurrentScene().objects['ground'].collisionCallbacks.append(callback) ...Николай, тут такая каверза у меня получилась. В текстовом редакторе есть два текста: SledKoles.py и SledKoles.init. Текст SledKoles.py тот который я не трогаю, а изменения провожу в тексте SledKoles.init, его и инициирует контроллер, по крайней мере я так думал. Однако был здорово удивлён тем что на самом деле контроллер инициировал не SledKoles.init, который я определил для инициализации, а SledKoles.py. Переименовал в SledKol.py и получил ошибку:
... допустим у тебя играют несколько детей, бросая разные мячи об стену ...Вроде понял. Время покажет, после нескольких применений модулей, так это или что-то не уяснил.
... то есть в сцене присутствует: стена, земля, дети, мячи - и могут быть несколько обработчиков ...
... если обработчик у стены, то он будет реагировать на любой мяч, который об него ударился ...
... обработчик земли будет реагировать на любой мяч и ребёнка, который с ней столкнулся ...
... обработчик меча будет реагировать на стену, землю, ребёнка и другие мячи ...
... если ты вешаешь обработчик на ground, то он будет реагировать на любой объект, который столкнулся с ground ...
... если ты вешаешь обработчик на колесо, то он будет реагировать на любой объект, который столкнулся с колесом ...
(при условии что нет групповых ограничений https://docs.blender.org/api/current/bge.types.KX_GameObject.html?highlight=collisioncallbacks#bge.types.KX_GameObject.collisionGroup и https://docs.blender.org/api/current/bge.types.KX_GameObject.html?highlight=collisioncallbacks#bge.types.KX_GameObject.collisionMask ) ...
... допустим у тебя обработчик установлен не на ground, а на колесо wheel - bge.logic.getCurrentScene().objects['wheel'].collisionCallbacks.append(callback1) ...
... когда при обработке коллизий столкновения этого объекта будет вызываться функция callback1 (или любая другая, которую ты определишь) ...
... в качестве аргументов при вызове будут приняты аргументы объект - столкновения (а также точка и нормаль) и можно проверить столкнулось ли колесо с ground ...
Если я всё правильно понял, то модули - это функции ( def имя_функции (список параметров функции): ), которые ты определил в файле SledKoles.pyСпасибо Samovar, а ведь в каком-то описании мне это попадалось и ты мне сейчас это напомнил. До сих пор я использовал исключительно скрипты, и на модули, собственно, и всё что касалось модулей, читал вполглаза.
Следовательно, как модули эти функции вызываются так: имя_файла_без расширения_py.имя_функции_в_этом_файле
В твоём случае модули будут:
SledKoles.init
SledKoles.callback (Но этот, как я понял, даже вызывать не надо, он автоматом вызывается при столкновениях, после инициализации)
Я плохо шарю в ООП, но получается, что при инициализации, ты определённому объекту добавляешь свой метод обработки функцией callback...
... файл с модулем или текстовый блок должен обязательно иметь расширение .py , без этого работать не будет (например app.py)...Понял. Исправил. Спасибо за помощь.
... для указания в контроллере вызов функции из модуля нужно писать имямодуля.имяфункции (например app.init) ...
https://docs.blender.org/manual/ru/dev/game_engine/logic/controllers/types/python.html#bpy-types-pythoncontroller
>> AttributeError: module 'SledKoles' has no attribute 'py'
... поскольку ты пытаешься запустить функцию py модуля SledKoles, которой в этом модуле нет ...
>> В принципе, та же горка, только подразделена плотнее. Колесо теперь с шипами - уже есть. Нужна идея для начала разработки, но сразу с возможностью видеть результат хоть в чём-то, хоть на каком-то этапе. Пока ничего путного в голову не приходит.Николай, то, что ты пишешь, наверно следующий этап. Колесо падает на горку и физика остановит падение, сменив его перекатыванием. Здесь ни скрипт, ни модуль не нужны. А вот точку касания колесом горки необходимо определить, и это делать надо через скрипт или модуль. Точка касания колеса, это скорее всего линия по оси Х имеющая U-образную конфигурацию колеса. Вот наверно с этого момента потребуются твои пункты.
1 брать каждый треугольник меша колеса:
1.1 для каждого треугольника брать вершину
1.2 для каждой вершины находить ближайшую вершину на меше горки
1.3 для найденных вершин на меше горки, если высоты соответствующих вершин колеса находятся ниже высот горки, сделать выбор вершин входящих в треугольную область, определяемую найденными вершинами и присвоит им высоты, рассчитанные линейными пропорциями взятыми из обрабатываемого треугольника колеса ...
... то есть для начала нужно подобрать быстрый алгоритм поиска вершины меша по заданным координатам ...
... сможешь пробить эту тему в Сети? ...
Вся игровая графика - это треугольники, а не четырёхугольники и многоугольники, т.к. любая плоскость проходит через 3 точки из курса геометрии...Samovar, насчёт трёх точек, ты конечно прав, наименьшее количество точек определяющее плоскость - 3. Однако добавь в Blender любой, кроме окружности и икосферы стандартный объект, и, перейдя в режим редактирования, посчитай чего в них больше треугольников или четырёхугольников.
Однако добавь в Blender любой, кроме окружности и икосферы стандартный объект, и, перейдя в режим редактирования, посчитай чего в них больше треугольников или четырёхугольников.Samovar имел ввиду, что все игровые движки (и BGE тоже) все полигоны преобразуют в треугольники, из чего бы ни состоял объект в редакторе Блендера.
Грани куба можно вручную разбить на треугольники добавляя рёбра, а если этот куб прошёл подразделение граней, то вручную разбивка на треугольники будет весьма трудоёмка. Есть ли способ в Blender подобной разбивки.В режиме редактирования выдели всё и нажми Ctrl-T
>> Есть ли способ в Blender подобной разбивки.Сработало. Николай, я вопрос, собственно, задал из-за твоего упоминания о треугольниках.
... в режиме редактирования выделить все полигоны A и далее Ctrl+T ...
Спасибо Striver.ЦитироватьОднако добавь в Blender любой, кроме окружности и икосферы стандартный объект, и, перейдя в режим редактирования, посчитай чего в них больше треугольников или четырёхугольников.Samovar имел ввиду, что все игровые движки (и BGE тоже) все полигоны преобразуют в треугольники, из чего бы ни состоял объект в редакторе Блендера.ЦитироватьГрани куба можно вручную разбить на треугольники добавляя рёбра, а если этот куб прошёл подразделение граней, то вручную разбивка на треугольники будет весьма трудоёмка. Есть ли способ в Blender подобной разбивки.В режиме редактирования выдели всё и нажми Ctrl-T
1 брать каждый треугольник меша колеса:Давай поэтапно. Треугольник меша колеса касающийся грунта, а как его определить? Я пока могу определить мировую позицию опорной точки этого колеса. Но что это даст?
Кстати, хотел давно спросить. Николай Николаев, а можно такую "цацку" сделать с рисованием в текстуру в BGE? А то, куча объектов для следа - это будет сильно тормозить, если их не уничтожать со временем... нужно для царапин и следов от выстрелов и холодного оружия... визуализации повреждений противников...
import bge
import random
from PIL import Image
from bgl import Buffer, GL_BYTE
dd = 1024
d2 = dd/2
bb = 128
b2 = 64
ss = 5
sc = bge.logic.getCurrentScene()
ob = sc.objects['ground']
ground = Image.open(bge.logic.expandPath("//ground.png"))
sled = Image.open(bge.logic.expandPath("//brush.png"))
def init():
ob.collisionCallbacks.append(order)
addSp(None)
def addSp(ob):
sp = sc.objectsInactive["Sphere"]
sp = sc.addObject(sp)
sp.worldPosition = (random.random()*ss-ss/2,random.random()*ss-ss/2,7)
if ob:
ob.endObject()
def order(object, point, normal):
x = int((1.0+point.x/ss)/2*dd-b2)
y = int((1.0-point.y/ss)/2*dd-b2)
image = ground
sleds = image.crop((x,y,x+bb,y+bb))
for i in range(int(random.random()*7+3)):
brush = sled.copy()
r = 180*random.random()
s = int(random.random()*bb)
brush = brush.rotate(r)
brush = brush.resize((s,s))
sleds.paste(brush,(0,0),brush)
image.paste(sleds,(x,y))
image = image.convert("RGB")
image = image.transpose(Image.FLIP_TOP_BOTTOM)
idata = image.tobytes()
ibuff = Buffer(GL_BYTE,len(idata),idata)
if "buff" not in ob:
ob["buff"] = bge.texture.ImageBuff()
ob["buff"].load(ibuff,dd,dd)
bge.logic.texture = bge.texture.Texture(ob,0)
bge.logic.texture.source = ob["buff"]
bge.logic.texture.refresh(True)
addSp(object)
>> Есть ли способ в Blender подобной разбивки.Николай, если я ещё не совсем надоел, то хочу поделиться ещё одной проблемой со следом (всё никак мне покоя не даёт моя горка с колесом). Тут такая петрушка получается. На малых скоростях, т.е. когда колесо катится с горки без понуждения, то след ложится ровно, однако если это колесо понуждать к ускорению, то с определённого момента след становится пунктирным. Думаю что колесо за один кадр проходит большее расстояние чем размер следа. Участить обращение к модулю возможно? Вроде и так сенсор "Всегда" будирует контроллер. Можно, конечно, удлинить плоскость с текстурой следа, но тогда при малых скоростях, будет не след а мазня.
... в режиме редактирования выделить все полигоны A и далее Ctrl+T ...
>> если я ещё не совсем надоелПринято. Просто терпеть не могу зануд, а сам сейчас занудствую, пытаясь расставить все точки над i. Некомфортно чувствую себя.
... нет никакой необходимости оправдываться, смело задавай вопросы и если ответа не последовала пробуй их задать ещё раз ...
>> Участить обращение к модулю возможно? Вроде и так сенсор "Всегда" будирует контроллер.Предыдущая позиция следа:
... суть в том, что ты не понял что "Всегда" тут не причём ...
... "Всегда" срабатывает один раз и вызывает не модуль, а функцию модуля (по ходу модуль инициализируется, но для тебя важен именно вызов функции модуля) ...
... для того чтобы решить задачу тебе нужно отчасти восстановить ту логику которую ты использовал ранее но в контексте модуля ...
... то есть - запоминать точку соприкосновения (которая сформировалась в результате срабатывания коллизии) и далее при следующем срабатывании коллизии заполнять путь от старого значения соприкосновения до нового с учётом длины следа, после чего новое значение нужно поместить на место ранее запомненного и ждать очередного срабатывания коллизии ...
... пусть у тебя уже есть траектория следа со всеми точками - какой алгоритм заполнение этой траектории элементами (следами)? ...Вопрос не понял.
if(ds>sl): #если участок больше длины следа, то нужно рисовать промежуточные следыБеру 37.96 см. и делю 24 см. и n получаю равным 1. Нет?
n = int(ds/sl)
>> Вопрос не понял.Погоди Николай, к коду давай вернёмся позже. Ты хоть определи что такое промежуточный след. След это плоскость определённого размера с определённой текстурой (рисунком), а промежуточный-то след это что за зверь такой?
>> Николай, я что-то совсем поплыл.
... признаю, что в изложенный алгоритм имеет некоторые скользкие моменты ...
... но это можно без труда поправить ...
... чтобы внести ясность и очевидность, попробуй текстом (простыми русскими фразами) изложить своё видение того как заполнить следами траекторию состоящую из нескольких фрагментов разной длины ...
... и чтобы понять где скользкость алгоритма из предыдущего поста попробуй на бумаге отработать не один, а, допустим, 5 отрезков равной длины по 38 см ...
... хотя в последующем наверное следует внести изменения dss=ds/(n+1) и vt=v0+dss*(i+1), и в самом начале, когда v0 = None просто нарисовать след в v1, а в конце не рисовать ...
v0 = None
def test(v1):
if(v0 is None):
рисовать след в v1
else:
dv = v1-v0
ds = dv.length
if(ds>sl): #если участок больше длины следа, то нужно рисовать промежуточные следы
n = int(ds/sl)
dss = ds/(n+1)
for i=0 to range(n):
vt = v0 + dss*(i+1)
vt - это точка в которой нужно рисовать след
... далее код рисования следа
...
v0 = v1
>> ... чтобы внести ясность и очевидность, попробуй текстом (простыми русскими фразами) изложить своё видение того как заполнить следами траекторию состоящую из нескольких фрагментов разной длины ...Настаиваешь на своём предложении? Хорошо. Колесо, находясь над определённой точкой поверхности передаёт следу проекцию своих координат на неё. След располагается на поверхности согласно переданных ему координат, и выравнивается в соответствии с нормалью данной точки координат поверхности. След занимает точно ту поверхность, которую он имеет по проектным данным.
... сможешь сделать? ...
>> Однако, если расстояние между проекциями точек колеса больше длины следаНиколай, да в том-то и дело, что между следами расстояние значительно меньше самого следа. При малой скорости - следы устанавливаются вплотную. С увеличением скорости, после определённых значений, появляются интервалы между следами равные десятым долям размера следа. С дальнейшим увеличением скорости увеличиваются и интервалы между следами. Смотри рисунок. У меня получались интервалы примерно до 0.9 размера следа. В то же время при низких скоростях, я сейчас рассмотрел, идёт наложение следов последующим на предыдущий. В работе BGE не видно, а вот на скрине, да с увеличением весьма заметно.
... то есть у тебя уже есть след в двух соседних точках и тогда найди точку между ними и добавь туда след ...
... если расстояние будет большим, то рассчитай количество нужных следов и добавь их ...
Николай, да в том-то и дело, что между следами расстояние значительно меньше самого следа. При малой скорости - следы устанавливаются вплотную. С увеличением скорости, после определённых значений, появляются интервалы между следами равные десятым долям размера следа. С дальнейшим увеличением скорости увеличиваются и интервалы между следами. Смотри рисунок. У меня получались интервалы примерно до 0.9 размера следа. В то же время при низких скоростях, я сейчас рассмотрел, идёт наложение следов последующим на предыдущий. В работе BGE не видно, а вот на скрине, да с увеличением весьма заметно.
>> появляются интервалы между следами равные десятым долям размера следа.Толчём воду в ступе?
... причина этого появления? только одна - расстояние между v1 и v0 больше следа, не так ли? ...
Однако, если расстояние между проекциями точек колеса больше длины следа, то образуются пробелы, коль меньше длины следа, происходит наложение следов.К чему переспрашиваешь?
Ещё вопрос: в строкеИ, всё же Николай, есть какие-то соображения по этому вопросу?
bge.logic.getCurrentScene().objects['ground'].collisionCallbacks.append(callback)
можно назначить столкновения только с одним объектом (в данном случае ground) или возможно назначить несколько объектов? Если возможно, то как назначить несколько объектов. Катится моё колесо по горке - тут объект столкновения ground. Скатилось оно с горки и попало в другую среду где будет уже другой объект столкновения ground2, ground3 ... ground22 - как быть? Ведь его надо ещё распознать. Замкнутый круг получается.
>> К чему переспрашиваешь?Николай, я что-то не пойму твою мысль. Расположились два следа, заполнив часть поверхности. Между ними промежуток в 0.3 длины следа. Добавляем в этот промежуток, прямо в его центр что? След? След перекроет не только промежуток, но и предыдущий и последующий след на 0.35 их длины, нарушит рисунок.
... а почему ты не хочешь поделить это расстояние пополам и добавить туда след? ...
... можно ввести оценку остатка от кратного деления пройденного пути на длину следа ...Вернулся к предложенному тобой файлу Sled 5.blend. Добавил простенькую текстуру для следа в виде вложенных квадратов и обнаружил что на малых скоростях идёт сплошное наложение следов одного на другой.
v0 = None
ss = 0
def test(v1):
if(v0 is None):
рисовать след в v1
else:
dv = v1-v0
ds = dv.length
dv = dv/ds
ss += ds
while(ss>sl):
vt = v0 + dv*sl
vt - это точка в которой нужно рисовать след
... далее код рисования следа ...
ss-=sl
v0 = vt
Novichok, ты ж прочёл до того как наш мудрый админ удалил... неприятно, правда ? :) А прикинь, каково тем людям, которые пытались тебе помочь, и в итоге нарвались на твои непонимание и грубость? :)Не понял, что за наезд, кому и какая грубость?
>> Можешь предложить что-то, что сделает след (в данном случае линию) видимым вне зависимости от направления взгляда?Опа, я думал об использовании трёх плоскостей в трёх осях с точкой в месте их пересечения, но как расположить в них след (линию) ничего придумать не смог.
... поменяй форму следа, например небольшой кубик или пирамидку ...
... кстати, а вы на работе используете какие-нибудь схемы или технологические карты? может тебе будет легче рисовать логику, чем описывать ...Технологические карты, графики, задания и т.д. это моя работа. Как руководитель подразделения даю направления при поручении разработки.
>> Вернёмся к нашим "баранам", к нашей "угадайке"Каким образом выполняется вызов подпрограмм?
... в целом в коде много путаницы, и самое главное отсутствие связи, например "... далее код рисования следа ..." имеется в виду что в этом блоке происходит вызов кода, который добавляет след в сцену, а у тебя след добавляется всегда, как только срабатывает коллизия, далее по тексту была замена ds на ls (этого не нужно делать, то есть это совершенно разные сущности) ...
>> (v0 is None) = True, меня не пускает дальше.v0 = None что ли? А, где я должен был это определить? Ты же опять ничего на этот счёт не пояснил. Я рассматривал вариант определения блоке def init():. Меня Python отматюгал, только и всего.
... так немного выше в коде ты написал v0 = ...
... предлагаю перейти на уровень алгоритма, уточнить логику и вернуться к коду ...Если это имеет смысл, то на словах это могу сформулировать примерно так.
... напиши текстом своё видение, как должен формироваться след, это важно чтобы сначала сформировалось общее представление о ходе процесса, а потом уже реализация в коде ...
1) В точке касания поверхности колесом устанавливается объект след с предварительной его инициацией, переводом из невидимого слоя в сцену.в 11-той строке
// это происходит всегда в точке касания? откуда берётся точка касания?
3) В следующем кадре проверяется следующая точка касания на предмет касания поверхности или следа.Наверно то что осталось необъяснённым.
// исходя из логики сенсоров (в контексте этого случая) нет никакого следующего кадра, а что есть?
5) Коль касание затрагивает объект след, то необходимо перейти к следующему касанию.Наверно там же, в том что осталось необъяснённым. Я трижды задавал вопрос о том как Python отслеживает построчный текст программы, но ты как партизан - тайну не выдал.
// где осуществляется переход к следующему касанию?
по ходу - допустим у тебя есть две точки касания v0 и v1, между ними 2.2 метра, длина следа 0.4 метра - как будешь заполнять траекторию? ...Николай, ты мне укажи номера тех ответов, в которых ты мне все свои вопросы уже объяснял. Вот интересно, много найдёшь?
>> Вот интересно, много найдёшь?Лихо! Всё-таки, Николай, ты меня поражаешь. На мой, дилетанта взгляд, код красив, следовательно, и красив алгоритм. Я думаю, что в первую очередь у тебя родился алгоритм, а уж потом подобрался код. Однако алгоритм ведь и есть пояснения к коду. Ну что мешает его вписать в код в качестве комментариев? Банальная лень? Вроде не логично, ведь помогаешь сам, добровольно, с желанием помочь. Тогда что мешает?
... да, но не в этом суть, посмотри ещё один тестовый вариант во вложении ...
import bge
from mathutils import Vector
v0 = None
up = Vector((0,0,1))
ls = 0.4
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
def init():
bge.logic.getCurrentScene().objects['ground'].collisionCallbacks.append(callback)
def callback(object, point, normal):
global v0
v1 = object.worldPosition
if v0 is None:
v0 = v1.copy()
else:
while((v1-v0).length>ls):
v0 += (v1-v0).normalized()*ls
ob = sc.addObject(sl)
vW = object.getAxisVect(up)
ob.alignAxisToVect(vW,0,1)
vS = ob.getAxisVect(up)
ob.worldPosition = v0
obp,point,normal = ob.rayCast(v0-vS*2)
if obp:
ob.worldPosition = point+vS*0.03
ob.alignAxisToVect(normal,2,1)
v0 = v0+dv*ls или если красивее, то v0+=dv*ls , что означает прибавить к вектору v0 вектор dv*ls , где dv*ls это произведение вектора на число (по сути умножение элементов вектора на одно и тоже число) ...М-м, да-а… Вектор это конечно круто, но я отвечу так же как в ответе 2 в твоей ссылке ответил LanuHum. Взгляни.
dv/=dv.length - означает деление вектора dv на число (длину самого вектора, по идее нормализация) ...
dv = v1-v0 никак не является расстоянием между точками, поскольку это вектор разности между точками, а вот длина этого вектора dv и есть расстояние ...
http://blender-3d.ru/forum/index.php/topic,326.msg4308.html#msg4308
while((v1-v0).length>ls): # пока расстояние между точками больше длины следа
Строка 14 – global v0, ls почему назначение глобальными переменных производится здесь а не в 5-7 строках, не в блоке init?Назначение или указание это не меняет причины места объявления, ведь я спрашиваю именно о причине. Ох, Николай.
[/color] - это не назначение, а указание что в указанном цепочке кода эти переменных нужно считать глобальными
>> Строка 9: def init(): - побуждается контроллером в ответ на сенсор «Всегда». Тут наверно вопрос по работе BGE. Как я понимаю, BGE систематически обновляет кадр. Отсюда сенсор «Всегда», так же покадрово должен возбуждать контроллер и соответственно часть модуля def init():. Однако ранее где-то ты утверждал, что эта часть модуля работает единожды. Что-то тут не вяжется. Попытайся понятнее изложить свою мысль.При старте, это при запуске BGE?
... моя мысль такая - мне нужно инициализировать переменные, для этого в начале работы требуется запустить эту процедуру, без разницы каким способом, главное один раз при старте ...
... можешь сделать это любым другим доступным способом ...
>> первую очередь у тебя родился алгоритм, а уж потом подобрался кодНиколай, так я каждый раз отвечал, по крайней мере, схематично описывал последовательность, поскольку я не знаю, что в твоём понимании является алгоритмом. Последний раз в ответе #144 : 30 Апреля 2018, 12:43:36 на который ты мне ответил анализом моего алгоритма в своём ответе #145 : 30 Апреля 2018, 15:06:21
... несколько раз спрашивал тебя о наличии алгоритма, ведь для него не требуется код, это же абстракция ...
>> Ну что мешает его вписать в код в качестве комментариев? Банальная лень?Опять меня на лирику потянуло. Я тебе сейчас много ужасов напишу.
>> код красив, следовательно, и красив алгоритм.
... это нарушает красоту кода, да-да, мне не нравятся комментарии, поскольку код становится не читаемым, чем меньше текста, тем легче код для понимания ...
>> А если твой блок применят там, где сбой в нём сможет убить или причинить огромный экономический ущерб?Я же написал: потянуло на лирику.
... насколько в курсе, то у нас здесь форум, а не служба технической поддержки, то есть живое человеческое общение ...
... по большому счёту и если мне не изменяет память здесь нет профессиональных программистов, которые зарабатывают себе кодом на хлеб, поэтому приветствуется конструктивный диалог по типу "делают вот так, не получается вот это, в чём может быть проблема" ...
... насколько в курсе, то у нас здесь форум, а не служба технической поддержки, то есть живое человеческое общение ...Николай, пока я "перевариваю" к слову пришёлся этот фрагмент нашей переписки. Вполне допускаю что на данном форуме нет профессиональных программистов, педагогов, а есть интересующиеся Blender'ом участники форума. Однако совсем неплохо бы ещё учитывать раздел форума, а он называется "Вопросы от новичков". Кому-то из новичков достаточно просто подсказать или дать готовый код, и он будет счастлив этим (я себя отношу к таким), а кому-то этого мало, им необходимо "докопаться до корней", вот комментарии таким необходимы как воздух (я иногда бываю таким).
... по большому счёту и если мне не изменяет память здесь нет профессиональных программистов, которые зарабатывают себе кодом на хлеб, поэтому приветствуется конструктивный диалог по типу "делают вот так, не получается вот это, в чём может быть проблема" ...
... так ты лирик или технолог? в целом это хорошая идея сделать форум человечнее и дружелюбнее, возьмись за разработку, организацию этого процесса, разработай технологию гуманного вспоможения новичкам, обучи волонтёров форума этой позитивной практике ...Я технолог по холодной обработке металла а не педагог - специфика несколько иная. А вот идею сделать форум человечнее и дружелюбнее поддерживаю целиком и полностью, ведь на сколько я понимаю, в оказании помощи конкурировать ни к чему.
... можно на тебя рассчитывать в этом деле? ...
... а как в целом поступать в тех случаях когда колесо отрывается от земли? например трамплин, есть рассуждения по этому поводу или алгоритм? ...Так последний след в месте отрыва, затем нет никаких следов в полёте, и вновь в первом месте касания. А, как ещё? По-моему, только так.
>> Так последний след в месте отрыва, затем нет никаких следов в полёте, и вновь в первом месте касания. А, как ещё? По-моему, только так.Очевидно в 13 строке должны прекратиться вызовы callback.
... как узнать место отрыва? ...
... допустим вызов прекратиться, навсегда? и как его прекращение влияет на определение места отрыва? ...Место последнего вызова является местом отрыва.
... как узнать математически находилось ли колесо в воздухе между двумя точками, которые получены в результате обработки коллизий? ...Не понял вопроса, это как? Коль есть касание, то есть и то чего касается. Коль нечего касаться откуда появится касание?
... все ответы на вопросы уже были приведены в топике, но это не снимает с меня ответственности за не внятность объяснения, а лишь подчёркивает определённую сложность обсуждаемой темы ...Бывает что тупость одолевает, грешен.
... "ихтамнет", это не про эти следы? скорее это именно subj, поэтому дополнительно нужно проверить находилось ли колесо в воздухе между двумя точками ...Скорее "ихтанедолжнобыть". Что за зверь такой "subj"?
... мы не ожидаем проявление коллизии в этом месте, но по каким-то причинам оно происходит ...А я всё думал и гадал что такое на вашем языке "костыль".
... 1) либо искать причины недолжного поведения, 2) или ставить костыль (например на "Последние три следа с большей разницей по оси Z, чем предыдущие.") ...
Каким образом выполняется вызов подпрограмм?Николай, ты мне не ответил или я прозевал ответ?
#определение
def sq(x):
return x*x
#использование
a = sq(3)
print(sq(2))
>> может укажешь на причину сохранения этой тениДа, действительно это тень от следа. Взгляни на изображение во вложении.
... это тень от следа, логично её отключить ...
>> Есть блок кода, что-то выполняющий, к которому возможно обратиться из разных участков кода.С возможностью использования части кода как функции понятно. Однако мой интерес несколько иной. Мне интересна возможность многократного использования части кода из разных мест кода.Код: python#определение
def sq(x):
return x*x
#использование
a = sq(3)
print(sq(2))
Короче, подобно бейсиковским go to и go sub что-то есть?Это давно считается дурным тоном и путаницей, потому вряд ли... (сейчас такое только на ассемблере)
def p1():
print("p1")
def p2():
print("p2")
def p3():
print("p3")
a = p1
a()
a = p2
a()
a = p3
a()
http://rupython.com/switch-python-116.htmlСтрашная ссылка. Даже не знаю, что страшнее, слитый в одну строку и потому убитый питоновский код, или текст, автоматически переведённый на псевдорусский язык...
Короче, подобно бейсиковским go to и go sub что-то есть?А как бы ты в Бейсике выбирал, где это самое go to поставить? Наверняка перед ним будет некое условие, что-то вроде
if a=4 thenНу так и в Питоне можно по-простому написать
goto 150
if a=6 then
goto 180
if a==4:где p1 и p2 - ранее определённые функции (например, как в коде от Николай Николаев)
p1()
if a==6:
p2()
Да уж... А человек тратил своё время...Цитироватьhttp://rupython.com/switch-python-116.htmlСтрашная ссылка. Даже не знаю, что страшнее, слитый в одну строку и потому убитый питоновский код, или текст, автоматически переведённый на псевдорусский язык...
Инструкция return здесь для чего? Что будет без неё?Просто return без возвращаемого значения просто возвращает управление из функции туда, откуда она вызвана.
Спасибо Striver за пояснение, просто я не понял его смысла в данном коде, потому и решил уточнить.ЦитироватьИнструкция return здесь для чего? Что будет без неё?Просто return без возвращаемого значения просто возвращает управление из функции туда, откуда она вызвана.
Имеет смысл, если в функции после этой строки есть ещё что-то, но нужно это проигнорировать.
Если пустой return находится в конце функции, он, фактически не нужен, без него будет работать точно также (хотя я обычно предпочитаю его ставить)
... ещё один вариант во вложении для обсуждения ...Всем привет. Николай, коль эту тему ещё с контроля не снял и есть время и желание, то хочу продолжить обсуждение появившихся у меня проблем с текстурным следом.
... приветствую ...Вот жеж блин, все настройки проверил, а в физику не посмотрел. Спасибо за подсказку. Николай, ты наверно видел что следы становятся на ребро? Сейчас мне чуть недосуг, на буднях попытаюсь разобраться откуда ноги растут у этой проблемы. Если не разберусь (что более всего вероятно) опять к тебе за помощью обращусь. Не возражаешь?
... у тебя колеса у колёс установлен тип физического представления No Collision, то есть отключено физическое столкновение и поэтому ничего не происходит ...
https://docs.blender.org/manual/ru/dev/game_engine/physics/types/no_collision.html?highlight=collision#no-collision-physics
>> Не возражаешь?Тут важно чтобы не было ограничений для желания ответить ;D
... на сколько в курсе, на этом форуме нет каких-либо ограничений на количество задаваемых вопросов ...
vu = vw.cross(dw).normalized()
print("74 vu = ", vu, " w1 = ", w1)
obp,point,normal = object.rayCast(w1+2*vu)
... кстати, если у тебя теперь 4 колеса, то можно изменить логику происходящего - не нужно вычислять по отдельности направления луча для определения нахождения следа, поскольку эти лучи перпендикулярны плоскости платформы автомобиля и только выходят из центров колес ...А нормали для следа? К тому же всхолмленность поверхности, наличие/отсутствие поверхности под одним или несколькими колёсами?
... и условие рисования следа можно упростить, проверив лишь расстояние от центра колеса до точки пересечения луча с землёй, например чтобы оно было не больше 1,05 радиуса колеса ...
import bge
from mathutils import Vector
up = Vector((0,0,1))
ls = 0.06
r = 0.3
up = Vector((0,0,1))
sc = bge.logic.getCurrentScene()
sl = sc.objectsInactive['sled']
car = sc.objects['Car']
def init():
bge.logic.getCurrentScene().objects['ground'].collisionCallbacks.append(callback)
def callback(object, point, normal):
if object.name[0:5]!='wheel':
return
db = object.attrDict
w = object.worldPosition
vw = car.getAxisVect(up)
vu = vw.normalized()
obp,point,normal = object.rayCast(w-2*vu)
if obp:
v1 = point
if not 'v0' in db:
db['v0'] = v1
return
if (w-v1).length<1.05*r:
v0 = db['v0']
while (v1-v0).length>=ls:
dv = (v1-v0)
ob = sc.addObject(sl)
ob.worldPosition = v0+vu*0.03
ob.alignAxisToVect(vw,2,1)
ob.alignAxisToVect(normal,2,1)
ob.alignAxisToVect(dv,0,1)
v0=v0+dv.normalized()*ls
db['v0'] = v0
... например так, только следы будут накладываться друг на друга ...Николай, что это в квадратных скобках, где можно прочитать?Код: python....
if object.name[0:5]!='wheel':
Что это за коэффициент "r", в чём его смысл?Кодif (w-v1).length<1.05*r:
if object.name[0:5]!='wheel':
что это в квадратных скобках, где можно прочитать?от строкового поля object.name взяты первые 5 символов (с 0-го по 4-й).
Спасибо Striver. Взгляни на рисунок. Изменяю размер следа по оси Y, а изменяется по оси Х. Как это получается, есть какие-то соображения на этот счёт?Цитироватьif object.name[0:5]!='wheel':Цитироватьчто это в квадратных скобках, где можно прочитать?от строкового поля object.name взяты первые 5 символов (с 0-го по 4-й).
>> Изменяю размер следа по оси Y, а изменяется по оси Х. Как это получается, есть какие-то соображения на этот счёт?Николай, направляю файл. Надеюсь что у тебя раскроются те же самые окна что и я вижу с выделенным объектом sled.
... не удалось добиться такого результата, изменения по осям соответствуют заявленным значениям ...
... опиши последовательность своих действий, приводящих к неверному результату ...
if obp:
v1 = point
if (w-v1).length<1.05*r and 'v0' in db:
v0 = db['v0']
while (v1-v0).length>=ls:
dv = (v1-v0)
ob = sc.addObject(sl)
ob.worldPosition = v0+vu*0.03
ob.alignAxisToVect(normal,2,1)
ob.alignAxisToVect(dv,1,1)
v0=v0+dv.normalized()*ls
db['v0'] = v0
else:
db['v0'] = v1
>>Во внутрь блока: while (v1-v0).length>=ls:Вложен в моём 196 ответе
>>вставил: print("46 ob = ", ob), и обнаружил что сюда Blender не заглядывает - нет распечатки в консоли этой строки. Тогда >>каким образом появляется след от колеса, если его появление выполняется только внутри этого блока?
... вложи файл с этой вставкой, это ненормальное поведение и в таком случае след не должен появляться ...
>> А, эта строка: v0=v0+dv.normalized()*ls зачем изменяет v0? и тут же db['v0'] = v0Уточню свой вопрос: строка: v0=v0+dv.normalized()*ls зачем изменяет v0?
... это не так, "тут же" не подходит для понимания хода исполнения кода на python, поскольку там разные отступы и следовательно это разные логические блоки, то есть v0=v0+dv.normalized()*ls выполняется в цикле, а db['v0'] = v0 после цикла (исходя из контекста кода) ...
>>Уточню свой вопрос: строка: v0=v0+dv.normalized()*ls зачем изменяет v0?Николай, я запустил движок в каркасном режиме отображения.
... ради этого затевался цикл, чтобы отрисовать все фрагменты следа длиной ls между v0 и v1 ...
>> Почему теряется текстура следа?
... не знаю ...
... у тебя ls чему равно? ...6 см. - 3 фрагмента, ширина 15 см.
... то есть ls = 0.06? попробуй увеличить ls так чтобы между фрагментами был виден зазор например ls = 0.16 ...Не понял идею. Изменить длину следа?
>> Не понял идею. Изменить длину следа?И, опять я не понял идею. Надо изменить в коде оставив прежние размеры объекта, надо изменить размеры объекта, оставив неизменными в коде, надо изменить в коде и размер объекта? Последняя моя картинка: в коде - ls=0.16, объект Х=15, Y=15, 6 сегментов (6 выступов на краях шины). До этого текстура была с 3-мя выступами и длиной 6 см.
... судя по картинке у тебя длина фрагмента не 6 см? установи ls=0.15 и посмотри будет ли наложение ...
>> Может здесь собака зарыта, потому и теряется текстура, что накладывается одна на другую со смещением?Николай, в моём "Ответ #209" на правом рисунке у меня объект sled, 15 см. шириной (ось Х), и, 6 см. длиной (ось Y). В коде ls=0.062. Разве это не то что ты пишешь?
>> И, опять я не понял идею.
... это же твой вопрос был, не так ли ...
... ответ на него положительный - у тебя объект 15 см, а рисуешь ты его через 6 см, отсюда наложение ...
... или мне не нужно прорабатывать эту тему? ...
... в моём понимании длина объекта (Y) и значение ls в коде должны быть одинаковыми ...
... выложи ещё раз модель со всеми текстурами ...Без проблем.
... желательно настроить в качестве текстурных координат UV развёртку, тогда такой проблемы со смазыванием текстуры не будет ...Ну, так это другое дело. Текстуры уже так назначал, но не думал что это так существенно. Спасибо за подсказку.
https://docs.blender.org/manual/ru/dev/editors/uv_image/uv/editing/applying_image.html#use-uv-coordinates
Novichok, мне непонятен смысл этих твоих изысканий про следы...У меня есть работа которой очень дорожу, но видно что-то остаётся ею невостребованным. Я не один такой. Очень много людей отдают себя полностью работе, но в то же время с такой же самоотверженностью отдаются какому-то другому занятию, например шахматам или маркам, авто или судомоделированию и т.д.
Это так важно? Если ДА, то почему и зачем?
А почему был выбран именно Блендер?Просто по совету, видно советующий был его фанатом на тот момент.
Более эффективней было бы выбрать ЯП Freebasic и какой-нибудь движок к нему на базе Irrlicht (Ninfa, Clady3D), раз соображаешь в Бейсике.Мне попадались ролики с подобным содержанием, КаМАЗ прокладывающий колею с пробуксовкой, но это ролик. Разыскивать автора для того чтобы поинтересоваться как и на чём он делал ролик, посчитал глупым занятием.
Ясно. Я думал, что тебя интересует именно физика реалтайм, которая не даст качественной реалистичной симуляции подобных явлений, т.к. более упрощённая... Но если рассчитывать симуляцию физики в Блендере для видео, то это можно сделать гораздо качественней и без программирования... Поэтому интересуюсь, какова конечная цель? Эффектное физически правильное видео, или приблизительный реалтайм? Два в одном вряд ли получится, для этого надо очень шустрое и дорогое "железо"...Я не знаю, какие идеи мной овладеют в дальнейшем, а сейчас мне интересна возможность макетирования с возможностью управления макетом. Вот то же самое колесо, которое здесь мучаю в BGE, могу сделать управляемым, т.е. послать колесо в любом направлении, толи в грязь или воду, толи в песок или снег и т.д. Модель с текстурированным следом, в общем-то, понятно как делать, правда, ещё не полностью, ну это Николай вроде обещал, посмотреть, в чём ошибка.
Кстати, BGE умер в апреле 2018 совсем... Его развитие больше никак не поддерживает команда разработчиков Блендера.Что так?
Вполне может статься, что эта наука мне сможет пригодиться когда-нибудь, а может так и остаться просто удовлетворением любопытства.Забей уже конкретно на BGE, так как он мёртв... Но в плане общего развития, я только приветствую твой энтузиазм...
Нет, я видел ролик с год, наверно, назад и почему-то в голове сидит что его делали на 3D Max'е. Поищу, может ссылка на ролик где-то есть, но не обещаю. 3D Max'ом не интересовался. Почему? Толком сам не знаю. Может из-за его коммерционности... Но честно сказать, просто не задумывался над этим. Заинтересовался Blender'ом, вот и лазию по его возможностям. Пока этого хватает.ЦитироватьВполне может статься, что эта наука мне сможет пригодиться когда-нибудь, а может так и остаться просто удовлетворением любопытства.Забей уже конкретно на BGE, так как он мёртв... Но в плане общего развития, я только приветствую твой энтузиазм...
Ты пробовал сделать свою мафынку и следы "с грязью" тоже физикой, и тоже в Блендере, но вне BGE?
>> тележка едет назад не оставляя следовНиколай, извиняюсь, проблема оказалась труднее чем предполагалось или просто занятость большая? Я никуда не спешу, но хотелось бы быть уверенным, что вопрос не забыт.
... буду искать причину ...
... сними у следа чек с Backface Cull https://docs.blender.org/manual/ru/dev/game_engine/materials.html?highlight=backface#game-settings ...Помогло, спасибо Николай.
... возможный вариант - сделать коллизийное колесо невидимым, и сделать второе колесо, связанное с первым родительским отношением ...Городулька будет, а блендер в чистом виде, каким-то образом центр колеса опустить не может?
... для второго колеса отменить коллизию и сделать его диаметр больше коллизийного ...
... возможный вариант - сделать коллизийное колесо невидимым, и сделать второе колесо, связанное с первым родительским отношением ...Николай, городульку попробовал сгородить с иной идеей. В твоей не нравится то, что если колесо с твоим принципом использовать, то это колесо будет равноуглублённо следовать по всей поверхности, а ведь интересно сделать поверхность с разной плотностью в разных местах.
... для второго колеса отменить коллизию и сделать его диаметр больше коллизийного ...
Ерунда какая-то, не даёт возможности пристегнуть файл. Попозже попробую.Странно, сделал несколько попыток отправить файл, но безуспешно, сайт не выдаёт окно поиска пристёгиваемого файла. Сбой на сайте, или я что-то нашкодил?
Странно, сделал несколько попыток отправить файл, но безуспешно, сайт не выдаёт окно поиска пристёгиваемого файла. Сбой на сайте, или я что-то нашкодил?http://blender-3d.ru/forum/index.php/topic,418.msg30991.html#msg30991
Спасибо за информацию, Striver. Подожду когда нормализуется всё. В конце концов есть файлообменники.ЦитироватьСтранно, сделал несколько попыток отправить файл, но безуспешно, сайт не выдаёт окно поиска пристёгиваемого файла. Сбой на сайте, или я что-то нашкодил?http://blender-3d.ru/forum/index.php/topic,418.msg30991.html#msg30991