2013-08-08 137 views
5

Tôi đã tạo một đối tượng 3D trong cho một trong các ứng dụng của tôi. Vật thể giống như cơ thể người và có thể xoay khi chạm vào. Làm thế nào tôi có thể phát hiện vị trí của cảm ứng trên đối tượng 3D này. Có nghĩa là nếu người dùng chạm vào đầu, tôi phải phát hiện ra đó là đầu. Nếu chạm là trên tay, sau đó phải được xác định. Nó sẽ hoạt động ngay cả khi đối tượng được xoay sang một hướng khác. Tôi nghĩ rằng các tọa độ của liên lạc trên đối tượng 3D là bắt buộc.
Đây là phương pháp mà tôi nhận được vị trí liên lạc trên màn hình.Phát hiện vị trí cảm ứng trên các đối tượng 3D trong openGL

- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event 
{ 
    UITouch* touch = [touches anyObject]; 
    CGPoint location = [touch locationInView: self]; 
    m_applicationEngine->OnFingerDown(ivec2(location.x, location.y)); 
} 

Có ai giúp được không? Cảm ơn trước!

Trả lời

5

Quên RayTracing và các thuật toán hàng đầu khác. Chúng tôi đã sử dụng một mẹo đơn giản cho một trong các ứng dụng của chúng tôi (Iyan 3D) trên App Store. Tuy nhiên, kỹ thuật này cần thêm một lần render mỗi khi bạn hoàn thành việc quay cảnh sang một góc mới. Hiển thị các đối tượng khác nhau (đầu, tay, chân, v.v.) với các màu khác nhau (không phải màu thực tế nhưng màu sắc riêng). Đọc màu trong hình ảnh được hiển thị tương ứng với vị trí màn hình. Bạn có thể tìm thấy đối tượng dựa trên màu sắc của nó.

Trong phương pháp này, bạn có thể sử dụng độ phân giải hình ảnh thay đổi để cân bằng độ chính xác và hiệu suất.

+0

+1 - Nó rất đơn giản và dễ thực hiện kỹ thuật. Ở đây bạn có thêm thông tin và mã nguồn trong Xử lý (ví dụ như Java) - http://wiki.processing.org/w/Picking_with_a_color_buffer – cyriel

+0

tôi có thể có bất kỳ mã mẫu ios nào trong chủ đề này không? –

+0

Tìm kiếm Hiển thị kết cấu để hiển thị. Sau đó, nó sẽ dễ dàng cho bạn để tìm màu sắc. http://stackoverflow.com/questions/8439697/opengl-es-2-0-render-to-texture – codetiger

4

Để xác định vị trí 3D của đối tượng tôi sẽ đề xuất dò tia.

Giả sử mô hình nằm trong tọa độ không gian thế giới, bạn cũng cần phải biết tọa độ không gian thế giới của vị trí mắt và tọa độ không gian thế giới của mặt phẳng ảnh. Sử dụng hai điểm đó, bạn có thể tính toán một tia mà bạn sẽ sử dụng để giao cắt với mô hình, mà tôi giả định bao gồm các hình tam giác.

Sau đó, bạn có thể sử dụng phép thử tam giác tia để xác định vị trí 3D của lần chạm, bằng cách tìm hình tam giác có giao điểm gần nhất với mặt phẳng ảnh. Nếu bạn muốn chạm vào tam giác nào, bạn cũng sẽ muốn lưu thông tin đó khi thực hiện các bài kiểm tra giao lộ.

Trang này đưa ra một ví dụ về cách làm ray kiểm tra giao tam giác: http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-9-ray-triangle-intersection/ray-triangle-intersection-geometric-solution/

Edit:

cập nhật để có một số mẫu mã. Một số mã hơi sửa đổi của nó tôi đã lấy từ một dự án raytracing C++ tôi đã làm một lúc trước, do đó bạn sẽ cần phải sửa đổi nó một chút để làm cho nó làm việc cho iOS. Ngoài ra các mã trong hình thức hiện tại của nó thậm chí sẽ không hữu ích vì nó không trả lại điểm giao nhau thực tế mà là nếu tia cắt giao nhau tam giác hay không.

// d is the direction the ray is heading in 
// o is the origin of the ray 
// verts is the 3 vertices of the triangle 
// faceNorm is the normal of the triangle surface 
bool 
Triangle::intersect(Vector3 d, Vector3 o, Vector3* verts, Vector3 faceNorm) 
{ 
    // Check for line parallel to plane 
    float r_dot_n = (dot(d, faceNorm)); 

    // If r_dot_n == 0, then the line and plane are parallel, but we need to 
    // do the range check due to floating point precision 
    if (r_dot_n > -0.001f && r_dot_n < 0.001f) 
     return false; 

    // Then we calculate the distance of the ray origin to the triangle plane 
    float t = (dot(faceNorm, (verts[0] - o))/r_dot_n); 
    if (t < 0.0) 
     return false; 

    // We can now calculate the barycentric coords of the intersection 
    Vector3 ba_ca = cross(verts[1]-verts[0], verts[2]-verts[0]); 
    float denom = dot(-d, ba_ca); 

    dist_out = dot(o-verts[0], ba_ca)/denom; 
    float b = dot(-d, cross(r.o-verts[0], verts[2]-verts[0]))/denom; 
    float c = dot(-d, cross(verts[1]-verts[0], o-verts[0]))/denom; 

    // Check if in tri or if b & c have NaN values 
    if ( b < 0 || c < 0 || b+c > 1 || b != b || c != c) 
     return false; 

    // Use barycentric coordinates to calculate the intersection point 
    Vector3 P = (1.f-b-c)*verts[0] + b*verts[1] + c*verts[2]; 

    return true; 
} 

Điểm giao thực tế bạn sẽ quan tâm đến là P.

+0

Tôi có thể lấy bất kỳ mã mẫu nào không, sử dụng giao điểm tam giác tia này trong iOS? –

+0

Tôi đã thêm một số mã mẫu để đưa ra những tính toán cần được thực hiện. Của nó trong C + + bởi vì tôi lấy nó từ một trong những dự án cũ của tôi, nhưng nó phải dễ hiểu. Ngoài ra giá trị trả về của hàm không phải là những gì bạn đang tìm kiếm, nhưng kết thúc của hàm, điểm giao nhau được tính toán để bạn có thể chuyển đổi nó thành định dạng hữu ích cho chính bạn. – illeyezur

+0

Cảm ơn người đàn ông! Sẽ cố gắng này. –

2

Ray tracing là một lựa chọn và được sử dụng trong nhiều ứng dụng để làm việc đó (chọn). Vấn đề với dò tia là giải pháp này là rất nhiều công việc để có được một tính năng cơ bản khá đơn giản làm việc. Ngoài ra ray truy tìm có thể được làm chậm nhưng nếu bạn chỉ có một ray để theo dõi (vị trí của ngón tay của bạn nói), sau đó nó sẽ không sao.

API của OpenGL cũng cung cấp kỹ thuật để chọn đối tượng. Ví dụ: bạn xem ví dụ: http://www.lighthouse3d.com/opengl/picking/

Cuối cùng, tùy chọn cuối cùng sẽ bao gồm chiếu các đối tượng trong không gian màn hình và sử dụng các kỹ thuật 2d đơn giản để tìm ra khuôn mặt nào của đối tượng mà ngón tay của bạn chồng lên nhau.

+0

ES không cung cấp API chọn nhưng anh ta có thể thực hiện điều tương tự bằng cách thực hiện hiển thị với mỗi đa giác kết xuất một màu duy nhất và sau đó sử dụng 'glReadPixels' để lấy màu ở vị trí cảm ứng hoặc thậm chí bằng cách phức tạp hơn nhưng có lẽ là hệ thống hiệu quả hơn dựa trên vẽ một bề mặt rất gần với một lỗ và tiếp tục với hình dạng chia và truy vấn tắc (được cung cấp trên iOS như iOS 5 nếu bộ nhớ phục vụ). Nếu phân đoạn được đóng lại thì bạn có thể làm tắc nghẽn khi bạn vẽ bằng cách đặt nắp trong nền và đảo chiều kiểm tra độ sâu. – Tommy