Как обнаружить события касания в определенной области Renderer в android?

В андроиде я привел пример вращающейся сферы, приведенный здесь . Он создает простое приложение, показывающее вращающуюся сферу (землю).

Теперь я хочу что-то сделать, если вращающаяся сфера нажата на дисплее телефона. Я не хочу реагировать на события за пределами вращающейся сферы. Вот что я пробовал до сих пор, используя производную версию GLSurfaceView :

 public class MyGLSurfaceView extends GLSurfaceView { MyGLSurfaceView(Context context) { super(context); } public boolean onTouchEvent(MotionEvent event) { int x = (int)event.getX(); int y = (int)event.getY(); Log.d("onTouchEvent",String.format("keyCode: %d coords: %d %d", event.getActionMasked(), x, y)); Renderer renderer = this.Renderer.getRenderer(); // ERROR return super.onTouchEvent(event); } } 

Без линии ERROR этот код работает, и когда я нажимаю на дисплей, я получаю координату x / y.

Однако, чтобы оценить, было ли событие в рамках сферы, мой подход состоял в том, чтобы получить рендерер, у которого есть объект Sphere чтобы определить, находятся ли координаты x / y в пределах сферы.

Но строка ERROR не работает, я получаю сообщение об ошибке

 Error:(26, 56) error: cannot find symbol method getRenderer() 

Как я могу исправить эту ошибку; Или существует более разумный способ автоматически узнать, было ли событие на Sphere -графическом объекте?

Может быть, это хорошая идея, чтобы изменить конструктор и передать экземпляр визуализации в MyGLSurfaceView ? ADDENDUM: эта идея, похоже, не работает. Я получаю ошибку конструктора, которую я не понимаю …

Ваш вопрос намного сложнее, чем просто обнаружение событий касания. Средство визуализации не только имеет сферический объект, но и содержит весь контент OpenGL ES. Таким образом, даже после того, как вы обнаружите ваши события касания, вам нужно будет преобразовать ваши 2D-координаты экрана в 3D-лучи и проверить, пересекается ли она с сферой. Это называется лучей . Вот хорошее объяснение алгоритмов лучевого каста. Также есть хорошее видеоурочное руководство по внедрению Java Java.

Также вам нужно передать рендерер в конструкторе GLSurfaceView как вы и @ satm12. В документации для этого есть пример .

Я думаю, как вы сказали, хорошая идея передать рендерер в конструкторе. Затем передайте событие, которое будет обрабатываться рендерером в игровом цикле. GLSurfaceView имеет метод добавления runnable в поток рендеринга, называемый queueEvent .

Затем в рендерере, где у вас есть все визуализированные объекты, вы можете использовать лучевое кастинг, чтобы проверить, был ли объект нажат.

 public SurfaceView(Context context, GLRenderer renderer) { super(context); setEGLContextClientVersion(2); setRenderer(renderer); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event == null) return false; // set touch coordinates to be between -1 and 1 float normalizedX = ((event.getX()/v.getWidth())*2 - 1; float normalizedY = -((event.getY()/v.getHeight())*2 - 1); if (event.getAction() == MotionEvent.ACTION_UP){ queueEvent(new Runnable() { @Override public void run() { renderer.handleTouchUP(normalizedX, normalizedY); } }); return true; } return false; } }); } 

То, что вы хотите сделать здесь, это проверить, находится ли ваше прикосновение в сфере. Самый прямой ответ – сделать 3D-луч, проходящий через позицию касания, и посмотреть, сталкивается ли луч с сферой, то есть столкновения Ray-Sphere. Для этого вы можете использовать gluUnProject () . Помните, что вам нужно использовать эту функцию дважды с точками ближней и дальней плоскости, чтобы получить 3D рядом с дальним вектором. Этот вектор является вашим трехмерным лучом для проверки коллизий.

Но в вашем случае у вас есть шар, который просто вращается. Центр фиксирован и известен радиус. Следовательно, более простой способ сделать это – найти круг на экране, который соответствует сфере и проверить, находится ли контакт внутри этого круга.

Сначала возьмите центр сферы, начиная с вашего примера кода, связанного с вашим вопросом. Так как вы переводите на (0, 0, -10), что является 3D-центром. center3d(0.0f, 0.0f, -10.0f) . Проецируйте его на экран и получите экранный центр. Вы можете использовать gluProject () . center2d что это результат в center2d . Теперь возьмите еще одну точку на поверхности вашей сферы, так как радиус сферы равен 2 (из вашей кодовой ссылки) точкой может быть point3d(2.0f, 0.0f, -10.0f) . Теперь спроектируйте это и на экране, и скажем, что вы получаете point2d . Теперь радиус окружности сферы на экране будет length(point2D - center2D) .

Теперь проверьте, находится ли входное значение в пределах круга. Просто установите расстояние от положения касания от центра круга и проверьте его радиус 2D. Это простой способ для вашего дела, но если у вас есть более сложные формы, луч-кастинг – это путь.

Intereting Posts
Import com.google.android.gms.location.LocationClient не может быть разрешен Android: двоичная строка XML-файла # 9: фрагмент фрагмента фрагмента ошибки Преобразование речи в текст Кордова – Проблемы, когда кросс-платформенное приложение для Android работает на альфа-симуляторе Blackberry 10 Где я должен сообщать о ошибках в документации на Android? Как удалить элементы из списка с помощью жестов, как в gmail OnFailedToRecieveAd (Недействительный запрос объявления) с помощью AdMob Портретная ориентация камеры Только исходный поток, создавший иерархию представлений, может коснуться его представлений Retrofit вызывает метод fail (), даже если код состояния заголовков 200 Передача пользовательских атрибутов в настраиваемый шейдер фрагмента Надежность приостановки воспроизведения мультимедиа в системе на Android ExpandableListView OnGroupCollapseListener -any слушатель / наблюдатель перед тем, как происходит сбой? Лучшая библиотека json rpc 2.0 для Android Android: Как проверить, является ли файл образным?