We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello beautiful people,
I have been working with processing for years and still haven't managed to create a nice, simple 3d navigation piece of code. I have tried various methods, including translation/rotation of the scene, as well as use of the camera() function, but no method gives me exactly the type of navigation I want.
That is the ability to pan/rotate/zoom around the center of the scene as it is currently viewed. Here is an example sketch using both methods:
float rotX, rotY, camX, camY, camZ;
void setup()
{
size(600, 600, P3D);
// camX = width /2.0;
// camY = height/2.0;
}
void draw()
{
background(255);
lights();
fill(192);
stroke(0);
//navigation style 1
translate(camX, camY, camZ);
translate(width/2.0-camX, height/2.0-camY);
rotateY(rotY);
rotateX(rotX);
translate(-(width/2.0-camX), -(height/2.0-camY));
//navigation style 2
// float D = (camZ*sin(rotY));
// camera( camX + camZ*sin(rotX), camY + camZ*sin(rotY), camZ*cos(rotY)*cos(rotX), camX ,camY, 0, 0,1,0);
rect(100,100,400,400);
}
void mouseDragged()
{
if (mouseButton == LEFT)
{
//navigation style 1
rotY += (pmouseX - mouseX)*0.01;
rotX += (pmouseY - mouseY)*0.01;
//navigation style 2
// rotX += (mouseX - pmouseX)*0.01;
// rotY += (mouseY - pmouseY)*0.01;
}
if (mouseButton == RIGHT)
{
//navigation style 1
camX -= (pmouseX - mouseX);
camY -= (pmouseY - mouseY);
//navigation style 2
// camX -= (mouseX - pmouseX);
// camY -= (mouseY - pmouseY);
}
if (mouseButton == CENTER)
{
//navigation style 1
camZ += (pmouseY - mouseY);
//navigation style 2
// camZ += (mouseY - pmouseY);
}
}
In the first case, I get the rotation roughly correct (it's not really rotating aligned to the view) but panning doesn't work properly. In the second one, I get panning and one-axis rotation working seemingly ok, but rotation along xgives funny results.
Any help with what seems to me a really trivial problem would be greatly appreciated.
PS: I am not interested in using a library, like PeaseyCam (both for compatibility reasons, as well as educational ones)
Answers
I was hoping for some more interaction on this but just in case, In thought I'd update this..
After all, I've decided to temporarily use the obsessive camera direction library (http://gdsstudios.com/processing/libraries/ocd/) which offers a few very nive implemented ways to control a camera. Most importantly you gan get the camera's position, which was essential in my case, as I wanted to use the camera on an -offscreen- PGraphics..
However, it's still not what I was hoping to get to.
Any ideas would be very welcome.
You can use mouseWheel scroll event for zooming in and out
Reference http://processing.org/reference/mouseWheel_.html
Thanks for the advice blyk. However I am looking more into the problem of navigation. I am surprised that no one has replied on this basic question yet. I suppose this is not a very interesting question.. :(
It's not uninteresting, but it's not really about processing, more about OpenGL. Projections are confusing. First, maybe frustum would give you a definite sense of what your viewpoint is? I'm not an expert in OpenGL, but I would suggest you ask on OpenGL.org where they specialize in this problem which is, after all, not really about Processing at all.
I like your basic concept, that you take deltaX and turn it into a rotation around Y, and deltaY and turn it into a rotation around X.
I find it very interesting and I remember another guy tried something like this
Alas, the maths is over my head.
What I don't like about your approach is the usage of pMouseX and pmouseY. With those you don't have a defined start position you can return to.
Instead I would prefer it if the center of the window would be 0 rotation
go 10 pixels right and he rotates 10 degree right or so
go 10 pixels left from the center and he rotates 10 degree right or so
and same for up and down
Thus a mouse screen pos always results in the same 2 angles...
you could use map or so
Best, Chrisir ;-)
Is the peasycam library any use?
Thanks for all the suggestions.
@hydrodog: Thanks for the OpenGl suggestion, I have indeed looked into the OpenGL projection and transformation matrix but still, I haven't been able to work out a simple version for processing.
Also, I kindly disagree with your suggestion that this is not relevant to processing, as in my experience a good mouse navigation has been needed numerous times.
@koogs of course, peasycam is a very good solution, although it has a couple of drawbacks. First all this lag in dragging which causes issues with sketches that run at lower framerates, but also the inability to rotate properly per axis.
@Chrisir Your suggestion for mapping the rotations to the frame is very interesting and I have also tried that. However my problem is that sometimes you need to be able to finely navigate - eg rotate a very small amount and zoom to a part of the scene - something that I believe would not be possible this way, although I would be very glad to be proven wrong.
Again thank you all for your answers!
PS: I forgot to attach these links for future reference:
http://www.songho.ca/opengl/gl_projectionmatrix.html
http://www.songho.ca/opengl/gl_transform.html
http://www.fastgraph.com/makegames/3drotation/
For 3D navigation I always use ProScene, it gives you a lot of work done and also lets you customize the way you use it. Just take a look at the examples included in the library to see how many things you can do with it.
Thanks, that's also a very good suggestion, I've used ProScene myself occasionally and found it very rich in features, but as mentioned in the question, I am looking for a solution that does not use libraries, both for compatibility and educational reasons.
In terms of compatibility ProScene has been quite error-prone, which I assume is due to its use of an independent renderer from processsing. Although it is rich in features it is also very heavy on the graphic card.
Especially for teaching, I believe it is essential for someone to have complete understanding and control of their code.
Thanks again for the good suggestion though.
Working with 3D is never a trivial exercise. At least I have never found it trivial. :)
Not sure what you mean by compatibility here. When discussing ProScene you talk about being 'error-prone' but PeasyCam is extremely stable.
On the educational side, are you a teacher? Are you teaching 3D manipulation?
The last point is a good one but surely 'their' code could be making use of the PeasyCam, not knowing the inner workings of PeasyCam does not mean they do not fully understand the code they created to make use of PeasyCam. (Unless it is about learning 3D manipulation). After all Processing and Java is just another software layer between us and the CPU, it doesn't mean we have to know all their inner workings. :)
This library uses damped actions to give smoother rotations so there is bound to be some delay with rapid mouse movements. Processing sets the framerate to ~60 fps irrespective of the computer hardware (must either be ancient hardware or very CPU intensive sketch for it to drop below)
depends on the coordinate system chosen, easy for the camera's local space (see below) but extremely difficult using world space.
So going back to your question regarding navigation style - I would go for style 2 i.e. the camera because it is easier to visualise using a camera to move though a 3D scene, rather than standing still and moving the scene round the camera.
In justification of my choice I am going to make some statements /assumptions about how it might work.
The origin of the 3D world is fixed and the position of any objects in the world are defined by their xyz coordinates relative to the world origin.
There would be a simple inner class to represent the camera and it would have a number of PVectors to represent the camera's position, heading, up and side vectors. The 'view' would only be changed through the class members (functions) which would change the PVectors mentioned.
Rotations would be in the camera's local coordinate space so you effectively have pitch, yaw and roll. (The rotations would NOT be about the world axis that would not give the visual effect of moving through the 3D scene)
Zooming would be movement along the heading vector
Panning would be movement along the side vector
Once the camera class has been built then you can experiment with mapping user input to the class methods to get the movement you want.
Actually I wrote such a class once
Maybe I can post it
The disadvantage is that lights() makes the scene dark (or lies in shadows) when the camera is behind the scene (seen from the lights)
The camera rotations for pitch, yaw and roll rotations are relative to the current state of the camera. They are NOT absolute it is important to recalculate the heading, side and up vectors after every rotation. Because PVector uses floats rather than doubles rounding errors can be introduced so the heading, side and up vectors have to be normalised after 20 or so rotations.
I have a camera class that will zoom (move forward/back), pan (move left/right), pitch, yaw and roll. It uses the Rot and Rot order classes from the Shapes3D library but they could easy be copied from the library then there would be no library dependencies. :)
have a look at my cam class
It's taken a while to respond, as I've been a bit snowed under..
So, again, thanks for great suggestions, it has certainly made me think through the problem more in depth than I expected. Specifically:
@Chrisir: thanks a lot for sharing your code! Your camera class is very helpful and if stripped down from the rest of the sketch, it's a nice implementation that uses the core camera function. I will try to find some time to simplify it and repost it soon. One of the issues I think I will still have is that sometimes rotations are not going to happen around the screen, like in a CAD software, but I might be mistaken.
@quark: Thank you a lot for your input! Very interesing points!
Yes, working in 3D is never trivial for me even more. I was suggesing that the navigation issue would be trivial for people with some computer science knowledge, but I am glad to know I am not the only one struggling. :)
PeasyCam is indeed very stable. I've never had a single compatibility problem with it - I was actually refering to ProScene and other camera libraries like the OCD that I have also used.
Yes I am teaching Processing and 3D manipulation, among other things and this is why I want to build a clear, super simple and robust camera class that students will be able to use and understand. But your point is very good indeed. My intention is that students have the ability to tweak the 3D navigation code, as they would be implementing it in different ways in their sketches, but also that they undertstand the inner workings of that camera, reaching as low as they can in the level of the process. Your example with Java and the machine is excellent though and has made me wonder about the validity of my argument, but to justify it I would say that similarly to my interest in understanding the inner works of the virtual machine (up to a point) I would hope that they would like to reach one level down in understanding 3D manipulation. But maybe you are right. Sometimes we just need to do things.
Final point, yes the damped actions are sometimes really hard to control, as the sketches produces are in many cases very CPU intensive (physcis simulation, optimization etc). Also I believe the rotation controls are not covering a CAD style navigation. I am insisting on the CAD style as sometimes we need to restrict rotations along one axis or plane and this is what I think the problem comes down to.
Finally, regarding your suggestion, I think you are right. That it the way to go about it. For all the reasons you mention, plus the fact that rotating/translating the whole scene affects the actual position of all geometry in the scene, which then would create more problems further, down, eg exporting a dxf, writing some vertices out etc..
I have some code that is based on the ocd library, which I will try to post soon. Again, thank you for your input, really appreciated!..
:D
hello,
you wrote
not sure what you mean.
Do you refer to this method within the class ?
It rotates around the camLookAt.You could add
When your scene (or its center) is somewhere else, you need to set camLookAt accordingly (e.g. average of your point cloud or whatever)
BTW
I think btw some functions in my class are not finished yet; e.g. moveParallelRelative and follow.
I enjoyed reading your post btw.
Best, Chrisir ;-)
Hi Chrisir,
Thanks for the reply and again apologies for taking long to reply. I have to fix my notification settings, really..
Yes I meant the rotation happening around the center of the screen. Adding this line sure helps combined also with relevant user input. Overall, I think your class is very good and thanks for sharing it. I am aiming to use it and hopefully come back with additions or more questions.
Thanks for taking the time to read the post and reply. After using processing for five years, it's so good to finally feel the community. :)