Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411490 Posts in 69371 Topics- by 58428 Members - Latest Member: shelton786

April 25, 2024, 01:57:34 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Custom 3D engine: rotating objects relative to screen plane
Pages: [1]
Print
Author Topic: Custom 3D engine: rotating objects relative to screen plane  (Read 1275 times)
Darth_Dan
Level 0
**


View Profile
« on: November 13, 2018, 02:11:53 PM »

Hi everyone!

I'm currently working on a programming project which involves a simple 3D renderer/engine, which displays a series of objects relative to a known point. I want to be able to drag, zoom and rotate the objects with my mouse. So far I've been able to implement zoom and drag, but I'm stuck with rotation.

I just don't understand how should I transform my mouse input into angular shifts, especially since I have 2 values available from mouse and 3 angular value that I need to change. I'm using 3 angular values (angle_x, angle_y and angle_z) to calculate rotation for the sake of mathematical simplicity (in other words I don't want to bother with quaternions  Wink).

Does anyone have experience in this area? Or understand the maths? Please help me or point me in the right direction.))
Logged
qMopey
Level 6
*


View Profile WWW
« Reply #1 on: November 13, 2018, 03:28:43 PM »

You should try out Maya or something to see how they rotate things in 3D. My friend Dimitri implemented 3D object manipulation widgets and hosted the code on Github: https://github.com/ddiakopoulos/tinygizmo

The rough idea I would go with, is to raycast along the view vector through the mouse coordinate projected onto the near plane, and compute the closest point on that ray to a 3D circle. You can track an angle delta from that original closest point, to any new closest point as the mouse moves.
Logged
Darth_Dan
Level 0
**


View Profile
« Reply #2 on: November 13, 2018, 04:13:35 PM »

I have no planes there as of right now. And I've used many 3D modelling programs, I know what you're talking about. But not the maths behind them...

What do you mean under a "3d circle"?
Logged
Darth_Dan
Level 0
**


View Profile
« Reply #3 on: November 13, 2018, 04:16:26 PM »

Seen your link... No, that is not what I'm trying to do. These things obstruct the view. In the same 3ds Max (assume the same is true for Maya) you can just drag with your MMB on a random point on screen, and everything will rotate...
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #4 on: November 13, 2018, 07:07:48 PM »

(in other words I don't want to bother with quaternions  Wink).

Bothering with quaternions is likely to be a lot less trouble than trying to make this work with Euler angles. Once you get past a certain threshold of complexity, Euler angles become a huge headache. Is there anything in particular stopping you from using quaternions? The internals of quaternion math might be kind of opaque, but a perfectly understandable API can be easily built on top of them.
Logged

d.c.elington
Level 0
*


View Profile
« Reply #5 on: November 13, 2018, 11:58:53 PM »

Sorry if this is a naive suggestion but can you combine the mouse inputs with additional keys or buttons?
For instance: right button to engage [yaw <-> x mouse motion] + [pitch <-> y mouse motion] rotation, ctrl + right button for [roll <-> x mouse motion]. Typically you would use the button / key down event to capture the current mouse position and use it as a reference point to compute the angles.
Logged
Daid
Level 3
***



View Profile
« Reply #6 on: November 14, 2018, 12:59:10 AM »

Does anyone have experience in this area? Or understand the maths? Please help me or point me in the right direction.))
Yes! Got experience here.

Quaternions are your friend. You don't need to understand the math behind it. Just the usage. Quaternions simply represent a rotation, and you can rotate that rotation by multiplying two quaternions. How does that works on the math side? No clue, magic. Who cares. You just want to use it.
So represent your objects rotation as a quaternion.

Next, on mouse movement, use the X and Y movement of the mouse to construct 2 quaternions to multiply the rotation of the object with that, for example, with my personal Quaternion class:

Code:
obj.rotation = obj.rotation * Quaternionf::fromAxisAngle(Vector3(1, 0, 0), mouse.delta_x) * Quaternionf::fromAxisAngle(Vector3(0, 1, 0), mouse.delta_y);

