processing / processing

Source code for the Processing Core and Development Environment (PDE)
http://processing.org
Other
6.47k stars 1.51k forks source link

modelX/Y/Z broken when aiming a camera #187

Closed processing-bugs closed 11 years ago

processing-bugs commented 11 years ago

Original author: b...@processing.org (June 07, 2010 01:11:02)

This bug automatically added from: http://dev.processing.org/bugs/show_bug.cgi?id=1074

Comment from jungalero, 2008-11-27 13:50

I'm running Processing 1.0 in Leopard (10.5.5) on a Macbook Pro.

Aiming a camera seems to distort the model functions severely. Below is the example code from modelX() on the website with an added camera that tries to continually "look" at the floating cubes:

// Adapted from http://dev.processing.org/bugs/show_bug.cgi?id=486 void setup() { size(500, 500, P3D); noFill(); }

void draw() { background(0);

pushMatrix(); // start at the middle of the screen translate(width/2, height/2);
// some random rotation to make things interesting rotateY(1.0); //yrot); rotateZ(2.0); //zrot); // rotate in X a little more each frame rotateX(frameCount / 100.0); // offset from center translate(0, 150, 0);

// draw a white box outline at (0, 0, 0) stroke(255); box(50);

// the box was drawn at (0, 0, 0), store that location float x = modelX(0, 0, 0); float y = modelY(0, 0, 0); float z = modelZ(0, 0, 0); // clear out all the transformations popMatrix();

// draw another box at the same (x, y, z) coordinate as the other pushMatrix(); translate(x, y, z); stroke(255, 0, 0); box(50); popMatrix();

//Try to aim a camera at that point and everything explodes camera(width/2, height/2, height/2, x, y, z, 0, 1, 0); }

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

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:02 Comment from fry, 2008-11-27 14:02

no, the example just needs to be fixed--the camera is far too close to the object.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:03 Comment from jungalero, 2008-11-27 14:24

Thanks for the quick reply, but I'm not sure I follow. Even pulling the camera way out shows that the boxes aren't superimposed as they should be:

camera(width/2, height/2, 2500, x, y, z, 0, 1, 0);

Is it possibly a mac thing? I'll attach a screenshot.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:03 Comment from fry, 2008-11-27 14:27

No, the blowing up is partly that clipping planes don't work perfectly in P3D (see the differences when you switch to OPENGL).

See Help > Environment for more about the coordinate system.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:03 Comment from jungalero, 2008-11-27 14:37

I'm actually using OPENGL for the main sketch that I'm working on and I'm afraid even changing the example to OPENGL shows that the boxes are not superimposed.

Maybe I'm not understanding something? The base example shows two superimposed boxes flying around thanks to the miracle of modelX/Y/Z. My expectation was that I should be able to point a camera at their location and still see two superimposed boxes, but that is not the case. Changing the eye of the camera to follow the target makes things even more insane:

camera(x, y, z - 2500, x, y, z, 0, 1, 0);

Does that make sense, it seems weird to me that changing the camera around would effect modelX/Y/Z's ability to superimpose as shown in the base example. It seems to be affecting the values these functions return.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:04 Comment from REAS, 2008-11-28 16:49

OK, I modified the initial translation to:

// start at the middle of the screen translate(width/2, height/2, -200);

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:04 Comment from jungalero, 2008-11-29 13:48

Created an attachment (id=256) Another screenshot of broken cubes.

This change:

translate(width/2, height/2, -200);

Admittedly makes things less jumpy, but the cubes are still not superimposed in the same way they are if no camera call is made. I'll work out another sketch to illustrate this.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:05 Comment from jungalero, 2008-11-29 13:49

I think maybe I'm explaining myself poorly. My point in all of this is that aiming a camera messes up subsequent calls to modelX/Y/Z. Here's another sketch with no movement at all.

You can see that there is a single, simple translation and the modelX/Y/Z values are saved to move a second cube to that spot. This works fine on the first loop. However, with each subsequent loop, the values returned by modelX/Y/Z become erratic and the culprit seems to be the camera I am aiming.

Incidentally, things work fine if the translation is half of the width and height (160, 120), but that's not the point I'm making. Camera() is somehow affecting the coordinate space in a way I find confusing and the result is that modelX/Y/Z is unreliable.

Am I just missing something? Is this by design?

import processing.opengl.*;

void setup() { size(320,240,OPENGL); noFill(); }

void draw() { float eyeX, eyeY, eyeZ;

pushMatrix(); translate(160, 160); box(50,10,10);

eyeX = modelX(0,0,0); eyeY = modelY(0,0,0); eyeZ = modelZ(0,0,0);

//Correctly prints 160.0,160.0,0.0 the first time //Subsequent loops print weird stuff like 160.0,115.894684,31.789322 println(eyeX + "," + eyeY + "," + eyeZ);

popMatrix();

pushMatrix(); translate(eyeX, eyeY, eyeZ); box(10,50,10); popMatrix();

//Nothing fancy here, I'm just trying to point the camera at the cubes //It doesn't make sense to me that pointing the camera would ruin modelX/Y/Z camera(width/2, height/2, height/2, eyeX, eyeY, eyeZ, 0, 1, 0); }

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:05 Comment from MrFeinberg, 2008-12-29 17:02

Ben and Casey,

I confirm this broken behavior. I'm procedurally drawing an object whose dimensions and bounding cube I can't know until it's finished, and attempting to use modelX etc. to compute the centroid. Moving the camera changes the values returned by model[X|Y|Z] erratically, even though the object itself is drawn the same way in the same place each time.

I note that the status is FIXED, but I don't see in what version. I'm using 1.0.1. How can I get and test the fix?

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:06 Comment from MrFeinberg, 2008-12-29 20:59

Demo of problem:

http://mrfeinberg.com/hilbert/

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:06 Comment from fry, 2009-02-20 11:34

The original bug report was incorrect, which is why this was closed. The problem was the example itself because the camera dimensions were wrong.

In your code, aren't you setting the camera after you've finished drawing? That's likely to cause erratic behavior.

But if you think it's a bug, please file a new entry with the description so we can try to track it down. (And/or be my guest at looking into it!)

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:06 Comment from MrFeinberg, 2009-02-20 11:40

In your code, aren't you setting the camera after you've finished drawing? That's likely to cause erratic behavior.

In my mental model, there's a "world space", in which one places vertices. Then when rendering, one applies some transforms that we call "the camera" when rasterizing. In my (obviously wrong) model, "modelX" is independent of whatever "camera" transforms are currently in effect; there's a separate reality to model space, and moving the camera shouldn't change what's returned by modelX().

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:07 Comment from jungalero, 2009-02-20 11:56

This is the exact thinking that caused me to file this bug in the first place and in my mind it's still broken, but I've obviously done a poor job of articulating it. I don't understand why where I'm looking from (camera position) should have any effect on modelx/y/z. If I put one box inside another, it should always be there no matter where I'm standing when I look at it.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:07 Comment from fry, 2009-03-03 06:45

k, sounds like something is still off and i'll need to take a closer look. i'll be doing some hacking on the graphics side later this week so i'll try and sneak this in along with that. it sounds like at the minimum, we're not explaining properly how a camera works, but i wouldn't be surprised if there's something broken in there as well.

in the meantime, the primary matrix that you're working with is both the model and the view (camera). so the modelX/Y/Z functions should be removing the view (camera) portion, so that values that come back allow you to realign objects back in space next to things that are already rendered. but from jdf's description it sounds like that's still not quite working.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:08 Comment from kof, 2009-04-03 05:41

Hello there, I also found the modelX,modelY.. as broken, if it can help, sending definite bug example of its behavior, example is running processing 1.0.1, so sorry if it has been fixed yet.

there is a code: [code] ... pushMatrix();

    translate(x,y);
    for(int i = 0;i<loms.length;i++){

            xes[i]=modelX(0,0,0);
        if(keyPressed) //just by reading modelY.. value of modeX is affected !!!
            yes[i]=modelY(0,0,0);

        translate(0,-step);

        ry+=step;

        rotate(radians(loms[i]));
        line(0,0,0,-step);
    }
    popMatrix();

    stroke(200,0,0);
    for(int i =0;i<xes.length;i++)
        point(xes[i],height-i);

... [/code]

(In reply to comment #13)

      Additional Comment #13 From
      fry
      2009-03-03 06:45 

      <!-- 
        addReplyLink(13); //-->[reply]

  k, sounds like something is still off and i'll need to take a

closer look. i'll be doing some hacking on the graphics side later this week so i'll try and sneak this in along with that. it sounds like at the minimum, we're not explaining properly how a camera works, but i wouldn't be surprised if there's something broken in there as well.

in the meantime, the primary matrix that you're working with is both the model and the view (camera). so the modelX/Y/Z functions should be removing the view (camera) portion, so that values that come back allow you to realign objects back in space next to things that are already rendered. but from jdf's description it sounds like that's still not quite working.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:08 Comment from kof, 2009-04-03 05:44

Created an attachment (id=314) correct behaviour if only modelX is called

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:09 Comment from kof, 2009-04-03 05:47

Created an attachment (id=315) this happens when just modelY is called from whitin push/popMatrix

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:10 Comment from kof, 2009-04-13 04:58

Huge apologize for messing with your bug database, please ignore my comments here, it is complete piece of crap. Kof

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:10 Comment from Noah Z., 2009-12-08 10:59

Was just wondering if there's been any progress made on this problem? It isn't mentioned in any v1.0.x Release Notes, and I was wondering if it had dropped off the radar. I really, really want to use some of the 1.0 features (and be able to give out my sketch to people without asking them to do their own build of a legacy version), but my app is unusable because of this huge bug.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:11 Comment from fry, 2009-12-09 08:38

No, I've not personally had time to fix it, and nobody else has given it a shot.

processing-bugs commented 11 years ago

From b...@processing.org on June 07, 2010 01:11:11 Comment from Seattle BRJ, 2010-05-06 13:21

(In reply to comment #20)

I think this problem is more general. The following sketch uses no camera, but produces incomprehensible results. It is trying to rotate one end or a line around the other, rotating around the z-axis.

float spx,spy,spz, fpx,fpy,fpz; // view vector coords float[][] m = new float[4][4]; float a;

void setup(){ size(600,400,P3D); noLoop(); spx = 0.; spy = 0.; spz = 0.; // values to edit & test with fpx = 100.; fpy = 0.; fpz = 0.; a = PI/4.;

// DIY version of Z-rotation

for(int i=0;i<4;i++ ){ // zero it for(int j=0;j<4;j++ ){ m[i][j]=0.0; } } for(int i=0;i<4;i++ ){m[i][i]=1.0;} // identity m[0][0]= cos(a); // rotation about z m[0][1]=-sin(a); m[1][0]= sin(a); m[1][1]= cos(a);

println("DIY matrix"); for(int i=0;i<4;i++) println(m[i][0]+" "+m[i][1]+" "+m[i][2]+" "+m[i][3] ); // print it println(); }

void draw(){ resetMatrix(); rotateZ( a ); println("Processing's 'printMatrix()'"); printMatrix();

println("Note! Same values as DIY matrix");

fpx = 100.; fpy = 0.;
fpz = 0.;

float tx,ty,tz; tx = modelX((fpx-spx),(fpy-spy), (fpz-spz) ); ty = modelY((fpx-spx),(fpy-spy), (fpz-spz) ); tz = modelZ((fpx-spx),(fpy-spy), (fpz-spz) );

println(" FP becomes "+tx+", "+ty+", "+tz );

fpx = 100.; fpy = 0.;
fpz = 0.;

float cx = m[0][0](fpx-spx)+m[0][1](fpy-spy)+m[0][2]_(fpz-spz)+m[0][3]1.0; float cy = m[1][0](fpx-spx)+m[1][1](fpy-spy)+m[1][2](fpz-spz)+m[1][3]1.0; float cz = m[2][0](fpx-spx)+m[2][1](fpy-spy)+m[2][2](fpz-spz)+m[2][3]_1.0;

println(" FP should be "+cx+", "+cy+", "+cz ); }

processing-bugs commented 11 years ago

From sca...@gmail.com on June 17, 2012 04:59:19 I don't think this is necessarily a bug; just unintuitive behavior and a poorly designed split between the camera and model matrices in Processing.

The way it currently works is: modelX(v) = inv(C) * E * v

where C is the camera matrix, E is the current modelview matrix, and v is the supplied point in object space. Usually, E = C M, where M is the set of transformations applied outside of beginCamera()/endCamera().

So, in BRJ's comment #20, you can get consistent results if you start draw() with: beginCamera(); resetMatrix(); endCamera();

The default camera setup is not the identity matrix. Print it with: ((PGraphics3D) this.g).camera.print(); This accounts for the disparity in the two FPs.

When you resetMatrix() outside a beginCamera block, you're still nuking the entire modelview, so C becomes irrelevant, and yet inv(C) is still used when calculating modelX(). Furthermore, since the "model" space is not independent of the camera, people are going to get weird results when they try to do intuitive things like point cameras at coordinates retrieved with modelX() etc, as jungalero did in the original report.

This is complicated by a poor API that doesn't allow the camera matrix to be post-multiplied: camera() resets the modelview and the camera matrix, and beginCamera() transforms are pre-multiply only.

Better documentation could alleviate this to some extent: it needs to be clear that modelspace is relative to the camera at the time of construction. An alternative to beginCamera() that made transforms post-multiply would allow something like:

popMatrix(); // modelview = C editCamera(); camera(ex, ey, ez, cx, cy, cz, ux, uy, uz); // like gluLookAt rotateY(theta); // post-multiplies endEditCamera(); // modelview = C'

processing-bugs commented 11 years ago

From andres.c...@gmail.com on June 20, 2012 20:14:25 Hello, the camera not being reset in resetMatrix() is a valid point. The best solution I was able to come up to take care of this issue consists of: 1) set camera/cameraInv to identity in resetMatrix, 2) add a camera stack so the current camera matrix is saved/restored when calling pushMatrix/popMatrix.

The code snippets that people posted throughout this thread, which I repeat below for reference:

////////////////////////////////////////////////////// // Cubes void setup() { size(500, 500, P3D); noFill(); }

void draw() { background(0);

pushMatrix(); // start at the middle of the screen translate(width/2, height/2);
// some random rotation to make things interesting rotateY(1.0); //yrot); rotateZ(2.0); //zrot); // rotate in X a little more each frame rotateX(frameCount / 100.0); // offset from center translate(0, 150, 0);

// draw a white box outline at (0, 0, 0) stroke(255); box(50);

// the box was drawn at (0, 0, 0), store that location float x = modelX(0, 0, 0); float y = modelY(0, 0, 0); float z = modelZ(0, 0, 0); // clear out all the transformations popMatrix();

// draw another box at the same (x, y, z) coordinate as the other pushMatrix(); translate(x, y, z); stroke(255, 0, 0); box(50); popMatrix();

//Try to aim a camera at that point and everything explodes camera(width/2, height/2, height/2, x, y, z, 0, 1, 0); }

////////////////////////////////////////////////////// // Crosses void setup() { size(320,240,P3D); noFill(); }

void draw() { float eyeX, eyeY, eyeZ;

pushMatrix(); translate(160, 160); box(50,10,10);

eyeX = modelX(0,0,0); eyeY = modelY(0,0,0); eyeZ = modelZ(0,0,0);

//Correctly prints 160.0,160.0,0.0 the first time //Subsequent loops print weird stuff like 160.0,115.894684,31.789322 println(eyeX + "," + eyeY + "," + eyeZ);

popMatrix();

pushMatrix(); translate(eyeX, eyeY, eyeZ); box(10,50,10); popMatrix();

//Nothing fancy here, I'm just trying to point the camera at the cubes //It doesn't make sense to me that pointing the camera would ruin modelX/Y/Z camera(width/2, height/2, height/2, eyeX, eyeY, eyeZ, 0, 1, 0); }

////////////////////////////////////////////////////// // DIYMat float spx,spy,spz, fpx,fpy,fpz; // view vector coords float[][] m = new float[4][4]; float a;

void setup(){ size(600,400,P3D); noLoop(); spx = 0.; spy = 0.; spz = 0.; // values to edit & test with fpx = 100.; fpy = 0.; fpz = 0.; a = PI/4.;

// DIY version of Z-rotation

for(int i=0;i<4;i++ ){ // zero it for(int j=0;j<4;j++ ){ m[i][j]=0.0; } } for(int i=0;i<4;i++ ){m[i][i]=1.0;} // identity m[0][0]= cos(a); // rotation about z m[0][1]=-sin(a); m[1][0]= sin(a); m[1][1]= cos(a);

println("DIY matrix"); for(int i=0;i<4;i++) println(m[i][0]+" "+m[i][1]+" "+m[i][2]+" "+m[i][3] ); // print it println(); }

void draw(){ resetMatrix(); rotateZ( a ); println("Processing's 'printMatrix()'"); printMatrix();

println("Note! Same values as DIY matrix");

fpx = 100.; fpy = 0.;
fpz = 0.;

float tx,ty,tz; tx = modelX((fpx-spx),(fpy-spy), (fpz-spz) ); ty = modelY((fpx-spx),(fpy-spy), (fpz-spz) ); tz = modelZ((fpx-spx),(fpy-spy), (fpz-spz) );

println(" FP becomes "+tx+", "+ty+", "+tz );

fpx = 100.; fpy = 0.;
fpz = 0.;

float cx = m[0][0](fpx-spx)+m[0][1](fpy-spy)+m[0][2]_(fpz-spz)+m[0][3]1.0; float cy = m[1][0](fpx-spx)+m[1][1](fpy-spy)+m[1][2](fpz-spz)+m[1][3]1.0; float cz = m[2][0](fpx-spx)+m[2][1](fpy-spy)+m[2][2](fpz-spz)+m[2][3]_1.0;

println(" FP should be "+cx+", "+cy+", "+cz ); }

appear to work without problems now, using r9752.

github-actions[bot] commented 3 years ago

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.