Обнаружение касания объекта OpenGL?
Я разрабатываю приложение, которое использует OpenGL для рендеринга изображений.
Теперь я просто хочу определить событие касания на объекте сферы opengl, который я вынул.
Здесь я рисую 4 объекта на экране. теперь, как мне узнать, какой объект был
прикосновения. Я использовал метод onTouchEvent(). Но он дает мне только координаты x и y, но мой
объект рисуется в 3D.
пожалуйста, помогите, так как я новичок в OpenGL.
С наилучшими пожеланиями,
~ Anup
![enter image description here]()
Ответы
Ответ 1
t В Google IO была сессия о том, как OpenGL использовался для Google Body на Android. Выбор частей тела был сделан путем рендеринга каждого из них сплошным цветом в скрытый буфер, а затем на основе цвета, который был на касании x, y соответствующий объект мог быть найден. В целях производительности только небольшая обрезанная область размером 20x20 пикселей вокруг точки касания была сделана таким образом.
Ответ 2
Оба подхода (1. скрытый цветовой буфер и 2. тест пересечения) имеют свои достоинства.
1. Скрытый буфер цвета: считывание пикселей - очень медленная операция.
Конечно, переполнение для простого теста пересечения лучей.
-
Тест пересечения лучей с шаром: это не так сложно.
Вот упрощенная версия реализации в Ogre3d.
std::pair<bool, m_real> Ray::intersects(const Sphere& sphere) const
{
const Ray& ray=*this;
const vector3& raydir = ray.direction();
// Adjust ray origin relative to sphere center
const vector3& rayorig = ray.origin() - sphere.center;
m_real radius = sphere.radius;
// Mmm, quadratics
// Build coeffs which can be used with std quadratic solver
// ie t = (-b +/- sqrt(b*b + 4ac)) / 2a
m_real a = raydir%raydir;
m_real b = 2 * rayorig%raydir;
m_real c = rayorig%rayorig - radius*radius;
// Calc determinant
m_real d = (b*b) - (4 * a * c);
if (d < 0)
{
// No intersection
return std::pair<bool, m_real>(false, 0);
}
else
{
// BTW, if d=0 there is one intersection, if d > 0 there are 2
// But we only want the closest one, so that ok, just use the
// '-' version of the solver
m_real t = ( -b - sqrt(d) ) / (2 * a);
if (t < 0)
t = ( -b + sqrt(d) ) / (2 * a);
return std::pair<bool, m_real>(true, t);
}
}
Возможно, необходимо также рассчитать луч, который соответствует позиции курсора. Снова вы можете обратиться к исходному коду Ogre3d: поиск getCameraToViewportRay. В принципе, вам нужна матрица зрения и проекции для вычисления луча (трехмерное положение и трехмерное направление) из 2D-положения.
Ответ 3
В моем проекте решение, которое я выбрал, было:
- Непроектируйте координаты 2D-экрана виртуальной 3D-линии, проходящей через вашу сцену.
- Обнаружение возможных пересечений этой линии и объектов сцены.
Это довольно сложный вкус.
Ответ 4
Я сделал это только в Direct3D, а не в OpenGL ES, но это следующие шаги:
-
Найдите ваши модели и проекционные матрицы. Кажется, что OpenGL ES удалил возможность извлекать матрицы, установленные gluProject() и т.д. Но вы можете использовать функции android.opengl.Matrix для создания этих матриц, затем установите с помощью glLoadMatrix().
-
Вызовите gluUnproject() дважды, один раз с winZ = 0, затем с winZ = 1. Передайте ранее вычисленные матрицы.
-
Это выведет 3D позицию из каждого вызова. Эта пара позиций определяет луч в "глобальном пространстве" OpenGL.
-
Выполняйте тест пересечения лучей с шаром по каждой из ваших сфер в порядке. (Ближе всего к камере, иначе вы можете выбрать сферу, которая скрыта за другим.) Если вы обнаружите пересечение, вы коснулись сферы.
Ответ 5
для нахождения точки касания внутри круга или нет.
public boolean checkInsideCircle(float x,float y, float centerX,float centerY, float Radius)
{
if(((x - centerX)*(x - centerX))+((y - centerY)*(y - centerY)) < (Radius*Radius))
return true;
else
return false;
}
где
1) centerX,centerY are center point of circle.
2) Radius is radius of circle.
3) x,y point of touch..