June 20 - Omni Update

Discussion in 'Dev Blog' started by OmnipotentEntity, Jun 20, 2014.

  1. OmnipotentEntity

    OmnipotentEntity Code Monkey Forum Administrator

    OmnipotentEntity submitted a new blog post:

    June 20 - Omni Update

    Continue reading the Original Blog Post
     
    Tamorr, Jbeetle, Zael and 1 other person like this.
  2. OmnipotentEntity

    OmnipotentEntity Code Monkey Forum Administrator

    Oh yeah right. I forgot to mention horse tits in my post.

    ...

    Horse tits.
     
    WoxandWarf, Zebe, Ami-Chan and 14 others like this.
  3. LemmyKillmaster

    LemmyKillmaster Void-Bound Voyager

    Why are you doing this to meigh?
     
  4. Eonwe

    Eonwe Macho Man

    If you get angry about the horse AI in this thread I will be much harsher than in previous threads.
     
    RottenCookies likes this.
  5. Neko-Chan

    Neko-Chan Aquatic Astronaut

    If you find a great answer for the code to define if a line cross a rectangle, could you sent it to me, because rigth now I can only find "not that good" answers
     
    Last edited: Jun 20, 2014
  6. Rainbow Dash

    Rainbow Dash Oxygen Tank

    this is why your my fav omni
     
    Owl_Stalker and Ramones_fan like this.
  7. Hessmix

    Hessmix Orbital Explorer

    I was going to say something in response but it's so damn obvious...I don't even need to.
     
  8. davidlolcat

    davidlolcat Subatomic Cosmonaut

    I logged in, just so that I could like this :)
     
  9. Disco2

    Disco2 Existential Complex

    Wonderful....
     
  10. Mystify

    Mystify Void-Bound Voyager

    couldn't you detect when the connections are far enough apart to potentially span the screen, and if so place dummy noes along the way that will render the wire if onscreen?
     
  11. Jeoshua

    Jeoshua Existential Complex

    The problem he's describing is due to the way the game renders the screen, around you. Only a certain amount of the world is even loaded into the client's memory, at one time. The game, at this point, only "knows" about the wire if at least one of the end points is currently on-screen. It's a step up from where it was, and Omni is to be thanked for that change. At least, it seems, they have a dev that is thinking about these kind of obscure things when others can't or won't... probably they just aren't geeky enough :geek:

    (+1 Omni for awesomeness... -1 for also fanning the flames)
     
    Kawa likes this.
  12. aravol

    aravol Scruffy Nerf-Herder

    If this is a matter of making a line (wire) check for crossing a box (the screen) couldn't you use a standard raycasting algorythm?

    Also, would it be terrible to disallow wiring connections beyond 64 blocks? It feels like that could be solved by introducing a "relay" wiring object, and a simple rule of "x distance is too far for one wire" makes sense for most kinds of actual wires (albeit we're usually talking a pretty good distance)
     
    Kawa and Jeoshua like this.
  13. OmnipotentEntity

    OmnipotentEntity Code Monkey Forum Administrator

    We can't actually use a ray casting algorithm as it stands right now because the problem is missing information. Right now, when you connect two nodes the connection is stored within both nodes. Both the client and the server might be unaware of either or both nodes, because they're not loaded into memory. If that's the case then the game isn't aware that there is even anything missing TO draw. The fix is we need to store the WireConnections that pass through a chunk as part of that chunk; however, that has its own problems, because the WireConnections in the chunk may come desynced from the WireConnections in the nodes. Which is why I didn't do it immediately. I wanted to fix one bug at a time without introducing more potentially.

    I'd rather avoid needing a relay wire because that's just an extra layer of complexity.
     
    Kawa likes this.
  14. Abion47

    Abion47 Void-Bound Voyager

    Here's a solution for Line-Rectangle intersection that comes to mind first (assumes that rectangles aren't rotated, i.e. the sides are parallel with the x and y axes).

    For detecting the Line-Rectangle intersection, first the algorithm would check to make sure that one of the endpoints is within the rectangle, as that would be the fastest case to determine intersection:

    The code for this is pretty simple:

    (I'm assuming that you guys already use this code in your existing checks for whether points are within rectangles. I'm including it for completion and for the sake of others that might read this.)


    Code:
    bool DoesRectangleContainPoint(Rectangle r, Point p)
    {
      return (p.X >= r.X)
            && (p.Y >= r.Y)
            && (p.X <= r.X + r.Width)
            && (p.Y <= r.Y + r.Height);
    }
    
    bool DoesLineHaveEndpointsInRectangle(Point p1, Point p2, Rectangle r)
    {
      return DoesRectangleContainPoint(r, p1) || DoesRectangleContainPoint(r, p2);
    }
    In the case where neither endpoint resides in the rectangle and the line just passes completely through, the algorithm will actually treat the check as detecting two Line-Line intersections by checking the line of the wire against the two diagonals of the rectangle, since any line that crosses the rectangle will intersect at least one of these two lines.

    The code for this is a bit trickier to understand, but it's still a cheap check. It involves treating the points as vectors and using cross products to find at what point along the lines the two vectors have the same value. Check out this guy's StackOverflow answer for an explanation, as he explains it better than I could (URL removed for not meeting forum requirements; apparently exactly 2 posts doesn't meet the "at least 2 posts" rule). The code itself is:

    Code:
    bool DoLineSegmentsIntersect(Point p, Point pr, Point q, Point qs)
    {
      Point r = pr - p;
      Point s = qs - q;
    
      Point qmp = q - p;
      double qmpxr = qmp.X * r.Y - qmp.Y * r.X;
      double rxs = r.X * s.Y - r.Y * s.X;
    
      // Are the lines collinear?
      if (qmpxr == 0 && rxs == 0)
      {
        // Do the lines overlap?
        return ((q.X - p.X < 0) != (q.X - pr.X < 0) != (qs.X - p.X < 0) != (qs.X - pr.X < 0))
            || ((q.Y - p.Y < 0) != (q.Y - pr.Y < 0) != (qs.Y - p.Y < 0) != (qs.Y - pr.Y < 0));
      }
    
      if (rxs == 0)
      {
        // Lines are parallel
        return true;
      }
    
      double u = qmpxr / rxs;
      double qmpxs = qmp.X * s.Y - qmp.Y * s.X;
      double t = qmpxs / rxs;
    
      return (t >= 0) && (t <= 1) && (u >= 0) && (u <= 1);
    }
    
    bool DoesLineCrossRectangle(Point p1, Point p2, Rectangle r)
    {
      Point d1 = new Point(r.X, r.Y);
      Point d2 = new Point(r.X + r.Width, r.Y + r.Height);
      Point d3 = new Point(r.X + r.Width, r.Y);
      Point d4 = new Point(r.X, r.Y + r.Height);
    
      return DoLineSegmentsIntersect(p1, p2, d1, d2) || DoLineSegmentsIntersect(p1, p2, d3, d4);
    }
    So to tie it all together, a function would only need to check for these two states - whether a line intersects by way of one endpoint being within the rectangle, or whether a line intersects by crossing one of the rectangle's diagonals.

    Code:
    bool DoesLineIntersectRectangle(Point p1, Point p2, Rectangle r)
    {
      return DoesLineHaveEndpointsInRectangle(p1, p2, r)
            || DoesLineCrossRectangle(p1, p2, r);
    }
    This is my approach to solving the Line-Rectangle intersection problem. I haven't run it through any benchmarks or anything, but since it only involves short functions and simple arithmetic, I imagine that it would run quite fast.
     
  15. minno

    minno Void-Bound Voyager

    If you can efficiently query for the endpoints, you can use the Cohen-Sutherland algorithm (which I apparently haven't posted here enough to put a link to) to check if a line with the given endpoints crosses the screen.
     
  16. Kawa

    Kawa Tiy's Beard

    Reading comprehension: low.
     
    Owl_Stalker likes this.
  17. Jeoshua

    Jeoshua Existential Complex

    @Abion47 Your code assumes that the entire space is held in memory at one time, but unfortunately, as Omni is trying to point out, that is not the case. He knows how to make a check to see if a line is crossing the screen, but what happens when one of the end points is not loaded into memory?
     
    Last edited: Jun 21, 2014
    Kawa likes this.
  18. NoMoreD20

    NoMoreD20 Scruffy Nerf-Herder

    Couldn't you use some kind of (quad-)tree structure to keep track of all wires? They are perfect for queries for 2D data.
    And you can sacrifice some accuracy when displaying cross-chunk wires to keep your data down (the slope need not be exact), because you KNOW there will be people filling every tile with wires to a different chunk.

    Another way is to allow deferred updates to chunks. What I mean is a way to store changes to be applied to chunks IF and WHEN they get loaded. This way updating a wire will defer updates for all the chunks the wire crosses.
     
  19. Abion47

    Abion47 Void-Bound Voyager

    I must have read the article right after I woke up and misinterpreted the problem.

    Maybe when a chunk gets loaded, it checks the unloaded chunks to the left and right of it for existing nodes, and if there is a node in the left chunks that corresponds to a chunk in the right nodes, the loaded chunk adds those nodes to memory? Though I don't know how wires are stored in the chunks currently, so this wouldn't work if the entire chunk needs to be loaded just to check for wiring. The obvious solution for this would be to save wiring data in a separate structure than terrain so it can be queried even if the chunk isn't loaded, but that might screw up whatever structure they currently have.
     
  20. Jeoshua

    Jeoshua Existential Complex

    @Abion47 I do believe that is what would be required, with the code base as it is. But by all means, with that in mind do keep brainstorming ideas. Maybe you will hit upon something that Omni hasn't yet considered.
     

Share This Page