[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Функция определения столкновения двух параллелепипедов
dpsstudioДата: Вторник, 07.04.2009, 22:21 | Сообщение # 1
Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
Хотелось бы выслушать идеи и посмотреть примеры кода функции,определяющей наличие столкновения между двумя моделями при помощи AABB(горизонтально расположенных параллелепипедов)
 
ninthДата: Среда, 08.04.2009, 00:55 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
как задан параллелепипед? Центр и размеры или вершины?
 
dpsstudioДата: Среда, 08.04.2009, 20:26 | Сообщение # 3
Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
Есть верхняя левая точка ближняя и нижняя правая дальняя.Узнать соответственно остальные вершины и размеры не проблема.Вообще данные об этих двух точках получают при использовании функции getTightBounds().
 
ninthДата: Среда, 08.04.2009, 23:48 | Сообщение # 4
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
По-идее можно спроецировать грани, принадлежащие одноимённой вершине на три оси и проверить пересечение соответствующих отрезков. Если боксы пересекаются, то соответствующие отрезки (лежащие на одной оси) тоже должны пересекаться.
 
dpsstudioДата: Четверг, 09.04.2009, 18:56 | Сообщение # 5
Сержант
Группа: Модераторы
Сообщений: 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
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
Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
Проверил эту функцию,к сожалению она не определяет столкновения правильно
 
ninthДата: Понедельник, 13.04.2009, 13:25 | Сообщение # 8
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Эм... в чём определяется неправильность?
 
dpsstudioДата: Понедельник, 13.04.2009, 19:44 | Сообщение # 9
Сержант
Группа: Модераторы
Сообщений: 29
Награды: 0
Репутация: 1
Статус: Offline
Скажем так,я включаю режим отображения ограничивающего параллелепипеда - showTightBounds(),двигаю объекты и функция пишет определение столкновения ДО того,как объект входит в зону ограничивающего параллелепипеда.Т.е. почти всегда она возвращает True.
 
ninthДата: Вторник, 14.04.2009, 02:08 | Сообщение # 10
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()
 
  • Страница 1 из 1
  • 1
Поиск: