2013-08-08 4 views
5

Ich habe ein 3D-Objekt in für eine meiner Anwendung erstellt. Das Objekt ist so etwas wie ein menschlicher Körper und kann bei Berührung gedreht werden. Wie kann ich die Position der Berührung auf diesem 3D-Objekt erkennen? Bedeutet, wenn der Benutzer den Kopf berührt, muss ich erkennen, dass es der Kopf ist. Wenn Berührung auf der Hand ist, dann muss das identifiziert werden. Es sollte funktionieren, auch wenn das Objekt in eine andere Richtung gedreht wird. Ich denke, die Koordinaten der Berührung auf dem 3D-Objekt sind erforderlich.
Dies ist die Methode, bei der ich die Position der Berührung auf die Ansicht bekomme.Erkennung der Berührungsposition auf 3D-Objekten in 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)); 
} 

Kann jemand helfen? Danke im Voraus!

Antwort

5

Vergessen Sie RayTracing und andere Top Notch-Algorithmen. Wir haben einen einfachen Trick für eine unserer Anwendungen (Iyan 3D) im App Store verwendet. Diese Technik benötigt jedoch jedes Mal, wenn Sie die Szene in einem neuen Winkel drehen, einen zusätzlichen Render-Durchlauf. Render verschiedene Objekte (Kopf, Hand, Bein usw.) in verschiedenen Farben (nicht tatsächliche Farben, sondern einzigartige). Lesen Sie die Farbe im gerenderten Bild, die der Bildschirmposition entspricht. Sie können das Objekt anhand seiner Farbe finden.

Bei dieser Methode können Sie die Auflösung von gerenderten Bildern verwenden, um Genauigkeit und Leistung auszugleichen.

+0

+1 - Es ist sehr einfach und einfach, Technik zu implementieren. Hier haben Sie mehr Informationen und Quellcode in Processing (so etwas wie Java) - http://wiki.processing.org/w/Picking_with_a_color_buffer – cyriel

+0

Kann ich irgendwelche iOS-Beispielcodes in diesem Thema haben? –

+0

Suche nach Render für Textur zum Rendern. Dann sollte es für Sie einfach sein, Farben zu finden. http://stackoverflow.com/questions/8439697/openg-l-es-2-0-render-to-texture – codetiger

4

Um die 3D-Position des Objekts zu bestimmen, würde ich Raytracing empfehlen.

Angenommen, das Modell befindet sich in Weltraumkoordinaten, müssen Sie auch die Weltraumkoordinaten der Augenposition und die Koordinaten des Weltenraums der Bildebene kennen. Mit diesen beiden Punkten können Sie einen Strahl berechnen, mit dem Sie das Modell schneiden, von dem ich anmaß, dass es aus Dreiecken besteht.

Dann können Sie den Strahldreieck-Test verwenden, um die 3D-Position der Berührung zu bestimmen, indem Sie das Dreieck finden, das den kürzesten Schnittpunkt mit der Bildebene hat. Wenn Sie möchten, welches Dreieck berührt wird, möchten Sie diese Informationen auch speichern, wenn Sie die Schnitttests durchführen.

Diese Seite gibt ein Beispiel, wie ray Dreieck Kreuzung Tests zu tun: http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-9-ray-triangle-intersection/ray-triangle-intersection-geometric-solution/

Edit:

Aktualisiert einige Beispiel-Code zu haben. Es ist ein leicht modifizierter Code, den ich aus einem Raytracing-Projekt von C++ übernommen habe, das ich vor einiger Zeit gemacht habe, also müssen Sie es etwas modifizieren, damit es für iOS funktioniert. Auch wäre der Code in seiner aktuellen Form nicht einmal nützlich, da er nicht den tatsächlichen Schnittpunkt zurückgibt, sondern eher, wenn der Strahl das Dreieck schneidet oder nicht.

// 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; 
} 

Die tatsächliche Schnittpunkt Sie interessieren würde, ist P.

+0

Kann ich irgendwelche Beispielcodes erhalten, die diese Dreiecksschnittlinie in iOS verwenden? –

+0

Ich habe einen Beispielcode hinzugefügt, der angibt, welche Berechnungen durchgeführt werden müssen. Es ist in C++, weil ich es aus einem meiner alten Projekte übernommen habe, aber es sollte leicht verständlich sein. Auch der Rückgabewert der Funktion ist nicht das, was Sie suchen, aber am Ende der Funktion wird der Schnittpunkt berechnet, so dass Sie in der Lage sein sollten, ihn in ein nützliches Format für sich selbst zu konvertieren. – illeyezur

+0

Danke Mann, ich werde es versuchen. –

2

Ray-Tracing ist eine Option und wird in vielen Anwendungen verwendet, nur dass dafür (Kommissionierung). Das Problem mit Raytracing ist, dass diese Lösung eine Menge Arbeit ist, um eine ziemlich einfache Grundfunktion zu erhalten. Auch Ray-Tracing kann langsam sein, aber wenn Sie nur einen Strahl verfolgen (die Position Ihres Fingers sagen), dann sollte es in Ordnung sein.

OpenGL-API bietet auch eine Technik zum Auswählen von Objekten. Ich schlage vor, dass Sie zum Beispiel schauen: http://www.lighthouse3d.com/opengl/picking/

Schließlich würde eine letzte Option darin bestehen, die Scheitelpunkte eines Objekts im Bildschirmraum zu projizieren und einfache 2D-Techniken zu verwenden, um herauszufinden, welche Flächen des Objekts Ihr Finger überlappt.

+0

ES stellt keine Pick-API zur Verfügung, aber er könnte eine ähnliche Aufgabe ausführen, indem er jedes Polygon mit einer eindeutigen Farbe rendert und dann 'glReadPixels' verwendet, um die Farbe an der Touch-Stelle zu erfassen oder sogar leicht zu kommen aufwendigeres, aber wahrscheinlich effizienteres System basierend auf dem Malen einer sehr nahen Fläche mit einem Loch und weiter mit geteilter Geometrie und der Okklusionsabfrage (die auf iOS ab iOS 5 angeboten wird, wenn der Speicher dient). Wenn Segmente geschlossen sind, können Sie die Okklusion beim Zeichnen machen, indem Sie das Cover in den Hintergrund stellen und den Tiefen-Test invertieren. – Tommy

Verwandte Themen