взять координаты объекта
|
|
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 использовать отрезок? другими словами- как лучше ограничить "область выделения"/работы луча выбора? и у вас сильно ли влияет на производительность использование коллизий?
Сообщение отредактировал 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, но как его использовать, пока не нишёл ни одного примера. С оптимизацией помучаюсь сегодня)
|
|
| |
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
|
|
| |