Rendering order of walls of “false 3D” prisms











up vote
0
down vote

favorite












I'm developing a "false 3D" game using Python and pygame. The gfx consists only of prisms created using 2D primitives of different sizes and colors:



enter image description here



How the gfx of the game works:



enter image description here



The issue appears in the 4th point, when I want to sort walls in correct order in render queue (to decide which one is the closest one and has to be rendered first, which one is the 2nd, which one is the last etc).



Currently, to sort walls I remove all invisible ones and measure the shortest distance between player and wall. It works... but only when there is one polygon on the scene. Example (2 polygons):



enter image description here



I can handle this specific kind of issue but i don't know if there will be other problems in the future. My question: is there any algorithm (which works...) that can sort my walls in correct order and I will be able to render them with smile on my face?










share|improve this question




















  • 4




    without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
    – Spektre
    Nov 9 at 8:46












  • If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
    – Yola
    Nov 9 at 8:49






  • 2




    Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
    – Spektre
    Nov 9 at 8:52















up vote
0
down vote

favorite












I'm developing a "false 3D" game using Python and pygame. The gfx consists only of prisms created using 2D primitives of different sizes and colors:



enter image description here



How the gfx of the game works:



enter image description here



The issue appears in the 4th point, when I want to sort walls in correct order in render queue (to decide which one is the closest one and has to be rendered first, which one is the 2nd, which one is the last etc).



Currently, to sort walls I remove all invisible ones and measure the shortest distance between player and wall. It works... but only when there is one polygon on the scene. Example (2 polygons):



enter image description here



I can handle this specific kind of issue but i don't know if there will be other problems in the future. My question: is there any algorithm (which works...) that can sort my walls in correct order and I will be able to render them with smile on my face?










share|improve this question




















  • 4




    without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
    – Spektre
    Nov 9 at 8:46












  • If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
    – Yola
    Nov 9 at 8:49






  • 2




    Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
    – Spektre
    Nov 9 at 8:52













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm developing a "false 3D" game using Python and pygame. The gfx consists only of prisms created using 2D primitives of different sizes and colors:



enter image description here



How the gfx of the game works:



enter image description here



The issue appears in the 4th point, when I want to sort walls in correct order in render queue (to decide which one is the closest one and has to be rendered first, which one is the 2nd, which one is the last etc).



Currently, to sort walls I remove all invisible ones and measure the shortest distance between player and wall. It works... but only when there is one polygon on the scene. Example (2 polygons):



enter image description here



I can handle this specific kind of issue but i don't know if there will be other problems in the future. My question: is there any algorithm (which works...) that can sort my walls in correct order and I will be able to render them with smile on my face?










share|improve this question















I'm developing a "false 3D" game using Python and pygame. The gfx consists only of prisms created using 2D primitives of different sizes and colors:



enter image description here



How the gfx of the game works:



enter image description here



The issue appears in the 4th point, when I want to sort walls in correct order in render queue (to decide which one is the closest one and has to be rendered first, which one is the 2nd, which one is the last etc).



Currently, to sort walls I remove all invisible ones and measure the shortest distance between player and wall. It works... but only when there is one polygon on the scene. Example (2 polygons):



enter image description here



I can handle this specific kind of issue but i don't know if there will be other problems in the future. My question: is there any algorithm (which works...) that can sort my walls in correct order and I will be able to render them with smile on my face?







algorithm 3d geometry 2d rendering






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 9 at 8:19

























asked Nov 9 at 1:09









dsonyy

2518




2518








  • 4




    without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
    – Spektre
    Nov 9 at 8:46












  • If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
    – Yola
    Nov 9 at 8:49






  • 2




    Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
    – Spektre
    Nov 9 at 8:52














  • 4




    without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
    – Spektre
    Nov 9 at 8:46












  • If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
    – Yola
    Nov 9 at 8:49






  • 2




    Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
    – Spektre
    Nov 9 at 8:52








4




4




without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
– Spektre
Nov 9 at 8:46






without Z buffer you need to divide the faces by each intersection/overlap and handle each one as individual face. As you can see it will be a horrible mess to code. Much much easier is to port your gfx into 3D using Z buffering ... Also using dot product with view direction and face normal is much easier way of removing unseen faces than sorting like you do now (its called FACE CULLING)...
– Spektre
Nov 9 at 8:46














If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
– Yola
Nov 9 at 8:49




If you want to go with 2D, you need to check every pixel, not polygon. Or you can adhere to Spektre advise.
– Yola
Nov 9 at 8:49




2




2




Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
– Spektre
Nov 9 at 8:52




Also Take a look at this Understanding 4x4 homogenous transform matrices there is small C++ example of 3D wireframe rendering in 2D GDI environment it might be handy if you do not have a 3D engine
– Spektre
Nov 9 at 8:52












1 Answer
1






active

oldest

votes

















up vote
1
down vote













I'm guessing we can fairly assume that the polygons do not intersect. If this is the case, we do not need to split anything. However, finding the correct order is still computationally heavy. Although one could probably come up with an incremental approach that only updates the necessary things from frame to frame.



So here is the thing. In your 2-polygon example, basing the order on the two closest points of a line does obviously not work since they have different view directions. But if you pick points with the same view direction (in an area where they overlap), you will clearly see that A is in front of B. So, what do we need to do:



First find all walls that are visible. We will create a visibility graph for these walls. So, create a graph where every wall is represented by a node. In the end, you will calculate a topological sort of this graph to get the drawing order. Now, how do we find the edges, i.e., information about what wall is in front of another? For this, first find the wall pairs that overlap (the extruded wall). You might want to use an acceleration data structure like a AABB tree to make this fast.



Then we need a 1D parametrization of the view direction. The angle between the direction and the x-axis might work pretty well (a = atan2(lineY - playerY, lineX - playerX)), although it has this annoying periodicity that you need to handle. We will now only consider the original polygon edges for the two walls (not the extruded ones). Find the 1D intervals for the two lines (e.g., line 1 is between 10° and 35° and line 2 is between 20° and 135°). If these two intervals do not overlap, you can skip this pair as their relative order does not matter. If they do, find any point in the overlapping interval (e.g. 25°), find the corresponding view direction (x = playerX + cos(25°), y = playerY + sin(25°)) and the points on the line that correspond to this direction (e.g. by calculating the intersection of the line with the view ray). Then, simply calculate the distances of the two lines along this ray. It does not matter what point in the overlap interval you choose because the lines are linear and the original polygons do not intersect. If the distance to line 1 is smaller than the distance to line 2, add a directed edge from line 1 to line 2 to the visibility graph (meaning that line 1 is in front of line 2), otherwise add the reverse edge.



Finally, calculate a topological ordering of the graph and you have your drawing order.



Option 2



Here is an alternative to the above approach that might be more efficient for a dynamic rendering. The idea is based on this publication.



First triangulate your scene, i.e., fill the voids with triangles (this needs to be done only once). Then, our visibility graph stores the triangles (not the edges). For each triangle edge that you see from the inside, add an edge from the triangle to the neighboring triangle incident to that edge. In the end, again calculate a topological sort and draw your walls in that order (skipping void triangles).



The efficiency in the dynamic case comes from the fact that you only have to do small updates to your graph. For each of the edges, you want to determine if you see them from the front or from the back. Hence, the direction of the edge will only be reversed if the view point crosses the infinite line specified by the edge. If you find all those edges (that changed direction since the last frame), you can update your graph and sort accordingly.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53218413%2frendering-order-of-walls-of-false-3d-prisms%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    I'm guessing we can fairly assume that the polygons do not intersect. If this is the case, we do not need to split anything. However, finding the correct order is still computationally heavy. Although one could probably come up with an incremental approach that only updates the necessary things from frame to frame.



    So here is the thing. In your 2-polygon example, basing the order on the two closest points of a line does obviously not work since they have different view directions. But if you pick points with the same view direction (in an area where they overlap), you will clearly see that A is in front of B. So, what do we need to do:



    First find all walls that are visible. We will create a visibility graph for these walls. So, create a graph where every wall is represented by a node. In the end, you will calculate a topological sort of this graph to get the drawing order. Now, how do we find the edges, i.e., information about what wall is in front of another? For this, first find the wall pairs that overlap (the extruded wall). You might want to use an acceleration data structure like a AABB tree to make this fast.



    Then we need a 1D parametrization of the view direction. The angle between the direction and the x-axis might work pretty well (a = atan2(lineY - playerY, lineX - playerX)), although it has this annoying periodicity that you need to handle. We will now only consider the original polygon edges for the two walls (not the extruded ones). Find the 1D intervals for the two lines (e.g., line 1 is between 10° and 35° and line 2 is between 20° and 135°). If these two intervals do not overlap, you can skip this pair as their relative order does not matter. If they do, find any point in the overlapping interval (e.g. 25°), find the corresponding view direction (x = playerX + cos(25°), y = playerY + sin(25°)) and the points on the line that correspond to this direction (e.g. by calculating the intersection of the line with the view ray). Then, simply calculate the distances of the two lines along this ray. It does not matter what point in the overlap interval you choose because the lines are linear and the original polygons do not intersect. If the distance to line 1 is smaller than the distance to line 2, add a directed edge from line 1 to line 2 to the visibility graph (meaning that line 1 is in front of line 2), otherwise add the reverse edge.



    Finally, calculate a topological ordering of the graph and you have your drawing order.



    Option 2



    Here is an alternative to the above approach that might be more efficient for a dynamic rendering. The idea is based on this publication.



    First triangulate your scene, i.e., fill the voids with triangles (this needs to be done only once). Then, our visibility graph stores the triangles (not the edges). For each triangle edge that you see from the inside, add an edge from the triangle to the neighboring triangle incident to that edge. In the end, again calculate a topological sort and draw your walls in that order (skipping void triangles).



    The efficiency in the dynamic case comes from the fact that you only have to do small updates to your graph. For each of the edges, you want to determine if you see them from the front or from the back. Hence, the direction of the edge will only be reversed if the view point crosses the infinite line specified by the edge. If you find all those edges (that changed direction since the last frame), you can update your graph and sort accordingly.






    share|improve this answer

























      up vote
      1
      down vote













      I'm guessing we can fairly assume that the polygons do not intersect. If this is the case, we do not need to split anything. However, finding the correct order is still computationally heavy. Although one could probably come up with an incremental approach that only updates the necessary things from frame to frame.



      So here is the thing. In your 2-polygon example, basing the order on the two closest points of a line does obviously not work since they have different view directions. But if you pick points with the same view direction (in an area where they overlap), you will clearly see that A is in front of B. So, what do we need to do:



      First find all walls that are visible. We will create a visibility graph for these walls. So, create a graph where every wall is represented by a node. In the end, you will calculate a topological sort of this graph to get the drawing order. Now, how do we find the edges, i.e., information about what wall is in front of another? For this, first find the wall pairs that overlap (the extruded wall). You might want to use an acceleration data structure like a AABB tree to make this fast.



      Then we need a 1D parametrization of the view direction. The angle between the direction and the x-axis might work pretty well (a = atan2(lineY - playerY, lineX - playerX)), although it has this annoying periodicity that you need to handle. We will now only consider the original polygon edges for the two walls (not the extruded ones). Find the 1D intervals for the two lines (e.g., line 1 is between 10° and 35° and line 2 is between 20° and 135°). If these two intervals do not overlap, you can skip this pair as their relative order does not matter. If they do, find any point in the overlapping interval (e.g. 25°), find the corresponding view direction (x = playerX + cos(25°), y = playerY + sin(25°)) and the points on the line that correspond to this direction (e.g. by calculating the intersection of the line with the view ray). Then, simply calculate the distances of the two lines along this ray. It does not matter what point in the overlap interval you choose because the lines are linear and the original polygons do not intersect. If the distance to line 1 is smaller than the distance to line 2, add a directed edge from line 1 to line 2 to the visibility graph (meaning that line 1 is in front of line 2), otherwise add the reverse edge.



      Finally, calculate a topological ordering of the graph and you have your drawing order.



      Option 2



      Here is an alternative to the above approach that might be more efficient for a dynamic rendering. The idea is based on this publication.



      First triangulate your scene, i.e., fill the voids with triangles (this needs to be done only once). Then, our visibility graph stores the triangles (not the edges). For each triangle edge that you see from the inside, add an edge from the triangle to the neighboring triangle incident to that edge. In the end, again calculate a topological sort and draw your walls in that order (skipping void triangles).



      The efficiency in the dynamic case comes from the fact that you only have to do small updates to your graph. For each of the edges, you want to determine if you see them from the front or from the back. Hence, the direction of the edge will only be reversed if the view point crosses the infinite line specified by the edge. If you find all those edges (that changed direction since the last frame), you can update your graph and sort accordingly.






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        I'm guessing we can fairly assume that the polygons do not intersect. If this is the case, we do not need to split anything. However, finding the correct order is still computationally heavy. Although one could probably come up with an incremental approach that only updates the necessary things from frame to frame.



        So here is the thing. In your 2-polygon example, basing the order on the two closest points of a line does obviously not work since they have different view directions. But if you pick points with the same view direction (in an area where they overlap), you will clearly see that A is in front of B. So, what do we need to do:



        First find all walls that are visible. We will create a visibility graph for these walls. So, create a graph where every wall is represented by a node. In the end, you will calculate a topological sort of this graph to get the drawing order. Now, how do we find the edges, i.e., information about what wall is in front of another? For this, first find the wall pairs that overlap (the extruded wall). You might want to use an acceleration data structure like a AABB tree to make this fast.



        Then we need a 1D parametrization of the view direction. The angle between the direction and the x-axis might work pretty well (a = atan2(lineY - playerY, lineX - playerX)), although it has this annoying periodicity that you need to handle. We will now only consider the original polygon edges for the two walls (not the extruded ones). Find the 1D intervals for the two lines (e.g., line 1 is between 10° and 35° and line 2 is between 20° and 135°). If these two intervals do not overlap, you can skip this pair as their relative order does not matter. If they do, find any point in the overlapping interval (e.g. 25°), find the corresponding view direction (x = playerX + cos(25°), y = playerY + sin(25°)) and the points on the line that correspond to this direction (e.g. by calculating the intersection of the line with the view ray). Then, simply calculate the distances of the two lines along this ray. It does not matter what point in the overlap interval you choose because the lines are linear and the original polygons do not intersect. If the distance to line 1 is smaller than the distance to line 2, add a directed edge from line 1 to line 2 to the visibility graph (meaning that line 1 is in front of line 2), otherwise add the reverse edge.



        Finally, calculate a topological ordering of the graph and you have your drawing order.



        Option 2



        Here is an alternative to the above approach that might be more efficient for a dynamic rendering. The idea is based on this publication.



        First triangulate your scene, i.e., fill the voids with triangles (this needs to be done only once). Then, our visibility graph stores the triangles (not the edges). For each triangle edge that you see from the inside, add an edge from the triangle to the neighboring triangle incident to that edge. In the end, again calculate a topological sort and draw your walls in that order (skipping void triangles).



        The efficiency in the dynamic case comes from the fact that you only have to do small updates to your graph. For each of the edges, you want to determine if you see them from the front or from the back. Hence, the direction of the edge will only be reversed if the view point crosses the infinite line specified by the edge. If you find all those edges (that changed direction since the last frame), you can update your graph and sort accordingly.






        share|improve this answer












        I'm guessing we can fairly assume that the polygons do not intersect. If this is the case, we do not need to split anything. However, finding the correct order is still computationally heavy. Although one could probably come up with an incremental approach that only updates the necessary things from frame to frame.



        So here is the thing. In your 2-polygon example, basing the order on the two closest points of a line does obviously not work since they have different view directions. But if you pick points with the same view direction (in an area where they overlap), you will clearly see that A is in front of B. So, what do we need to do:



        First find all walls that are visible. We will create a visibility graph for these walls. So, create a graph where every wall is represented by a node. In the end, you will calculate a topological sort of this graph to get the drawing order. Now, how do we find the edges, i.e., information about what wall is in front of another? For this, first find the wall pairs that overlap (the extruded wall). You might want to use an acceleration data structure like a AABB tree to make this fast.



        Then we need a 1D parametrization of the view direction. The angle between the direction and the x-axis might work pretty well (a = atan2(lineY - playerY, lineX - playerX)), although it has this annoying periodicity that you need to handle. We will now only consider the original polygon edges for the two walls (not the extruded ones). Find the 1D intervals for the two lines (e.g., line 1 is between 10° and 35° and line 2 is between 20° and 135°). If these two intervals do not overlap, you can skip this pair as their relative order does not matter. If they do, find any point in the overlapping interval (e.g. 25°), find the corresponding view direction (x = playerX + cos(25°), y = playerY + sin(25°)) and the points on the line that correspond to this direction (e.g. by calculating the intersection of the line with the view ray). Then, simply calculate the distances of the two lines along this ray. It does not matter what point in the overlap interval you choose because the lines are linear and the original polygons do not intersect. If the distance to line 1 is smaller than the distance to line 2, add a directed edge from line 1 to line 2 to the visibility graph (meaning that line 1 is in front of line 2), otherwise add the reverse edge.



        Finally, calculate a topological ordering of the graph and you have your drawing order.



        Option 2



        Here is an alternative to the above approach that might be more efficient for a dynamic rendering. The idea is based on this publication.



        First triangulate your scene, i.e., fill the voids with triangles (this needs to be done only once). Then, our visibility graph stores the triangles (not the edges). For each triangle edge that you see from the inside, add an edge from the triangle to the neighboring triangle incident to that edge. In the end, again calculate a topological sort and draw your walls in that order (skipping void triangles).



        The efficiency in the dynamic case comes from the fact that you only have to do small updates to your graph. For each of the edges, you want to determine if you see them from the front or from the back. Hence, the direction of the edge will only be reversed if the view point crosses the infinite line specified by the edge. If you find all those edges (that changed direction since the last frame), you can update your graph and sort accordingly.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 11 at 7:47









        Nico Schertler

        25k42350




        25k42350






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53218413%2frendering-order-of-walls-of-false-3d-prisms%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            JBPM : POST request for execute process go wrong