Rotate object in world space - Raytracing

Started by
59 comments, last by ellenature 3 years, 8 months ago

I’m programming a C raytracing project.

I’ve been wanting to implement object rotations (square, cylinder) for several days but I can’t do it.

For each object, I have its position (x, y, z) in the world space and its 3d normalized orientation vector.

For the moment, I do nothing more than applying once of the three following functions on the 3d normalized orientation vector. I don’t know if I’m doing it right. Rotation doesn't work well.

For example, I want to rotate my object left with the j key and right with the l key (x_rotation), up with the i key and down with the k key (y_rotation). I'm not sure how to use the z axis.

I'm starting to despair, can you please help me?

I will be very grateful for your help :)

t_vec       x_rotation(t_vec vec, float alpha)
{
   t_vec   res;

   res.x = vec.x;
   res.y = vec.y * cos(alpha) - vec.z * sin(alpha);
   res.z = vec.y * sin(alpha) + vec.z * cos(alpha);
   return (res);
}

t_vec       y_rotation(t_vec vec, float alpha)
{
   t_vec   res;
   
   res.x = vec.z * sin(alpha) + vec.x * cos(alpha);
   res.y = vec.y;
   res.z = vec.z * cos(alpha) - vec.x * sin(alpha);
   return (res);
}

t_vec       z_rotation(t_vec vec, float alpha)
{
   t_vec   res;
   
   res.x = vec.x * cos(alpha) - vec.y * sin(alpha);
   res.y = vec.x * sin(alpha) + vec.y + cos(alpha);
   res.z = vec.z;
   return (res);
}
Advertisement

What is this “3d normalized orientation vector” you speak of? An object's attitude can be represented in several different ways. Some popular choices are:

  • Euler angles (or other similar composition of three rotations along axes)
  • an orthogonal matrix
  • a quaternion

They have different trade-offs, but for computer graphics you often want to use either an orthogonal matrix or a quaternion, because composition is nearly impossible to implement with Euler angles.

Your object's vertices are originally described in local coordinates. You can think of these as vectors from the center of the object to each vertex. In order to place your object in the world, you apply the rotation to those vectors and then add them to the object's position in the world.

Once you have this working, you can worry about how keyboard input will modify the rotation.

Also,

   res.y = vec.x * sin(alpha) + vec.y + cos(alpha);

There is a typo there. It should be

   res.y = vec.x * sin(alpha) + vec.y * cos(alpha);

My C++ code is:

	// https://www.cs.helsinki.fi/group/goa/mallinnus/3dtransf/3drot.html
	
	inline void rotate_x(const float &radians)
	{
		float t_y = y;

		y = t_y*cos(radians) + z*sin(radians);
		z = t_y*-sin(radians) + z*cos(radians);
	}

	inline void rotate_y(const float &radians)
	{
		float t_x = x;

		x = t_x*cos(radians) + z*-sin(radians);
		z = t_x*sin(radians) + z*cos(radians);
	}

	inline void rotate_z(const float& radians)
	{
		float t_x = x;

		x = t_x * cos(radians) + y * sin(radians);
		y = t_x * -sin(radians) + y * cos(radians);
	}

@undefined Thanks you !

@undefined This 3D normalized orientation vector is for the square its normal to the central point of its face for example.
I wish to realize the rotation of an object in the world space and not in the object space.
Do my functions correspond to the orthogonal matrix method?
What's not working for me?

This 3D normalized orientation vector is for the square its normal to the central point of its face for example.

I assume with 'rotation vector' you mean a single direction, e.g. to represent the up axis of an cylinder.
But this is not enough to represent the orientation of an object in 3D, because the object can still rotate about its up axis, and this rotation is then undefined.

The represent orientation think of 3 unit vectors, orthogonal to each other.
You probably know some 3D modeling program or game engine that illustrates those 3 vectors as red, green and blue lines sharing the same origin (the position).
If we use the common representation of an object transform with a 4x4 matrix, the numbers (may) be set like this, for example:

1,0,0, 0 // x axis of the object in worldspace
0,1,0, 0 // y axis of the object in worldspace
0,0,1, 0 // z axis of the object in worldspace
5,4,6, 1 // position of the object in worldspace

The first 3 rows are our 3 axis vectors (followed by a zero)

The 4th row is a point representing the position (followed by a one)

So this is quite intuitive, and after some work of understandig dot product, 3D rotations can be understood geometrically.

I propose you look it up, the first tutorial o found is this: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

This is a commonly used math library you could use to get started quickly: https://glm.g-truc.net/0.9.9/index.html​​

To transform a ray into the local space of the object, or to transform reflection back to world space, you need both ‘unrotation’ and ‘rotation’, or ‘inverse transform’ and ‘transfrom’, which usually boils down to matrx - vector multiplication and matrix inversion (which in case of pure rotation is just transpose).
If this all sounds new, focus on dot product which can explain it all.

It is also common to use only a 3x3 matrix for rotations, and handle positions seperately. (For me that's more intuitive)
Quaternions represent orientations with only 4 numbers and make some things easier, e.g. interpolating orientations, or converting to/from axis and angle.

I think axis and angle is the best mind model to think about rotation, while 3x3 matrix is best to imagine orientation.
Differentiating rotation from orientation is similar like differentiating vector form point, although we always can use the same math for both of those.

Euler angles often suck because they are a series of 3 rotations actually, leading to expensive calculations but useful for human interface.

‘Rotation vectors’ are often used in physics simulation, e.g. to model angular velocity or torque. The 3 number describe rotation in radians about the 3 principal axis.
But they only make sense if initial orientation is given, and integrating it requires conversion to axis and angle to update given orientation. It's usually not very useful for geometry applications.

Notice your or @taby s code only perform 2D rotations in planes of principal axis, which is not a complete toolbox to model arbitary 3D rotations like necessary for a bone hierarchy of a character skeleton.
Such code can be used to convert Euler angles into 3 matrices, multiplied in given order to get a single rotation, which you then multiply with the orientation matrix of the parent bone to get the current child, for example.

So my square has its position in world space and its normalized 3D orientation vector (its normal).

Therefore, I don't see how to get the x, y and z axes of the object in world space because it is already positioned and oriented in world space. Thus, it is not positioned at the origin of world space.

I don't understand the steps to follow to rotate on this vector. Can you break the steps down into simple steps so that I can better understand?

ellenature said:
So my square has its position in world space and its normalized 3D orientation vector (its normal).

Sounds my assumption is right. If you only have position and normal of a square, it's orientation is not defined at all. See this example:

There's a blue and a black square in 3D, both having the same center position, and both having the same normal (red arrow).

So there is no way to ray trace or render those rectangles from given incomplete data. (But it would work for a disc or circle shape, or a sphere which does not need orientation at all. Assuming no texturing.)

To define orientation if the black square completely, we need it's full coordinate frame:

For example, red arrow = it's x axis = normal, green = y axis, blue = z axis. Together with center position and dimensions of the square in y and z we had enough information to render the square.
I could give code example of tracing a ray against this, if you want.

This topic is closed to new replies.

Advertisement