collision and found a bug in PointInPoly ?
Monkey Forums/Monkey Programming/collision and found a bug in PointInPoly ?
| ||
As you probably already know, i'm busy with the png tracer bla bla. AND I solved IT a few days ago ! :) I'm testing it very good before i'm posting it. And yesterday I was testing the next step collision checks. And what happend was this: The method PointInPoly is a second collision option, not what I want for the main goal, but I can use that later. But it does not do what it says, or the Mouse coordinates are wrong ? When I touch a line from the left, it says its inside the verts[] (that wrong) When I touch a line from the right, it says its not inside the vers[] (that good) When the mouse is inside the verts[] is oke ! But behind that method I was searching for this function: If PointHitTheLineOrIsInsidePoly(MouseX(),MouseY(),verts) Then If PointInPoly(MouseX(),MouseY(),verts) Then hit = True Else hit = False End '' Found this at monkey forums, at several places Function PointInPoly:Bool(x:Float, y:Float, poly:Float[]) Local i:Int, j:Int, c:Bool Local v1:Bool, v2:Bool, v3:Bool, v4:Bool, v5#, v6#, v7# c = False Local p_count% = (poly.Length() / 2) For i = 0 To p_count-1 j = (i+1) Mod p_count v1 = (poly[i*2+1] <= y) v2 = (y < poly[j*2+1]) v3 = (poly[j*2+1] <= y) v4 = (y < poly[i*2+1]) v5 = (poly[j*2]-poly[i*2]) * (y-poly[i*2+1]) v6 = (poly[j*2+1]-poly[i*2+1]) If v6 = 0.0 Then v6 = 0.0001 v7 = poly[i*2] If (((v1 And v2) Or (v3 And v4)) And (x < v5 / v6 + v7)) Then c = Not c Next Return c End I can create lines from the points like this either. Function distanceToPoly:Bool(p:Point,points:Stack<Point>) 'For Local point:Point = Eachin points For Local i:Int = 0 Until points.Length()-1 Print distToSegment(p,points.Get(i),points.Get(i+1)) If distToSegment(p,points.Get(i),points.Get(i+1))<=0 Then Return True End Next Return False End Function distance:Float(x1:Int, y1:Int, x2:Int, y2:Int) Local x:Float=Sqrt(((x1 - x2)*(x1 - x2)) + ((y1 - y2)*(y1 - y2)) ) Return x End Function Function sqr:Float(x:Float) Return (x * x) End Function dist2:Float(v:Point, w:Point) Return sqr(v.x - w.x) + sqr(v.y - w.y) End ' p = point to check ' v = start point line ' w = end point line Function distToSegmentSquared:Float(p:Point, v:Point, w:Point) Local l2:Float = dist2(v, w) If (l2 = 0) Then Return dist2(p, v) End Local t:Float = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2 If (t < 0) Then Return dist2(p, v) End If (t > 1) Then Return dist2(p, w) End Return dist2(p, New Point(v.x + t * (w.x - v.x),v.y + t * (w.y - v.y) )) End Function distToSegment:Float(p:Point, v:Point, w:Point) Return Sqrt(distToSegmentSquared(p, v, w)) End edit: the blue line is a visual line, i'm checking against only the corner points that are inside the blue line. In this example there are 12 points that creating this figure. There are in counter / anti clockwise order |
| ||
If you need a good PointInPoly, that works with concave polygons, you can use this: |
| ||
Thanks, I will check this later today. I always wondering how people can create methods like this haha. |
| ||
I think the one I posted originates form : http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html and http://paulbourke.net/geometry/polygonmesh/ |
| ||
Your code is maybe working, but not now at the moment I think that there is something else that I have to check first. Because several other similar algorithms din't work either. So i'm going to take one step back and going to create a simple convex box, and hide the default cursor and use one pixel point as the cursor. That way I can exactly see in osx what the program does. And in the final game I want to hide the default cursor as well and make a custom one for the desktop target. I found this on the internet, but don't know how to get the variable window in osx at the moment. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); game programming is like solving one big puzzle haha |
| ||
@GC-Martijn: A bit off topic, but use 'HideMouse'. If you want to do it directly, you could use 'SetMouseVisible' (Use "BBGame.Game()"). This is effectively the exact same thing as doing it natively. Finally, if you want to do it directly using GLFW3, you can use 'glfwSetInputMode' like this: I recommend doing it using Mojo or the standard BBGame functionality, though. |
| ||
Thanks for the info, what I do is checking this page http://www.monkey-x.com/docs/html/Index.html using some keywords. Yesterday my keywords where: cursor & pointer haha HideMouse() is the thing I need ;) EDIT: @Difference The funny thing is that your code does the opposite what is oke, because I can use both methods to check if there is a collision. I have to rename them, and make one whole function from it, but its working ;) If PointInPoly(MouseX(),MouseY(),verts) Or IsInsidePoly(verts,MouseX(),MouseY()) Then hit = True Else hit = False End |
| ||
@Difference The funny thing is that your code does the opposite what is oke, because I can use both methods to check if there is a collision. I made a test program for you below. IsInsidePoly() is behaving as it should. |
| ||
@Differcence Nope, I tested the code again and its not working correct, but I made a fix. First hide the cursor and draw a dot, was helping me in osx because the cursor shadow din't show exactly where my mouse was. Then check all the lines , including the bottom corners (left and right) using your code, some bottom corners din't work, and some lines. check it with this code. I don't know how to optimize my polycheck more at the moment, but its working.= :) Strict Import mojo Function Main:Int() New MyApp Return 0 End Class MyApp Extends App Field poly1:Float[26] Field inside:int Field hit:Bool Method OnCreate:Int() HideMouse() poly1[0] = 22.0 poly1[1] = 130.0 poly1[2] = 31.0 poly1[3] = 130.0 poly1[4] = 31.0 poly1[5] = 45.0 poly1[6] = 210.0 poly1[7] = 45.0 poly1[8] = 210.0 poly1[9] = 130.0 poly1[10] = 219.0 poly1[11] = 130.0 poly1[12] = 219.0 poly1[13] = 45.0 poly1[14] = 240.0 poly1[15] = 45.0 poly1[16] = 240.0 poly1[17] = 1.0 poly1[18] = 1.0 poly1[19] = 1.0 poly1[20] = 1.0 poly1[21] = 45.0 poly1[22] = 22.0 poly1[23] = 45.0 poly1[24] = 22.0 poly1[25] = 129.0 Return 0 End Method OnRender:Int() Cls(255,255,255) If hit Then SetColor(255,0,0) Else SetColor(0,0,255) End Local n2:Int = poly1.Length - 2 For Local n:Int = 0 Until poly1.Length Step 2 DrawLine poly1[n2],poly1[n2+1],poly1[n],poly1[n+1] n2 = n Next n SetColor(0,0,255) DrawPoint(MouseX(),MouseY()) Return 0 End Method OnUpdate:Int() If KeyHit(KEY_SPACE) Then EndApp() End If PolyCollision(poly1,MouseX(),MouseY()) Then hit = True Else hit = False End Return 0 End End ' not working if the cursor is on the right side on the line Function IsInsidePoly:Int(polypoints:Float[],x:Float,y:Float) Local j:Int = polypoints.Length()-2 Local oddNodes:Int For Local i:Int =0 Until polypoints.Length() Step 2 If (polypoints[i+1]< y And polypoints[j+1]>=y ) Or (polypoints[j+1]< y And polypoints[i+1]>=y) If (polypoints[i]<=x Or polypoints[j]<=x) If (polypoints[i]+(y-polypoints[i+1])/(polypoints[j+1]-polypoints[i+1])*(polypoints[j]-polypoints[i])<x) oddNodes = 1 ~ oddNodes Endif Endif Endif j=i Next Return oddNodes End Function ' 0 = no collision ' 1 = line collion ' 2 = point inside Function PolyCollision:Int(polypoints:Float[],x:Float,y:Float) Local j:Int = polypoints.Length()-2 Local cn:Int = 0 Local cn2:Int = 0 For Local i:Int=0 Until polypoints.Length() Step 2 If i<=polypoints.Length()-3 And (((polypoints[i+1] <= y) And (polypoints[i+3] > y)) Or ((polypoints[i+1] > y) And (polypoints[i+3] <= y))) Then Local vt:Float = (y - polypoints[i+1]) / (polypoints[i+3] - polypoints[i+1]) If (x < polypoints[i] + vt * (polypoints[i+2] - polypoints[i])) Then cn = 1 ~ cn End Elseif (polypoints[i+1]<y And polypoints[j+1]>=y) Or (polypoints[j+1]< y And polypoints[i+1]>=y) If (polypoints[i]<=x Or polypoints[j]<=x) If (polypoints[i]+(y-polypoints[i+1])/(polypoints[j+1]-polypoints[i+1])*(polypoints[j]-polypoints[i])<x) cn2 = 1 ~ cn2 Endif Endif End ' corners at the bottem If polypoints[i]=x And polypoints[i+1]=y Then cn = 1 ~ cn End j=i Next Return (cn&1)+(cn2&1) End Function |