Two CCDrawNode.DrawPolygon bugs

I've found two bugs with the DrawPolygon routine in CCDrawNode - these apply both to iOS and Android:

Test 1 - bottom border too thin - see test1.png

CCDrawNode node = new CCDrawNode();
List<CCPoint> points = new List<CCPoint>();
points.Add(new CCPoint(10.0f, 0.0f));
points.Add(new CCPoint(50.0f, 0.0f));
points.Add(new CCPoint(50.0f, 50.0f));
points.Add(new CCPoint(10.0f, 50.0f));
node.DrawPolygon(points.ToArray(), points.Count, CCColor4B.Gray, 1.0f, CCColor4B.White);

Test 2 - filled area fills outside of shape (border outline ok except for bottom edge) - see test2.png

CCDrawNode node = new CCDrawNode();
List<CCPoint> points = new List<CCPoint>();
points.Add(new CCPoint(40.0f, 50.0f));
points.Add(new CCPoint(80.0f, 30.0f));
points.Add(new CCPoint(80.0f, 10.0f));
points.Add(new CCPoint(10.0f, 10.0f));
points.Add(new CCPoint(40.0f, 20.0f));
node.DrawPolygon(points.ToArray(), points.Count, CCColor4B.Gray, 1.0f, CCColor4B.White);

This is a bit of a problem as I'm drawing masked areas to reveal part of an image underneath.

