[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Форум Panda3D - по русски » Panda3D » Общие вопросы » взять координаты объекта
взять координаты объекта
akzyДата: Пятница, 10.05.2013, 19:06 | Сообщение # 1
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
Добрый день, в процессе работы наткнулся на невозможность вытаскивания координат
прилагаю картинку и кусок кода
Код
def __init__(self):

         k=G6()
         k.rand()
         k.close()
         self.cubeRoot= render.attachNewNode(k.node)
         #base.cam.setPos(0,-50,15)
         #base.cam.lookAt(15, 15, 0)

         # Обработчик столкновений "луча" мышки и объектов ______________________
         self.picker = CollisionTraverser()              # создаём traverser
         self.pq     = CollisionHandlerQueue()           # создаём обработчик столкновений
         self.pickerNode = CollisionNode('mouseRay')     # создаём луч столкновений

         self.pickerNP = camera.attachNewNode(self.pickerNode) #

         self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
         self.pickerRay = CollisionRay()                 #собственно создаётся луч
         self.pickerNode.addSolid(self.pickerRay)

         self.picker.addCollider(self.pickerNP, self.pq)

         #self.picker.showCollisions(render)

         self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')

         #self.debugConsole()
         #self.updateDebugConsoleTask=taskMgr.add(self.updateDebugConsoleTask,'updateDebugConsoleTask')
         self.showmenu()
         #self.cubeRoot = render.attachNewNode("cubeRoot")

     def mouseTask(self,task):
         if base.mouseWatcherNode.hasMouse():
             mpos = base.mouseWatcherNode.getMouse()
             self.pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
             #self.menutext[4]=str(base.camNode)
             self.picker.traverse(self.cubeRoot)
             #self.menutext[5]=str(self.pq)
             if self.pq.getNumEntries() > 0:
                 self.menutext[2]=str(self.pq.getNumEntries())+" entries"
                 self.pq.sortEntries()
                 entry = self.pq.getEntry(0)
                 self.menutext[3]=str(entry)
                 #(x,y,z) = entry.getIntoNodePath().getParent().getPos()
                 #self.menutext[4]=str(entry.getIntoNodePath().getParent().getPos())
             #self.menutext[0]=str(mpos.getX())
            # self.menutext[1]=str(mpos.getY())

         return task.cont
на картинке видно, что обнаружены коллизии, и даны их координаты, но как их оттуда вытащить пока не понятно, гуглинг помощи не сделал...
ещё- может, вместо Ray использовать отрезок?
другими словами- как лучше ограничить "область выделения"/работы луча выбора?
и у вас сильно ли влияет на производительность использование коллизий?
Прикрепления: 1818096.png (604.9 Kb)


Сообщение отредактировал akzy - Пятница, 10.05.2013, 19:11
 
ninthДата: Пятница, 10.05.2013, 19:49 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
entry.getSurfacePoint(render) - точка коллизии в координатах render
entry.getSurfaceNormal(render) - нормаль в точке коллизии
если нужно получить именно объект с которым было пересечение, то можно глянуть пример с шахматами - там это реализовано.

Скорость работы коллизий зависит от довольно большого числа факторов. Количество полигонов, степень и способ их разбиения на ноды, иерархия нодов, тела, которыми проверяют коллизии.
Использование отрезка вместо луча действительно должно улучшить быстродействие, но только в том случае если сцена разбита на некоторое кол-во нодов т.к. прежде чем обрабатывать пересечение собственно с полигонами ноды проверяется пересечение с её боундингбоксом, которое делается значительно быстрее и позволяет сразу отбросить часть геометрии с которой гарантированно не будет пересечения.
 
akzyДата: Суббота, 11.05.2013, 12:30 | Сообщение # 3
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
у меня почему то эта тема не отображалась после создания, вот повторял вопрос.
На текущий момент мне пока достаточно (надеюсь) этих методов, параллельно анализирую пару десятков других примеров на панде.
Деление на ноды будет, но насколько скоро, не могу сказать....
черпаю мысли из https://github.com/search?q=panda3d&ref=simplesearch&type=Repositories
 
ninthДата: Суббота, 11.05.2013, 14:04 | Сообщение # 4
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
О, а я чёт не догадался на гитхабе поискать. Добавлю в полезные ссылки, если не возражаешь
 
akzyДата: Суббота, 11.05.2013, 15:56 | Сообщение # 5
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
Конечно не возражаю, в ближайшее время, как с основами разберусь, поделюсь своими находками тоже.
Примеров работы с CollisionLine не удалось найти, не сталкивался с ней? не получается её правильно запустить (сужу по производительности, она никак не повышается)
В общей сложности добавление к проекту просчёта коллизий замедляет всё от 3 до 20 раз (сужу по fps)... вот задумался что делать


Сообщение отредактировал akzy - Суббота, 11.05.2013, 15:59
 
ninthДата: Суббота, 11.05.2013, 23:08 | Сообщение # 6
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Тебе не нужна не CollisionLine, а CollisionSegment.
Код
myFromObject.node().addSolid(CollisionSegment(x1, y1, z1, x2, y2, z2))

Где x1, y1, z1 - начало отрезка, x2, y2, z2 - конец отрезка в координатах myFromObject
 
akzyДата: Пятница, 24.05.2013, 11:59 | Сообщение # 7
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
если честно, думаю,что сделал чтото не так (работает , но производительность просто г..)
Сделал простую замену (код пишу по памяти на работе,точный код выложу вечером)
Код
# Обработчик столкновений "луча" мышки и объектов ______________________
          self.picker = CollisionTraverser()              # создаём traverser
          self.pq     = CollisionHandlerQueue()           # создаём обработчик столкновений
          self.pickerNode = CollisionNode('mouseRay')     # создаём луч столкновений

          self.pickerNP = camera.attachNewNode(self.pickerNode) #

          self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
          #                #собственно создаётся луч
          self.pickerNode.addSolid(CollisionSegment(0, 0, 0, 2, 2, 2))
            
          self.picker.addCollider(self.pickerNP, self.pq)

обработчик будет для 1)выделения "близлежащих" объектов, в радиусе 5 от экрана к примеру, и 2) до первого попавшегося в поле обзора объекта (радиус 1000).
подскажите, куда копать