I could be wrong on the axis, and maybe the axis should be in camera space. But I think this will give you full rotation control over the object.

Only other piece of code you need is converting the Quaternion to a 4x4 matrix so you can use it for rendering easier:
https://github.com/daid/SeriousProton2/blob/master/include/sp2/math/matrix4x4.h#L49



HOWEVER!
Generally people don't really want full control. They generally want to rotate along the plane of your game (yaw) and some pitch. In which case, you might just want just yaw and pitch controls and forget about roll.
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
Darth_Dan
Level 0
**


View Profile
« Reply #7 on: November 14, 2018, 02:38:33 AM »

Sorry if this is a naive suggestion but can you combine the mouse inputs with additional keys or buttons?
For instance: right button to engage [yaw <-> x mouse motion] + [pitch <-> y mouse motion] rotation, ctrl + right button for [roll <-> x mouse motion].

Of course I'm doing that! But you are probably thinking about rotating a first-person camera, while in my case, "camera" (viewport) is static, and I'm roting a certain object around its point of origin.

Is there anything in particular stopping you from using quaternions?

Understandability. For me a quaternion is an abstract mathematical obect, while an angle has a real imagineable representation.

You don't need to understand the math behind it. Just the usage. Quaternions simply represent a rotation, and you can rotate that rotation by multiplying two quaternions. How does that works on the math side? No clue, magic. Who cares. You just want to use it.

Who cares? I do. I'm that kind of weirdo who wants to know exactly what is going on in my program. I will not content with putting a random piece of code in there "because it works". I did so in my early days, but now I want a different approach.
Tried to understand quaternions once. Got a headache and some basic maths concepts, forgot everything else. I will try again one day. Just not today.

For now I'd like to get a solution for my situation. I have no problem with rotating in absolute angles (x,y,z). I just somehow need to figure out how to transform mouse input into relative angles. Ever used a 3D modeller/viewer? Remember how you can spin the view in the viewport around? That's what I want.

Quote
HOWEVER!
Generally people don't really want full control. They generally want to rotate along the plane of your game (yaw) and some pitch. In which case, you might just want just yaw and pitch controls and forget about roll.

Generally people think in two dimensions, you want to say  Cheesy Wink
Not me. I think in 3 dimensions. If I have roll in real life, why should I forget about it in my games?

What you described matches a description of a first- or a third person game where character/objects are located on a terrain with stable, unchanging gravity. Gravity basically describes our sense of "down", which in games we usually show as camera roll. Ground above my head? I'm probably upside down.
This is all irrelevant if we are talking about deep space. Or about a 0g environment. There is no up and down in space combat, on a starmap or inside a 21-century -ish space station. In other words, I love my roll. I need my roll.
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #8 on: November 14, 2018, 06:37:19 AM »

Who cares? I do. I'm that kind of weirdo who wants to know exactly what is going on in my program. I will not content with putting a random piece of code in there "because it works". I did so in my early days, but now I want a different approach.
Tried to understand quaternions once. Got a headache and some basic maths concepts, forgot everything else. I will try again one day. Just not today.

I've been there too. What helped me get comfortable with the innards of quaternions was to just copy the magic formulas and use them for a while, study their observable behavior, read over the implementation a few times with the basis of understanding of what the results of the functions look like, and rewrite it with my own variable names and syntax. It might seem backward, and it'll be uncomfortable for a while, but the results were totally worth it for me.

Are you familiar with gimbal lock? The real issue I see with Euler angles is how unintuitive and messy they get for certain operations. From certain orientations, in order to change what seems like it should be just one axis of rotation, you'll need to completely recalculate the other two values from a different perspective. This ends up being a lot more complicated than using a different system entirely. I was never able to solve it, and switching to quaternions saved me from attempting something that was ultimately much harder and less flexible.

Also, I haven't read this article in detail, but here's a possible alternative: http://marctenbosch.com/quaternions/

Another alternative is to use a 3x3 or 4x4 matrix if you're more comfortable with those.
Logged

Crimsontide
Level 5
*****


View Profile
« Reply #9 on: November 14, 2018, 07:34:28 AM »

When trying to understand quaternions, you have to realize that they're taught very poorly in online material.

They always start with imaginary numbers, and then try to show how quaternions are some extension of them.  They're not.  They share similar properties, and if you have a math background the intuition from working with imaginary numbers might serve you well here.  But they are not related to imaginary numbers, and you don't need to understand imaginary numbers to understand quaternions.  Once I realized this, I found it much easier.

Basically a quaternion is an axis to rotate around, and the amount to rotate, stored in a 'compact' and 'mathematically special' way.  To be more precise, its mapped to a 4D hypersphere (if you look up quaternion and hypersphere you'll come up with many examples showing this mapping).  So you can convert any axis+rotation to a quaternion, and back.  While in quaternion form operations become very simple, stupidly so in many cases.  You can find all the operations and their implementations everywhere online.

Quaternions are pretty straightforward to use, even if you don't completely understand them.
Logged
Daid
Level 3
***



View Profile
« Reply #10 on: November 14, 2018, 12:13:47 PM »

Who cares? I do. I'm that kind of weirdo who wants to know exactly what is going on in my program. I will not content with putting a random piece of code in there "because it works". I did so in my early days, but now I want a different approach.
Tried to understand quaternions once. Got a headache and some basic maths concepts, forgot everything else. I will try again one day. Just not today.
Ah, but you can never really understand every single bit. Do you know how your code is translated into machine instructions? And how those instructions are really then turned into microcode?, and at some point they become really logical levels in transistors?, which are actually analog levels switching really fast?, and saturating transistors. And a transistor is really actually a current amplifier?
(Ignoring a few levels of things here, like the CPU pipeline, memory, caches, etc...)


Do you think about how the binary representation of a floating point number is done? I see a Quaternion the same way. It's something that is represented with 4 floats. Just like a float is represented with 32 or 64 bits of memory.
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
Darth_Dan
Level 0
**


View Profile
« Reply #11 on: November 14, 2018, 12:58:49 PM »

You all seem really intent on forcing me to learn quaternions, and thank those of you who actually shared some material, but you really are avoiding the question...
You know, give me explanation in your beloved quaternions, I might be able to translate it to myspeak...

I CAN rotate stuff. Around any axis I want, by any angle I want. BUT. HOW DO I TRANSFORM MOUSE INPUT INTO ROTATION INPUT???
Right now I tied x rotation with y axis and y rotation with x axis. It's fine for the first grab and drag, but after that you may want to start dragging in a different orientation and ACTUALLY ROTATE AROUND z axis!!!
How do I know what proportion of mouse input goes toward which axis at this point?

Are you familiar with gimbal lock?

Heard of it. But only in terms of mechanics. I don't see how that concept would be relevant in virtual world.

Quote
Another alternative is to use a 3x3 or 4x4 matrix if you're more comfortable with those.

I'm using a 3x3 rotation matrix at the moment. Works fine for me.

When trying to understand quaternions, you have to realize that they're taught very poorly in online material.

I had a person explain that to me. She started with imaginary numbers too, and that was important for me to realise that it does not matter.

Quote
Quaternions are pretty straightforward to use, even if you don't completely understand them.

I am NOT looking for "straightforward to use". I'm looking for "understandable enough to dissect and rebuild into something new".

Ah, but you can never really understand every single bit. Do you know how your code is translated into machine instructions? And how those instructions are really then turned into microcode?, and at some point they become really logical levels in transistors?, which are actually analog levels switching really fast?, and saturating transistors. And a transistor is really actually a current amplifier?
(Ignoring a few levels of things here, like the CPU pipeline, memory, caches, etc...)

That isn't really going on in my program. It happens in the compiler and the hardware. In these levels it is enough for me to know it DOES these things. To know where to go next once I master the higher level.

Quote
Do you think about how the binary representation of a floating point number is done? I see a Quaternion the same way. It's something that is represented with 4 floats. Just like a float is represented with 32 or 64 bits of memory.

I sometimes wonder how do you represent the point in that floating point number... Is it a separate byte which stores the point position?... Or is that byte really a binary exponent for all the rest? One day this will start bugging me enough to actually look it up. It does not yet.

32 or 64 bits of 1s and 0s don't really mean ANYTHING to my human brain. 4 or 8 bytes in decimal or hexadecimal mean just that - they are numbers. Meaningless until you use them to describe something. Something like an angle. Or a distance. I'm sure the same is true with quaternions...
Logged
qMopey
Level 6
*


View Profile WWW
« Reply #12 on: November 14, 2018, 02:00:44 PM »

I CAN rotate stuff. Around any axis I want, by any angle I want.

I already answered this question with the 3D circle example. The circles would be a circle around your object on the X, Y or Z axes. When the user makes a click, cast a ray in the direction of their mouse click in object-space. To do this you need a function that takes your screen position and transforms it into world position. Here is an example. Here is an explanation.

When you click, compute the closest point from the mouse ray to any given circle. To be clear, these are the circles that work well for 3D manipulation:



This point can be named A. Then, as the user continues holding down the mouse button, continue computing the closest point from the mouse ray to the *same circle* that A corresponds to. The new point is called B. We know the object's center, since it's a given. Now compute the angle from A to center to B. Cross A and B. You now have an axis and an angle. Construct your rotation with an axis/angle construction function, and you have your desired rotation.

Yet another way to build a rotation manipulator is to forget circles and use a sphere. Use the same algorithm as above, but compute the intersection from mouse ray to the object's circle. You can find points A and B, compute an angle between them along with an axis of rotation. You will need to handle the special case of the ray missing the sphere. There are many good ways to handle this. One way is to compute the closest points between the ray and the sphere.

Here is code for the sphere manipulator by Stan Melax. Stan wrote an article all about it in Game Programming Gems. Many of Stan's examples use this function. You can download his samples and build them and try it out-of-the-box. Just do a search to find them all.

Also you have a poor learning and forum attitude. You're lucky the question you asked is interesting.
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #13 on: November 14, 2018, 02:04:16 PM »

I CAN rotate stuff. Around any axis I want, by any angle I want. BUT. HOW DO I TRANSFORM MOUSE INPUT INTO ROTATION INPUT???

Oh gotcha, I may have misunderstood your initial question. Here's how I implement mouselook:

Code:
void mouselook(float offsetX, float offsetY) {
Quaternionf_rotate(&cameraDirection, VECTOR3f_UP, offsetX * ROTATIONAL_SENSITIVITY);
Quaternionf_rotate(&cameraDirection, Quaternionf_multiplyVector3f(Quaternionf_inverted(cameraDirection), VECTOR3f_RIGHT), offsetY * ROTATIONAL_SENSITIVITY);
}

Arguments are mouse position x and y deltas in pixels; ROTATIONAL_SENSITIVITY is set to 0.0078125f in my test application. Not sure how I arrived at that number, but it feels pretty good to me. Tune to your liking. Quaternionf_rotate arguments are target, axis of rotation, angle in radians. The basic premise is to first rotate around a fixed Y axis, then use the inverse of the current orientation to compute an appropriate X axis to rotate around. This doesn't have any limiting built in for looking straight up and down, so you can roll all the way around the focal point.

This exact same set of operations could be applied to your 3x3 matrix instead of a quaternion and it would work the same way. I wouldn't have any idea how to translate this into Euler angles without going through an intermediate quaternion or matrix layer, though. Good luck!

Edit: Here's the quaternion code I use in case it helps. Look in the same directory for its header, and accompanying matrix code if needed: http://ludobloom.com/svn/StemLibProjects/gamemath/trunk/source/gamemath/Quaternionf.c
« Last Edit: November 14, 2018, 02:11:14 PM by ThemsAllTook » Logged

Darth_Dan
Level 0
**


View Profile
« Reply #14 on: November 14, 2018, 02:18:56 PM »

This point can be named A. Then, as the user continues holding down the mouse button, continue computing the closest point from the mouse ray to the *same circle* that A corresponds to. The new point is called B. We know the object's center, since it's a given. Now compute the angle from A to center to B. Cross A and B. You now have an axis and an angle. Construct your rotation with an axis/angle construction function, and you have your desired rotation.

Yet another way to build a rotation manipulator is to forget circles and use a sphere. Use the same algorithm as above, but compute the intersection from mouse ray to the object's circle. You can find points A and B, compute an angle between them along with an axis of rotation. You will need to handle the special case of the ray missing the sphere. There are many good ways to handle this. One way is to compute the closest points between the ray and the sphere.

Thank you, that is the kind of solution I was asking for. First time it felt more like you thought that I need to make a gizmo. I likely misunderstood you.

Quote
Also you have a poor learning and forum attitude. You're lucky the question you asked is interesting.
I dislike learning in a rush and people misunderstanding my questions. The most annoying part was that while I specifically pointed out that I do not wish to use quaternions in this project, suddenly a bunch of people decided to tell me how great quaternions are. And you know, as soon as I'm not on a schedule, I will actually look into that. THese people sounded quite convincing...

Oh gotcha, I may have misunderstood your initial question. Here's how I implement mouselook:

Code:
void mouselook(float offsetX, float offsetY) {
Quaternionf_rotate(&cameraDirection, VECTOR3f_UP, offsetX * ROTATIONAL_SENSITIVITY);
Quaternionf_rotate(&cameraDirection, Quaternionf_multiplyVector3f(Quaternionf_inverted(cameraDirection), VECTOR3f_RIGHT), offsetY * ROTATIONAL_SENSITIVITY);
}

Arguments are mouse position x and y deltas in pixels; ROTATIONAL_SENSITIVITY is set to 0.0078125f in my test application. Not sure how I arrived at that number, but it feels pretty good to me. Tune to your liking. Quaternionf_rotate arguments are target, axis of rotation, angle in radians. The basic premise is to first rotate around a fixed Y axis, then use the inverse of the current orientation to compute an appropriate X axis to rotate around. This doesn't have any limiting built in for looking straight up and down, so you can roll all the way around the focal point.

This exact same set of operations could be applied to your 3x3 matrix instead of a quaternion and it would work the same way. I wouldn't have any idea how to translate this into Euler angles without going through an intermediate quaternion or matrix layer, though. Good luck!

Edit: Here's the quaternion code I use in case it helps. Look in the same directory for its header, and accompanying matrix code if needed: http://ludobloom.com/svn/StemLibProjects/gamemath/trunk/source/gamemath/Quaternionf.c

Thanks a lot for this explanation. One thing is clear for all the examples above: looks like I need to create another set of angles representing my viewport. Will look into it more in depth...
Logged
Crimsontide
Level 5
*****


View Profile
« Reply #15 on: November 14, 2018, 09:00:13 PM »

Also you have a poor learning and forum attitude. You're lucky the question you asked is interesting.

Oh give me a break, he's not intentionally being a jerk.  I can't count the number of times I've asked a question and instead of getting an answer I get a 12-page argument over why I shouldn't do it that way.  He doesn't HAVE to use quaternions; its still a legitimate question.  And insulting someone simply because you don't want to answer their question but would rather answer this new one you came up with... well that's what I would call a poor forum attitude.
Logged
qMopey
Level 6
*


View Profile WWW
« Reply #16 on: November 14, 2018, 09:07:09 PM »

I insulted his attitude, not him. There's a difference  Cool

And sure it's a legit question, that's why I answered it. It's also nice to answer these questions for future people googling around and such.
Logged
Daid
Level 3
***



View Profile
« Reply #17 on: November 17, 2018, 11:45:37 AM »

This exact same set of operations could be applied to your 3x3 matrix instead of a quaternion and it would work the same way.
Except that small rounding errors will accumulate (in both the quaternion and matrix solutions), causing a buildup of error, which can cause skew or scaling problems. And then a quaterion is much easier to normalize then a matrix.
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic