Intro, полную физику в игорах никто не реализует, пч она целиком кладётся на проц и обнуляет роль видюхи + для реальной физИки требуется длинную арифу крутить == такое чудо и супер-пупер комп не потянет тч в гамисах пиши физИку по фене шуеву == юзверям похЪ, им нужна красочность и динамика + умеренная требовательность к компу
UbIvItS, физика в играх использует float для относительно небольших уровней с квадратным радиусом 1-2 км, и double для больших уровней. Более высокая точность не требуется. В общем вот такая эволюция кода. Код (Lua): local dir_angular = vector() -------------------------------------------------------------------------------------------------------------------------- --v0.03 local dir_angular = vector() local force_yaw_pitch = angular_yaw + vel_angular_pitch if force_yaw_pitch~=0 then dir_angular:rotate_angle90(axis_yaw, axis_pitch, vel_angular_pitch/force_yaw_pitch*Deg90) end local force_angular = force_yaw_pitch + vel_angular_roll if force_angular~=0 then dir_angular:rotate_angle90(dir_angular, axis_roll, vel_angular_roll/force_angular*Deg90) end ph_shell:set_angular_vel(dir_angular:mul(force_angular)) -------------------------------------------------------------------------------------------------------------------------- --v0.04 if angular_roll<0 then axis_roll:invert() end if angular_yaw<0 then axis_yaw:invert() end if angular_pitch<0 then axis_pitch:invert() end if angular_yaw~=0 then dir_angular:rotate_angle90(axis_yaw, axis_pitch, math.atan(math.abs(angular_pitch/angular_yaw))) else dir_angular:set(axis_pitch) end local force_angular = math.sqrt(angular_yaw*angular_yaw + angular_pitch*angular_pitch) if force_angular~=0 then dir_angular:rotate_angle90(dir_angular, axis_roll, math.atan(math.abs(angular_roll/force_angular))) else dir_angular:set(axis_roll) end force_angular = math.sqrt(force_angular*force_angular + angular_roll*angular_roll) ph_shell:set_angular_vel(dir_angular:mul(force_angular)) -------------------------------------------------------------------------------------------------------------------------- --v0.05 local force_angular = angular_roll local force_yaw_pitch = math.sqrt(angular_yaw^2 + angular_pitch^2) if force_yaw_pitch~=0 then local scale0, scale1 = angular_yaw/force_yaw_pitch, angular_pitch/force_yaw_pitch dir_angular.x = axis_yaw.x*scale0 + axis_pitch.x*scale1 dir_angular.y = axis_yaw.y*scale0 + axis_pitch.y*scale1 dir_angular.z = axis_yaw.z*scale0 + axis_pitch.z*scale1 force_angular = math.sqrt(force_yaw_pitch^2 + angular_roll^2) scale0, scale1 = force_yaw_pitch/force_angular, angular_roll/force_angular dir_angular.x = dir_angular.x*scale0 + axis_roll.x*scale1 dir_angular.y = dir_angular.y*scale0 + axis_roll.y*scale1 dir_angular.z = dir_angular.z*scale0 + axis_roll.z*scale1 else dir_angular:set(axis_roll) end -------------------------------------------------------------------------------------------------------------------------- --v0.05a local force_angular = math.sqrt(angular_yaw^2 + angular_pitch^2 + angular_roll^2) if force_angular>0 then local scale0, scale1, scale2 = angular_yaw/force_angular, angular_pitch/force_angular, angular_roll/force_angular dir_angular.x = axis_yaw.x*scale0 + axis_pitch.x*scale1 + axis_roll.x*scale2 dir_angular.y = axis_yaw.y*scale0 + axis_pitch.y*scale1 + axis_roll.y*scale2 dir_angular.z = axis_yaw.z*scale0 + axis_pitch.z*scale1 + axis_roll.z*scale2 end dir_angular:mul(force_angular) -------------------------------------------------------------------------------------------------------------------------- --v0.05b local force_angular = math.sqrt(angular_yaw^2 + angular_pitch^2 + angular_roll^2) if force_angular>0 then local scale0, scale1, scale2 = angular_yaw/force_angular, angular_pitch/force_angular, angular_roll/force_angular dir_angular.x = (axis_yaw.x*scale0 + axis_pitch.x*scale1 + axis_roll.x*scale2)*force_angular dir_angular.y = (axis_yaw.y*scale0 + axis_pitch.y*scale1 + axis_roll.y*scale2)*force_angular dir_angular.z = (axis_yaw.z*scale0 + axis_pitch.z*scale1 + axis_roll.z*scale2)*force_angular end -------------------------------------------------------------------------------------------------------------------------- --v0.06 dir_angular.x = axis_yaw.x*angular_yaw + axis_pitch.x*angular_pitch + axis_roll.x*angular_roll dir_angular.y = axis_yaw.y*angular_yaw + axis_pitch.y*angular_pitch + axis_roll.y*angular_roll dir_angular.z = axis_yaw.z*angular_yaw + axis_pitch.z*angular_pitch + axis_roll.z*angular_roll -------------------------------------------------------------------------------------------------------------------------- Вот так. Сейчас надо найти формулу, где надо восстановить angular_yaw, angular_pitch, angular_roll, если dir_angular и остальные векторы известны. Ну смоделировать работу трёхосных акселерометров и гироскопа. У нас на скорость может что-то внешние повлиять, коллизия например.
Intro, дабл и флоут - такие лапочки https://docs.python.org/3/tutorial/floatingpoint.html если делать мало-мальски приличный контроль аппроксимации - ошибка останется на высоком уровне, а вот скорости заметно упадут, поэтому в научно-валидных расчётах пользуют именно длинную арифу.
UbIvItS, питухоний? Это бред для питухонцев у которых проблемы с математикой, даже с элементарной. У любого моделирования есть погрешность, для научных часто double не хватает, используют четвертную. А для игр используется даже половинная в два байта, правда с этим типом работает В/К, для некоторых рассчётов. Насчёт восстановить angular_yaw, angular_pitch, angular_roll. Вот: Код (Lua): -------------------------------------------------------------------------------------------------------------------------- --v0 mag = dir_angular:magnitude() dir_angular:normalize() angle = math.acos(axis_yaw:dotproduct(dir_angular)) angular_yaw = math.cos(angle)*mag angle = math.acos(axis_pitch:dotproduct(dir_angular)) angular_pitch = math.cos(angle)*mag angle = math.acos(axis_roll:dotproduct(dir_angular)) angular_roll = math.cos(angle)*mag -------------------------------------------------------------------------------------------------------------------------- --v1 mag = dir_angular:magnitude() dir_angular:normalize() angular_yaw = axis_yaw:dotproduct(dir_angular)*mag angular_pitch = axis_pitch:dotproduct(dir_angular)*mag angular_roll = axis_roll:dotproduct(dir_angular)*mag -------------------------------------------------------------------------------------------------------------------------- --v2 angular_yaw = axis_yaw:dotproduct(dir_angular) angular_pitch = axis_pitch:dotproduct(dir_angular) angular_roll = axis_roll:dotproduct(dir_angular) -------------------------------------------------------------------------------------------------------------------------- Как видно правила прямого треугольника. Так же сделал оптимизацию, и получилось весьма хорошо и быстро.
да, при чём там питоха??? == это Вопрос арифы флоутов: 580000 - .00000000001 == 580000. 128 бит - тожЪ слёзы == меньше 256 для приличных расчётов брать не стоит.. в большинстве случаев гораздо дешевле и сильно лучше себя стенды показывают
Нафлудили тут понимаш, ладно. С сопротивлением при угле атаки тела вращения типа ракета разобрались. А вот какое будет сопротивлением у тела более сложной формы, но так же симметричное типа самолёт, вертолёт, квадрокоптер? Очевидно от угла атаки dir_vel:dotproduct(axis_roll), а так же от крена. Код (Lua): -------------------------------------------------------------------------------------------------------------------------- --v0 --сила сопротивления воздуха... local lvel, dir_vel = vector(), vector() ph_shell:get_linear_vel(lvel) local vel, k_air = lvel:magnitude(), 1 local atack_pitch, atack_roll = 0, 0 if vel>0.005 then --зависит от угла атаки тангажа и крена, зависимость синусоидальная. dir_vel:set(lvel):normalize() atack_pitch = math.acos(clamp(dir_vel:dotproduct(axis_roll), -1.0, 1.0)) --тангаж if atack_pitch>0.001 then local pitch90 = vector():slerp(axis_roll, dir_vel, Deg90/atack_pitch) atack_roll = math.acos(clamp(pitch90:dotproduct(axis_pitch), -1.0, 1.0)) - Deg90 --крен end local angle_sin = math.sin(atack_pitch) local k_max = k_front + angle_sin*(k_top-k_front) local k_min = k_front + angle_sin*(k_side-k_front) k_air = k_min + math.cos(atack_roll)*(k_max-k_min) end local k = -vel*k_air*self.mass100*fDelta -------------------------------------------------------------------------------------------------------------------------- --v1 --сила сопротивления воздуха... local lvel, dir_vel = vector(), vector() ph_shell:get_linear_vel(lvel) local vel, k_air = lvel:magnitude(), 1 local atack_pitch, atack_roll = 0, 0 if vel>0.005 then --зависит от угла атаки тангажа и крена, зависимость синусоидальная. dir_vel:set(lvel):normalize() atack_pitch = math.acos(clamp(dir_vel:dotproduct(axis_roll), -1.0, 1.0)) --тангаж if atack_pitch>0.001 then local pitch90 = vector():crossproduct(dir_vel, axis_roll):normalize() atack_roll = math.acos(clamp(pitch90:dotproduct(axis_pitch), -1.0, 1.0)) --крен end local angle_sin = math.sin(atack_pitch) local k_max = k_front + angle_sin*(k_top-k_front) local k_min = k_front + angle_sin*(k_side-k_front) k_air = k_min + math.cos(math.abs(atack_roll))*(k_max-k_min) end local k = -vel*k_air*self.mass100*fDelta Я тут конечно выбрал сложный путь, и в v0 нагородил много кода, потом вспомнил crossproduct, которая сильно проще slerp. В общем, тут предполагается что тело у нас близко к параллелепипеду, и мы приблизительно вычисляем площадь миделя, которая приблизительно равна текущему коэффициенту сопротивления воздуха. Хотя для более точных расчётах можно взять табличный данные по всем этим углам атаки и скорости. Но нам и так сойдёт. К тому же у нас просто нет этих таблиц, это надо обдувать либо реальной трубе, либо в виртуальной. В общем, надо ещё раз оптимизировать, там как видно можно убрать тригонометрию.