Сообщение отредактировал akzy - Пятница, 24.05.2013, 12:07
 
ninthДата: Пятница, 24.05.2013, 12:55 | Сообщение # 8
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Первое: возможно ты вызываешь обработку коллизий каждый фрейм, а тебе она нужна только по щелчку мыши
Второе: раз код работает, знач всё правильно, теперь надо оптимизировать геометрию - назначить маски лучу и тем объектам которые нужно детектить чтобы избежать лишних проверок, оптимизировать колизиооную геометрию. Возможно она у тебя берётся из видимой, а по-хорошему нужно сильно упрощать и делить на части чтобы не обрабатывать всю сетку
 
akzyДата: Суббота, 25.05.2013, 15:31 | Сообщение # 9
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
намёк понял, буду искать дальше...
но пока вопрос- если я хочу сделать предварительную подсветку куба под курсором (в определённом радиусе), то мне нужно: по координате камеры взять ближайшие наборы кубов и назначить им и лучу (сегменту) маску + если hprxyz не поменялись,то не проверять ещё раз
потом удалить ноду куба, создать новую с изменённым цветом?

заметил такую вещь, что сегмент работает также как и луч, т.е. при коде
Код
self.picker = CollisionTraverser()              # создаём traverser
         self.pq     = CollisionHandlerQueue()           # создаём обработчик столкновений
         self.pickerNode = CollisionNode('mouseRay')     # создаём луч столкновений

         self.pickerNP = camera.attachNewNode(self.pickerNode) #

         self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
         #                #собственно создаётся луч
         #self.pickerNode.addSolid(CollisionSegment(0, 0, 0, 2, 2, 2))
         #self.pickerRay =CollisionRay()#  CollisionSegment()
         self.pickerRay =CollisionSegment(0, 0, 0, 1, 1, 1)
         self.pickerNode.addSolid(self.pickerRay)

         self.picker.addCollider(self.pickerNP, self.pq)

должны как я понял, на расстоянии 1 куб от камеры только проверять коллизии, но словно не отрезок, а луч идёт опять
 
ninthДата: Суббота, 25.05.2013, 19:53 | Сообщение # 10
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Хм. Ты хочешь сказать, что сегмент коллидится со всей геометрией как луч, а не останавливается в единице от камеры? Если да, можешь сделать минимальный пирмер для демонстрации, возможно баг?

Цитата (akzy)
по координате камеры взять ближайшие наборы кубов и назначить им и лучу (сегменту) маску

