How to rotate a line around one of its vertexes - c++

I am making my first raycasting engine, and would like to rotate a line over an angle θ
How does one do this? Would it be possible to show me some basic C++ code or some pseudocode?
This image describes my problem:
Optional question
I decided to make all of this in graphics.h, because it is the simplest graphics header for C/C++.

You want:
B = P + M * (A - P)
Where M is a 2D rotation matrix:
M = | cos(ϴ) -sin(ϴ) |
| sin(ϴ) cos(ϴ) |
In C++ it could be written as:
float c = cos(theta), s = sin(theta);
float dx = ax - px, dy = ay - py;
float bx = px + c * dx - s * dy;
float by = py + s * dx + c * dy;

One simple algorithm:
Move the circle -P, so that P is at (0, 0).
Rotate A by the angle by multiplying it by the rotation matrix.
Move the circle P to restore its original position.
All these three steps can be done using one 3x3 matrix multiplication.

The scalar product of two vectors have the following property:
vec(PA) . vec(PB) = rho cos theta
Taking the definition of our two vectors:
vec(PA) = (x_a-x_p, y_a-y_p)
vec(PB) = (x_b-x_p, y_b-y_p)
We can get:
(x_a-x_p)(x_b-x_p) + (y_a-y_p)(y_b-y_p) = rho cos theta (1)
Since PA=PB, we also have:
(x_a-x_p)^2 + (y_a-y_p)^2 = (x_b-x_p)^2 + (y_b-y_p)^2 (2)
From (1) and (2) you can derive x_band y_b with some arithmetic autopilot.

Related

How to check if a point in a triangle (or on it's edge)

I'm trying to write an algorithm to determine if point is located inside a triangle or on it's edge in 3D coordinate space.
For example, I try to reach such results for different cases
I've figured out how to check if point P inside the triangle, I calculated normal vectors for triangles ABP, BCP, CAP and checked if they are similar.
Can someone explain how to check if a point is on the edge of a triangle (but not outside of a triangle)? You can provide formulas or code as you wish.
Make vectors:
r = p - A (r.x = p.x - A.x, r.y = p.y - A.y, r.z = p.z - A.z)
s = B - A
q = C - A
Calculate normal to ABC plane:
n = s x q (vector product)
Check if p lies in ABC plane using dot product:
dp = n.dot.r
If dp is zero (or has very small value like 1.0e-10 due to the floating point errors, then p is in the plane, and we can continue
Decompose vector p by base vectors s and q. At first check if z-component of normal (n.z) is non-zero. If so, use the next pair of equations (otherwise choose equations for x/z or y/z components):
px = a * sx + b * qx
py = a * sy + b * qy
Solve this system
a = (sy * qx - sx * qy) / (py * qx - px * qy)
b = (px - a * sx) / qx
If resulting coefficients a and b fulfill limits:
a >= 0
b >= 0
a + b <= 1.0
then point p lies in triangle plane inside it.

Find 2 points based off how much a point has rotated around a center point

I am making a little game and I am now working on a "radar". Now to do this I need to find two points based off how much a point has rotated around a center point.
A is going to rotate around C.
As A rotates around C, B & D will move along with A and stay in the same "positions" based off of where A is.
So for example, if A rotates around C 90 degrees B & D would then move and be in this position
But I am not very good at trig, so I don't really know the math I would need in order to find B & D based off how much A has rotated around C.
How do i find B & D based off of how much A has rotated around C?
I would image the final math would look somewhat similar to this:
float * returnB(float * APoint, float * CPoint)
{
float B_Out[2];
//calculate where B is based off A & C
B_Out[0] = B_X;
B_Out[1] = B_Y;
return B_Out;
}
float B[2];
B[0] = returnB(A,C)[0];
B[1] = returnB(A,C)[1];
float * returnD(float * APoint, float * CPoint)
{
float D_Out[2];
//calculate where D is based off A & C
D_Out[0] = D_X;
D_Out[1] = D_Y;
return D_Out;
}
float D[2];
D[0] = returnD(A,C)[0];
D[1] = returnD(A,C)[1];
You can rotate a point (x, y) around the origin by performing a simple matrix multiplication, which gives the following equations for the transformed point (x0, y0):
x0 = x * cos(theta) - y * sin(theta);
y0 = x * sin(theta) + y * cos(theta);
So you know A's relative 2d position respect to C. Lets say it is (ax, ay).
If you cross product(0,0,1) with (ax, ay, 0) you will find relative position of D that will be something like (dx, dy, 0)
d = (dx, dy) is relative position of D.
b is also -d
https://en.wikipedia.org/wiki/Cross_product

How to get vertices for a sphere? [duplicate]

Are there any tutorials out there that explain how I can draw a sphere in OpenGL without having to use gluSphere()?
Many of the 3D tutorials for OpenGL are just on cubes. I have searched but most of the solutions to drawing a sphere are to use gluSphere(). There is also a site that has the code to drawing a sphere at this site but it doesn't explain the math behind drawing the sphere. I have also other versions of how to draw the sphere in polygon instead of quads in that link. But again, I don't understand how the spheres are drawn with the code. I want to be able to visualize so that I could modify the sphere if I need to.
One way you can do it is to start with a platonic solid with triangular sides - an octahedron, for example. Then, take each triangle and recursively break it up into smaller triangles, like so:
Once you have a sufficient amount of points, you normalize their vectors so that they are all a constant distance from the center of the solid. This causes the sides to bulge out into a shape that resembles a sphere, with increasing smoothness as you increase the number of points.
Normalization here means moving a point so that its angle in relation to another point is the same, but the distance between them is different.
Here's a two dimensional example.
A and B are 6 units apart. But suppose we want to find a point on line AB that's 12 units away from A.
We can say that C is the normalized form of B with respect to A, with distance 12. We can obtain C with code like this:
#returns a point collinear to A and B, a given distance away from A.
function normalize(a, b, length):
#get the distance between a and b along the x and y axes
dx = b.x - a.x
dy = b.y - a.y
#right now, sqrt(dx^2 + dy^2) = distance(a,b).
#we want to modify them so that sqrt(dx^2 + dy^2) = the given length.
dx = dx * length / distance(a,b)
dy = dy * length / distance(a,b)
point c = new point
c.x = a.x + dx
c.y = a.y + dy
return c
If we do this normalization process on a lot of points, all with respect to the same point A and with the same distance R, then the normalized points will all lie on the arc of a circle with center A and radius R.
Here, the black points begin on a line and "bulge out" into an arc.
This process can be extended into three dimensions, in which case you get a sphere rather than a circle. Just add a dz component to the normalize function.
If you look at the sphere at Epcot, you can sort of see this technique at work. it's a dodecahedron with bulged-out faces to make it look rounder.
I'll further explain a popular way of generating a sphere using latitude and longitude (another
way, icospheres, was already explained in the most popular answer at the time of this writing.)
A sphere can be expressed by the following parametric equation:
F(u, v) = [ cos(u)*sin(v)*r, cos(v)*r, sin(u)*sin(v)*r ]
Where:
r is the radius;
u is the longitude, ranging from 0 to 2π; and
v is the latitude, ranging from 0 to π.
Generating the sphere then involves evaluating the parametric function at fixed intervals.
For example, to generate 16 lines of longitude, there will be 17 grid lines along the u axis, with a step of
π/8 (2π/16) (the 17th line wraps around).
The following pseudocode generates a triangle mesh by evaluating a parametric function
at regular intervals (this works for any parametric surface function, not just spheres).
In the pseudocode below, UResolution is the number of grid points along the U axis
(here, lines of longitude), and VResolution is the number of grid points along the V axis
(here, lines of latitude)
var startU=0
var startV=0
var endU=PI*2
var endV=PI
var stepU=(endU-startU)/UResolution // step size between U-points on the grid
var stepV=(endV-startV)/VResolution // step size between V-points on the grid
for(var i=0;i<UResolution;i++){ // U-points
for(var j=0;j<VResolution;j++){ // V-points
var u=i*stepU+startU
var v=j*stepV+startV
var un=(i+1==UResolution) ? endU : (i+1)*stepU+startU
var vn=(j+1==VResolution) ? endV : (j+1)*stepV+startV
// Find the four points of the grid
// square by evaluating the parametric
// surface function
var p0=F(u, v)
var p1=F(u, vn)
var p2=F(un, v)
var p3=F(un, vn)
// NOTE: For spheres, the normal is just the normalized
// version of each vertex point; this generally won't be the case for
// other parametric surfaces.
// Output the first triangle of this grid square
triangle(p0, p2, p1)
// Output the other triangle of this grid square
triangle(p3, p1, p2)
}
}
The code in the sample is quickly explained. You should look into the function void drawSphere(double r, int lats, int longs):
void drawSphere(double r, int lats, int longs) {
int i, j;
for(i = 0; i <= lats; i++) {
double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats);
double z0 = sin(lat0);
double zr0 = cos(lat0);
double lat1 = M_PI * (-0.5 + (double) i / lats);
double z1 = sin(lat1);
double zr1 = cos(lat1);
glBegin(GL_QUAD_STRIP);
for(j = 0; j <= longs; j++) {
double lng = 2 * M_PI * (double) (j - 1) / longs;
double x = cos(lng);
double y = sin(lng);
glNormal3f(x * zr0, y * zr0, z0);
glVertex3f(r * x * zr0, r * y * zr0, r * z0);
glNormal3f(x * zr1, y * zr1, z1);
glVertex3f(r * x * zr1, r * y * zr1, r * z1);
}
glEnd();
}
}
The parameters lat defines how many horizontal lines you want to have in your sphere and lon how many vertical lines. r is the radius of your sphere.
Now there is a double iteration over lat/lon and the vertex coordinates are calculated, using simple trigonometry.
The calculated vertices are now sent to your GPU using glVertex...() as a GL_QUAD_STRIP, which means you are sending each two vertices that form a quad with the previously two sent.
All you have to understand now is how the trigonometry functions work, but I guess you can figure it out easily.
If you wanted to be sly like a fox you could half-inch the code from GLU. Check out the MesaGL source code (http://cgit.freedesktop.org/mesa/mesa/).
See the OpenGL red book: http://www.glprogramming.com/red/chapter02.html#name8
It solves the problem by polygon subdivision.
My example how to use 'triangle strip' to draw a "polar" sphere, it consists in drawing points in pairs:
const float PI = 3.141592f;
GLfloat x, y, z, alpha, beta; // Storage for coordinates and angles
GLfloat radius = 60.0f;
int gradation = 20;
for (alpha = 0.0; alpha < GL_PI; alpha += PI/gradation)
{
glBegin(GL_TRIANGLE_STRIP);
for (beta = 0.0; beta < 2.01*GL_PI; beta += PI/gradation)
{
x = radius*cos(beta)*sin(alpha);
y = radius*sin(beta)*sin(alpha);
z = radius*cos(alpha);
glVertex3f(x, y, z);
x = radius*cos(beta)*sin(alpha + PI/gradation);
y = radius*sin(beta)*sin(alpha + PI/gradation);
z = radius*cos(alpha + PI/gradation);
glVertex3f(x, y, z);
}
glEnd();
}
First point entered (glVertex3f) is as follows the parametric equation and the second one is shifted by a single step of alpha angle (from next parallel).
Although the accepted answer solves the question, there's a little misconception at the end. Dodecahedrons are (or could be) regular polyhedron where all faces have the same area. That seems to be the case of the Epcot (which, by the way, is not a dodecahedron at all). Since the solution proposed by #Kevin does not provide this characteristic I thought I could add an approach that does.
A good way to generate an N-faced polyhedron where all vertices lay in the same sphere and all its faces have similar area/surface is starting with an icosahedron and the iteratively sub-dividing and normalizing its triangular faces (as suggested in the accepted answer). Dodecahedrons, for instance, are actually truncated icosahedrons.
Regular icosahedrons have 20 faces (12 vertices) and can easily be constructed from 3 golden rectangles; it's just a matter of having this as a starting point instead of an octahedron. You may find an example here.
I know this is a bit off-topic but I believe it may help if someone gets here looking for this specific case.
Python adaptation of #Constantinius answer:
lats = 10
longs = 10
r = 10
for i in range(lats):
lat0 = pi * (-0.5 + i / lats)
z0 = sin(lat0)
zr0 = cos(lat0)
lat1 = pi * (-0.5 + (i+1) / lats)
z1 = sin(lat1)
zr1 = cos(lat1)
glBegin(GL_QUAD_STRIP)
for j in range(longs+1):
lng = 2 * pi * (j+1) / longs
x = cos(lng)
y = sin(lng)
glNormal(x * zr0, y * zr0, z0)
glVertex(r * x * zr0, r * y * zr0, r * z0)
glNormal(x * zr1, y * zr1, z1)
glVertex(r * x * zr1, r * y * zr1, r * z1)
glEnd()
void draw_sphere(float r)
{
float pi = 3.141592;
float di = 0.02;
float dj = 0.04;
float db = di * 2 * pi;
float da = dj * pi;
for (float i = 0; i < 1.0; i += di) //horizonal
for (float j = 0; j < 1.0; j += dj) //vertical
{
float b = i * 2 * pi; //0 to 2pi
float a = (j - 0.5) * pi; //-pi/2 to pi/2
//normal
glNormal3f(
cos(a + da / 2) * cos(b + db / 2),
cos(a + da / 2) * sin(b + db / 2),
sin(a + da / 2));
glBegin(GL_QUADS);
//P1
glTexCoord2f(i, j);
glVertex3f(
r * cos(a) * cos(b),
r * cos(a) * sin(b),
r * sin(a));
//P2
glTexCoord2f(i + di, j);//P2
glVertex3f(
r * cos(a) * cos(b + db),
r * cos(a) * sin(b + db),
r * sin(a));
//P3
glTexCoord2f(i + di, j + dj);
glVertex3f(
r * cos(a + da) * cos(b + db),
r * cos(a + da) * sin(b + db),
r * sin(a + da));
//P4
glTexCoord2f(i, j + dj);
glVertex3f(
r * cos(a + da) * cos(b),
r * cos(a + da) * sin(b),
r * sin(a + da));
glEnd();
}
}
One way is to make a quad that faces the camera and write a vertex and fragment shader that renders something that looks like a sphere. You could use equations for a circle/sphere that you can find on the internet.
One nice thing is that the silhouette of a sphere looks the same from any angle. However, if the sphere is not in the center of a perspective view, then it would appear perhaps more like an ellipse. You could work out the equations for this and put them in the fragment shading. Then the light shading needs to changed as the player moves, if you do indeed have a player moving in 3D space around the sphere.
Can anyone comment on if they have tried this or if it would be too expensive to be practical?

Polar Rose 2D offset

I'm having some trouble trying to plot a polar rose with a offset C of the equation r(theta) = cos(k*theta) + C.
I'm trying to plot this polar rose: http://en.wikipedia.org/wiki/Polar_coordinate_system#/media/File:Cartesian_to_polar.gif
The polar equation can be:
r(theta) = cos(k * theta)
or
r(theta) = sin(k * theta)
The equation of the polar rose I want to draw is:
r(theta) = 2 + sin(6 * theta)
Ok, and the parametric equations will be:
x = C + sin(k * theta) * cos(theta)
y = C + sin(k * theta) * sin(theta)
In my Canvas(drawing area), my origin is not at the center of the screen, so I need to translate the rose to it. Ok, no big deal. Another point is that I need to scale the rose for it to be visible or it will be too small, but still no problem, this explains the: 100*. Here is my code, it is on C++ btw:
for ( float t = 0; t < PI_2; t+= 0.01 )
{
r = Origin.get_x() + 100*(2+(sin(6*t) * cos(t)));
h = Origin.get_y() + 100*(2+(sin(6*t) * sin(t)));
point(r,h);
}
I know that I'm doing it wrong, because when I add the +2 which should be the C constant is not working the way I want to, It's just translating more and drawing a polar rose without an offset. How do I prevent the "extra translation" and draw it properly?
x = r cos(theta), y = r sin(theta) so your parametric equations should be x(theta) = C * cos(theta) + sin(k*theta) * cos(theta) and y(theta) = C * sin(theta) + sin(k*theta) * sin(theta). You just forgot to multiply C by cos(theta) and by sin(theta) respectively.

2D Euclidean vector rotations

I have a euclidean vector a sitting at the coordinates (0, 1).
I want to rotate a by 90 degrees (clockwise) around the origin: (0, 0).
If I have a proper understanding of how this should work, the resultant (x, y) coordinates after the rotation should be (1, 0).
If I were to rotate it by 45 degrees (still clockwise) instead, I would have expected the resultant coordinates to be (0.707, 0.707).
theta = deg2rad(angle);
cs = cos(theta);
sn = sin(theta);
x = x * cs - y * sn;
y = x * sn + y * cs;
Using the above code, with an angle value of 90.0 degrees, the resultant coordinates are: (-1, 1).
And I am so damn confused.
The examples seen in the following links represent the same formula shown above surely?
What have I done wrong?
Or have I misunderstood how a vector is to be rotated?
Rotating a vector 90 degrees is particularily simple.
(x, y) rotated 90 degrees around (0, 0) is (-y, x).
If you want to rotate clockwise, you simply do it the other way around, getting (y, -x).
you should remove the vars from the function:
x = x * cs - y * sn; // now x is something different than original vector x
y = x * sn + y * cs;
create new coordinates becomes, to avoid calculation of x before it reaches the second line:
px = x * cs - y * sn;
py = x * sn + y * cs;
Rotate by 90 degress around 0,0:
x' = -y
y' = x
Rotate by 90 degress around px,py:
x' = -(y - py) + px
y' = (x - px) + py
Sounds easier to do with the standard classes:
std::complex<double> vecA(0,1);
std::complex<double> i(0,1); // 90 degrees
std::complex<double> r45(sqrt(2.0),sqrt(2.0));
vecA *= i;
vecA *= r45;
Vector rotation is a subset of complex multiplication. To rotate over an angle alpha, you multiply by std::complex<double> { cos(alpha), sin(alpha) }
You're calculating the y-part of your new coordinate based on the 'new' x-part of the new coordinate. Basically this means your calculating the new output in terms of the new output...
Try to rewrite in terms of input and output:
vector2<double> multiply( vector2<double> input, double cs, double sn ) {
vector2<double> result;
result.x = input.x * cs - input.y * sn;
result.y = input.x * sn + input.y * cs;
return result;
}
Then you can do this:
vector2<double> input(0,1);
vector2<double> transformed = multiply( input, cs, sn );
Note how choosing proper names for your variables can avoid this problem alltogether!