Half of my ellipse drawn in the wrong place - c++

Here is the code for an oval drawing method I am working on. I am applying the Bresenham method to plot its co-ordinates, and taking advantage of the ellipse's symmetrical properties to draw the same pixel in four different places.
void cRenderClass::plotEllipse(int xCentre, int yCentre, int width, int height, float angle, float xScale, float yScale)
{
if ((height == width) && (abs(xScale - yScale) < 0.005))
plotCircle(xCentre, yCentre, width, xScale);
std::vector<std::vector <float>> rotate;
if (angle > 360.0f)
{
angle -= 180.0f;
}
rotate = maths.rotateMatrix(angle, 'z');
//rotate[0][0] = cos(angle)
//rotate[0][1] = sin(angle)
float theta = atan2(-height*rotate[0][1], width*rotate[0][0]);
if (angle > 90.0f && angle < 180.0f)
{
theta += PI;
}
//add scalation in at a later date
float xShear = (width * (cos(theta) * rotate[0][0])) - (height * (sin(theta) * rotate[0][1]));
float yShear = (width * (cos(theta) * rotate[0][1])) + (height * (sin(theta) * rotate[0][0]));
float widthAxis = abs(sqrt(((rotate[0][0] * width) * (rotate[0][0] * width)) + ((rotate[0][1] * height) * (rotate[0][1] * height))));
float heightAxis = (width * height) / widthAxis;
int aSquared = widthAxis * widthAxis;
int fourASquared = 4*aSquared;
int bSquared = heightAxis * heightAxis;
int fourBSquared = 4*bSquared;
x0 = 0;
y0 = heightAxis;
int sigma = (bSquared * 2) + (aSquared * (1 - (2 * heightAxis)));
while ((bSquared * x0) <= (aSquared * y0))
{
drawPixel(xCentre + x0, yCentre + ((floor((x0 * yShear) / xShear)) + y0));
drawPixel(xCentre - x0, yCentre + ((floor((x0 * yShear) / xShear)) + y0));
drawPixel(xCentre + x0, yCentre + ((floor((x0 * yShear) / xShear)) - y0));
drawPixel(xCentre - x0, yCentre + ((floor((x0 * yShear) / xShear)) - y0));
if (sigma >= 0)
{
sigma += (fourASquared * (1 - y0));
y0--;
}
sigma += (bSquared * ((4 * x0) + 6));
x0++;
}
x0 = widthAxis;
y0 = 0;
sigma = (aSquared * 2) + (bSquared * (1 - (2 * widthAxis)));
while ((aSquared * y0) <= (bSquared * x0))
{
drawPixel(xCentre + x0, yCentre + ((floor((x0 * yShear) / xShear)) + y0));
drawPixel(xCentre - x0, yCentre + ((floor((x0 * yShear) / xShear)) + y0));
drawPixel(xCentre + x0, yCentre + ((floor((x0 * yShear) / xShear)) - y0));
drawPixel(xCentre - x0, yCentre + ((floor((x0 * yShear) / xShear)) - y0));
if (sigma >= 0)
{
sigma += (fourBSquared * (1 - x0));
x0--;
}
sigma += (aSquared * (4 * y0) + 6);
y0++;
}
//the above algorithm hasn't been quite completed
//there are still a few things I want to enquire Andy about
//before I move on
//this other algorithm definitely works
//however
//it is computationally expensive
//and the line drawing isn't as refined as the first one
//only use this as a last resort
/* std::vector<std::vector <float>> rotate;
rotate = maths.rotateMatrix(angle, 'z');
float s = rotate[0][1];
float c = rotate[0][0];
float ratio = (float)height / (float)width;
float px, py, xNew, yNew;
for (int theta = 0; theta <= 360; theta++)
{
px = (xCentre + (cos(maths.degToRad(theta)) * (width / 2))) - xCentre;
py = (yCentre - (ratio * (sin(maths.degToRad(theta)) * (width / 2)))) - yCentre;
x0 = (px * c) - (py * s);
y0 = (px * s) + (py * c);
drawPixel(x0 + xCentre, y0 + yCentre);
}*/
}
Here's the problem. When testing the rotation matrix on my oval drawing function, I expect it to draw an ellipse at a slant from its original horizontal position as signified by 'angle'. Instead, it makes a heart shape. This is sweet, but not the result I want.
I have managed to get the other algorithm (as seen in the bottom part of that code sample) working successfully, but it takes more time to compute, and doesn't draw lines quite as nicely. I only plan to use that if I can't get this Bresenham one working.
Can anyone help?

Related

3D sphere vs sphere collision resolve problem

I have been watching OneLoneCoder video about circle collision resolve
and use the code from git.
But the code is for 2D case, i.e. circles, and I need a solution for spheres. So I tried to add Z-component to equations but getting failures.
So I am testing the next way: I create two spheres, one above other. Lower is situated a heavy sphere, upper a tiny. The higher sphere is falling. In reality tiny should bounce up, but it just stuck, and they are falling as a single body for a while, but then the higher sphere is bouncing up. Also the sphere per each jump gets higher(see gif):
Here is the code:
/*
vertex - VERTEX **vertex=new VERTEX*[100];
vc - vertex count (how many vertices are currently created)
*/
void Update()
{
auto DoCirclesOverlap = [](float x1, float y1, float z1, float r1, float x2, float y2, float z2, float r2)
{
return ((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2)) <= (r1 + r2)*(r1 + r2);
};
vector<pair<VERTEX*, VERTEX*>> vecCollidingPairs;
// Update vertex[i] Positions
for (int i = 0;i < vc;i++)
{
// Update vertex[i] physics
vertex[i]->x += vertex[i]->vx * TIME_QUANT_CONSTANT;
vertex[i]->y += vertex[i]->vy * TIME_QUANT_CONSTANT;
vertex[i]->z += vertex[i]->vz * TIME_QUANT_CONSTANT;
}
// Static collisions, i.e. overlap
for (int i(0);i < vc;i++)
{
for(int j(0);j < vc;j++)
{
if (vertex[i]->index != vertex[j]->index)
{
if (DoCirclesOverlap(vertex[i]->x, vertex[i]->y, vertex[i]->z, vertex[i]->size, vertex[j]->x, vertex[j]->y, vertex[j]->z, vertex[j]->size))
{
// Collision has occured
vecCollidingPairs.push_back({ vertex[i], vertex[j] });
// Distance between vertex[i] centers
float fDistance = sqrtf((vertex[i]->x - vertex[j]->x)*(vertex[i]->x - vertex[j]->x) + (vertex[i]->y - vertex[j]->y)*(vertex[i]->y - vertex[j]->y) + (vertex[i]->y - vertex[j]->y)*(vertex[i]->y - vertex[j]->y));
// Calculate displacement required
float fOverlap = 0.5f * (fDistance - vertex[i]->size - vertex[j]->size);
// Displace Current vertex[i] away from collision
vertex[i]->x -= fOverlap * (vertex[i]->x - vertex[j]->x) / fDistance;
vertex[i]->y -= fOverlap * (vertex[i]->y - vertex[j]->y) / fDistance;
vertex[i]->z -= fOverlap * (vertex[i]->z - vertex[j]->z) / fDistance;
// Displace vertex[j] vertex[i] away from collision
vertex[j]->x += fOverlap * (vertex[i]->x - vertex[j]->x) / fDistance;
vertex[j]->y += fOverlap * (vertex[i]->y - vertex[j]->y) / fDistance;
vertex[j]->z += fOverlap * (vertex[i]->z - vertex[j]->z) / fDistance;
}
}
}
}
// Now work out dynamic collisions
for (auto c : vecCollidingPairs)
{
VERTEX *b1 = c.first;
VERTEX *b2 = c.second;
// Distance between vertex[i]s
float fDistance = sqrtf((b1->x - b2->x)*(b1->x - b2->x) + (b1->y - b2->y)*(b1->y - b2->y) + (b1->z - b2->z)*(b1->z - b2->z));
// Normal
float nx = (b2->x - b1->x) / fDistance;
float ny = (b2->y - b1->y) / fDistance;
float nz = (b2->z - b1->z) / fDistance;
// Tangent
float tx = -ny;
float ty = nx;
float tz = nz;
// Dot Product Tangent
float dpTan1 = b1->vx * tx + b1->vy * ty + b1->vz * tz;
float dpTan2 = b2->vx * tx + b2->vy * ty + b2->vz * tz;
// Dot Product Normal
float dpNorm1 = b1->vx * nx + b1->vy * ny + b1->vz * nz;
float dpNorm2 = b2->vx * nx + b2->vy * ny + b2->vz * nz;
// Conservation of momentum in 1D
float m1 = (dpNorm1 * (b1->mass - b2->mass) + 2.0f * b2->mass * dpNorm2) / (b1->mass + b2->mass);
float m2 = (dpNorm2 * (b2->mass - b1->mass) + 2.0f * b1->mass * dpNorm1) / (b1->mass + b2->mass);
// Update ball velocities
b1->vx = tx * dpTan1 + nx * m1;
b1->vy = ty * dpTan1 + ny * m1;
b1->vz = tz * dpTan1 + nz * m1;
b2->vx = tx * dpTan2 + nx * m2;
b2->vy = ty * dpTan2 + ny * m2;
b2->vz = tz * dpTan2 + nz * m2;
}
}
What is the problem?
Thanks for #Tyyppi_77 from Stack GameDev, where I posted the same question, that pointed that the issue was on line
float fDistance = sqrtf((vertex[i]->x - vertex[j]->x)*(vertex[i]->x - vertex[j]->x) + (vertex[i]->y - vertex[j]->y)*(vertex[i]->y - vertex[j]->y) + (vertex[i]->y - vertex[j]->y)*(vertex[i]->y - vertex[j]->y));
And the correct one is
float fDistance = sqrtf((vertex[i]->x - vertex[j]->x)*(vertex[i]->x - vertex[j]->x) + (vertex[i]->y - vertex[j]->y)*(vertex[i]->y - vertex[j]->y) + (vertex[i]->z - vertex[j]->z)*(vertex[i]->z - vertex[j]->z));
It just solved almost all of issues. The only terrible thing is, because of static collision, the lower and much more heavier sphere is a little bit shifts down while it is hit by the sphere above. Do You know how it can be solved?

What did i wrong in my image turn algoritm?

I just want to turn image #1 and write it in memory #2 (#1 Body #2 TurnBody) (rotation around the center of the image)
KI and KJ its just (i-radius) and (j-radius) for usage. SIN and COS its just sin and cos of turn angle.
radius - just half of image side (my image is square)
6.28 = pi*2
example i need to turn
example i have:
(i turn not all image, just a small square in center and add it to big screen image)
TurnAngle - just my global value (shows what angle the image is now rotated)
void Turn(double angle, int radius, COLORREF* Body, COLORREF* TurnBody)
{
if (abs(TurnAngle += angle) > 6.28)
{
TurnAngle = 0;
}
int i, ki, j, kj;
const double SIN = sin(TurnAngle), COS = cos(TurnAngle);
for (i = 0, ki = -radius; i < 2 * radius; i++, ki++)
{
for (j = 0, kj = -radius; j < 2 * radius; j++, kj++)
{
if (Body[i * 2 * radius + j]) // if Pixel not black
{
TurnBody[static_cast<int>(kj * COS - ki * SIN + radius + (ki * COS + kj * SIN + radius) * 2 * radius)] = Body[i * 2 * radius + j];
}
}
}
}
this work, smth was wrong with ( ) or double values i rly dont know... Thank you guys
this->TurnBody[(int)(kj * COS - ki * SIN) + this->radius + ((int)(ki * COS + kj * SIN) + this->radius) * 2 * this->radius] = this->Body[i * 2 * this->radius + j];
I think this is wrong:
TurnBody[static_cast<int>(kj * COS - ki * SIN + radius + (ki * COS + kj * SIN + radius) * 2 * radius)] = Body[i * 2 * radius + j];
I think it should be more like this:
TurnBody[(int)(kj * COS) + radius + ((int)(kj * SIN) + radius) * 2*radius] = Body[i * 2 * radius + j];

How do I resolve a collision's position properly in 2D collision detection?

My current implementation looks like this:
if (shapesCollide) {
if (velocity.y > 0) entity.position.y = other.position.y - entity.size.y;
else entity.position.y = other.position.y + other.size.y;
velocity.y = 0;
if (velocity.x > 0) entity.position.x = other.position.x - entity.size.x;
else entity.position.x = other.position.x + other.size.x;
velocity.x = 0;
}
However, this leads to weird handling when movement is happening on both axes - for example, having entity moving downward to the left of object, and then moving it to collide with object, will correctly resolve the horizontal collision, but will break the vertical movement.
I previously simply went
if (shapesCollide) {
position = oldPosition;
velocity = { 0, 0 };
}
But this lead to another multi-axis issue: if I have my entity resting atop the object, it will be unable to move, as the gravity-induced movement will constantly cancel out both velocities. I also tried considering both axes separately, but this lead to issues whenever the collision only occurs when both velocities are taken into account.
What is the best solution to resolving collision on two axes?
I assume that the entities can be considered to be more or less round and that size is the radius of the entities?
We probably need a little vector math to resolve this. (I don't know the square-root function in c++, so be aware at sqrt.) Try replacing your code inside if(shapesCollide) with this and see how it works for you.
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x + other.position.x) / 2.0;
float midY = (entity.position.y + other.position.y) / 2.0;
float dx = entity.position.x - midX;
float dy = entity.position.y - midY;
float D = sqrt(dx * dx + dy * dy);
rEntity and rOther are the radii of the objects, and midX and midY are their center coordinates. dx and dy are the distances to the center from the entity.
Then do:
entity.position.x = midX + dx * rEntity / D;
entity.position.y = midY + dy * rEntity / D;
other.position.x = midX - dx * rOther / D;
other.position.y = midY - dy * rOther / D;
You should probably check that D is not 0, and if it is, just set dx = 1, dy = 0, D = 1 or something like that.
You should also still do:
velocity.x = 0;
velocity.y = 0;
if you want the entities to stop.
For more accurate modelling, you could also try the following:
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x * rOther + other.position.x * rEntity) / (rEntity + rOther);
float midY = (entity.position.y * rOther + other.position.y * rEntity) / (rEntity + rOther);
float dxEntity = entity.position.x - midX;
float dyEntity = entity.position.y - midY;
float dEntity = sqrt(dxEntity * dxEntity + dyEntity * dyEntity);
float dxOther = other.position.x - midX;
float dyOther = other.position.y - midY;
float dOther = sqrt(dxOther * dxOther + dyOther * dyOther);
entity.position.x = midX + dxEntity * rEntity / dEntity;
entity.position.y = midY + dyEntity * rEntity / dEntity;
other.position.x = midX + dxOther * rOther / dOther;
other.position.y = midY + dyOther * rOther / dOther;
which finds the midpoints when the radii are taken into account. But I won't guarantee that that works. Also, the signs on the last additions are important.
I hope this helps (and works). Let me know if something is unclear.

Animating along an elliptical path in OpenGL

I am trying to make a red circle follow the path of a semi-circle using the DDA algorithm in OpenGL. I almost have it, though the circle is slightly offset on its X-axis, which increases as the angle of the semi-circle increases.
Any assistance would be greatly appreciated! Here's my code:
scrPt movecircle (scrPt p1, scrPt p2)
{
scrPt circlePos;
float angle, x = p1.x, y = p1.y, vectorX, vectorY;
// Get tahe x distance between the two points
int dx = p2.x - p1.x, steps;
// Get the y distance between the two points
int dy = p2.y - p1.y;
// Get the length between the points
float length = sqrt(dx*dx + dy*dy);
if (fabs (dx) > fabs (dy))
steps = fabs (dx);
else
steps = fabs (dy);
// calculate the direction
float xIncrement = float (dx) / float (steps);
float yIncrement = float (dy) / float (steps);
if (nextPos == 0)
{
for(int i = 0; i < steps; i++)
{
glClear(GL_COLOR_BUFFER_BIT);
angle = PI * i / steps;
vectorX = x + (length / 2) * cos(angle + theta);
vectorY = y + dy / 2 + (length / 2) * sin(angle + theta);
circlePos.x = round(vectorX - length / 2);
circlePos.y = round(vectorY);
drawCircle (circlePos.x, circlePos.y);
drawArch();
glFlush();
usleep(3000);
}
}
else
{
for (int i = 0; i < steps; i++)
{
glClear(GL_COLOR_BUFFER_BIT);
drawCircle (round(x),round(y));
glFlush();
usleep(3000);
x += xIncrement;
y += yIncrement;
}
}
return circlePos;
}
There were a couple of errors in the for-loop that were causing the issue. I needed to change
this:
vectorX = x + (length / 2) * cos(angle + theta);
to this:
vectorX = x + (dx / 2) + (length / 2) * cos(angle + theta);
and this:
circlePos.x = round(vectorX - (length / 2));
to this:
circlePos.x = round(vectorX);

How does this lighting calculation work?

I have that piece of code that is responsible for lighting a pyramid.
float Geometric3D::calculateLight(int vert1, int vert2, int vert3) {
float ax = tabX[vert2] - tabX[vert1];
float ay = tabY[vert2] - tabY[vert1];
float az = tabZ[vert2] - tabZ[vert1];
float bx = tabX[vert3] - tabX[vert1];
float by = tabY[vert3] - tabY[vert1];
float bz = tabZ[vert3] - tabZ[vert1];
float Nx = (ay * bz) - (az * by);
float Ny = (az * bx) - (ax * bz);;
float Nz = (ax * by) - (ay * bx);;
float Lx = -300.0f;
float Ly = -300.0f;
float Lz = -1000.0f;
float lenN = sqrtf((Nx * Nx) + (Ny * Ny) + (Nz * Nz));
float lenL = sqrtf((Lx * Lx) + (Ly * Ly) + (Lz * Lz));
float res = ((Nx * Lx) + (Ny * Ly) + (Nz * Lz)) / (lenN * lenL);
if (res < 0.0f)
res = -res;
return res;
}
I cannot understand calculations at the end. Can someone explain me the maths that is behind them? I know that firstly program calculates two vectors of a plane to compute the normal of it (which goes for vector N). Vector L stand for lighting but what happens next? Why do we calculate length of normal and light then multiply it and divide by their sizes?