Ну, не обязательно настолько, но учитывая, что ты, если мне память не изменяет, игрешь с подобной майнкрафту геометрией, то в принципе, да есть смысл ставить маску только на те чанки (группы) рядом с которыми находится игрок. Делать их "активными".

Если у тебя кубы не собраны в единую геометрию, то можно просто менять цвет нода setColor. Я, когда мне нужно было подсвечивать, делал шейдером выделение грани, но это весьма специфичная техника. Можешь например просто ставить поверх чуть увеличенный куб в режиме сетки, т.е чтобы только грани подсвечивались. myNodepath.setRenderModeWireframe() А можешь ещё использовать LineNodePath
 
akzyДата: Суббота, 25.05.2013, 22:32 | Сообщение # 11
Лейтенант
Группа: Пользователи
Сообщений: 55
Награды: 0
Репутация: 3
Статус: Offline
в приложении текущий проектег с небольшими комментариями.
CollisionRay() и CollisionSegment() дают одинаковый эффект.
кубы собираются в единую геому для оптимизации производительности, поэтому setcolor действует на весь блок.
думаю для подсветки делать сделать сетчатый куб, да, но получается - каждый раз его создавать и уничтожать?
думаю, можно использовать GeomVertexRewriter, но как его использовать, пока не нишёл ни одного примера.
С оптимизацией помучаюсь сегодня)
Прикрепления: toupload.7z (95.2 Kb)
 
ninthДата: Суббота, 25.05.2013, 23:42 | Сообщение # 12
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Ок, пример гляну, если действительно похоже на баг - спрошу на оффоруме.

Зачем каждый раз создавать и уничтожать? Есть же методы hide() и show() у тебя ведь кубы одинаковые вот и дежи в памяти фигуру типа курсора, когда надо - ставь на место и показывай/скрывай это значительно проще и быстрее. И посмотри всё же в сторону LineNodePath - это более гибкий инструмент чем wireframe.
 
ninthДата: Воскресенье, 26.05.2013, 00:21 | Сообщение # 13
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
По поводу CollisionSegment - вкурил. Он растягиявается линзой камеры до конца поля видимости. Можно сделать такой хак:
Код
        proj = camera.attachNewNode(LensNode('proj'))
         lens = PerspectiveLens()
         lens.setFov(base.cam.node().getLens().getFov())
         lens.setNearFar(0.1, 5.0)
         proj.node().setLens(lens)
         self.helper = proj.node()

         ....

         self.pickerRay.setFromLens(self.helper, mpos.getX(),mpos.getY())


Здесь мы создаём ещё одну линзу с дальностью всего 5 единиц, и цепляем к камере. Она ничего не рендерит, зато позволяет ограничит дальность сегмента
 
ninthДата: Воскресенье, 26.05.2013, 00:41 | Сообщение # 14
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
К слову о производительности - сейчас у тебя детектится видимая геометрия, а тут получается какая фигня - что для видеокарточки хорошо, то для коллизий - смерть. Т.к. геометрия у тебя одним куском, то каждый проход коллидеру приходится проверять всю пачку полигонов. Помимо этого на оффоруме обсуждалось, что если ставить маску на видимую геометрию, то движку приходится каждый раз на лету пересчитывать на её основе колизионную геометрию, так что даже созданная один к одному с видимой, но заранее - будет быстрее. Тебе надо попробовать сделать отдельный колизионный кубик с помощью CollisionPolygon и размножить его в нужных местах в данном случае не надо объединять это всё в одну кучу. Тут же автоматом у тебя появится шанс оптимизировать кол-во проверок - ставить колизионные кубы только недалеко от игрока и когда он отходит - удалять лишние
 
ninthДата: Воскресенье, 26.05.2013, 00:55 | Сообщение # 15
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Вот пост с оффорума, расставляющий точки над i с коллизиями
Цитата
Collision geometry is far, far cheaper than visible geometry. Although it is true that simpler geometry is faster still, collision geometry would be about 100 times faster even if you exactly duplicated your visible geometry 1:1 in the scene graph.

This is because the code path that supports visible geometry has to do it by creating a CollisionPolygon on the fly--each frame!--for each visible triangle in your mesh.

This is necessary because the visible triangles don't store all of the data that is needed for the collision system to work, like the plane equation of the polygon.

Visible geometry as collision data was always intended as a quick hack to get something to work when you just need something now. It should not be considered a viable long-term solution.

David
 
Форум Panda3D - по русски » Panda3D » Общие вопросы » взять координаты объекта
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Поиск: