Функция определения столкновения двух параллелепипедов
|
|
dpsstudio | Дата: Вторник, 07.04.2009, 22:21 | Сообщение # 1 |
![dpsstudio](/avatar/11/805792.jpg) Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
| Хотелось бы выслушать идеи и посмотреть примеры кода функции,определяющей наличие столкновения между двумя моделями при помощи AABB(горизонтально расположенных параллелепипедов)
|
|
| |
ninth | Дата: Среда, 08.04.2009, 00:55 | Сообщение # 2 |
![ninth](/avatar/95/7636-764462.gif) Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| как задан параллелепипед? Центр и размеры или вершины?
|
|
| |
dpsstudio | Дата: Среда, 08.04.2009, 20:26 | Сообщение # 3 |
![dpsstudio](/avatar/11/805792.jpg) Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
| Есть верхняя левая точка ближняя и нижняя правая дальняя.Узнать соответственно остальные вершины и размеры не проблема.Вообще данные об этих двух точках получают при использовании функции getTightBounds().
|
|
| |
ninth | Дата: Среда, 08.04.2009, 23:48 | Сообщение # 4 |
![ninth](/avatar/95/7636-764462.gif) Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| По-идее можно спроецировать грани, принадлежащие одноимённой вершине на три оси и проверить пересечение соответствующих отрезков. Если боксы пересекаются, то соответствующие отрезки (лежащие на одной оси) тоже должны пересекаться.
|
|
| |
dpsstudio | Дата: Четверг, 09.04.2009, 18:56 | Сообщение # 5 |
![dpsstudio](/avatar/11/805792.jpg) Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
| Спасибо,вот тут нашёл вроде эту формулу: http://www.x-sky.ru/2006/11/25/stolknovenija_v_igrakhkolizii.html Потом попытался перевести в код в виде такой вот функции: Code def CollideAABB(node1,node2):
vec1_size=VBase3(math.fabs(node1.getTightBounds()[0].getX()-node1.getTightBounds()[1].getX()), math.fabs(node1.getTightBounds()[0].getY()-node1.getTightBounds()[1].getY()), math.fabs(node1.getTightBounds()[0].getZ()-node1.getTightBounds()[1].getZ())) vec2_size=VBase3(math.fabs(node2.getTightBounds()[0].getX()-node2.getTightBounds()[1].getX()), math.fabs(node2.getTightBounds()[0].getY()-node2.getTightBounds()[1].getY()), math.fabs(node2.getTightBounds()[0].getZ()-node2.getTightBounds()[1].getZ()))
# vec1_center=Point3(node1.getTightBounds()[0].getX()+vec1_size.getX()/2.0, # node1.getTightBounds()[0].getY()+vec1_size.getY()/2.0, # node1.getTightBounds()[0].getZ()+vec1_size.getZ()/2.0) # # vec2_center=Point3(node2.getTightBounds()[0].getX()+vec2_size.getX()/2.0, # node2.getTightBounds()[0].getY()+vec2_size.getY()/2.0, # node2.getTightBounds()[0].getZ()+vec2_size.getZ()/2.0) vec1_center=node1.getBounds().getCenter() vec2_center=node2.getBounds().getCenter() if math.fabs(vec1_center.getX()-vec2_center.getX())>vec1_center.getX() / 2.0+vec2_center.getX() / 2.0: return False if math.fabs(vec1_center.getY()-vec2_center.getY())>vec1_center.getY() / 2.0+vec2_center.getY() / 2.0: return False if math.fabs(vec1_center.getZ()-vec2_center.getZ())>vec1_center.getZ() / 2.0+vec2_center.getZ() / 2.0: return False
print "Collision AABB detected" return True Функция столкновения не определяет.Хотелось бы узнать,что неправильно(следует учитывать,что в панде ось Z идёт вверх,потом Y и Z из той формулы я поменял местами).
|
|
| |
ninth | Дата: Четверг, 09.04.2009, 22:32 | Сообщение # 6 |
![ninth](/avatar/95/7636-764462.gif) Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| попробуй такую функцию np1,np2 - nodePath Code def checkCollision(np1,np2): res=False min1,max1=np1.getTightBounds() min2,max2=np2.getTightBounds() if ((min1[0]<=min2[0]<=max1[0]) or (min1[0]<=max2[0]<=max1[0])): if ((min1[1]<=min2[1]<=max1[1]) or (min1[1]<=max2[1]<=max1[1])): if ((min1[2]<=min2[2]<=max1[2]) or (min1[2]<=max2[2]<=max1[2])): res=True return res
|
|
| |
dpsstudio | Дата: Воскресенье, 12.04.2009, 12:35 | Сообщение # 7 |
![dpsstudio](/avatar/11/805792.jpg) Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
| Проверил эту функцию,к сожалению она не определяет столкновения правильно
|
|
| |
ninth | Дата: Понедельник, 13.04.2009, 13:25 | Сообщение # 8 |
![ninth](/avatar/95/7636-764462.gif) Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| Эм... в чём определяется неправильность?
|
|
| |
dpsstudio | Дата: Понедельник, 13.04.2009, 19:44 | Сообщение # 9 |
![dpsstudio](/avatar/11/805792.jpg) Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
| Скажем так,я включаю режим отображения ограничивающего параллелепипеда - showTightBounds(),двигаю объекты и функция пишет определение столкновения ДО того,как объект входит в зону ограничивающего параллелепипеда.Т.е. почти всегда она возвращает True.
|
|
| |
ninth | Дата: Вторник, 14.04.2009, 02:08 | Сообщение # 10 |
![ninth](/avatar/95/7636-764462.gif) Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
| У меня всё работает. Вот мой проверочный код. Единственное, что у меня небыло под рукой модели сложнее бокса, так что проверял на нём Code from pandac.PandaModules import * import direct.directbase.DirectStart from direct.showbase.DirectObject import DirectObject
b1=loader.loadModel('box') b1.reparentTo(render) b1.setHpr(45,45,45) b1.showTightBounds() min1,max1=b1.getTightBounds() print min1,max1 b2=loader.loadModel('box') b2.reparentTo(render) b2.showTightBounds() min2,max2=b1.getTightBounds() print min2,max2
class control(DirectObject): def __init__(self): self.accept('arrow_left',self.moveObj,[Vec3(0.5,0,0)]) self.accept('arrow_right',self.moveObj,[Vec3(-0.5,0,0)]) self.accept('arrow_up',self.moveObj,[Vec3(0,0.5,0)]) self.accept('arrow_down',self.moveObj,[Vec3(0,-0.5,0)]) self.accept('a',self.moveObj,[Vec3(0,0,0.5)]) self.accept('z',self.moveObj,[Vec3(0,0,-0.5)]) def moveObj(self,vector): b2.setPos(b2,vector) print self.checkCollision(b1,b2)
def checkCollision(self,np1,np2): res=False min1,max1=np1.getTightBounds() min2,max2=np2.getTightBounds() if ((min1[0]<=min2[0]<=max1[0]) or (min1[0]<=max2[0]<=max1[0])): if ((min1[1]<=min2[1]<=max1[1]) or (min1[1]<=max2[1]<=max1[1])): if ((min1[2]<=min2[2]<=max1[2]) or (min1[2]<=max2[2]<=max1[2])): res=True return res
control() run()
|
|
| |