C++: Rotate vector around normal of plane - c++

I'm trying to rotate a point on a plane around the normal of the plane with a certain angle (so it stays on the plane).
For example:
Point = (0,0,1) (on the plane)
Normal = (0,1,0)
Angle = 33 degrees
But can't seem to figure out how to do it
EDIT:
The axis of rotation always passes through the origin (0,0,0)

If you're looking for axis-angle rotations in 3-space, Rodrigues's Rotation Formula is very useful. The Wikipedia page is pretty good: here

Probably not optimal, but: find the span vectors of the plane (call them U and V), express the point P in terms of U and V and apply 2D rotation. PS: a normal does not fully define a plane; you need at least a point in the plane in addition.

To compute the rotation matrix you want, you will need a bit of linear algebra. There is an article on Wikipedia which explains what you need to do.

Related

Rotating plane such that it has a certain normal vector

I've got the following problem:
In 3D there's a vector from fixed the center of a plane to the origin. This plane has arbitrary coordinates around this center thus its normal vector is not necessarily the mentioned vector. Therefore I have to rotate the plane around this fixed center such that the mentioned vector is the plane's normal vector.
My first idea was to compute the angle between the vector and the normal vector, but the problem then is how to rotate the plane.
Any ideas?
A plane is a mathematical entity which satisfies the following equation:
Where n is the normal, and a is any point on the plane (in this case the center point as above). It makes no sense to "rotate" this equation - if you want the plane to face a certain direction, just make the normal equal to that direction (i.e. the "mentioned" vector).
You later mentioned in the comments that the "plane" is an OpenGL quad, in which case you can use Quaternions to compute the rotation.
This Stackoverflow post tells you how to compute the rotation quaternion from your current normal vector to the "mentioned" vector. This site tells you how to convert a quaternion into a rotation matrix (whose dimensions are 3x3).
Let's suppose the center point is called q, and that the rotation matrix you obtain has the following form:
This can only rotate geometry about the origin. A rotation about a general point requires a 4x4 matrix (what OpenGL uses), which can be constructed as follows:

Calculating the perspective projection matrix according to the view plane

I'm working with openGL but this is basically a math question.
I'm trying to calculate the projection matrix, I have a point on the view plane R(x,y,z) and the Normal vector of that plane N(n1,n2,n3).
I also know that the eye is at (0,0,0) which I guess in technical terms its the Perspective Reference Point.
How can I arrive the perspective projection from this data? I know how to do it the regular way where you get the FOV, aspect ration and near and far planes.
I think you created a bit of confusion by putting this question under the "opengl" tag. The problem is that in computer graphics, the term projection is not understood in a strictly mathematical sense.
In maths, a projection is defined (and the following is not the exact mathematical definiton, but just my own paraphrasing) as something which doesn't further change the results when applied twice. Think about it. When you project a point in 3d space to a 2d plane (which is still in that 3d space), each point's projection will end up on that plane. But points which already are on this plane aren't moving at all any more, so you can apply this as many times as you want without changing the outcome any further.
The classic "projection" matrices in computer graphics don't do this. They transfrom the space in a way that a general frustum is mapped to a cube (or cuboid). For that, you basically need all the parameters to describe the frustum, which typically is aspect ratio, field of view angle, and distances to near and far plane, as well as the projection direction and the center point (the latter two are typically implicitely defined by convention). For the general case, there are also the horizontal and vertical asymmetries components (think of it like "lens shift" with projectors). And all of that is what the typical projection matrix in computer graphics represents.
To construct such a matrix from the paramters you have given is not really possible, because you are lacking lots of parameters. Also - and I think this is kind of revealing - you have given a view plane. But the projection matrices discussed so far do not define a view plane - any plane parallel to the near or far plane and in front of the camera can be imagined as the viewing plane (behind the camere would also work, but the image would be mirrored), if you should need one. But in the strict sense, it would only be a "view plane" if all of the projected points would also end up on that plane - which the computer graphics perspective matrix explicitely does'nt do. It instead keeps their 3d distance information - which also means that the operation is invertible, while a classical mathematical projection typically isn't.
From all of that, I simply guess that what you are looking for is a perspective projection from 3D space onto a 2D plane, as opposed to a perspective transformation used for computer graphics. And all parameters you need for that are just the view point and a plane. Note that this is exactly what you have givent: The projection center shall be the origin and R and N define the plane.
Such a projection can also be expressed in terms of a 4x4 homogenous matrix. There is one thing that is not defined in your question: the orientation of the normal. I'm assuming standard maths convention again and assume that the view plane is defined as <N,x> + d = 0. From using R in that equation, we can get d = -N_x*R_x - N_y*R_y - N_z*R_z. So the projection matrix is just
( 1 0 0 0 )
( 0 1 0 0 )
( 0 0 1 0 )
(-N_x/d -N_y/d -N_z/d 0 )
There are a few properties of this matrix. There is a zero column, so it is not invertible. Also note that for every point (s*x, s*y, s*z, 1) you apply this to, the result (after division by resulting w, of course) is just the same no matter what s is - so every point on a line between the origin and (x,y,z) will result in the same projected point - which is what a perspective projection is supposed to do. And finally note that w=(N_x*x + N_y*y + N_z*z)/-d, so for every point fulfilling the above plane equation, w= -d/-d = 1 will result. In combination with the identity transform for the other dimensions, which just means that such a point is unchanged.
Projection matrix must be at (0,0,0) and viewing in Z+ or Z- direction
this is a must because many things in OpenGL depends on it like FOG,lighting ... So if your direction or position is different then you need to move this to camera matrix. Let assume your focal point is (0,0,0) as you stated and the normal vector is (0,0,+/-1)
Z near
is the distance between focal point and projection plane so znear is perpendicular distance of plane and (0,0,0). If assumption is correct then
znear=R.z
otherwise you need to compute that. I think you got everything you need for it
cast line from R with direction N
find closest point to focal point (0,0,0)
and then the z near is the distance of that point to R
Z far
is determined by the depth buffer bit width and z near
zfar=znear*(1<<(cDepthBits-1))
this is the maximal usable zfar (for mine purposes) if you need more precision then lower it a bit do not forget precision is higher near znear and much much worse near zfar. The zfar is usually set to the max view distance and znear computed from it or set to min focus range.
view angle
I use mostly 60 degree view. zang=60.0 [deg]
Common males in my region can see up to 90 degrees but that is peripherial view included the 60 degree view is more comfortable to view.
Females have a bit wider view ... but I did not heard any complains from them on 60 degree views ever so let assume its comfortable for them too...
Aspect
aspect ratio is determined by your OpenGL window dimensions xs,ys
aspect=(xs/ys)
This is how I set the projection matrix:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(zang/aspect,aspect,znear,zfar);
// gluPerspective has inacurate tangens so correct perspective matrix like this:
double perspective[16];
glGetDoublev(GL_PROJECTION_MATRIX,perspective);
perspective[ 0]= 1.0/tan(0.5*zang*deg);
perspective[ 5]=aspect/tan(0.5*zang*deg);
glLoadMatrixd(perspective);
deg = M_PI/180.0
perspective is projection matrix copy I use it for mouse position conversions etc ...
If you do not correct the matrix then you will be off when using advanced things like overlapping more frustrum to get high precision depth range. I use this to obtain <0.1m,1000AU> frustrum with 24bit depth buffer and the inaccuracy would cause the images will not fit perfectly ...
[Notes]
if the focal point is not really (0,0,0) or you are not viewing in Z axis (like you do not have camera matrix but instead use projection matrix for that) then on basic scenes/techniques you will see no problem. They starts with use of advanced graphics. If you use GLSL then you can handle this without problems but fixed OpenGL function can not handle this properly. This is also called PROJECTION_MATRIX abuse
[edit1] few links
If your view is standard frustrum then write the matrix your self gluPerspective otherwise look here Projections for some ideas how to construct it
[edit2]
From your comment I see it like this:
f is your viewing point (axises are the global world axises)
f' is viewing point if R would be the center of screen
so create projection matrix for f' position (as explained above), create transform matrix to transform f' to f. The transformed f must have Z axis the same as in f' the other axises can be obtained by cross product and use that as camera or multiply booth together and use as abused Projection matrix
How to construct the matrix is explained in the Understanding transform matrices link from my earlier comments