Posts

  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    I thought I'd share a partial solution that I found to this problem when trying to fill in concave polygons (although it won't fill polygons with holes in - so beware). Basically it takes the vertices of a polygon and works out how two split it up into triangles.

    See http://wiki.unity3d.com/index.php?title=Triangulator for more information.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    We are tracking this here: https://github.com/mono/CocosSharp/issues/111

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    On the first one:

    CCDrawNode node = new CCDrawNode();
    List<CCPoint> points = new List<CCPoint>();
    points.Add(new CCPoint(10.0f, 0.0f));
    points.Add(new CCPoint(50.0f, 0.0f));
    points.Add(new CCPoint(50.0f, 50.0f));
    points.Add(new CCPoint(10.0f, 50.0f));
    node.DrawPolygon(points.ToArray(), points.Count, CCColor4B.Gray, 1.0f, CCColor4B.White);
    

    It looks like you are drawing at y offset 0 in the lower left corner of the screen. This does not take into account the border that is being painted. If you move this up to non zero y offset then let's see if the border show up correctly.

    The same would go for the x offset value as well if it was zero.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    Test 2 - filled area fills outside of shape (border outline ok except for bottom edge)

    I think I understand what you are wanting here based off of the second post.

    We unfortunately do not provide anything like this as CocosSharp does not provide a full cross platform graphics 2D drawing stack using the drawing interface provided to us by the primitives. Basically we draw lines and triangles which is what the graphics cards understands.

    What you are asking for, if I understand correctly, has to do with polygon clipping and the use of algorithms such as Vatti and Sutherland–Hodgman.

    If that is the case then I am not sure we can provide that right now as again we do not provide a full 2D drawing stack. It is something that can be looked into but that is a lot of code to deliver to everyone that would not need this type of functionality and would be better delivered as an extension.

    Having been down this path before, with more or less your problem with clipping regions, there is great library called Clipper and the accompanying website that provides a very fast and efficient c# implementation. The interface is easy to understand and should provide you with what you are looking for including winding, concave and polygon holes. The information returned from this library will provide you with everything that is needed to pass on to the base primitive routines provided by DrawNode.

    Would love to see something like this in action. We can add an issue for a feature enhancement to provide this but not sure when we would get to it which does not help your immediate problem.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    I may have read too much into what you wanted to do in the previous based off of your second post.

    Add a call to Reverse() on your points.

    CCDrawNode node = new CCDrawNode();
    List<CCPoint> points = new List<CCPoint>();
    points.Add(new CCPoint(40.0f, 50.0f));
    points.Add(new CCPoint(80.0f, 30.0f));
    points.Add(new CCPoint(80.0f, 10.0f));
    points.Add(new CCPoint(10.0f, 10.0f));
    points.Add(new CCPoint(40.0f, 20.0f));
    
    points.Reverse();  <----- Make sure your polygon is winding correctly;
    
    node.DrawPolygon(points.ToArray(), points.Count, CCColor4B.Gray, 1.0f, CCColor4B.White);
    
  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    Hi Kenneth, Thanks for the info on the clipping library, I'll take a look at it as I will need clipping with holes.

    As to my first bug - doh! I feel silly not having spotted the fact that I was drawing at 0 co-ord - I'd forgotten that Cocos draws on the point so you only get half a line thickness as you only see the half of the line above the point. On to remember!

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    No problem. We would love to see what you come up with. Maybe even including your solution as an upcoming extension to CocosSharp if you would not mind :-) It would be great maybe even as an extension of CCClippingNode.

    Any advice on this please let us know.

  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    I am currently creating a mask by drawing a complex polygon and then applying the mask to an image. The problem is that the mask that I am drawing can be a mixture of concave, convex and more complicated combinations of both concave an convex areas in the same polygon.

    My solution is as follows and I have attached the Triangulator.cs code (I had to change the file extension from .cs to .txt as upload not allowed of .cs) that I have adapted to use CCPoint directly that converts any polygon into a list of triangles that cover it, these triangles are then drawn using DrawPolygon and this gets around the problem that I have.

    Triangulator tris = new Triangulator(points);
    int [] indices = tris.Triangulate();
    CCPoint [] newVerts = new CCPoint[3];
    for (int i = 0; i < indices.Length; i += 3)
    {
            newVerts[0] = verts[indices[i]];
            newVerts[1] = verts[indices[i + 1]];
            newVerts[2] = verts[indices[i + 2]];
            node.DrawPolygon(newVerts, 3, CCColor4B.Gray, 0, CCColor4B.White);
    }
    

    Best regards, Adrian

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    That is great. Thank you for letting us know.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai
    edited February 2015

    Adrian

    Here is something else you might want to take a look at.

    https://github.com/asinesio/cocos2d-PRKit

    https://github.com/speps/LibTessDotNet <- looks like it handles the holes that you were talking about and smaller source code base than clipper.

  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    Very interesting... I see that the fill polygon with texture first of all triangulates the polygon and then uses a custom shader (which CocosSharp doesn't currently support) to fill each triangle using a texture (without custom shade support the solution is to do what I am going to do, which is to draw the triangulated polygon into a mask sprite and blend it with a texture sprite to achieve the same thing). Anyway, useful to see how it's done here as it could be convertible in the future.

    Thanks, Adrian

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    CCGeometryBatch will do that for you. Of course in the next release. You can see an example of it's use here .

    Unfortunately only in the upcoming release.

  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    Thanks, will bear that in mind.

  • JonJarnJonJarn SEMember

    Hi Adrian,
    For reference: Which solution did you end up going with? Are you using GeometryBatch(/Node in 1.5) now?

  • AdrianNelson.0022AdrianNelson.0022 ✭✭ GBMember ✭✭

    In the end I didn't even use the triangulation code as there were other bugs lurking in CocosSharp when some triangles get very thin and CocosSharp (or maybe it's the underlying MonoGame) has overdraw problems. I solved my problems by working out when I had to specify the points in reverse order to get the correct behaviour.

    I haven't updated any of my code for v1.5 - in fact I've not updated it to reflect v1.4 either. My personal project has stopped for the moment - I got as far as having a working prototype but I kept running into problems CocosSharp and the available documentation is lacking - or at least it was - haven't checked for a while.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Adrian

    Thanks for your honesty. We have improved a lot but you will probably still have problems with our CCDrawNode and not being able to draw with the 2D primitives the way you want. On each iteration we are improving the primitives drawing but still do not have a full 2D graphics stack implemented with the LineJoin code that is causing your problem with the very thin triangles. We did add line caps just recently though :-)

    Although, this being a problem it still should not effect Jarnsater though as he should be using the CCGeometryNode and mapping textures to his triangulation solution.

    Good hearing from you again.

  • JonJarnJonJarn SEMember

    Hi Adrian, thanks for sharing your progress.

    I can inform you that I had the same drawing issues (with small overdrawn pointy triangles) when using CCDrawNode, but am glad to say that all those went away when I tried CCGeometryNode instead (drawing my triangulated polygons). It also gives you the added benefit of being able to use a texture (if you want).

  • JonJarnJonJarn SEMember

    Btw, I don't fully understand why Reversing the points works. Could you (or kjpou1) explain that a bit more? Also, iyt would be great if you could share how you determine if it should be reversed or not.

    Thanks / Jon

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Convex polygons on CCDrawNode do not work well depending on the winding used. That is the reason for reversing the points. Since you are creating your own UV geometry you will probably not run into that.

  • FFuFFFuF DEMember

    @JonJarnster
    Would you be so kind to share parts of your code using CCGeometryNode?
    I'm currently trying to overcome the overdrawing problem (especially visible if the fill color is half transparent) but I'm very confused on how to use the required "vertices" and "indicies" based on a list of CCPoints (which resulted from triangulation). Couldn't find a good example anywhere, either.

    Thank you!
    Jonas

  • JonJarnJonJarn SEMember

    @FFuF
    Writing a blog post right now, will post here soon.

  • JonJarnJonJarn SEMember
  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Hey guys

    @JonJarnsater Thanks for the example post.

    You can do the same with CCDrawNode if the DrawPolygon's line joining by extruding the vertices is not working for you. You can create your own geometry. The following is from DrawTestBlend.

            triangleList1 = new CCDrawNode();
            triangleList1.BlendFunc = CCBlendFunc.NonPremultiplied;
    
            AddChild(triangleList1, 10);
    
            byte alpha = 100; // 255 is full opacity
    
            var green = new CCColor4B(0, 255, 0, alpha);
    
            CCV3F_C4B[] verts = new CCV3F_C4B[] {
                new CCV3F_C4B( new CCPoint(0,0), green),
                new CCV3F_C4B( new CCPoint(30,60), green),
                new CCV3F_C4B( new CCPoint(60,0), green)
            };
    
            triangleList1.DrawTriangleList (verts);
    

    This also includes DrawLineList for as you would guess Line Lists.

    There are multiple simplistic examples here. Including a couple of CCGeometryNode minimalistic tests. GeometryBatchTest1 and GeometryBatchTest2

    All the code for CCDrawNode can be found in the source so you could rewrite every one of the drawing methods to work exactly the way you want. For instance you want to create a DrawSolidPolygon you could just copy the code from here and take out the code for extrude vertices. The source code for CCDrawNode is a great example of how things are implemented so you could do your own.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    @FFuF

    What exactly is the overdrawing problem. Can you post an example of this with the half transparent fill color.

  • FFuFFFuF DEMember
    edited August 2015

    @kjpou1
    using the same code from here:
    https://forums.xamarin.com/discussion/comment/99233/#Comment_99233

    but using
    CCColor4F color = new CCColor4F(CCColor3B.Red); color.A = 0.3f;
    as fill color and 0 as border width results into the display shown in the attachment (thats only a part of the polygons, but you'll notice the thin red lines).

    with the polygons being:
    P1: 380:-160 P2: 200:-240 P3: 160:-420 P1: 160:-420 P2: 200:-520 P3: 360:-540 P1: 360:-540 P2: 420:-600 P3: 520:-520 P1: 520:-520 P2: 380:-160 P3: 160:-420 P1: 160:-420 P2: 360:-540 P3: 520:-520

    By the way, the same code works in the original Cocos2D without any extra red lines.

    EDIT:
    Apparently using DrawTriangleList from your previous post fixes this. Cool! But I kinda wonder why.

    @JonJarnster thank you! Looks helpful.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    @FFuF

    I see what you mean now. If this was the original posters over draw problem then it was totally misunderstood.

    Either way you can still work around that by creating your own DrawSolidPolygon as outlined earlier. You really do not need the outline code that is there for DrawPolygon nor the extrude points routine. This could be from the new functionality for ClosePolygon that is there for when we finally get rid of CCDrawingPrimitives We will need to create an issue for this and look at fixing it.

    Anyway here is the gist of it. There is a new test out there DrawNodeTriangleVertex. This basically takes the points that you gave above and draws them without this glitch you are showing.

    Here is the DrawSolidPolygon routine:

       void DrawSolidPolygon(CCPoint[] points, CCColor4B color)
        {
            for (int i = 0; i < points.Length - 2; i++)
            {
                drawTriangles.AddTriangleVertex(new CCV3F_C4B(points[0], color)); 
                drawTriangles.AddTriangleVertex(new CCV3F_C4B(points[i + 1], color)); 
                drawTriangles.AddTriangleVertex(new CCV3F_C4B(points[i + 2], color)); 
            }
    
        }
    

    Call it as follows:

            //P1: 380:-160 P2: 200:-240 P3: 160:-420
            CCPoint[] points = new CCPoint[]
            {
                //P1: 380:-160 P2: 200:-240 P3: 160:-420
                new CCPoint(380,-160),
                new CCPoint(200,-240),
                new CCPoint(160,-420),
            };
    
            DrawSolidPolygon(points, color);
    

    Let us know if this helps.

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Oh I see that you have already fixed this. What is the original Cocos2D you are referring too?

  • JonJarnJonJarn SEMember

    @kjpou1
    Thanks for the added comments, I've missed the CCDrawnode:DrawTriangleList completely, good to know!

    When it comes to rendering a bunch of triangles, what would your recommendation be? (CCDrawnode vs CCGeometryNode). CCGeometryNode can be textured and can reuse vertices, but do you know other major differences or scenarios where one is better than the other?

    Do you have any gut feeling about performance differences? (I assume they do similar things under the hood).

  • kjpou1kjpou1 Xamurai LUMember, Xamarin Team Xamurai

    Jon

    They are all just pushing primitives to the graphics card so probably should be no difference. It really depends on if you need texturing or not.

    The CCGeometryNode really was created with Textures in mind but not exclusively. The idea came from this link actually on GeometryInstancing.

    CCDrawNode is more or a poor mans graphics 2D stack. More for debugging in mind that anything else. It has expanded a lot though.

Sign In or Register to comment.