Для начала мы создадим физический мир Bullet. Для тех кто не в курсе как это происходит, поясняю что физика существует отдельно от геометрии, а в процессе просто синхронизируются объекты геометрии(3D модели) с физическими объектами. Так вот для начала нужно задать параметры физического мира, который будет содержать такие объекты.
Code
from direct.showbase.DirectObject import DirectObject import direct.directbase.DirectStart from pandac.PandaModules import *
Code
# Выполняем импорт нужных классов из модуля физики from panda3d.bullet import BulletWorld from panda3d.bullet import BulletPlaneShape from panda3d.bullet import BulletRigidBodyNode from panda3d.bullet import BulletBoxShape
# Дополнительно класс для отладки, с помочью его мы можем выполнить визуализацию объектов Bullet, это я #добавил для лучшего восприятия. Можно обойтись и без этого.
from panda3d.bullet import BulletDebugNode
# Создадим объект для отображения физической геометрии. debugNode = BulletDebugNode('Debug') debugNP = render.attachNewNode(debugNode)
# Теперь функцию для управления объектом def toggleDebug(): if debugNP.isHidden(): # Проверка состояния, скрыт или отображен. debugNP.show() # Если скрыт, то отображаем. else: debugNP.hide() # Если отображен, то скрываем.
# Функцию будем выполнять по нажатию кнопки F1. press_f1 = DirectObject() press_f1.accept('f1', toggleDebug)
1.
Code
# Собственно создаем мир. world = BulletWorld() # Устанавливаем режим отладки миру. world.setDebugNode(debugNP.node()) # Устанвливем силу гравитации и вектор для создания земного притяжения world.setGravity(Vec3(0, 0, -9.81))
И мир создан, но в нем пусто.
2.
Code
#Создаем плоскость, условно назовём её землёй. # Устанавливаем в горизонтальное положение . shape = BulletPlaneShape(Vec3(0, 0, 1), 0) # Создаем нод тела для физических объектов. node = BulletRigidBodyNode('Ground') # Добавляем к ноду плоскость node.addShape(shape) np = render.attachNewNode(node) # Устанавливаем начальную позицию. np.setPos(0, 0, -2) # Добавляем настроенный объект в физический мир. world.attachRigidBody(node)
И появилась земля.
3. Добавим динамический объект, стоит заметить если не задать массу, то объект будет статичным.
Code
# Создаем геометрию бокса(кубика) размером 0.5 shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5)) # Нод node = BulletRigidBodyNode('Box') # Задаем массу, тем самым делаем его динамическим. node.setMass(1.0) # Добавляем к ноду геометрию бокса node.addShape(shape) np = render.attachNewNode(node) np.setPos(0, 0, 0)
# Добавляем настроенный объект в физический мир. world.attachRigidBody(node)
# Загружаем модель кубика model = loader.loadModel('models/box.egg') model.setPos(-0.5, -0.5, -0.5) model.flattenLight() model.reparentTo(np)
И есть у нас динамический объект.
4. Теперь мир нужно оживить. Пишем для этого функцию.
Code
def update(task): dt = globalClock.getDt() # Берем время рендеринга предыдущего кадра. world.doPhysics(dt) # И передаем аргументом функции которая запускает шаг симуляции физики в указанном мире. return task.cont
taskMgr.add(update, 'update')
# И как всегда. run()
Однако стоит заметить что здесь в отличии от ODE панда автоматически определяет какой геометрический объект синхронизировать с физическим. На основании взаимно связей нодов. физ. нод – рендер(узел) – геом. нод.
Code
# -*- coding: utf-8 -*- from direct.showbase.DirectObject import DirectObject import direct.directbase.DirectStart from pandac.PandaModules import * # Выполняем импорт нужных классов из модуля физики. from panda3d.bullet import BulletWorld from panda3d.bullet import BulletPlaneShape from panda3d.bullet import BulletRigidBodyNode from panda3d.bullet import BulletBoxShape
# Дополнительно класс для отладки, с помочью его мы можем выполнить визуализацию объектов Bullet, это я добавил для лучшего восприятия. Можно обойтись и без этого. from panda3d.bullet import BulletDebugNode
# Создадим объект для отображения физической геометрии. debugNode = BulletDebugNode('Debug') debugNP = render.attachNewNode(debugNode)
# Теперь функцию для управления объектом. def toggleDebug(): if debugNP.isHidden(): # Проверка состояния, скрыт или отображен. debugNP.show() # Если скрыт, то отображаем. else: debugNP.hide() # Если отображен, то скрываем.
# Функцию будем выполнять по нажатию кнопки F1. press_f1 = DirectObject() press_f1.accept('f1', toggleDebug)
# Собственно создаем мир. world = BulletWorld() # Устанавливаем режим отладки миру. world.setDebugNode(debugNP.node()) # Устанвливем силу гравитации и вектор для создания земного притяжения. world.setGravity(Vec3(0, 0, -9.81))
#Создаем плоскость, условно назовём её землёй. # Устанавливаем в горизонтальное положение . shape = BulletPlaneShape(Vec3(0, 0, 1), 0) # Создаем нод тела для физических объектов. node = BulletRigidBodyNode('Ground') # Добавляем к ноду плоскость. node.addShape(shape) np = render.attachNewNode(node) # Устанавливаем начальную позицию. np.setPos(0, 0, -2) # Добавляем настроенный объект в физический мир. world.attachRigidBody(node)
# Создаем геометрию бокса(кубика) размером 0.5 shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5)) # Нод node = BulletRigidBodyNode('Box') # Задаем массу, тем самым делаем его динамическим. node.setMass(1.0) # Добавляем к ноду геометрию бокса. node.addShape(shape) np = render.attachNewNode(node) np.setPos(0, 0, 0)
# Добавляем настроенный объект в физический мир. world.attachRigidBody(node)
# Загружаем модель кубика. model = loader.loadModel('models/box.egg') model.setPos(-0.5, -0.5, -0.5) model.flattenLight() model.reparentTo(np)
def update(task): dt = globalClock.getDt() # Берем время рендеринга предыдущего кадра. world.doPhysics(dt) # И передаем аргументом функции которая запускает шаг симуляции физики в указанном мире. return task.cont
Ну интерес странная вещь, порой если не знаешь как пользоваться чем либо, то яростно ищешь ответы на свои вопросы, и думаешь вот-бы найти инфу, да на руском языке, прям как заветная мечта. При этом ворча сетуя на несправедливость в отношениях к русско-язычным. Для кого-то это стимул для познания, а для других повод отказаться от этого, аргументируя не популярностью, а раз не популярно значит отстой. Вот для таких и стоит писать, ведь у некоторых с таким мышлением первые впечатления бывают ошибочны. Ну чтож приятно услышать, благодарность.