CannonBallSim.h 4.13 KB
Newer Older
Yuwei Xiao's avatar
Yuwei Xiao committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "Simulation.h"

using namespace std;

/*
 * Simulation that shoots a sphere in a given direction with a given force using
 * several kinds of integrators.
 */
class CannonBallSim : public Simulation {
public:
    CannonBallSim() : Simulation() {
        init();
        m_trajectories.clear();
        m_trajectoryColors.clear();
    }

	virtual void init() override {
		std::string path = "sphere.off";
		m_objects.clear();
		m_objects.push_back(RigidObject(path));
		p_ball = &m_objects.back();

		m_dt = 5e-2;
		m_mass = 1.0;
		m_log_frequency = 5;
		m_method = 0;
		m_gravity << 0, -9.81, 0;

		reset();
	}

    virtual void resetMembers() override {
        p_ball->reset();
        p_ball->setScale(0.1);
        p_ball->setPosition(Eigen::Vector3d(0, 0, 0));
        p_ball->setMass(m_mass);
        updateVars();

        if (m_trajectories.size() == 0 || m_trajectories.back().size() > 1) {
            m_trajectories.push_back(vector<Eigen::Vector3d>());
            m_trajectoryColors.push_back(m_color);
        } else {
            m_trajectoryColors.back() = m_color;
        }

        setMethod(m_method);
    }

    virtual void updateRenderGeometry() override {
        p_ball->getMesh(m_renderV, m_renderF);
    }

	virtual bool advance() override;

    virtual void renderRenderGeometry(
        igl::opengl::glfw::Viewer &viewer) override {
        viewer.data().set_mesh(m_renderV, m_renderF);

        for (size_t trajectory = 0; trajectory < m_trajectories.size();
             trajectory++) {
            for (size_t point = 0; point < m_trajectories[trajectory].size();
                 point++) {
                viewer.data().add_points(
                    m_trajectories[trajectory][point].transpose(),
                    m_trajectoryColors[trajectory]);
            }
        }
    }

    void clearTrajectories() {
        m_trajectories.clear();
        m_trajectories.push_back(vector<Eigen::Vector3d>());
        m_trajectoryColors.clear();
        m_trajectoryColors.push_back(m_color);
    }

#pragma region SettersAndGetters
    /*
     * Compute magnitude and direction of momentum and apply it to ball
     */
    void updateVars() {
        Eigen::Vector3d momentum;
        momentum << std::cos(m_angle), std::sin(m_angle), 0;
        momentum *= m_force;
        p_ball->setLinearVelocity(momentum / p_ball->getMass());
    }

    void setAngle(double a) {
        m_angle = a;
        updateVars();
    }

    void setForce(double f) {
        m_force = f;
        updateVars();
    }

    void setMass(double m) { m_mass = m; }

    void setMethod(int m) {
        m_method = m;
        switch (m_method) {
            case 0:
                m_color = Eigen::RowVector3d(1.0, 0.0, 0.0);
                break;
            case 1:
                m_color = Eigen::RowVector3d(0.0, 1.0, 0.0);
                break;
            case 2:
                m_color = Eigen::RowVector3d(0.0, 0.0, 1.0);
                break;
            default:
                std::cerr << m_method << " is not a valid integrator method."
                          << std::endl;
        }
        if (m_step == 0) {
            m_trajectoryColors.back() = m_color;
        }
    }

    void setLogFrequency(int f) { m_log_frequency = f; }

    void getTrajectories(int index, Eigen::MatrixX3d &mat) const {
        int num_points = m_trajectories[index].size();
        mat.resize(num_points, 3);
        for (int i = 0; i < num_points; i++) {
            mat.row(i) = m_trajectories[index][i];
        }
    }

    int getNumTrajectories() const { return m_trajectories.size(); }
#pragma endregion SettersAndGetters

private:
    int m_method;  // id of integrator to be used (0: analytical, 1: explicit euler, 2: semi-implicit euler)
    double m_angle;
    double m_force;
    double m_mass;

    Eigen::Vector3d m_gravity;

    RigidObject *p_ball;

    Eigen::MatrixXd m_renderV;  // vertex positions for rendering
    Eigen::MatrixXi m_renderF;  // face indices for rendering

    int m_log_frequency;  // how often should we log the COM in the GUI
    vector<vector<Eigen::Vector3d> > m_trajectories;
    Eigen::RowVector3d m_color;
    vector<Eigen::RowVector3d> m_trajectoryColors;
};