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

init

parents
build/
.DS_Store
.vscode
.clang-format
*.aux
*.log
*.gz
*.out
\ No newline at end of file
[submodule "libigl"]
path = libigl
url = http://dalab.se.sjtu.edu.cn/gitlab/xiaoyuwei/libigl.git
cmake_minimum_required(VERSION 3.1)
project(0_dummy)
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 "DummySim.h"
using namespace std;
/*
* Example simulation that changes the colors of a cube.
*/
DummySim::DummySim() : Simulation() {
init();
}
void DummySim::init() {
// create a cube on [-1,1]^3
// vertices
m_V.resize(8, 3);
int v = 5;
m_V << -v, -v, -v, v, -v, -v, -v, v, -v, v, v, -v, -v, -v, v, v, -v, v,
-v, v, v, v, v, v;
// faces
m_F.resize(12, 3);
m_F << 0, 2, 1, 2, 3, 1, 1, 3, 5, 3, 7, 5, 2, 6, 3, 6, 7, 3, 5, 7, 4, 7,
6, 4, 4, 6, 0, 6, 2, 0, 0, 4, 1, 4, 5, 1;
// face colors
m_C.resize(12, 3);
reset();
}
void DummySim::resetMembers() {
m_C.setZero();
m_C.col(0).setOnes();
}
void DummySim::updateRenderGeometry() {
m_renderV = m_V;
m_renderF = m_F;
m_renderC = m_C;
}
bool DummySim::advance() {
// do next step of some color animation
int speed = 60;
int decColor = (m_step / speed) % 3;
int incColor = (decColor + 1) % 3;
for (int i = 0; i < m_C.rows(); i++) {
m_C(i, decColor) = (m_C(i, decColor) * speed - 1) / speed;
m_C(i, incColor) = (m_C(i, incColor) * speed + 1) / speed;
}
// advance step
m_step++;
return false;
}
void DummySim::renderRenderGeometry(
igl::opengl::glfw::Viewer &viewer) {
viewer.data().set_mesh(m_renderV, m_renderF);
viewer.data().set_colors(m_renderC);
}
\ No newline at end of file
#include "Simulation.h"
/*
* Example simulation that changes the colors of a cube.
*/
class DummySim : public Simulation {
public:
DummySim();
virtual void init() override;
virtual void resetMembers() override;
virtual void updateRenderGeometry() override;
virtual bool advance() override;
virtual void renderRenderGeometry(igl::opengl::glfw::Viewer &viewer) override;
private:
Eigen::MatrixXd m_V; // vertex positions
Eigen::MatrixXi m_F; // face indices
Eigen::MatrixXd m_C; // colors per face
Eigen::MatrixXd m_renderV; // vertex positions for rendering
Eigen::MatrixXi m_renderF; // face indices for rendering
Eigen::MatrixXd m_renderC; // colors per face for rendering
};
\ No newline at end of file
#include <igl/writeOFF.h>
#include <thread>
#include "DummySim.h"
#include "Gui.h"
#include "Simulator.h"
/*
* This class is a GUI for our dummy simulation. It extends the basic GUI
* defined in Gui.h. We could add more controls and visuals here, but we don't
* need any additional functionality for this dummy simulation.
*/
class DummyGui : public Gui {
public:
DummySim *p_dummySim = NULL; // pointer to the dummy simulation
DummyGui() {
// create a new dummy simulation
p_dummySim = new DummySim();
// set this simulation as the simulation that is running in our GUI
setSimulation(p_dummySim);
// start the GUI
start();
}
virtual void updateSimulationParameters() override {
// We don't have any simulation parameters to update periodically so we
// don't need to do anything here
};
};
int main(int argc, char *argv[]) {
// create a new instance of the GUI for the dummy simulation
new DummyGui();
return 0;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.1)
project(PBS)
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-1_cannonball)
add_subdirectory(1-2_spring)
add_subdirectory(2-1_spinning)
add_subdirectory(2-2_gyro)
add_subdirectory(3_collision)
add_subdirectory(4_mss)
add_subdirectory(5_fluid)
\ No newline at end of file
# Computer Animation 2020 - Exercise
## Overview
Code framework for course exercise.
## Installation
Install **Git** and build system **Cmake**.
### 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
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
```
## 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`*.
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.01 -1
1 -0.01 -1
-1 0.01 -1
1 0.01 -1
-1 -0.01 1
1 -0.01 1
-1 0.01 1
1 0.01 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
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