Home > Enterprise >  How to trace a path with pixels in Raylib?
How to trace a path with pixels in Raylib?

Time:09-09

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();
    }

}

CodePudding user response:

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