Показать сообщение отдельно
Старый 15.05.2009, 11:46   #1
drwoland
AnyKey`щик
 
Регистрация: 15.05.2009
Сообщений: 3
Написано 0 полезных сообщений
(для 0 пользователей)
Сообщение синхронизация физики и анимации (newton)

Пользую newton для создания создания прототипа игрушки.
В процессе столкнулся с необходимостью подогнать физику под анимацию модели. Т.е. придать физическому телу (phBody) такие линейную и угловую скорость, что бы при следующем проходе phWorldStep() оно заняло то же положение, что и Entity, которому оно соответствует. В Ньютоне я подходящих инструментов не нашел. Пришлось писать самому. Все значения подгонял ручками на глазок, поэтому не везде работает гладко. Но если использовать предложенные значения, то результат получается достаточно точный. (у меня разница между координатами Entity и phBody при каждом проходе в среднем составляла 0,02 единицы)

Скажу большое спасибо тому, кто сумеет повысить точность и позволит использовать промежуточные значения шага phWorldStep, кроме указанных.

Function SyncBodyWithEntity(Body%,Entity%,phTiming#)
;Перемещает Физ.Тело в положение, которое занимает Entity 
;Криво работает со значениями шага phWorldStep(phTiming#) меньше 0.1
;Точнее всего работает со значениями 0.01, 0.05, 0.1 и выше. 
;При значении Меньше чем 0.01 - безбожно глючит

a#=1/phTiming ;обратная величина от шага phWorldStep()

;рассчитываем угловую скорость Entity исходя из разницы углов тела и Entity
Local deltaAngX=EntityPitch(Entity,1)- phBodyGetPitch(Body)
Local deltaAngY=EntityYaw(Entity,1)- phBodyGetYaw(Body)
Local deltaAngZ=EntityRoll(Entity,1)- phBodyGetRoll(Body)

;обрезаем полученный угол до диапазона от -180 до +180
If Abs(deltaAngX)> 180 Then deltaAngX = deltaAngX -360 * deltaAngX/Abs(deltaAngX)
If Abs(deltaAngY)> 180 Then deltaAngY = deltaAngY -360 * deltaAngY/Abs(deltaAngY)
If Abs(deltaAngZ)> 180 Then deltaAngZ = deltaAngZ -360 * deltaAngZ/Abs(deltaAngZ)
Local OmegaX#=(deltaAngZ)Mod 360
Local OmegaY#=(deltaAngZ)Mod 360
Local OmegaZ#=(deltaAngZ)Mod 360

;разворачиваем вектор скорости в обратную сторону
OmegaX=OmegaX*-1
OmegaY=OmegaY*-1
OmegaZ=OmegaZ*-1

;Вычисляем линейную скорость Entity исходя из разницы координат тела и Entity
Local fdeltax#=EntityX(Entity,1)-phBodyGetX(Body)
Local fdeltay#=EntityY(Entity,1)-phBodyGetY(Body)
Local fdeltaz#=EntityZ(Entity,1)-phBodyGetZ(Body)

Local k = phTiming*60 ;Коэффициент скорости. Пришлось оставить Int. Иначе падает точность :(  		

Local VelX# = fdeltax*a*k
Local VelY# = fdeltay*a*k
Local VelZ# = fdeltaz*a*k

;придаем телу угловую и линейную скорость
phBodySetVel(Body,VelX,VelY,VelZ)
phBodySetOmega(Body,OmegaX,OmegaY,OmegaZ)

End Function
P.s. На blitz'e пишу недавно, поэтому не ругайте, если в коде что то коряво.
(Offline)
 
Ответить с цитированием