Commit a743ae3f authored by DALAB\sjtud's avatar DALAB\sjtud
Browse files

initialize

parent 9814ef6b
cmake_minimum_required(VERSION 3.1)
project(CA)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
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_subdirectory(0_dummy)
# add_subdirectory(1-0_earth)
# add_subdirectory(1-1_cannonball)
# add_subdirectory(1-2_spring)
# add_subdirectory(2-1_bead)
# add_subdirectory(2-2_pendulum)
# add_subdirectory(3_cloth)
# add_subdirectory(4-1_spinning)
# add_subdirectory(4-2_collision)
add_subdirectory(5_fluid)
\ No newline at end of file
# Computer Animation 2022 - Exercise
## Overview
Code framework for course exercise.
## Installation
Install **Git** and build system **Cmake**. For windows user, MSVC need to be installed.
### Note for linux users
Many linux distributions do not include `gcc` and the basic development tools in their default installation. On Ubuntu, you need to install the following packages:
```
sudo apt-get install build-essential libx11-dev mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxi-dev libxmu-dev libblas-dev libxinerama-dev libxcursor-dev
```
### Build
Clone this repo (together with the submodule `libigl`):
```
git clone --recursive http://dalab.se.sjtu.edu.cn/gitlab/courses/ca-framework-2022.git
# if you forget clone submodule at first place
git submodule update --init --recursive
```
Run the following commands inside the relevant subfolder to setup the build folder:
```
mkdir build
cd build
cmake ..
```
Compile and run the executable, e.g. Ubuntu:
```
make && ./0_dummy/0_dummy
```
### For Windows
Cmake will generate Microsft visual studio project. Click the `*.sln` file to open the project and build.
## Exercise Handin
**You only need to handin the directory containing the modified executable**. For example (homework 0), you only need to compress folder *0_dummy* and submit the compressed file. *Please don't include any build file, only the source code and related resource file*.
```
zip NAME_ID_0_dummy.zip 0_dummy/*
```
Rename your compressed file following the rule *`NAME_ID_XXX`*.
## FAQ
* Command `cmake ../` stuck at `Cloning into 'eigen'...` or other cloning.
This may caused by problem of accessing github. Please first try use [SJTU VPN](!https://net.sjtu.edu.cn/wlfw/VPN.htm) and compile.
~~Also, some repos are available on our own server, such as *Eigen*. The download info of libigl dependencies is located at file `libigl/cmake/LibiglDownloadExternal.cmake`. For example, you can change the link at line 70 to `http://dalab.se.sjtu.edu.cn/gitlab/xiaoyuwei/eigen.git` use eigen mirror repo at DALAB server.~~
~~glfw (http://dalab.se.sjtu.edu.cn/gitlab/xiaoyuwei/glfw.git) and imgui (http://dalab.se.sjtu.edu.cn/gitlab/xiaoyuwei/imgui.git) are also available on our server.~~
* The menu bar isn't rendered correctly in Release mode using VS2019.
Solution 1: Use Debug mode.
Solution 2: Remove `ImGuiWindowFlags_AlwaysAutoResize` flag used in `ImGui::Begin()` and comment out `ImGui::SetNextWindowSizeConstraints()` in `include/Gui.cpp`. See [#1669](https://github.com/libigl/libigl/issues/1669) for more details.
----
The main part of this framework refers to physical-based simulation course at ETH Zurich.
# - Try to find the LIBIGL library
# Once done this will define
#
# LIBIGL_FOUND - system has LIBIGL
# LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory
if(LIBIGL_FOUND)
return()
endif()
find_path(LIBIGL_INCLUDE_DIR igl/readOBJ.h
HINTS
ENV LIBIGL
ENV LIBIGLROOT
ENV LIBIGL_ROOT
ENV LIBIGL_DIR
PATHS
${CMAKE_SOURCE_DIR}/../..
${CMAKE_SOURCE_DIR}/..
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/libigl
${CMAKE_SOURCE_DIR}/../libigl
${CMAKE_SOURCE_DIR}/../../libigl
${CMAKE_SOURCE_DIR}/../../lib/libigl
${CMAKE_SOURCE_DIR}/lib/libigl
${CMAKE_SOURCE_DIR}/../lib/libigl
/usr
/usr/local
/usr/local/igl/libigl
PATH_SUFFIXES include
)
message(${LIBIGL_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBIGL
"\nlibigl not found --- You can download it using:\n\tgit clone --recursive https://github.com/libigl/libigl.git ${CMAKE_SOURCE_DIR}/../libigl"
LIBIGL_INCLUDE_DIR)
mark_as_advanced(LIBIGL_INCLUDE_DIR)
list(APPEND CMAKE_MODULE_PATH "${LIBIGL_INCLUDE_DIR}/../cmake")
message(${CMAKE_MODULE_PATH})
include(libigl)
OFF
# cube.off
# A cube
8 12 0
-1 -1 -1
1 -1 -1
-1 1 -1
1 1 -1
-1 -1 1
1 -1 1
-1 1 1
1 1 1
3 0 2 1
3 2 3 1
3 1 3 5
3 3 7 5
3 2 6 3
3 6 7 3
3 5 7 4
3 7 6 4
3 4 6 0
3 6 2 0
3 4 0 1
3 4 1 5
\ No newline at end of file
OFF
# cube.off
# A cube
8 24 0
-1 -1 -1
1 -1 -1
-1 1 -1
1 1 -1
-1 -1 1
1 -1 1
-1 1 1
1 1 1
3 0 2 1
3 2 3 1
3 1 3 5
3 3 7 5
3 2 6 3
3 6 7 3
3 5 7 4
3 7 6 4
3 4 6 0
3 6 2 0
3 4 0 1
3 4 1 5
3 0 3 1
3 2 3 0
3 1 7 5
3 3 7 1
3 2 7 3
3 6 7 2
3 5 7 6
3 6 4 5
3 4 6 2
3 4 2 0
3 5 0 1
3 4 0 5
\ No newline at end of file
OFF
# cube.off
# A cube
8 12 0
-1 -1 -1
1 -1 -1
-1 1 -1
1 1 -1
-1 -1 1
1 -1 1
-1 1 1
1 1 1
3 0 2 1
3 2 3 1
3 2 6 3
3 6 7 3
3 5 7 4
3 7 6 4
3 1 7 5
3 3 7 1
#3 2 7 3
#3 6 7 2
3 4 6 2
3 4 2 0
3 5 0 1
3 4 0 5
\ No newline at end of file
OFF
# cube.off
# A cube
8 12 0
-1 -0.1 -1
1 -0.1 -1
-1 0.1 -1
1 0.1 -1
-1 -0.1 1
1 -0.1 1
-1 0.1 1
1 0.1 1
3 0 2 1
3 2 3 1
3 1 3 5
3 3 7 5
3 2 6 3
3 6 7 3
3 5 7 4
3 7 6 4
3 4 6 0
3 6 2 0
3 4 0 1
3 4 1 5
\ No newline at end of file
This diff is collapsed.
OFF
# cube.off
# A cube
20 36 0
-1 -1 -1
1 -1 -1
-1 1 -1
1 1 -1
-1 -1 1
1 -1 1
-1 1 1
1 1 1
-3 -1 -1
3 -1 -1
-3 1 -1
3 1 -1
-3 -1 1
3 -1 1
-3 1 1
3 1 1
-1 -3 -1
1 -3 -1
-1 -3 1
1 -3 1
3 0 2 1
3 2 3 1
3 9 11 13
3 11 15 13
3 2 6 3
3 6 7 3
3 5 7 4
3 7 6 4
3 12 14 8
3 14 10 8
3 18 16 17
3 18 17 19
3 8 10 0
3 10 2 0
3 3 9 1
3 3 11 9
3 12 6 14
3 12 4 6
3 7 5 15
3 15 5 13
3 14 2 10
3 2 14 6
3 8 0 12
3 4 12 0
3 3 7 11
3 7 15 11
3 5 1 9
3 5 9 13
3 0 1 17
3 0 17 16
3 19 5 18
3 5 4 18
3 0 16 4
3 4 16 18
3 1 5 19
3 17 1 19
\ No newline at end of file
#ifndef AABB_H
#define AABB_H
#include <Eigen/Core>
#include "RigidObject.h"
class AABB {
public:
AABB()
: m_minCoord(
Eigen::Vector3d::Constant(std::numeric_limits<double>::min())),
m_maxCoord(
Eigen::Vector3d::Constant(std::numeric_limits<double>::max())) {}
AABB(const Eigen::Vector3d& minCoord, const Eigen::Vector3d& maxCoord)
: m_minCoord(minCoord), m_maxCoord(maxCoord) {}
const Eigen::Vector3d& getMinCoord() const { return m_minCoord; };
const Eigen::Vector3d& getMaxCoord() const { return m_maxCoord; };
void setMinCoord(const Eigen::Vector3d& minCoord) { m_minCoord = minCoord; }
void setMaxCoord(const Eigen::Vector3d& maxCoord) { m_maxCoord = maxCoord; }
bool testCollision(const AABB& other) const {
if (m_maxCoord.x() < other.m_minCoord.x() ||
other.m_maxCoord.x() < m_minCoord.x())
return false;
if (m_maxCoord.y() < other.m_minCoord.y() ||
other.m_maxCoord.y() < m_minCoord.y())
return false;
if (m_maxCoord.z() < other.m_minCoord.z() ||
other.m_maxCoord.z() < m_minCoord.z())
return false;
return true;
}
void computeAABB(const RigidObject & obj) {
Eigen::MatrixXd V;
Eigen::MatrixXi F;
obj.getMesh(V, F);
Eigen::Vector3d minCoord = V.colwise().minCoeff();
setMinCoord(minCoord);
Eigen::Vector3d maxCoord = V.colwise().maxCoeff();
setMaxCoord(maxCoord);
}
void clear() {
m_minCoord =
Eigen::Vector3d::Constant(std::numeric_limits<double>::min());
m_maxCoord =
Eigen::Vector3d::Constant(std::numeric_limits<double>::max());
}
private:
Eigen::Vector3d m_minCoord;
Eigen::Vector3d m_maxCoord;
};
#endif // AABB_H
\ No newline at end of file
//=============================================================================
// Physically-based Simulation in Computer Graphics
// ETH Zurich
//
// Author: Christian Schumacher
//=============================================================================
#pragma once
#include <vector>
#include <assert.h>
// Simple 2D array
template <typename SCALAR>
class Array2T
{
public:
// Default constructor
Array2T()
{
m_size[0] = 0;
m_size[1] = 0;
}
// Constructor with given size
Array2T(int size0, int size1, SCALAR value = (SCALAR)0)
{
resize(size0, size1, value);
}
// Copy constructor
Array2T(const Array2T<SCALAR> &m)
{
*this = m;
}
// Resize array
void resize(int size0, int size1, SCALAR value = (SCALAR)0)
{
m_size[0] = size0;
m_size[1] = size1;
m_data.resize(size0 * size1, value);
}
// Fill array with scalar s
void fill(SCALAR s)
{
std::fill(m_data.begin(), m_data.end(), s);
}
// Fill array with 0
void zero()
{
fill(0);
}
// Read & write element access
SCALAR& operator()(unsigned int i, unsigned int j)
{
assert(i >= 0 && i < m_size[0] && j >= 0 && j < m_size[1]);
return m_data[i * m_size[1] + j];
}
// Read only element access
const SCALAR& operator()(unsigned int i, unsigned int j) const
{
assert(i >= 0 && i < m_size[0] && j >= 0 && j < m_size[1]);
return m_data[i * m_size[1] + j];
}
// Dimension
int size(int dimension) const
{
assert(dimension >= 0 && dimension < 2);
return (int)m_size[dimension];
}
// Assignment
Array2T<SCALAR> &operator=(const Array2T<SCALAR> &m2)
{
if (&m2 != this)
{
resize(m2.size(0), m2.size(1));
int n = (int)m_data.size();
for (int i = 0; i < n; i++)
m_data[i] = m2.m_data[i];
}
return *this;
}
protected:
unsigned int m_size[2];
std::vector<SCALAR> m_data;
};
typedef Array2T<double> Array2d;
#ifndef ARROW_H
#define ARROW_H
#include <Eigen/Core>
#include <vector>
class Arrow {
public:
Arrow(const Eigen::RowVector3d& s, const Eigen::RowVector3d& e) {
Arrow(s, e, Eigen::RowVector3d(1.0, 0, 0));
}
Arrow(const Eigen::RowVector3d& s, const Eigen::RowVector3d& e,
const Eigen::RowVector3d& c)
: start(s), end(e), color(c) {
direction = (end - start).normalized();
Eigen::RowVector3d per1 =
direction.cross(Eigen::Vector3d(1, 0, 0)).normalized() * 0.5;
if (std::isnan(per1.sum())) {
per1 = direction.cross(Eigen::Vector3d(0, 1, 0)).normalized() * 0.5;
}
Eigen::RowVector3d per2 =
direction.cross(per1.normalized()).normalized() * 0.5;
head.resize(4);
head[0] = end - 0.1 * (direction + per1);
head[1] = end - 0.1 * (direction - per1);
head[2] = end - 0.1 * (direction + per2);
head[3] = end - 0.1 * (direction - per2);
}
Eigen::RowVector3d start;
Eigen::RowVector3d end;
Eigen::RowVector3d direction;
std::vector<Eigen::RowVector3d> head;
Eigen::RowVector3d color;
size_t id;
};
#endif // ARROW_H
\ No newline at end of file
#include "BaseObject.h"
#include <igl/per_face_normals.h>
#include <igl/per_vertex_normals.h>
#include <igl/readOBJ.h>
#include <igl/readOFF.h>
bool BaseObject::loadMesh(const std::string& path) {
bool succ = false;
std::ifstream infile(path);
if (!infile.good()) {
return false;
}
const std::string OFF(".off");
if (path.compare(path.size() - OFF.size(), OFF.size(), OFF) == 0) {
succ = igl::readOFF(path, m_mesh.V, m_mesh.F, m_mesh.V_normals);
if (succ) {
std::cout << "Reading OFF-file from " << path << " ..."
<< std::endl;
}
}
const std::string OBJ(".obj");
if (path.compare(path.size() - OBJ.size(), OBJ.size(), OBJ) == 0) {
succ = igl::readOBJ(path, m_mesh.V, m_mesh.F);
if (succ) {
std::cout << "Reading OBJ-file from " << path << " ..."
<< std::endl;
igl::per_vertex_normals(m_mesh.V, m_mesh.F, m_mesh.V_normals);
}
}
m_mesh.C = Eigen::MatrixXd(1, 3);
m_mesh.C << 255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0;
return succ;
}
void BaseObject::setMesh(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F) {
m_mesh.V = V;
m_mesh.F = F;
}
void BaseObject::findAndLoadMesh(const std::string& file) {
if (loadMesh(file)) return;
if (loadMesh("data/" + file)) return;
if (loadMesh("../data/" + file)) return;
if (loadMesh("../../data/" + file)) return;
if (loadMesh("../../../data/" + file)) return;
std::cerr << "Failed to find " << file << std::endl;
}
void BaseObject::reset() {
setPosition(Eigen::Vector3d::Zero());
setRotation(Eigen::Matrix3d::Identity());
resetMembers();
}
void BaseObject::recomputeCOM() {
Eigen::Vector3d COM = m_mesh.V.colwise().mean();
m_mesh.V = m_mesh.V.rowwise() - COM.transpose();
}
void BaseObject::setScale(double s) { m_scale = s; }
void BaseObject::setID(int id) { m_id = id; }
void BaseObject::setType(ObjType t) { m_type = t; }
void BaseObject::setPosition(const Eigen::Vector3d& p) { m_position = p; }
void BaseObject::setRotation(const Eigen::Quaterniond& q) {
m_quat = q;
m_rot = q.toRotationMatrix();
}
void BaseObject::setRotation(const Eigen::Matrix3d& R) {
m_rot = R;
m_quat = R;
}
void BaseObject::setColors(const Eigen::MatrixXd& C) { m_mesh.C = C; }
double BaseObject::getScale() const { return m_scale; }
int BaseObject::getID() const { return m_id; }
ObjType BaseObject::getType() const { return m_type; }
Eigen::Vector3d BaseObject::getPosition() const { return m_position; }
Eigen::Quaterniond BaseObject::getRotation() const { return m_quat; }
Eigen::Matrix3d BaseObject::getRotationMatrix() const { return m_rot; }
Eigen::Vector3d BaseObject::getVertexPosition(int vertexIndex) const {
return m_mesh.V.row(vertexIndex) * m_scale *
getRotationMatrix().transpose() +
getPosition().transpose();
}
void BaseObject::getMesh(Eigen::MatrixXd& V, Eigen::MatrixXi& F) const {
// get mesh after rotation and translation
V = (m_mesh.V * m_scale * getRotationMatrix().transpose()).rowwise() +
getPosition().transpose();
F = m_mesh.F;
}
void BaseObject::getColors(Eigen::MatrixXd& C) const { C = m_mesh.C; }
\ No newline at end of file
#ifndef BASEOBJECT_H
#define BASEOBJECT_H
#include <igl/per_face_normals.h>
#include <igl/per_vertex_normals.h>
#include <igl/readOBJ.h>
#include <igl/readOFF.h>
#include <Eigen/Core>
struct Mesh {
Eigen::MatrixXd V;
Eigen::MatrixXi F;
Eigen::MatrixXd C;
// Per face attributes
Eigen::MatrixXd F_normals; // One normal per face
// Per vertex attributes
Eigen::MatrixXd V_normals; // One normal per vertex
// UV parametrization
Eigen::MatrixXd V_uv; // UV vertices
Eigen::MatrixXi F_uv; // optional faces for UVs
};
enum class ObjType { STATIC, DYNAMIC };
class BaseObject {
public:
bool loadMesh(const std::string& path);
void setMesh(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F);
void findAndLoadMesh(const std::string& file);
void reset();
void recomputeCOM();
void setScale(double s);
void setID(int id);
virtual void setType(ObjType t);
void setPosition(const Eigen::Vector3d& p);
void setRotation(const Eigen::Quaterniond& q);
void setRotation(const Eigen::Matrix3d& R);
void setColors(const Eigen::MatrixXd& C);
double getScale() const;
int getID() const;
ObjType getType() const;
Eigen::Vector3d getPosition() const;
Eigen::Quaterniond getRotation() const;
Eigen::Matrix3d getRotationMatrix() const;
Eigen::Vector3d getVertexPosition(int vertexIndex) const;
void getMesh(Eigen::MatrixXd& V, Eigen::MatrixXi& F) const;
void getColors(Eigen::MatrixXd& C) const;
virtual ~BaseObject() {}
protected:
/*
* Reset class variables specific to a certain object. Is called by
* BaseObject::reset().
*/
virtual void resetMembers() = 0;
int m_id = -1;
Mesh m_mesh;
ObjType m_type;
double m_scale = 1.0; // Scale
Eigen::Vector3d m_position; // Position of the center of mass
Eigen::Quaterniond m_quat; // Rotation (quaternion)
Eigen::Matrix3d m_rot; // Rotation (matrix)
};
#endif
\ No newline at end of file
#ifndef GRID2_H
#define GRID2_H
#include <igl/colormap.h>
#include <Eigen/Core>
#include "Array2T.h"
class Grid2 {
public:
Grid2(int res_x, int res_y, double dx) {
m_res_x = res_x;
m_res_y = res_y;
m_dx = dx;
m_x = Array2d(res_x, res_y);
buildMesh();
}
Array2d& x() { return m_x; }
void buildMesh() {
int num_vertices = (m_res_x + 1) * (m_res_y + 1);
int num_faces = m_res_x * m_res_y * 2; // 2 triangles per cell
m_V = Eigen::MatrixXd(num_vertices, 3);
m_F = Eigen::MatrixXi(num_faces, 3);
int i = 0;
for (int y = 0; y <= m_res_y; ++y) {
for (int x = 0; x <= m_res_x; ++x) {
m_V.row(i++) = Eigen::RowVector3d(x, y, 0) * m_dx;
}
}
i = 0;
for (int y = 0; y < m_res_y; ++y) {
for (int x = 0; x < m_res_x; ++x) {
int vid = y * (m_res_x + 1) + x;
int vid_right = vid + 1;
int vid_right_up = vid_right + (m_res_x + 1);
int vid_up = vid + (m_res_x + 1);
m_F.row(i++) = Eigen::RowVector3i(vid, vid_right, vid_right_up);
m_F.row(i++) = Eigen::RowVector3i(vid, vid_right_up, vid_up);
}
}
}
void reset() {
m_x.zero();
}
void applySource(double xmin, double xmax, double ymin, double ymax) {
for (int y = (int)(ymin * m_res_y); y < (int)(ymax * m_res_y); y++) {
for (int x = (int)(xmin * m_res_x); x < (int)(xmax * m_res_x); x++) {
m_x(x, y) = 1.0;
}
}
}
void getMesh(Eigen::MatrixXd& V, Eigen::MatrixXi& F) const {
V = m_V;
F = m_F;
}
void getColors(Eigen::MatrixXd& C, bool normalize=false, bool faceColor=true) const {
if (faceColor) {
if (C.rows() == 0) {
int num_faces = m_res_x * m_res_y * 2; // 2 triangles per cell
C = Eigen::MatrixXd(num_faces, 3);
}
int i = 0;
double cmin = m_x(0, 0);
double cmax = cmin;
for (int y = 0; y < m_res_y; ++y) {
for (int x = 0; x < m_res_x; ++x) {
double c = m_x(x, y);
if (normalize) {
if (c > cmax) cmax = c;
if (c < cmin) cmin = c;
}
else {
C.row(i++).setConstant(c);
C.row(i++).setConstant(c);
}
}
}
if (!normalize) return;
else if (cmin == cmax) {
C.setZero();
return;
}
// std::cout << "cmin:" << cmin << " cmax:" << cmax << std::endl;
for (int y = 0; y < m_res_y; ++y) {
for (int x = 0; x < m_res_x; ++x) {
double c = m_x(x, y);
c = (c - cmin) / (cmax - cmin); // [0,1]
double r, g, b;
igl::colormap(igl::COLOR_MAP_TYPE_VIRIDIS, c, r, g, b);
C.row(i++) = Eigen::RowVector3d(r, g, b);
C.row(i++) = Eigen::RowVector3d(r, g, b);
}
}
}
else {
// vertex color
if (C.rows() == 0) {
int num_vertices = (m_res_x + 1) * (m_res_y + 1);
C = Eigen::MatrixXd(num_vertices, 3);
}
int i = 0;
double cmin = m_x(0, 0);
double cmax = cmin;
for (int y = 0; y <= m_res_y; ++y) {
for (int x = 0; x <= m_res_x; ++x) {
int x0 = std::max(x - 1, 0);
int x1 = std::min(x, m_res_x - 1);
int y0 = std::max(y - 1, 0);
int y1 = std::min(y, m_res_y - 1);
double c00 = m_x(x0, y0);
double c01 = m_x(x0, y1);
double c10 = m_x(x1, y0);
double c11 = m_x(x1, y1);
double c = (c00 + c01 + c10 + c11) / 4;
if (normalize) {
if (c > cmax) cmax = c;
if (c < cmin) cmin = c;
}
C.row(i++).setConstant(c);
}
}
if (!normalize) return;
else if (cmin == cmax) {
C.setZero();
return;
}
i = 0;
// std::cout << "cmin:" << cmin << " cmax:" << cmax << std::endl;
for (int y = 0; y <= m_res_y; ++y) {
for (int x = 0; x <= m_res_x; ++x) {
double c = (C(i, 0) - cmin) / (cmax - cmin); // [0,1]
double r, g, b;
igl::colormap(igl::COLOR_MAP_TYPE_VIRIDIS, c, r, g, b);
C.row(i++) = Eigen::RowVector3d(r, g, b);
}
}
}
}
protected:
int m_res_x, m_res_y;
double m_dx;
Array2d m_x;
Eigen::MatrixXd m_V;
Eigen::MatrixXi m_F;
};
#endif // GRID2_H
\ No newline at end of file
This diff is collapsed.
#ifndef GUI_H
#define GUI_H
#include <igl/opengl/glfw/Viewer.h>
#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
#include "Arrow.h"
#include "ReferencePlane.h"
#include "Simulator.h"
/*
* Base class to open a window with a simple GUI for simulation. Inherit from
* this class to perform a simulation and customize the menu.
*/
class Gui {
public:
Gui() {}
~Gui() {}
/*
* Set simulation to be performed in the simulator.
*/
void setSimulation(Simulation *sim);
/*
* Initialize all the necessary data structures and callbacks and open the
* window.
*/
void start();
/*
* Call the setters for your simulation in this method to update the
* parameters entered in the GUI. This method is called before the
* simulation is started for the first time.
*/
virtual void updateSimulationParameters() = 0;
/*
* Clear some custom datastructures/visualizations when the user requests
* it.
*/
virtual void clearSimulation() {}
/*
* Callback to enable custom shortcuts.
*/
virtual bool childKeyCallback(igl::opengl::glfw::Viewer &viewer,
unsigned int key, int modifiers) {
return false;
}
/*
* Setup your own (additional) ImGUI components in this method.
*/
virtual void drawSimulationParameterMenu() {}
/*
* Setup your own (additional) ImGUI debugging output.
*/
virtual void drawSimulationStats() {}
#pragma region ArrowInterface
/*
* Create and add an arrow to be displayed in the GUI. Returns the index of
* the drawn arrow (keep it if you want to delete this arrow later).
*/
int addArrow(const Eigen::Vector3d &start, const Eigen::Vector3d &end,
const Eigen::Vector3d &color=Eigen::RowVector3d(1, 0, 0));
/*
* Delete arrow at given index.
*/
void removeArrow(size_t index);
#pragma endregion ArrowInterface
/*
* Show the standard basis axis (x, y, z)
*/
void showAxes(bool show_axes);
/*
* Callback to show a different vector for a clicked vertex than the normal
*/
std::function<void(int clickedVertexIndex, int clickedObjectIndex,
Eigen::Vector3d &pos, Eigen::Vector3d &dir)>
callback_clicked_vertex = nullptr;
void turnOffLight() { m_viewer.core().lighting_factor = 0; }
protected:
void drawArrow(const Arrow &arrow);
void drawReferencePlane();
void showVertexArrow();
void toggleSimulation();
void singleStep();
void resetSimulation();
void exportRecording();
void clearScreen();
bool keyCallback(igl::opengl::glfw::Viewer &viewer, unsigned int key,
int modifiers);
bool keyReleasedCallback(igl::opengl::glfw::Viewer &viewer,
unsigned int key, int modifiers);
void drawMenuWindow(igl::opengl::glfw::imgui::ImGuiMenu &menu);
bool drawMenu(igl::opengl::glfw::Viewer &viewer,
igl::opengl::glfw::imgui::ImGuiMenu &menu);
bool drawCallback(igl::opengl::glfw::Viewer &viewer);
bool scrollCallback(igl::opengl::glfw::Viewer &viewer, float delta_y);
bool mouseCallback(igl::opengl::glfw::Viewer &viewer,
igl::opengl::glfw::imgui::ImGuiMenu &menu, int button,
int modifier);
igl::opengl::glfw::Viewer m_viewer;
Simulator *p_simulator = NULL;
bool m_request_clear = false;
int m_simSpeed = 60;
bool m_fastForward = false;
int m_clickedVertex = -1; // index of clicked vertex
int m_clickedObject = -1; // id of clicked object
int m_clickedArrow = -1; // index of arrow of clicked vertex
std::vector<Arrow> m_arrows; // data structure to store all the arrows
// to be rendered
unsigned long m_numArrows = 0; // increasing counter for arrows
int m_axesID = -1; // (lowest) id of the 3 base axes
bool m_showAxes = true;
ReferencePlane m_referencePlane;
bool m_showReferencePlane = true;
bool m_showStats = true;
double m_timerAverage = 0; // running average of execution time of
// one iteration of the simulation
int m_maxSteps = -1;
int m_numRecords = 100; // number of records to keep
};
#endif
\ No newline at end of file
#ifndef MACGRID2_H
#define MACGRID2_H
#include <igl/colormap.h>
#include <Eigen/Core>
#include "Array2T.h"
class MACGrid2 {
public:
MACGrid2(int res_x, int res_y, double dx) {
m_res_x = res_x;
m_res_y = res_y;
m_dx = dx;
m_x = Array2d(res_x + 1, res_y);
m_y = Array2d(res_x, res_y + 1);
buildGrid();
}
Array2d& x() { return m_x; }
Array2d& y() { return m_y; }
const Eigen::MatrixXd& s() { return m_start; }
const Eigen::MatrixXd& e() { return m_end; }
const Eigen::MatrixXd& vs() { return m_vs; }
const Eigen::MatrixXd& ve() { return m_ve; }
const Eigen::MatrixXd& vc() { return m_vc; }
void buildGrid() {
int num_edges = 2 * m_res_x * m_res_y + m_res_x + m_res_y;
m_start = Eigen::MatrixXd(num_edges, 3);
m_end = Eigen::MatrixXd(num_edges, 3);
int i = 0;
for (int y = 0; y <= m_res_y; ++y)
for (int x = 0; x <= m_res_x; ++x) {
if (x < m_res_x) {
m_start.row(i) = Eigen::RowVector3d(x, y, 0) * m_dx;
m_end.row(i++) = Eigen::RowVector3d(x + 1, y, 0) * m_dx;
}
if (y < m_res_y) {
m_start.row(i) = Eigen::RowVector3d(x, y, 0) * m_dx;
m_end.row(i++) = Eigen::RowVector3d(x, y + 1, 0) * m_dx;
}
}
}
void updateEdges(double scale = 1) {
int num_edges = (m_res_x + 1) * m_res_y + m_res_x * (m_res_y + 1) + m_res_x * m_res_y;
if (m_vs.rows() == 0) {
m_vs = Eigen::MatrixXd(num_edges, 3);
m_ve = Eigen::MatrixXd(num_edges, 3);
m_vc = Eigen::MatrixXd(num_edges, 3);
}
int i = 0;
for (int y = 0; y <= m_res_y; ++y)
for (int x = 0; x <= m_res_x; ++x) {
if (y < m_res_y) {
m_vc.row(i) = Eigen::RowVector3d(1, 0, 0);
m_vs.row(i) = Eigen::RowVector3d(x, y + 0.5, 0) * m_dx;
m_ve.row(i++) = Eigen::RowVector3d(x + m_x(x, y) * scale, y + 0.5, 0) * m_dx;
}
if (x < m_res_x) {
m_vc.row(i) = Eigen::RowVector3d(0, 0, 1);
m_vs.row(i) = Eigen::RowVector3d(x + 0.5, y, 0) * m_dx;
m_ve.row(i++) = Eigen::RowVector3d(x + 0.5, y + m_y(x, y) * scale, 0) * m_dx;
}
if (y < m_res_y && x < m_res_x) {
double vx = (m_x(x, y) + m_x(x + 1, y)) * 0.5;
double vy = (m_y(x, y) + m_y(x, y + 1)) * 0.5;
m_vc.row(i) = Eigen::RowVector3d(0, 1, 0);
m_vs.row(i) = Eigen::RowVector3d(x + 0.5, y + 0.5, 0) * m_dx;
m_ve.row(i++) = Eigen::RowVector3d(x + 0.5 + vx * scale, y + 0.5 + vy * scale, 0) * m_dx;
}
}
}
void reset() {
m_x.zero();
m_y.zero();
}
protected:
int m_res_x, m_res_y;
double m_dx;
Array2d m_x;
Array2d m_y;
Eigen::MatrixXd m_start;
Eigen::MatrixXd m_end;
Eigen::MatrixXd m_vs;
Eigen::MatrixXd m_ve;
Eigen::MatrixXd m_vc;
};
#endif // MACGRID2_H
\ No newline at end of file
#include <Eigen/Core>
#include <vector>
class ReferencePlane {
public:
ReferencePlane() : size(10), color(Eigen::RowVector3d(0.25, 0.25, 0.25)) {
//// for set_edges
//int num_edges = 2 * (2 * size)*(2 * size) + (2 * size) * 2;
//int num_points = (2 * size + 1)*(2 * size + 1);
//points = Eigen::MatrixXd(num_points, 3);
//edges = Eigen::MatrixXi(num_edges, 2);
//int i = 0;
//for (int z = -size; z <= size; ++z) {
// for (int x = -size; x <= size; ++x) {
// points.row(i++) = Eigen::RowVector3d(x, -5, z);
// }
//}
//i = 0;
//for (int z = 0; z <= 2*size; ++z) {
// for (int x = 0; x <= 2*size; ++x) {
// int p1 = z * (2 * size + 1) + x;
// int p2 = p1 + 1;
// int p3 = p1 + (2 * size + 1);
// if (x < 2*size)
// edges.row(i++) = Eigen::RowVector2i(p1, p2);
// if (z < 2 * size)
// edges.row(i++) = Eigen::RowVector2i(p1, p3);
// }
//}
int num_edges = 2 * (2 * size)*(2 * size) + (2 * size) * 2;
start = Eigen::MatrixXd(num_edges, 3);
end = Eigen::MatrixXd(num_edges, 3);
int e = 0;
for (int z = -size; z <= size; ++z)
for (int x = -size; x <= size; ++x) {
if (x < size) {
start.row(e) = Eigen::RowVector3d(x, 0, z);
end.row(e++) = Eigen::RowVector3d(x + 1, 0, z);
}
if (z < size) {
start.row(e) = Eigen::RowVector3d(x, 0, z);
end.row(e++) = Eigen::RowVector3d(x, 0, z + 1);
}
}
}
//Eigen::MatrixXd points;
//Eigen::MatrixXi edges;
int size;
Eigen::MatrixXd start;
Eigen::MatrixXd end;
Eigen::RowVector3d color;
};
\ No newline at end of file
This diff is collapsed.
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