equation of a horizontal plane

I am having a constructor for a Plane using vector3d and position3d. I want to get horizontal plane at a desired height (say z1). So, I think my plane normal should be (0,0,1). I don't have any other information.
Plane::Plane(const position3d &point, const vector3d &normal)
I am now really confusing what would be my plane as I am thinking how should I give the position3d only with that Z1.
quick help soon. thanks..
Your position needs to be a point in the plane, no matter which.
Since you said its parallel to XY, you can choose x and y in the position3d arbitrarily.
position3d(0,0,z1);
normal(0,0,1);
would do the job just fine. Note that you can choose n and m randomly to create position3d(n,m,z1), and still get the same plane.
point can be any point on the plane, for instance (0,0,Z1).
A plane can be determined by either 3 points in the space, or a point in the space and a normal (a normalized vector) indicate the direction perpendicular to the plane. In your Plane function, it uses the later definition. So you need to give the point (for example, a point at (0,0,z1)) and the vector (0,0,1) for the Z-axis.

How to check if a point is inside a quad in perspective projection?

I want to test if any given point in the world is on a quad/plane? The quad/plane can be translated/rotated/scaled by any values but it still should be able to detect if the given point is on it. I also need to get the location where the point should have been, if the quad was not applied any rotation/scale/translation.
For example, consider a quad at 0, 0, 0 with size 100x100, rotated at an angle of 45 degrees along z axis. If my mouse location in the world is at ( x, y, 0, ), I need to know if that point falls on that quad in its current transformation? If yes, then I need to know if no transformations were applied to the quad, where that point would have been on it? Any code sample would be of great help
A ray-casting approach is probably simplest:
Use gluUnProject() to get the world-space direction of the ray to cast into the scene. The ray's origin is the camera position.
Put this ray into object space by transforming it by the inverse of your rectangle's transform. Note that you need to transform both the ray's origin point and direction vector.
Compute the intersection point between this ray and the XY plane with a standard ray-plane intersection test.
Check that the intersection point's x and y values are within your rectangle's bounds, if they are then that's your desired result.
A math library such as GLM will be very helpful if you aren't confident about some of the math involved here, it has corresponding functions such as glm::unProject() as well as functions to invert matrices and do all the other transformations you'd need.

Find nearest rotation for cube

I have camera that look at cube from above. I can rotate cube so cube can have rotation values like z=258.18594 x=1. I need advice how to get nearest rotation with cube stand on ground and camera see top face.
Look for Quaternion mathematics and Quaternion interpolation. This will make the task rather easy.
See also Nearest Neighbours using Quaternions