Commit cf071f8b authored by Yuwei Xiao's avatar Yuwei Xiao
Browse files

ex1 update

parent d5fd26f7
cmake_minimum_required(VERSION 3.1)
project(1_earth)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
set(CMAKE_CXX_FLAGS "-Wall")
# libigl
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF)
option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF)
option(LIBIGL_WITH_CGAL "Use CGAL" OFF)
option(LIBIGL_WITH_COMISO "Use CoMiso" OFF)
option(LIBIGL_WITH_CORK "Use Cork" OFF)
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
option(LIBIGL_WITH_LIM "Use LIM" OFF)
option(LIBIGL_WITH_MATLAB "Use Matlab" OFF)
option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF)
option(LIBIGL_WITH_OPENGL "Use OpenGL" ON)
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON)
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" ON)
option(LIBIGL_WITH_PNG "Use PNG" OFF)
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF)
option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF)
option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" ON)
option(LIBIGL_WITH_XML "Use XML" OFF)
if (NOT LIBIGL_FOUND)
find_package(LIBIGL REQUIRED QUIET)
endif()
# Add default project files
file(GLOB LIBFILES ${PROJECT_SOURCE_DIR}/../include/*.*)
source_group("Library Files" FILES ${LIBFILES})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
# Add your project files
file(GLOB SRCFILES *.cpp)
file(GLOB HFILES *.h)
add_definitions(-DIGL_VIEWER_VIEWER_QUIET)
add_executable(${PROJECT_NAME} ${SRCFILES} ${HFILES} ${LIBFILES} )
target_link_libraries(${PROJECT_NAME} igl::core igl::opengl_glfw igl::opengl_glfw_imgui)
\ No newline at end of file
#include "Simulation.h"
using namespace std;
class EarthSim : public Simulation {
public:
EarthSim() : Simulation() {
init();
}
virtual void init() override {
std::string path = "sphere.off";
m_objects.clear();
m_objects.push_back(RigidObject(path));
m_objects.push_back(RigidObject(path));
p_earth = &m_objects[0];
p_moon = &m_objects[1];
m_dt = 5e-2;
m_radius = 10;
reset();
}
virtual void resetMembers() override {
p_earth->reset();
p_earth->setScale(0.3);
p_earth->setPosition(Eigen::Vector3d(0, 0, 0));
p_moon->reset();
p_moon->setScale(0.1);
p_moon->setPosition(Eigen::Vector3d(cos(getTime()), 0, sin(getTime())) * m_radius);
}
virtual void updateRenderGeometry() override {
for (size_t i = 0; i < m_objects.size(); i++) {
RigidObject &o = m_objects[i];
if (o.getID() < 0) { // negative id means newly created object, reverse memory for it
m_renderVs.emplace_back();
m_renderFs.emplace_back();
}
m_objects[i].getMesh(m_renderVs[i], m_renderFs[i]);
}
}
virtual bool advance() override {
// TODO update p_moon
// update m_time
// update m_step
return false;
}
virtual void renderRenderGeometry(igl::opengl::glfw::Viewer &viewer) override {
for (size_t i = 0; i < m_objects.size(); i++) {
RigidObject &o = m_objects[i];
if (o.getID() < 0) {
int new_id = 0;
if (i > 0) {
new_id = viewer.append_mesh();
o.setID(new_id);
} else {
o.setID(new_id);
}
size_t meshIndex = viewer.mesh_index(o.getID());
viewer.data_list[meshIndex].set_face_based(true);
viewer.data_list[meshIndex].point_size = 2.0f;
viewer.data_list[meshIndex].clear();
}
size_t meshIndex = viewer.mesh_index(o.getID());
viewer.data_list[meshIndex].set_mesh(m_renderVs[i], m_renderFs[i]);
viewer.data_list[meshIndex].compute_normals();
Eigen::MatrixXd color;
o.getColors(color);
viewer.data_list[meshIndex].set_colors(color);
}
}
void setRadius(float r) { m_radius = r; }
private:
RigidObject *p_earth, *p_moon;
float m_radius;
std::vector<Eigen::MatrixXd> m_renderVs; // vertex positions for rendering
std::vector<Eigen::MatrixXi> m_renderFs; // face indices for rendering
};
\ No newline at end of file
#include "EarthSim.h"
#include "Gui.h"
/*
* GUI for the earth simulation.
*/
class EarthGui : public Gui {
public:
// simulation parameters
float m_dt = 1e-2;
float m_radius = 10.0;
EarthSim *p_EarthSim = NULL;
EarthGui() {
// create a new Earth simulation, set it in the GUI, and start the GUI
p_EarthSim = new EarthSim();
setSimulation(p_EarthSim);
start();
}
virtual void updateSimulationParameters() override {
// change all parameters of the simulation to the values that are set in the GUI
p_EarthSim->setTimestep(m_dt);
p_EarthSim->setRadius(m_radius);
}
virtual void drawSimulationParameterMenu() override {
ImGui::InputFloat("Radius", &m_radius, 0, 0);
ImGui::InputFloat("dt", &m_dt, 0, 0);
}
};
int main(int argc, char *argv[]) {
// create a new instance of the GUI for the Earth simulation
new EarthGui();
return 0;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.1)
project(1-1_cannonball)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
set(CMAKE_CXX_FLAGS "-Wall")
# libigl
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF)
option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF)
option(LIBIGL_WITH_CGAL "Use CGAL" OFF)
option(LIBIGL_WITH_COMISO "Use CoMiso" OFF)
option(LIBIGL_WITH_CORK "Use Cork" OFF)
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
option(LIBIGL_WITH_LIM "Use LIM" OFF)
option(LIBIGL_WITH_MATLAB "Use Matlab" OFF)
option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF)
option(LIBIGL_WITH_OPENGL "Use OpenGL" ON)
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON)
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" ON)
option(LIBIGL_WITH_PNG "Use PNG" OFF)
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF)
option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF)
option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" ON)
option(LIBIGL_WITH_XML "Use XML" OFF)
if (NOT LIBIGL_FOUND)
find_package(LIBIGL REQUIRED QUIET)
endif()
# Add default project files
file(GLOB LIBFILES ${PROJECT_SOURCE_DIR}/../include/*.*)
source_group("Library Files" FILES ${LIBFILES})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
# Add your project files
file(GLOB SRCFILES *.cpp)
file(GLOB HFILES *.h)
add_definitions(-DIGL_VIEWER_VIEWER_QUIET)
add_executable(${PROJECT_NAME} ${SRCFILES} ${HFILES} ${LIBFILES} )
target_link_libraries(${PROJECT_NAME} igl::core igl::opengl_glfw igl::opengl_glfw_imgui)
\ No newline at end of file
#include "CannonBallSim.h"
bool CannonBallSim::advance() {
// perform time integration with different integrators
// use p_ball, m_dt, m_gravity
Eigen::Vector3d v = p_ball->getLinearVelocity();
Eigen::Vector3d p = p_ball->getPosition();
// TODO
switch (m_method) {
case 0:
// analytical solution
// v(t) = v_0*t + 0.5*a*t^2
break;
case 1:
// explicit euler
// p' = p + dt*v
// v' = v + dt*a
break;
case 2:
// symplectic euler
// v' = v + dt*a
// p' = p + dt*v'
break;
default:
std::cerr << m_method << " is not a valid integrator method."
<< std::endl;
}
// advance time
m_time += m_dt;
m_step++;
// log
if ((m_step % m_log_frequency) == 0) {
m_trajectories.back().push_back(p_ball->getPosition());
}
return false;
}
\ No newline at end of file
#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;
};
\ No newline at end of file
#include <igl/writeOFF.h>
#include "CannonBallSim.h"
#include "Gui.h"
/*
* GUI for the cannonball simulation. This time we need additional paramters,
* e.g. which integrator to use for the simulation and the force applied to the
* cannonball, and we also add some more visualizations (trajectories).
*/
class CannonBallGui : public Gui {
public:
// simulation parameters
float m_angle = 1.047f;
float m_force = 30.0f;
float m_dt = 1e-2;
float m_mass = 1.0;
int m_log_frequency = 30;
CannonBallSim *p_cannonBallSim = NULL;
const vector<char const *> m_integrators = {"Analytic", "Explicit Euler",
"Symplectic Euler"};
int m_selected_integrator = 0;
CannonBallGui() {
// create a new cannonball simulation, set it in the GUI,
// and start the GUI
p_cannonBallSim = new CannonBallSim();
setSimulation(p_cannonBallSim);
// show vertex velocity instead of normal
callback_clicked_vertex = [&](int clickedVertexIndex,
int clickedObjectIndex,
Eigen::Vector3d &pos,
Eigen::Vector3d &dir) {
RigidObject &o = p_cannonBallSim->getObjects()[clickedObjectIndex];
pos = o.getVertexPosition(clickedVertexIndex);
dir = o.getVelocity(pos);
};
start();
}
virtual void updateSimulationParameters() override {
// change all parameters of the simulation to the values that are set in
// the GUI
p_cannonBallSim->setForce(m_force);
p_cannonBallSim->setAngle(m_angle);
p_cannonBallSim->setTimestep(m_dt);
p_cannonBallSim->setMass(m_mass);
p_cannonBallSim->setMethod(m_selected_integrator);
p_cannonBallSim->setLogFrequency(m_log_frequency);
}
virtual void clearSimulation() override {
p_cannonBallSim->clearTrajectories();
}
/*
* Writes each trajectory to an individual off-file.
*/
void exportTrajectories() {
Eigen::MatrixX3d mat;
for (int i = 0; i < p_cannonBallSim->getNumTrajectories(); i++) {
string filename = "trajectory" + to_string(i) + ".off";
p_cannonBallSim->getTrajectories(i, mat);
if (mat.rows() <= 1) {
continue;
}
if (igl::writeOFF(filename, mat, Eigen::MatrixXi())) {
cout << "Wrote trajectory to " << filename << endl;
} else {
cout << "Failed to write trajectory to " << filename << endl;
}
}
}
virtual void drawSimulationParameterMenu() override {
if (ImGui::Button("Export Trajectories", ImVec2(-1, 0))) {
exportTrajectories();
}
ImGui::SliderAngle("Angle", &m_angle, -180.0f, 180.0f);
ImGui::InputFloat("Force", &m_force, 0, 0);
ImGui::InputFloat("Mass", &m_mass, 0, 0);
ImGui::InputFloat("dt", &m_dt, 0, 0);
ImGui::Combo("Integrator", &m_selected_integrator, m_integrators.data(),
m_integrators.size());
ImGui::InputInt("Log Frequency", &m_log_frequency, 0, 0);
}
};
int main(int argc, char *argv[]) {
// create a new instance of the GUI for the cannonball simulation
new CannonBallGui();
return 0;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.1)
project(1-2_spring)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
set(CMAKE_CXX_FLAGS "-Wall")
# libigl
option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF)
option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF)
option(LIBIGL_WITH_CGAL "Use CGAL" OFF)
option(LIBIGL_WITH_COMISO "Use CoMiso" OFF)
option(LIBIGL_WITH_CORK "Use Cork" OFF)
option(LIBIGL_WITH_EMBREE "Use Embree" OFF)
option(LIBIGL_WITH_LIM "Use LIM" OFF)
option(LIBIGL_WITH_MATLAB "Use Matlab" OFF)
option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF)
option(LIBIGL_WITH_OPENGL "Use OpenGL" ON)
option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON)
option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" ON)
option(LIBIGL_WITH_PNG "Use PNG" OFF)
option(LIBIGL_WITH_PYTHON "Use Python" OFF)
option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF)
option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF)
option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" ON)
option(LIBIGL_WITH_XML "Use XML" OFF)
if (NOT LIBIGL_FOUND)
find_package(LIBIGL REQUIRED QUIET)
endif()
# Add default project files
file(GLOB LIBFILES ${PROJECT_SOURCE_DIR}/../include/*.*)
source_group("Library Files" FILES ${LIBFILES})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
# Add your project files
file(GLOB SRCFILES *.cpp)
file(GLOB HFILES *.h)
add_definitions(-DIGL_VIEWER_VIEWER_QUIET)
add_executable(${PROJECT_NAME} ${SRCFILES} ${HFILES} ${LIBFILES} )
target_link_libraries(${PROJECT_NAME} igl::core igl::opengl_glfw igl::opengl_glfw_imgui)
\ No newline at end of file
#include "SpringSim.h"
bool SpringSim::advance() {
// perform time integration with different integrators
// use p_cube, m_spring, m_dt, m_gravity
Eigen::Vector3d v = p_cube->getLinearVelocity();
Eigen::Vector3d p = p_cube->getPosition();
// TODO
// note that it is required to update both m_sptring.end and p_cube's position
switch (m_method) {
case 0: // analytical solution
{
break;
}
case 1: // explicit euler
break;
case 2: // symplectic euler
break;
case 3: // midpoint
break;
default:
std::cerr << m_method << " is not a valid integrator method."
<< std::endl;
}
// update spring end position
m_spring.end = p_cube->getPosition();
// advance m_time
m_time += m_dt;
m_step++;
// log
if ((m_step % m_log_frequency) == 0) {
m_trajectories.back().push_back(p_cube->getPosition());
}
return false;
}
\ No newline at end of file
#include "Simulation.h"
using namespace std;
struct Spring {
public:
float stiffness;
float length;
float damping;
Eigen::Vector3d start;
Eigen::Vector3d end;
};
/*
* Simulation of a string with an attached mass.
*/
class SpringSim : public Simulation {
public:
SpringSim() : Simulation() {
init();
m_trajectories.clear();
m_trajectoryColors.clear();
}
virtual void init() override {
std::string path = "cube.off";
m_objects.clear();
m_objects.push_back(RigidObject(path));
p_cube = &m_objects.back();
m_dt = 1e-2;
m_mass = 1.0;
m_log_frequency = 30;
m_method = 0;
m_gravity << 0, -9.81, 0;
reset();
}
virtual void resetMembers() override {
p_cube->reset();
m_spring.end = m_spring.start - m_spring.length * Eigen::Vector3d(0, 1, 0);
p_cube->setPosition(m_spring.end);
p_cube->setMass(m_mass);
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_cube->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]);
}
}
// draw the spring
for (int i = 0; i < 20; ++i) {
double w = i / 20.0;
Eigen::RowVector3d p = m_spring.start * w + m_spring.end * (1 - w);
viewer.data().add_points(p, Eigen::RowVector3d(0, 0, 0));
}
}
void clearTrajectories() {
m_trajectories.clear();
m_trajectories.push_back(vector<Eigen::Vector3d>());
m_trajectoryColors.clear();
m_trajectoryColors.push_back(m_color);
}
#pragma region SettersAndGetters
void setMass(double m) { m_mass = m; }
void setSpring(const Spring &s) {
m_spring = s;
m_spring.end =
m_spring.start - m_spring.length * Eigen::Vector3d(0, 1, 0);
p_cube->setPosition(m_spring.end);
}
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;
case 3:
m_color = Eigen::RowVector3d(1.0, 1.0, 0.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, 3: midpoint)
double m_mass;
Eigen::Vector3d m_gravity;
Spring m_spring;
RigidObject *p_cube;
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;
};
\ No newline at end of file
#include <igl/writeOFF.h>
#include <thread>
#include "Gui.h"
#include "Simulator.h"
#include "SpringSim.h"
/*
* GUI for the spring simulation. This time we need additional paramters,
* e.g. which integrator to use for the simulation and the force applied to the
* cube, and we also add some more visualizations (trajectories).
*/
class SpringGui : public Gui {
public:
// simulation parameters
float m_dt = 1e-2;
float m_mass = 1.0;
int m_log_frequency = 30;
Spring m_spring; // stores properties of a spring
SpringSim *p_springSim = NULL;
const vector<char const *> m_integrators = {"Analytic", "Explicit Euler", "Symplectic Euler", "Midpoint"};
int m_selected_integrator = 0;
SpringGui() {
// initialize the spring to be used
m_spring.length = 5.0;
m_spring.stiffness = 5.0;
m_spring.damping = 0.1;
m_spring.start = m_spring.end = Eigen::Vector3d::Zero();
p_springSim = new SpringSim();
p_springSim->setSpring(m_spring);
setSimulation(p_springSim);
// show vertex velocity instead of normal
callback_clicked_vertex =
[&](int clickedVertexIndex, int clickedObjectIndex,
Eigen::Vector3d &pos, Eigen::Vector3d &dir) {
RigidObject &o = p_springSim->getObjects()[clickedObjectIndex];
pos = o.getVertexPosition(clickedVertexIndex);
dir = o.getVelocity(pos);
};
start();
}
virtual void updateSimulationParameters() override {
// change all parameters of the simulation to the values that are set in
// the GUI
p_springSim->setTimestep(m_dt);
p_springSim->setMethod(m_selected_integrator);
p_springSim->setLogFrequency(m_log_frequency);
p_springSim->setMass(m_mass);
p_springSim->setSpring(m_spring);
}
virtual void clearSimulation() override {
p_springSim->clearTrajectories();
}
/*
* Writes each trajectory to an individual off-file.
*/
void exportTrajectories() {
Eigen::MatrixX3d mat;
for (int i = 0; i < p_springSim->getNumTrajectories(); i++) {
string filename = "trajectory" + to_string(i) + ".off";
p_springSim->getTrajectories(i, mat);
if (mat.rows() <= 1) {
continue;
}
if (igl::writeOFF(filename, mat, Eigen::MatrixXi())) {
cout << "Wrote trajectory to " << filename << endl;
} else {
cout << "Failed to write trajectory to " << filename << endl;
}
}
}
virtual bool childKeyCallback(igl::opengl::glfw::Viewer &viewer,
unsigned int key, int modifiers) override {
switch (key) {
case 'e':
case 'E':
exportTrajectories();
return true;
// cicle through different integrators
case '>':
m_selected_integrator++;
m_selected_integrator %= m_integrators.size();
return true;
case '<':
m_selected_integrator--;
m_selected_integrator =
(m_integrators.size() + m_selected_integrator) %
m_integrators.size();
return true;
}
return false;
}
virtual void drawSimulationParameterMenu() override {
if (ImGui::Button("Export Trajectories", ImVec2(-1, 0))) {
exportTrajectories();
}
ImGui::InputFloat("Spring Stiffness", &m_spring.stiffness, 0, 0);
ImGui::InputFloat("Spring Length", &m_spring.length, 0, 0);
ImGui::InputFloat("Mass", &m_mass, 0, 0);
ImGui::InputFloat("Damping", &m_spring.damping, 0, 0);
ImGui::InputFloat("dt", &m_dt, 0, 0);
ImGui::Combo("Integrator", &m_selected_integrator, m_integrators.data(),
m_integrators.size());
ImGui::InputInt("Log Frequency", &m_log_frequency, 0, 0);
}
};
int main(int argc, char *argv[]) {
// create a new instance of the GUI for the spring simulation
new SpringGui();
return 0;
}
\ No newline at end of file
......@@ -27,4 +27,7 @@ if (NOT LIBIGL_FOUND)
find_package(LIBIGL REQUIRED QUIET)
endif()
add_subdirectory(0_dummy)
\ No newline at end of file
# add_subdirectory(0_dummy)
add_subdirectory(1-0_earth)
add_subdirectory(1-1_cannonball)
add_subdirectory(1-2_spring)
\ No newline at end of file
......@@ -43,6 +43,7 @@ public:
* touch any rendering data structures at all). You have to update the time
* variables at the end of each step if they are necessary for your
* simulation.
* Return true means the simulation is finished.
*/
virtual bool advance() = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment