Results 1 to 6 of 6

Thread: For loop and boolean expression in it and other troubles..

  1. #1

    For loop and boolean expression in it and other troubles..

    Hi.
    I have "weird" problem. In my map editor i must draw selection boxes and i only have to draw in the current camera viewing range. Currently when i move camera somewhere, the selectionboxes are floating in air.

    Im rendering only small portion of the map (rectangle type).
    Now im trying to limit the rendering. Tried many things.. Dunno how to do it.
    The camera range is X,Y and is defined as 4 variables that hold current visible area:
    Code:
    X1 -- X2
    Y1 -- Y2
    X camera range starts from X1 and goes to X2, same with Y.
    Anyway here is piece of code im drawing the selectorblocks with:

    Code:
       
    
    // This currently limits the drawing of selectorblocks at the right "side" of the camera.
    // Works fine, what about the math?
    
    // XSelection contains how many blocks are selected in the X axis
    // StartPnt is just a record with X,Y integers, holding the selection start coordinates, after first mousedown!
    
    for SelCountX:= Iff(
        DragPnt.X > x2, x2 - startpnt.x, xselection
       ) downto 0
    
          do
          begin
         
            for SelCountY:=  0 to YSelection do
            begin
              for SelCountZ :=  0 to ZSelection do
              begin
                
                glPushMatrix();
    
    
                      glTranslatef(
    
    
                        SelCountX + selX  -0.5,
                        SelCountZ + selZ  -0.5,
                        SelCountY + selY  -0.5
    
    
                      );
    
    
    // Just draws cube, nothing special in there.
                    DrawCube(SelCountZ, SelCountX, SelCountY);
    
    
    
                glPopMatrix();
              end;
            end;
          end;
    "Iff" is from JclSysUtils.pas from JEDI.
    Code:
    // Replacement for the C ternary conditional operator ? :
    function Iff(const Condition: Boolean; const TruePart, FalsePart: string): string; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Char): Char; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Byte): Byte; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Integer): Integer; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Cardinal): Cardinal; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Float): Float; overload;
    function Iff(const Condition: Boolean; const TruePart, FalsePart: Boolean): Boolean; overload;
    My question is how to make that "for X:" loop neat enough so i can use the Iff twice there, so i can do like: Less than.. also in that loop.

    The right side "drawing limitation" for selectorblocks works, i would like to do the same for left side also. But it seems impossible within "for loop" without repeating code.


    Is it even possible in Pascal (Delphi) ?
    Code:
    Iff(
        DragPnt.X < x2, x2 - startpnt.x, xselection
       ) downto 0

    I cant say Delphi, if THIS is true then loop that way, but if THIS is NOT true, loop another way. Also i cant say him to use either DOWNTO or TO. But this would probably fix it.

    With separate loops and repeated code maybe yes, but without it?

    Impossible?

    EDIT: In C++ it seems possible:
    http://stackoverflow.com/questions/1...loop-statement
    Last edited by hwnd; 27-11-2013 at 02:52 PM.

  2. #2

    Exclamation

    Personally I don't like the IFF function a lot. The C's "?:" operator is quite tricky and isn't easy to translate it to Pascal as you may think. Note that in C, when the "?:" operator is executed, only the "TRUE" part of the operator is executed (even if the compiler isn't configured to cut-away boolean expressions!) but in Pascal when the IFF function is called then both parts are executed, so side effects may occur (fortunately it isn't your case, but it might be!). Also it isn't too readable.

    Personally I recommend you to use an IF ... THEN ... ELSE ... statement to assign a variable and then use that variable in the FOR loop:
    Code:
      IF DragPnt.X > x2 THEN
        StartX :=  x2 - startpnt.x
      ELSE
        StartX :=  xselection;
    
      FOR X := StartX DOWNTO 0 DO
       ...
    About the "if" statement inside "for" statement, it is not possible in Pascal (AFAIK). Note that in C (and in C++) everything is an expression, so everything return a value (sometimes its a void value, but it is a value). That allows you to do a lot of weird stuff like the "for( int i = elevator1CurrentStatus.floorNumber; (if(boundary == 9) i<boundary else i>boundary) ;i+=i+countDirection)" you linked. Even weirder:
    Code:
    int a[10];
    
    a[2]=20;
    3[a]=4; /* Assigning a value to an integer constant? */
    It is "correct", compiles and runs in most major compilers*...

    Again, I recommend you the IF .. THEN ... ELSE ... statement.

    I really like C language but its "for" statement is actually "a WHILE loop with embedded entering section and two execution blocks specially designed to confuse you". It's so flexible that sometimes it brings you more problems than solutions, but it's a really nice feature that allows to hide your algorithms pretty well.
    No signature provided yet.

  3. #3
    Why don't you simply trim the selection rectangle to camera rectangle boundaries.

    First make yourself a SelectionBox record similar like this:
    Code:
    RSelectionBox = record
      LeftBorder: Single;
      RightBorder: Single;
      TopBorder: Single;
      BottomBorder: Single;
    end;
    Then I also recomend making similar record for storing camera viewpoint boundaries:
    Code:
    RCameraViewpoint = record
      LeftBorder: Single;
      RightBorder: Single;
      TopBorder: Single;
      BottomBorder: Single;
    end;
    Finaly you simply check to see if selection borders are within camera viewpoint boundaries if not you modify them to be on camera viewpoint boundaries. Code would look something like this:
    Code:
    function TrimSelectionBox(SelectionBox: RSelectionBox; CameraViewpoint: RCameraViewpoint): RSelectionBox;
    begin
      if SelectionBox.LeftBorder < CameraViewpoint.Leftborder then Result.LeftBorder := CameraViewpoint.LeftBorder;
      if SelectionBox.RightBorder < CameraViewpoint.RightBorder then SelectionBox.RightBorder := CameraViewpoint.RightBorder;
      if SelectionBox.TopBorder < CameraViewpoint.TopBorder then SelectionBox.TopBorder := CameraViewpoint.TopBorder;
      if SelectionBox.BottomBorder < CameraViewpoint.BottomBorder then SelectionBox.BottomBorder := CameraViewpoint.BottomBorder;
      result := SelectionBox;
    end;

  4. #4
    Nice idea, but im not sure if it helps. I will try of course.
    I actually even got it to work for both left and right of X.
    But if i do negative selection with mouse, ex: from right to left. They still appear and limiting is buggy.
    So there are somewhere problems with negative numbers, either in rendering or limiting code, or in both..
    If selection goes from left to right, limiting works fine. Everywhere.

    There are just so many things to check for. Ex: if selection is negative or positive, how many selector blocks there are in total etc..

    Btw, the total nr of blocks that are selected do not depend on this "limitation". Its just visual thingy, If some of the selector blocks are outside the camera, these blocks will be taken into account anyway, just like in original editor. They just are not drawn. But the map array contents will be modified at this location anyway. Which is fine.

    Its just the visual side of things that must be "good".
    Here is the selectorblocks without left side limit:
    http://i.minus.com/ityQSjPUTELoh.JPG

    Here is the selectorblocks with left side limited, it means, i moved camera to the right for 1 step (column). Camera X incremented by 1.
    http://i.minus.com/igCMGYgji107s.JPG

    Because one column of blocks is outside the cameras left border, its now only 3 columns left.

    The blue "ER" tiles from word "DINER" are rendered for whole camera range. So blue tiles show exactly the camera viewport or drawing range.

    EDIT
    Ok, here is better view of "floating" selectorblocks: Look how its limited from left, but NOT from the BOTTOM.
    http://i.minus.com/ichfPhVMiUDbF.JPG


    This of course is Y coordinate, but anyway it shows clearly how bad it looks when it goes off the camera range.
    Last edited by hwnd; 30-11-2013 at 11:17 AM.

  5. #5
    Quote Originally Posted by hwnd View Post
    There are just so many things to check for. Ex: if selection is negative or positive, how many selector blocks there are in total etc..
    You can solve this easly by sorting X1 and X2 so that X1 is alyways lower. Same goes for Y1 and Y2.
    The number of selector blocks rendered only depends on trimmed selection dimensions.

  6. #6
    Ok, im kinda "hack and try" guy, of course i did a little bit of thinking and as result i got it almost working for X1 and X2.
    If all of the X1..X2 will work then its just copy paste for Y1..Y2 with few variable name changes. At least i hope so.

    But its late and im tired, my head hurts. Have to rest..


    But atm it works for every side, except if you negative select (from right to left) and move either up or down, then the right side is not "limited". All selector blocks just disappear without going away block by block like with other sides.

    But i know what piece of code is responsible for that, i will take a break, come back and try again.
    I already did so much today.

    And i cant get past of the selector blocks either, i want to make them working before moving on.
    Because all of the (ok 99% or so) map editing depends on them.
    Selector blocks must be pickable also by mouse, i tried this already and it seems to work (again credit goes to User137 and his excellent nxPascal), but i decided to first limit the rendering of the selector blocks.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •