How to trace a path with pixels in Raylib? - c++

I am making a double pendulum simulator in Raylib and before I get into the deep physics behind how it works I wanted to finish creating the graphics for it.
So far I created a window, made a double pendulum, and can rotate the pendulums however I want, but as the last thing I need to do before working on the physics is trace its path and I went about it using textures using a RenderTexture2D variable.
However when doing so it does trace the path but only 1/4th of the entire window and I am not sure why.
Most likely it has to do with rltranslatef but I am not sure how to fix it. I have a pendulum.h & .cpp file but they are unrelated to making the graphics for this. Any help is appreciated.
pendulum.h:
#ifndef DOUBLE_PENDULUM_SIM_PENDULUM_H
#define DOUBLE_PENDULUM_SIM_PENDULUM_H
class pendulum {
public:
float pLength{};
float pMass{};
float x{};
float y{};
float pAngle{};
public:
[[nodiscard]] float getX() const ;
[[nodiscard]] float getY() const ;
[[nodiscard]] float getAngle() const ;
void setX(float length, float angle);
void setY(float length, float angle);
void setLength(float length);
void setMass(float mass);
void setAngle(float angle);
pendulum();
pendulum(float length, float mass, float angle) : pLength(length), pMass(mass), pAngle(angle) {}
~pendulum();
};
#endif //DOUBLE_PENDULUM_SIM_PENDULUM_H
pendulum.cpp:
#include "includes/pendulum.h"
#include <cmath>
#include <iostream>
#include <raylib.h>
void pendulum::setX(float length, float angle) {
x = length * sin(angle);
}
void pendulum::setY(float length, float angle) {
y = length * cos(angle);
}
float pendulum::getX() const {
return x;
}
float pendulum::getY() const {
return y;
}
void pendulum::setLength(float length) {
pLength = length;
}
void pendulum::setMass(float mass) {
pMass = mass;
}
float pendulum::getAngle() const {
return pAngle;
}
pendulum::~pendulum() {
std::cout << "\nPendulum destroyed" << std::endl;
}
void pendulum::setAngle(float angle) {
pAngle = angle * DEG2RAD;
}
//Default constructor
pendulum::pendulum() = default;
main.cpp in which the main graphics is drawn:
#include <iostream>
#include "raylib.h"
#include "includes/pendulum.h"
#include <rlgl.h>
#include <cmath>
void _testPendulum();
pendulum pen1;
pendulum pen2;
int main() {
//Prompt to make the initial values themselves
float uLength1, uLength2, uMass1, uMass2, uAngle1, uAngle2;
try {
std::cout << "Please choose the length of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits, " << "\n" << "length MUST BE greater than 50 and less than 200" << "\n";
std::cin >> uLength1 >> uLength2;
std::cout << "Please choose the mass of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits, " << "\n" << "mass MUST BE greater than 20 and less than 100" << "\n";
std::cin >> uMass1 >> uMass2;
std::cout << "Please choose the starting angle of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits" << "\n";
std::cin >> uAngle1 >> uAngle2;
} catch (const std::exception & e) {
std::cout << e.what();
}
//Pendulum 1 settings
pen1.setMass(uMass1);
pen1.setLength(uLength1);
pen1.setAngle(uAngle1);
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;
//Pendulum 2 settings
pen2.setMass(uMass2);
pen2.setLength(uLength2);
pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;
Vector2 origin{0,0};
const double screenWidth = 1440;
const double screenHeight = 1080;
InitWindow((int) screenWidth, (int) screenHeight, "Double-Pendulum-Sim");
int frameCounter = 0;
SetTargetFPS(60);
float px1 = pen1.getX();
float py1 = pen1.getY();
float px2 = pen2.getX();
float py2 = pen2.getY();
RenderTexture2D target = LoadRenderTexture((int) screenWidth, (int) screenHeight);
BeginTextureMode(target);
ClearBackground(RAYWHITE);
EndTextureMode();
while (!WindowShouldClose()) {
Vector2 rod1{px1,py1};
Vector2 rod2 {px2, py2};
/**------------------Update------------------*/
frameCounter++;
uAngle1 += 1.0f;
pen1.setAngle(uAngle1); //Can only set this once and cant anywhere else, why?
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
px1 = pen1.getX();
py1 = pen1.getY();
uAngle2 -= 1.0f;
pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
px2 = pen2.getX();
py2 = pen2.getY();
std::cout << frameCounter << std::endl;
/**---------------------------------Draw-Pendulums & Path---------------------------------- */
//TODO: Get pathing to work
BeginDrawing();
BeginTextureMode(target);
DrawPixelV(rod2, RED);
EndTextureMode();
rlTranslatef((float) screenWidth/2,(float) screenHeight/4,0);
DrawTextureRec(target.texture, (Rectangle){0,0, (float) target.texture.width, (float) -target.texture.height}, (Vector2){0,0}, WHITE);
ClearBackground(RAYWHITE);
DrawFPS(-350, -200);
DrawLineEx(origin, rod1, 5.0f, BLACK);
DrawCircle( px1,py1,pen1.pMass,BLACK);
DrawLineEx(rod1, rod2, 5.0f, BLACK);
DrawCircle(px2,py2,pen2.pMass,BLACK);
std::cout << "Pendulum 1 X & Y: " << pen1.getX() << " " << pen1.getY() << std::endl;
std::cout << "Pendulum 2 X & Y: " << pen2.getX() << " " << pen2.getY() << std::endl;
EndDrawing();
}
CloseWindow();
return 0;
}
//Test function
void _testPendulum() {
try {
pen1.setMass(20.0f);
pen1.setLength(150.0f);
pen1.setAngle(0.0f);
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;
pen2.setMass(50.0f);
pen2.setLength(150.0f);
pen2.setAngle(0.0f);
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;
} catch (const std::exception & e) {
std::cout << e.what();
}
}

Your problem comes from DrawPixelV(rod2, RED); which is unable to write where position is negative (try without rlTranslatef to see the idea).
Solution:
Don't use rlTranslatef
Instead make origin, px1, py1, px2 and py2 centered on the screen center (not 0,0).
In main.cpp, I changed these lines and the problem disappeared
Vector2 origin{700,200}; // was origin{0,0};
...
float px1 = pen1.getX() + 700; // +700 was not here
float py1 = pen1.getY() + 200; // +200 was not here
float px2 = pen2.getX() + 700;
float py2 = pen2.getY() + 200;
...
px1 = pen1.getX() + 700;
py1 = pen1.getY() + 200;
...
px2 = pen2.getX() + 700;
py2 = pen2.getY() + 200;

Related

VS2022 code analysis error using uninitialized memory C++ [duplicate]

This question already has answers here:
Uninitialized variable behaviour in C++
(4 answers)
What happens when I print an uninitialized variable in C++? [duplicate]
(4 answers)
Calling function with variable that is being initialized [duplicate]
(1 answer)
Closed 5 months ago.
Here are the errors on the following code after the VS2022(v143) upgrade:
Could someone please suggest what is wrong here and how to fix it?
//Cricle properties problem
#include <iostream>
using namespace std;
float Qradius(float diameter)
{
float radius = diameter / 2;
return radius;
}
float Warea(float radius)
{
float area = (radius *radius) *3.14;
return area;
}
float Ecircumference(float diameter)
{
float circumference = 3.14 * diameter;
return circumference;
}
float Rarclength(float arcangle, float circumference)
{
float arclength = (circumference *arcangle) / 360;
return arclength;
}
int main()
{
float diameter, arcangle;
float area, circumference, arclength, radius;
cout << "Type the diameter ";
cin >> diameter;
cout << "Type the arcangle ";
cin >> arcangle;
cout << "The radius of the circle is " << Qradius(diameter) << endl;
cout << "The area is " << Warea(radius) << endl;
cout << "The circumference is " << Ecircumference(diameter) << endl;
cout << "The arc length is " << Rarclength(arcangle, circumference) << endl;
}
I solved the warnings and explained why they were coming up in the comments in the code. Also do not use using namespace std;
#include <iostream>
float Qradius(float diameter)
{
float radius = diameter / 2;
return radius;
}
float Warea(float radius)
{
// if no f is specified, the compiler assumes it is a double
// the warning tells you that it converts a double to float
// which could lead to loss of data (C4244)
float area = (radius *radius) * 3.14f;
return area;
}
float Ecircumference(float diameter)
{
// same as aboth
float circumference = 3.14f * diameter;
return circumference;
}
float Rarclength(float arcangle, float circumference)
{
float arclength = (circumference *arcangle) / 360;
return arclength;
}
int main()
{
float diameter, arcangle;
// area and arclength are unused (C4101)
float /*area,*/ circumference, /*arclength,*/ radius;
std::cout << "Type the diameter ";
std::cin >> diameter;
std::cout << "Type the arcangle ";
std::cin >> arcangle;
// radius and circumference is never set
// and later used without setting any value (C6001)
radius = Qradius(diameter);
circumference = Ecircumference(diameter);
std::cout << "The radius of the circle is " << radius << std::endl;
std::cout << "The area is " << Warea(radius) << std::endl;
std::cout << "The circumference is " << circumference << std::endl;
std::cout << "The arc length is " << Rarclength(arcangle, circumference) << std::endl;
}

Need help utilizing two classes in one function,

So basically I created two classes for two vectors and got there norms. How would I approach using both classes to find the distance between both vectors in my main function ? I know I can use the friend function but we have not been taught that in class so I have to use the scope :: operator and constructor and destructors. I been trying different things but nothing works any ideas ? I am fairly new to c++.
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
class Vector {
private:
float x;
float y;
float z;
public:
Vector(float xaxis, float yaxis, float zaxis)
{
x = xaxis;
y = yaxis;
z = zaxis;
}
float getx() { return x; }
float gety() { return y; }
float getz() { return z; }
float normVector()
{
float result = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));
return result;
}
};
class Vectortwo {
private:
float x;
float y;
float z;
public:
Vectortwo(float xaxis, float yaxis, float zaxis)
{
x = xaxis;
y = yaxis;
z = zaxis;
}
float getx() { return x; }
float gety() { return y; }
float getz() { return z; }
float normVectortwo()
{
float result = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));
return result;
}
};
int main()
{
Vector v(2, 2, 2);
v.getx();
v.gety();
v.getz();
v.normVector();
cout << " X axis" << v.getx() << endl;
cout << " Y axis" << v.gety() << endl;
cout << " Z axis" << v.getz() << endl;
cout << " The norm of our first vector " << v.normVector() << endl;
Vectortwo b(3, 3, 3);
b.getx();
b.gety();
b.getz();
b.normVectortwo();
cout << " X axis" << b.getx() << endl;
cout << " Y axis" << b.gety() << endl;
cout << " Z axis" << b.getz() << endl;
cout << " The norm of our first vector " << b.normVectortwo() << endl;
return 0;
}
I know I can use the friend function but we have not been taught that in class [...]
You can always use getx(), gety() and getz() directly to calculate the distance. Since this gets a bit tiresome to write more than once you can write a little function that wraps the calculation:
float distance(Vector v1, Vectortwo v2)
{
return sqrt(
pow(v1.getx() - v2.getx(), 2)
+ pow(v1.gety() - v2.gety(), 2)
+ pow(v1.getz() - v2.getz(), 2)
);
}
It has to be declared before main() (but after Vector and Vectortwo) and could be used like this:
cout << "The distance is " << distance(v, b) << " units." << endl;
Since you somehow declared to vector classes Vector and Vectortwo that are basically identical (apart from the name), you can also just remove Vectortwo and use Vector for both instances, v and b. That would simplify the code and both parameters of the distance() function could be of type Vector.

Coordinate conversion in c++

I am trying to convert different coordinate systems. From polar to rectangular and vice versa. My pol_to_rect()function is not working properly. It is giving very small values(~10^(-44)) after converting and also before converting. There might be some problem while using the sin() and cos() functions. The rect_to_pol() is working fine for positive values.
Edit - When I changed atan() to atan2() how can I incorporate other values of x and y.
#include <iostream>
#include <cmath>
using namespace std;
#define PI 3.1415926
class Polar; // Forward declaration
class Rectangular {
private:
float x, y;
public:
Rectangular() {} // default constructor
Rectangular(float mv_x, float mv_y) {
x = mv_x;
y = mv_y;
}
void showData() const;
Polar rect_to_pol();
float& get_x() {
return x;
}
float& get_y() {
return y;
}
};
void Rectangular::showData() const {
cout << "--Rectangular--" << endl;
cout << "x: " << x << "\t" <<"y: " << y << endl;
}
class Polar {
private:
float r;
float theta;
public:
Polar() {} // default constructor
Polar(float mv_r, float mv_theta) {
r = mv_r;
theta = mv_theta;
}
void showData();
Rectangular pol_to_rect();
float& get_r(){
return r;
}
float& get_theta() {
return theta;
}
};
void Polar::showData() {
cout << "--Polar--" << endl;
cout << "r:" << r << "\t" << "Theta(Radians):" << theta << endl;
}
Rectangular Polar::pol_to_rect() {
Rectangular temp;
temp.get_x() = r * cos(theta*(PI/180.0)); // in degrees
temp.get_y() = r * sin(theta*(PI/180.0));
return temp;
}
Polar Rectangular::rect_to_pol() {
Polar temp;
temp.get_r() = sqrt(pow(x, 2) + pow(y, 2));
temp.get_theta() = atan2(y, x);
return temp;
}
int main()
{
Rectangular r1(-1, -1), r2;
Polar p1(12.0, 30.0), p2;
r1.showData();
p2 = r1.rect_to_pol();
cout << "After Conversion (RECT TO POLAR)->" << endl;
p2.showData();
p1.showData();
r2 = p1.pol_to_rect();
cout << "After Conversion (POLAR TO RECT)" << endl;
r2.showData();
return 0;
}

C++ Simple calculation outputting 0.0000000000000000 instead of 0.003333

The calculation for dx and dy is returning 0 and I don't see what the issue is. The console seems to show all the correct values are being used.
void drawBackground()
{
double r, g, b, dx, dy, Wx, Wy, Wz;
Ray ray;
cout << "xmax: " << sceneDescription::imagePlaneXmax << " xmin: " << sceneDescription::imagePlaneXmin << endl;
cout << "ymax: " << sceneDescription::imagePlaneYmax << " ymin: " << sceneDescription::imagePlaneYmin << endl;
cout << "Iw: " << sceneDescription::Iw << " Ih: " << sceneDescription::Ih << endl;
cout << " " << endl;
dx = (sceneDescription::imagePlaneXmax - (sceneDescription::imagePlaneXmin))/sceneDescription::Iw;
dy = (sceneDescription::imagePlaneYmax - (sceneDescription::imagePlaneYmin))/sceneDescription::Ih;
std::cout << "dx: "<< boost::format("%1$.16f") % dx << " dy: "<< boost::format("%1$.16f") % dy << endl;
}
sceneDescription.h
#include <glm/glm.hpp>
using namespace glm;
class sceneDescription{
public:
static const int imagePlaneXmin = -1;
static const int imagePlaneXmax = 1;
static const int imagePlaneYmin = -1;
static const int imagePlaneYmax = 1;
static const int Iw = 600;
static const int Ih = 800;
};
Console output:
xmax: 1 xmin: -1
ymax: 1 ymin: -1
Iw: 600 Ih: 800
dx: 0.0000000000000000 dy: 0.0000000000000000
The problem is that the statement:
dx = (sceneDescription::imagePlaneXmax -
(sceneDescription::imagePlaneXmin))/sceneDescription::Iw;
will give the following result:
(1-(-1))/600 = 2/600 = 0.00 (since this is integer division).
You may want to cast the number to double.
Something like this would work:
dx = (double)(sceneDescription::imagePlaneXmax -
(sceneDescription::imagePlaneXmin)) / sceneDescription::Iw;
Since cast operator has higher priority than division, the numerator will be cast by (double) and the denominator will be cast implicitly giving the double result.
Hope that helps!

converting to int from float

#include <iostream>
using namespace std;
int main(){
float const PI = 3.1415926;
int radius = 4;
int peri = 0;
int area = 0;
peri =(float) (PI * 2)* radius;
area = (float) PI * (radius * radius);
cout << "Radius is " << radius << endl;
cout << "Perimeter is " << peri << endl;
cout << "Area is " << area << endl;
return 0;
};
peri and area are not converting to float and always receiving a warning "converting to int from float" what seems to be the problem ..
If you really want to truncate peri and area to integers, you should do so explicitly:
peri=static_cast<int>(2*PI*radius);
area=static_cast<int>(PI*radius*radius);
Otherwise, you'll get a warning and it will look like a mistake to anyone who reads your code.