Skip to content

ortho function is broken #1278

Closed
Closed

Description

@processing-bugs

Original author: bearmoun...@gmail.com (September 12, 2012 17:01:00)

  1. ortho() works fine
  2. ortho(0, width, 0, height) seem to be be misaligned
  3. ortho(0, width, 0, height, -10, 10) don't seem to show anything

For any practical use of ortho(...) function you must now be followed up with a call to translate(...) with specific coordinates which depend on the left, right, top, and bottom parameters for the ortho call as well as width and height of your window. This is unpractical.

Reproduce:
void setup() {
size(800, 600, OPENGL);
}

void draw() {
float x0 = 124213;
float x1 = x0 + 512;
float y0 = 2342;
float y1 = y0 + 384;
float tx = width/2 + x0;
float ty = height/2 - y1;

ortho(x0, x1, y0, y1);

translate(tx, ty);

background(0x234567);
rect(0, 0, 10, 10);
line(0, 0, width, height);
rect(x1-x0, y1-y0, -10, -10);

}

Version 2.0b3 Mac OSX Mountain Lion 10.8.1

note: I have yet to figure out how to get ortho(left,right,bottom,top,far,near) to display anything.

Original issue: http://code.google.com/p/processing/issues/detail?id=1240

Activity

  1. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From bearmoun...@gmail.com on September 12, 2012 17:55:03
    Above contains error for tx and ty, please use following:

    void setup() {
    size(800, 600, OPENGL);
    }

    void draw() {
    float x0 = 124213;
    float x1 = x0 + 512;
    float y0 = 2342;
    float y1 = y0 + 384;
    float tx = width/2;
    float ty = height/2 - y1 - y0;

    ortho(x0, x1, y0, y1);
    
    translate(tx, ty);
    
    background(0x234567);
    rect(x0, y0, 10, 10);
    rect(x1, y1, -10, -10);
    line(x0,y0,x1,y1);
    

    }

  2. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From andres.c...@gmail.com on September 13, 2012 18:46:18
    Hello, what happens is that the left, right, bottom, top arguments in ortho() refer to the center of the screen, with the y-axis inverted with respect to the default orientation in Processing: e.g: botton-to-top instead of top-to-bottom. The reason for this is to follow the convention of the original OpenGL function glOrtho(), in the same way that frustum() follows glFrustum().

    For instance, if you need to set the an orthographic projection exactly covering the rectangle starting at the origin and having the same dimensions as the screen size, then you would call ortho(-width/2, +width/2, -height/2, +height/2) (not ortho(0, width, 0, height)).

    In general, if you want to set an orthographic projection covering the rectangle determined by the top-left corner (x0, y0) and bottom-right corner (x1, y1), you would need to pass to ortho() the following parameters:
    left = x0 - width/2
    right = x1 - width/2
    bottom = -(y1 - height/2)
    top = -(y0 - height/2)
    that correspond to the change of coordinates between the system located at the screen center with the Y-axis bottom-to-top, and Processing's system.

    So the following code in your example should work:

    void setup() {
    size(800, 600, P3D);
    }

    void draw() {
    float x0 = 124213;
    float x1 = x0 + 512;
    float y0 = 2342;
    float y1 = y0 + 384;

    ortho(x0-width/2, x1-width/2, -(y1-height/2), -(y0-height/2));

    background(0x234567);
    rect(x0, y0, 10, 10);
    rect(x1, y1, -10, -10);
    line(x0,y0,x1,y1);
    }

  3. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From bearmoun...@gmail.com on September 15, 2012 09:12:28
    I've looked into the source code and I've figured out what was wrong and this is how it can be solved

    Overview

    • small change to ortho()
    • small change ortho(float,float,float,float)
    • revert comment for ortho
    • swap and invert bottom and top variables in both main frustum function and main ortho function (the ones that do all the calc)
    • add information to reference documentation of ortho() and frustum() about calling resetMatrix()

    Discussion
    The problems we have previously experienced derive from Processing creates a default camera which is centered at width/2 and height/2. Each frame the camera matrix is added to the modelview matrix in beginDraw. I believe this is desired for most users and sketches. However, we can avoid future misunderstandings regarding this if we add information in the ortho(), frustum() as well as the camera() documentation.

    I've looked hard and tested many things for any side effects this change would have, but I've found nothing yet. Doing the suggested changes will make Processing OpenGL work as all others OpenGL implementations. The parameter "bottom" in frustum and ortho really means 'top' since processing y-coordinates is reversed in comparison to cartesian coordinates. The perspective()-function will continue to work as expected.

    Details of changes:

    In PGraphicsOpenGL.java fix the following:

    1. line 4451 frustum(float, float, float, floaf, float, float) function, right after "flush();"
      add
      float temp = -bottom;
      bottom = -top;
      top = temp;
    2. line 4380 ortho(float, float, float, floaf, float, float) function, right after "flush();"
      add
      float temp = -bottom;
      bottom = -top;
      top = temp;
    3. line 4346:
      change
      ortho(left, right, bottom, top, cameraNear, cameraFar);
      to
      ortho(left, right, bottom, top, -10, 10);
    4. line 4335:
      change
      ortho(-width/2, +width/2, -height/2, +height/2, cameraNear, cameraFar);
      to the default as it says in the help text for ortho
      ortho(0, width, 0, height, -10, 10);

    Changes to reference documentation

    1. in camera() add something along the lines of:
      "camera() is called once automatically when creating 3d context"
    2. in ortho() and..
    3. in frustum() add something like:
      "camera() is called once automatically when creating 3d context with default values. If this is undesirable you can reset the camera matrix with resetMatrix()".
  4. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From andres.c...@gmail.com on September 18, 2012 15:07:36
    Thanks a lot for your suggestions. I will pass them along the other member of the team in order to discuss the final form of the ortho() function.

  5. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From bearmoun...@gmail.com on October 25, 2012 04:48:57
    Is there any update on this issue?

  6. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From f...@processing.org on November 25, 2012 02:15:15
    Is this actually a problem where ortho() is not behaving like glOrtho/gluOrtho? (and is broken)
    http://www.khronos.org/opengles/documentation/opengles1_0/html/glOrtho.html

    Or is it just that the method is not as convenient as it could be?

  7. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From bearmoun...@gmail.com on November 25, 2012 18:32:46
    Short answer: Yes ortho is broken.

    Long answer: My suggested changes mentioned above will solve the issue, but I'm not sure it's the most proper way to go at it.

    1. One part of the problem is caused by Processing use left handed coordinates compared to OpenGL's right handed coordinate system. I mean, what is "bottom" in processing (as parameters are called in ortho/glOrtho and frustum/glFrustum). Bottom in opengl's right-handed system is both low-y and down compared to "top" parameter when viewed from person eye, but what should it be Processing? It's unclear, and it affects both frustum(), perspective(), ortho() calls. Therefore I cannot say if the most proper way to use ortho is
      ortho(lowX, highX, lowY, highY, nearZ, farZ) or
      ortho(lowX, highX, highY, lowY, nearZ, farZ).
      Though as it is now, neither of them work.

    The inverted y axis also affects the camera() function (which is also broken). It's supposed to mimic gluLookAt which you call with eye and lookat positions together with the up direction. But in Processing you call it with eye and lookat pos but with the DOWN direction.

    1. The other part is the deafult camera wich you set it to look at center which works for perspective projection but if you want to use ortho you need to reset the camera by resetMatrix. That should be mentioned in the documentation some place.
  8. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From caseyr...@gmail.com on December 04, 2012 23:09:32
    In regard to the ortho() example in the reference:

    size(100, 100, P3D);
    noFill();
    ortho(0, width, 0, height, -10, 10);
    translate(100, 100, 0);
    rotateX(-PI/6);
    rotateY(PI/3);
    box(45);

    The current code 2b6 behaves differently. To get the equivalent images in 2b6, the following changes need to be made:

    ortho(0, width, 0, height);
    translate(width/2, height/2, 0);

  9. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From bearmoun...@gmail.com on December 14, 2012 16:25:19
    I just tried it with 2.0b7 and I the changes to ortho has once again confused me. This is my workaround that gives "correct" (read below) results:

    void simpleOrtho(float xLo, float xHi, float yLo, float yHi, float near, float far) {
    resetMatrix(); // get rid of default model view

    // calculations according to glOrtho spec
    float tx = - (xHi+xLo) / (xHi-xLo);
    float ty = - (yHi+yLo) / (yHi-yLo);
    float tz = - (far+near) / (far-near);
    float a = 2.0/(xHi-xLo);
    float b = 2.0/(yHi-yLo);
    float c = -2.0/(far-near);
    
    // invert y axis (this is done to account for Processing's different coordinate system than OpenGL)
    b = -b;
    ty = -ty;
    
    PMatrix3D mat = new PMatrix3D(); 
    mat.set(  a, 0.0, 0.0, tx, 
    0.0, b, 0.0, ty, 
    0.0, 0.0, c, tz, 
    0.0, 0.0, 0.0, 1.0);
    
    PGraphicsOpenGL gl = (PGraphicsOpenGL)g;
    gl.setProjection(mat);
    

    }

    Notice that I've gotten changed the parameter names of "left, right, top, bottom" to avoid confusion. As you can see in the image (from OpenGL red book), the parameter "bottom" is the one that usually corresponds to the plane that is aligned to the lower part of the screen/window, and it makes sense in OpenGL as positive y axis goes upwards. If you want to stay true to the function name and correct order of parameters, ortho would be default as ortho(0,width,height,0,-1,1), but I think it makes more sense to use as I have.

    Anyway, hope this can be to some help, and I'm happy to answer any questions.


    Also, you can check the example sketch I've attached which demonstrates that it works.

  10. processing-bugs commented on Feb 10, 2013

    @processing-bugs
    Author

    From ericthe...@gmail.com on January 09, 2013 18:39:05
    I'm running 2.0b7 on a Mac. The example code on the website doesn't produce any visible results, nor does the code in Comment 3. The change in Comment 9 does work.

    Is this issue stabilizing & if so could someone update the example?

  11. codeanticode commented on Jun 3, 2013

    @codeanticode
    Contributor

    I think that many of the arguments in this discussion boil down to a matter of preference, and also to the idea of following the original gl functions (gluOrtho(), glFustrum, etc). About the latter, it should be noted that GLES 2.0+, GL 3.0+ and WebGL deprecated all those functions, so their value as a model is not very significant at this point.

    About perspective() and frustum(): I think they shouldn't be changed. The main reason for this is that many camera libraries that are around use the current "up" convention.

    Regarding ortho(), one thing I should note to @alignedleft is that the example in the reference page:

    http://trunk.processing.org/reference/ortho_.html

    is indeed broken and does not work with the latest revision from the repo.

    The following modified example code does work:

    size(100, 100, P3D);
    noFill();
    ortho(0, width, 0, height); // same as ortho()
    translate(width/2, height/2, 0);
    rotateX(-PI/6);
    rotateY(PI/3);
    box(45);

    Regarding the near and far arguments in ortho(), they now have exactly the same meaning as in perspective(), i.e.: near and far are the distances from the eye of the camera to the near and far planes, respectively (while before they didn't, notice the -10, 10 values used in the example). The following code makes the equivalence more clear:

    boolean persp = true;
    
    void setup() {
      size(100, 100, P3D);
      noFill();
    }
    
    void draw() {
      background(150);
      float far = map(mouseX, 0, width, 10, 150);
      if (persp) perspective(PI/3.0, float(width)/float(height), 10, far);  
      else ortho(0, width, 0, height, 10, far);
      translate(width/2, height/2, 0);
      rotateX(-PI/6);
      rotateY(PI/3);
      box(45);
    }
    
    void keyPressed() {
      persp = !persp;  
    }

    @benfry, @REAS: let me know if you have any comments about this.

  12. REAS commented on Jun 3, 2013

    @REAS
    Member

    @codeanticode If you think it's the way to do it, it's OK with me. I've just changed the reference entry to include the modified example.

  13. codeanticode commented on Jun 3, 2013

    @codeanticode
    Contributor

    great, thank you Casey.

    I was thinking that it could be useful to add the last example I mentioned above to the Basic|Camera section. Do you guys agree?

  14. REAS commented on Jun 3, 2013

    @REAS
    Member

    Yes, I'll add it. I will make it 600 x 360 and format it like the rest of the examples. Thanks for making it and sorting this out.

  15. 19 remaining items

  16. yousifalyousifi commented on Jun 2, 2015

    @yousifalyousifi

    Hello again, I should have mentioned this earlier, but I think I fixed this issue.

    In PGraphicsOpenGL's ortho(float, float, float, float, float, float) function there were unnecessary translations.
    There is no need to apply camera translation. Comment out the following lines:

    left -= cameraEyeX;
    right -= cameraEyeX;
    bottom -= cameraEyeY;
    top -= cameraEyeY;

    Going off my previous example, the cube rotates around the centre now, as expected.

    void setup() {
      size(1024, 512, P3D);
    }
    
    void draw() {
      background(200);
    
      //cam variables
      float fov = PI / 3;
      float cameraEyeZ = (height / 2) / (tan(fov / 2));
      float angle = (mouseY * 1.0 / height) * 2 * PI; //cam rotation angle around the origin [0, 2*PI]
    
      camera(
      cameraEyeZ * sin(angle), 0.0, cameraEyeZ * cos(angle), //position
      0.0, 0.0, 0.0, //centre
      0.0, 1.0, 0.0); //up
    
      //ortho
      float m = 1.0;
      ortho2(-width/2 * m, width/2  * m, -height/2  * m, height/2 * m, cameraEyeZ * 0.10, cameraEyeZ * 100.0);
      stroke(0);
      fill(255);
      box(30, 30, 30);
    }
    
    void ortho2(float left, float right, 
    float bottom, float top, 
    float near, float far) {
      float w = right - left;
      float h = top - bottom;
      float d = far - near;
    
      //This causes bugs
      // Applying the camera translation (only on x and y, as near and far
      // are given as distances from the viewer)
      //    left   -= cameraEyeX;
      //    right  -= cameraEyeX;
      //    bottom -= cameraEyeY;
      //    top    -= cameraEyeY;
      // Flushing geometry with a different perspective configuration.
      flush();
    
      float x = +2.0f / w;
      float y = +2.0f / h;
      float z = -2.0f / d;
    
      float tx = -(right + left) / w;
      float ty = -(top + bottom) / h;
      float tz = -(far + near) / d;
    
      // The minus sign is needed to invert the Y axis.
      ((PGraphics3D) g).projection.set(x, 0, 0, tx, 
      0, -y, 0, ty, 
      0, 0, z, tz, 
      0, 0, 0, 1);
    
      ((PGraphics3D) g).updateProjmodelview();
    }
  17. codeanticode commented on Jun 2, 2015

    @codeanticode
    Contributor

    @yousifucv yes you are right, thanks for the note! I removed those translations in code I didn't pushed yet. I'm doing some extra testing to make sure that Processing's ortho() is consistent with gluOrtho(), hopefully will be able to close this long-standing issue soon.

  18. codeanticode commented on Jun 5, 2015

    @codeanticode
    Contributor

    @REAS, @alignedleft where are the examples stored now so I can update the ones using ortho()? The reference also needs updating.

  19. scotthmurray commented on Jun 5, 2015

    @scotthmurray
    Member

    @codeanticode Example are under processing-docs/content/examples (although be aware that p5 adaptations are in progress, though that may not apply to 3D examples). Reference page examples are in processing-docs/content/api_en/ XML files.

    If you want to send me specific changes, I can apply them.

  20. codeanticode commented on Jun 7, 2015

    @codeanticode
    Contributor

    @alignedleft The changes are the following:

    • In the Basics|Camera|Orthographic example, the line
    ortho(0, width, 0, height, 10, far);

    should be replaced with

    ortho(-width/2, width/2, -height/2, height/2, 10, far);
    • In the reference page for ortho(), the the example code should have
    ortho(-width/2, width/2, -height/2, height/2); // same as ortho()

    instead of

    ortho(0, width, 0, height); // same as ortho()
  21. codeanticode commented on Jun 9, 2015

    @codeanticode
    Contributor

    @yousifucv if you have the chance to run some tests using the latest revisions from, let me know if you find any other issues with orthographic projection. Thanks a lot!

  22. codeanticode commented on Jun 10, 2015

    @codeanticode
    Contributor

    @alignedleft I already updated the example and reference.

    I no one has any further comments, I will close this issue in the following days.

  23. scotthmurray commented on Jun 11, 2015

    @scotthmurray
    Member

    @codeanticode I didn't see those edits, so I went ahead and applied them. This should be all set, but I will let you close the issue.

  24. codeanticode commented on Jun 12, 2015

    @codeanticode
    Contributor

    Hi Scott, sorry I did the chances but forgot to push them :-) And then I pushed a conflicted file :-O but everything is fixed now!

  25. felzam commented on Oct 2, 2015

    @felzam

    Hi guys, while the Examples section of ortho() in the Reference has been correctly updated, the Description section still says that ortho() defaults to ortho(0, width, 0, height).

    Also, the DomeProjection example in examples/Topics/Shaders doesn't work properly in v3.0 because of this change. In the drawDomeMaster() function, the line ortho(0, width, 0, height) should be changed to either ortho() or the same function with the new correct arguments.

  26. codeanticode commented on Oct 2, 2015

    @codeanticode
    Contributor

    This should be reported in the processing-docs repo:

    processing/processing-docs#324
    processing/processing-docs#325

  27. github-actions commented on Jun 16, 2021

    @github-actions

    This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

  28. locked as resolved and limited conversation to collaborators on Jun 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions