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
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;
}
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.
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;
}
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!
#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.