├── resources ├── simple_frag.glsl ├── simple_vert.glsl ├── phong_vert.glsl ├── phong_frag.glsl └── box.obj ├── src ├── runner.h ├── UtilEOL.h ├── remeshExtension.h ├── parseParams.h ├── Collisions.h ├── external │ ├── SolverWrappers │ │ ├── Gurobi │ │ │ ├── eigen_gurobi_api.h │ │ │ └── Gurobi.h │ │ └── Mosek │ │ │ ├── QuadProg.h │ │ │ └── QuadProgMosek.h │ └── ArcSim │ │ ├── referenceshape.hpp │ │ ├── magic.cpp │ │ ├── tensormax.hpp │ │ ├── referenceshape.cpp │ │ ├── dynamicremesh.hpp │ │ ├── io.hpp │ │ ├── subset.hpp │ │ ├── magic.hpp │ │ ├── remesh.hpp │ │ ├── winport.hpp │ │ ├── blockvectors.hpp │ │ ├── transformation.hpp │ │ ├── subset.cpp │ │ ├── geometry.hpp │ │ ├── util.cpp │ │ ├── optimization.hpp │ │ ├── tensormax.cpp │ │ ├── transformation.cpp │ │ ├── util.hpp │ │ └── io.cpp ├── Preprocessor.h ├── conversions.cpp ├── conversions.h ├── Brenderable.h ├── Points.h ├── Points.cpp ├── ComputeInertial.h ├── main.cpp ├── GeneralizedSolver.h ├── BrenderManager.h ├── ComputeBending.h ├── ComputeMembrane.h ├── genSet.h ├── FixedList.h ├── Forces.h ├── online │ ├── Program.h │ ├── GLSL.h │ ├── Camera.h │ ├── MatrixStack.h │ ├── Camera.cpp │ ├── MatrixStack.cpp │ ├── Program.cpp │ └── GLSL.cpp ├── Rigid.h ├── Obstacles.h ├── matlabOutputs.h ├── Shape.h ├── Constraints.h ├── Scene.h ├── Obstacles.cpp ├── Box.h ├── UtilEOL.cpp ├── BrenderManager.cpp ├── Cloth.h ├── Collisions.cpp ├── Scene.cpp ├── Box.cpp ├── matlabOutputs.cpp ├── Rigid.cpp ├── GeneralizedSolver.cpp ├── ComputeInertial.cpp ├── boxTriCollision.h ├── remeshExtension.cpp ├── Shape.cpp ├── runner.cpp └── raytri.cpp ├── generalSettings.json ├── LICENSE ├── simulationSettingsBox.json ├── simulationSettings.json └── README.md /resources/simple_frag.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | varying vec3 color; 4 | 5 | void main() 6 | { 7 | gl_FragColor = vec4(color, 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /src/runner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __runner__ 3 | #define __runner__ 4 | 5 | #include 6 | 7 | void start_running(const std::string &GENSET_FILE, const std::string &SIMSET_FILE); 8 | 9 | #endif -------------------------------------------------------------------------------- /resources/simple_vert.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | uniform mat4 P; 4 | uniform mat4 MV; 5 | varying vec3 color; 6 | 7 | void main() 8 | { 9 | gl_Position = P * MV * gl_Vertex; 10 | color = gl_Color.rgb; 11 | } 12 | -------------------------------------------------------------------------------- /generalSettings.json: -------------------------------------------------------------------------------- 1 | // General EOL Cloth settings 2 | // Not including a setting will fall back to its default 3 | { 4 | 5 | "online": true, 6 | "exportObjs": false, 7 | "exportTimings": false, 8 | "RESOURCE_DIR": "D:/Git/eol-cloth/resources", 9 | "OUTPUT_DIR": "D:/Git/eol-cloth/build/objs" 10 | 11 | } -------------------------------------------------------------------------------- /src/UtilEOL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __UTILEOL__ 3 | #define __UTILEOL__ 4 | 5 | #include "external\ArcSim\mesh.hpp" 6 | 7 | #define EIGEN_DONT_ALIGN_STATICALLY 8 | #include 9 | 10 | Eigen::MatrixXd deform_grad(const Face *f); 11 | 12 | Eigen::MatrixXd deform_grad_v(const Vert* v); 13 | 14 | #endif -------------------------------------------------------------------------------- /src/remeshExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __remeshExtension__ 3 | #define __remeshExtension__ 4 | 5 | #include "external\ArcSim\remesh.hpp" 6 | 7 | RemeshOp split_edgeForced(Edge* edge, double d, double thresh); 8 | 9 | RemeshOp collapse_edgeForced(Edge* edge, int i); 10 | 11 | RemeshOp split_face(Face* face, Vec3 b); 12 | 13 | #endif -------------------------------------------------------------------------------- /src/parseParams.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __parseParams__ 3 | #define __parseParams__ 4 | 5 | #include "genSet.h" 6 | #include "Scene.h" 7 | #include 8 | #include 9 | 10 | void load_genset(const std::shared_ptr genset, const std::string &JSON_FILE); 11 | 12 | void load_simset(std::shared_ptr scene, const std::string &JSON_FILE); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /resources/phong_vert.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | attribute vec4 aPos; 4 | attribute vec3 aNor; 5 | attribute vec2 aTex; 6 | uniform mat4 P; 7 | uniform mat4 MV; 8 | varying vec3 vPos; 9 | varying vec3 vNor; 10 | varying vec2 vTex; 11 | 12 | void main() 13 | { 14 | vec4 posCam = MV * aPos; 15 | gl_Position = P * posCam; 16 | vPos = posCam.xyz; 17 | vNor = (MV * vec4(aNor, 0.0)).xyz; 18 | vTex = aTex; 19 | } 20 | -------------------------------------------------------------------------------- /src/Collisions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Collisions__ 3 | #define __Collisions__ 4 | 5 | #include "external\ArcSim\mesh.hpp" 6 | #include "boxTriCollision.h" 7 | #include "Obstacles.h" 8 | 9 | void CD(const Mesh& mesh, const std::shared_ptr obs, std::vector > &cls); 10 | 11 | void CD2(const Mesh& mesh, const std::shared_ptr obs, std::vector > &cls); 12 | 13 | #endif -------------------------------------------------------------------------------- /src/external/SolverWrappers/Gurobi/eigen_gurobi_api.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef WIN32 4 | #define EIGEN_GUROBI_DLLIMPORT __declspec(dllimport) 5 | #define EIGEN_GUROBI_DLLEXPORT __declspec(dllexport) 6 | #else 7 | #define EIGEN_GUROBI_DLLIMPORT 8 | #define EIGEN_GUROBI_DLLEXPORT 9 | #endif 10 | 11 | #ifdef EIGEN_GUROBI_EXPORT 12 | #define EIGEN_GUROBI_API EIGEN_GUROBI_DLLEXPORT 13 | #else 14 | #define EIGEN_GUROBI_API EIGEN_GUROBI_DLLIMPORT 15 | #endif 16 | -------------------------------------------------------------------------------- /src/Preprocessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Preprocessor__ 3 | #define __Preprocessor__ 4 | 5 | #include "external\ArcSim\mesh.hpp" 6 | #include "boxTriCollision.h" 7 | 8 | void preprocess(Mesh& mesh, const Eigen::MatrixXd &boundaries, std::vector > cls); 9 | 10 | void preprocessPart(Mesh& mesh, const Eigen::MatrixXd &boundaries, const std::vector > cls, int &part); 11 | 12 | void preprocessClean(Mesh& mesh); 13 | 14 | #endif -------------------------------------------------------------------------------- /src/conversions.cpp: -------------------------------------------------------------------------------- 1 | #include "conversions.h" 2 | 3 | #include "external\ArcSim\vectors.hpp" 4 | 5 | using namespace Eigen; 6 | 7 | Vec2 e2v(const Vector2d v) 8 | { 9 | return Vec2(v(0), v(1)); 10 | } 11 | 12 | Vec3 e2v(const Vector3d v) 13 | { 14 | return Vec3(v(0), v(1), v(2)); 15 | } 16 | 17 | Vector2d v2e(const Vec2 v) 18 | { 19 | return Vector2d(v[0], v[1]); 20 | } 21 | 22 | Vector2d v322e(const Vec3 v) 23 | { 24 | return Vector2d(v[0], v[1]); 25 | } 26 | 27 | Vector3d v2e(const Vec3 v) 28 | { 29 | return Vector3d(v[0], v[1], v[2]); 30 | } -------------------------------------------------------------------------------- /src/conversions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __CONVERSIONS__ 3 | #define __CONVERSIONS__ 4 | 5 | #include "external\ArcSim\vectors.hpp" 6 | 7 | #define EIGEN_DONT_ALIGN_STATICALLY 8 | #include 9 | 10 | // These conversions translate ArcSim vectors to Eigen vectors 11 | 12 | // Eigen 2 vec 13 | Vec2 e2v(const Eigen::Vector2d); 14 | Vec3 e2v(const Eigen::Vector3d); 15 | 16 | // Vec 2 Eigen 17 | Eigen::Vector2d v2e(const Vec2); 18 | Eigen::Vector3d v2e(const Vec3); 19 | 20 | // Vec 3D to Eigen 2D 21 | Eigen::Vector2d v322e(const Vec3 v); 22 | 23 | #endif -------------------------------------------------------------------------------- /resources/phong_frag.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | varying vec3 vPos; // in camera space 4 | varying vec3 vNor; // in camera space 5 | varying vec2 vTex; 6 | uniform vec3 kdFront; 7 | uniform vec3 kdBack; 8 | 9 | void main() 10 | { 11 | vec3 lightPos = vec3(0.0, 0.0, 0.0); 12 | vec3 n = normalize(vNor); 13 | vec3 l = normalize(lightPos - vPos); 14 | vec3 v = -normalize(vPos); 15 | vec3 h = normalize(l + v); 16 | vec3 kd = kdFront; 17 | float ln = dot(l, n); 18 | if(ln < 0.0) { 19 | kd = kdBack; 20 | ln = -ln; 21 | } 22 | vec3 diffuse = ln * kd; 23 | vec3 color = diffuse; 24 | gl_FragColor = vec4(color, 1.0); 25 | } 26 | -------------------------------------------------------------------------------- /src/Brenderable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: Gustavo Lopez 10-21-17 3 | * 4 | * @version: 1.0 5 | */ 6 | 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "BrenderManager.h" 13 | 14 | 15 | class Brenderable 16 | { 17 | public: 18 | Brenderable() {}; 19 | virtual ~Brenderable() {} 20 | virtual int getBrenderCount() const { return 1; } 21 | virtual std::vector getBrenderNames() const { return std::vector(1, ""); } 22 | virtual void exportBrender(std::vector< std::shared_ptr< std::ofstream > > outfiles) const = 0; 23 | private: 24 | 25 | }; -------------------------------------------------------------------------------- /src/Points.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Points__ 3 | #define __Points__ 4 | 5 | #include 6 | 7 | #define EIGEN_DONT_ALIGN_STATICALLY 8 | #include 9 | 10 | #ifdef EOLC_ONLINE 11 | class MatrixStack; 12 | class Program; 13 | #endif // EOLC_ONLINE 14 | 15 | class Points 16 | { 17 | public: 18 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 19 | 20 | Points() : num_points(0) {}; 21 | virtual ~Points() {}; 22 | 23 | int num_points; 24 | Eigen::MatrixXd pxyz; 25 | Eigen::MatrixXd norms; 26 | 27 | #ifdef EOLC_ONLINE 28 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 29 | #endif // EOLC_ONLINE 30 | 31 | private: 32 | 33 | }; 34 | 35 | #endif -------------------------------------------------------------------------------- /resources/box.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.78 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib box.mtl 4 | o Cube 5 | v 0.500000 -0.500000 -0.500000 6 | v 0.500000 -0.500000 0.500000 7 | v -0.500000 -0.500000 0.500000 8 | v -0.500000 -0.500000 -0.500000 9 | v 0.500000 0.500000 -0.500000 10 | v 0.500000 0.500000 0.500000 11 | v -0.500000 0.500000 0.500000 12 | v -0.500000 0.500000 -0.500000 13 | vn 0.0000 -0.5000 0.0000 14 | vn 0.0000 0.5000 0.0000 15 | vn 0.5000 0.0000 0.0000 16 | vn -0.0000 -0.0000 0.5000 17 | vn -0.5000 -0.0000 -0.0000 18 | vn 0.0000 0.0000 -0.5000 19 | usemtl Material 20 | s off 21 | f 1//1 2//1 3//1 4//1 22 | f 5//2 8//2 7//2 6//2 23 | f 1//3 5//3 6//3 2//3 24 | f 2//4 6//4 7//4 3//4 25 | f 3//5 7//5 8//5 4//5 26 | f 5//6 1//6 4//6 8//6 27 | -------------------------------------------------------------------------------- /src/Points.cpp: -------------------------------------------------------------------------------- 1 | #include "Points.h" 2 | 3 | #ifdef EOLC_ONLINE 4 | 5 | #ifdef EOLC_ONLINE 6 | #define GLEW_STATIC 7 | #include 8 | #include 9 | 10 | #define GLM_FORCE_RADIANS 11 | #include 12 | #include 13 | #include "glm/ext.hpp" 14 | 15 | #include "online/Program.h" 16 | #include "online/MatrixStack.h" 17 | #endif // EOLC_ONLINE 18 | 19 | using namespace std; 20 | 21 | void Points::drawSimple(shared_ptr MV, const shared_ptr prog) const 22 | { 23 | for (int i = 0; i < pxyz.cols(); i++) { 24 | glColor3f(0.0f, 1.0f, 1.0f); 25 | glPointSize(10.0f); 26 | glBegin(GL_POINTS); 27 | glVertex3f(pxyz(0,i), pxyz(1, i), pxyz(2, i)); 28 | glEnd(); 29 | } 30 | } 31 | 32 | #endif // EOLC_ONLINE -------------------------------------------------------------------------------- /src/ComputeInertial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __ComputeInertial__ 3 | #define __ComputeInertial__ 4 | 5 | void ComputeInertial( 6 | const double *xa, // [input 3x1] World position of vertex A 7 | const double *xb, // [input 3x1] World position of vertex B 8 | const double *xc, // [input 3x1] World position of vertex C 9 | const double *Xa, // [input 2x1] Material position of vertex A 10 | const double *Xb, // [input 2x1] Material position of vertex B 11 | const double *Xc, // [input 2x1] Material position of vertex C 12 | const double *g, // [input 3x1] 3D gravity vector 13 | double rho, // [input 1x1] Density (mass per area) 14 | double *W, // [output 1x1] Gravitational potential energy 15 | double *f, // [output 9x1] Gravity force vector 16 | double *M) // [output 9x9] Inertia matrix 17 | ; 18 | 19 | #endif -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef EOLC_MOSEK 5 | #include "external\SolverWrappers\Mosek\QuadProgMosek.h" 6 | #endif 7 | 8 | #ifdef EOLC_GUROBI 9 | #include "external\SolverWrappers\Gurobi\Gurobi.h" 10 | #endif 11 | 12 | #include "conversions.h" 13 | 14 | #include "runner.h" 15 | 16 | using namespace std; 17 | using namespace Eigen; 18 | 19 | int main(int argc, char **argv) 20 | { 21 | if (argc < 3) { 22 | cout << "Usage: " << endl; 23 | cout << " " << argv[0] << " " << endl; 24 | cout << "where the settings arguments are json file" << endl; 25 | cout << endl << "Refer to the examples and json templates for further details" << endl; 26 | return 0; 27 | } 28 | 29 | srand(time(NULL)); 30 | 31 | start_running(argv[1], argv[2]); 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /src/GeneralizedSolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __GeneralizedSolver__ 3 | #define __GeneralizedSolver__ 4 | 5 | #include 6 | #include 7 | 8 | #define EIGEN_DONT_ALIGN_STATICALLY 9 | #include 10 | #include 11 | 12 | class GeneralizedSolver 13 | { 14 | public: 15 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 16 | 17 | GeneralizedSolver(); 18 | virtual ~GeneralizedSolver() {}; 19 | 20 | enum Solver { 21 | NoSolver = 0, Mosek = 1, Gurobi = 2 22 | }; 23 | 24 | int whichSolver; 25 | 26 | bool velocitySolve(const bool& fixedPoints, const bool& collisions, 27 | Eigen::SparseMatrix& MDK, const Eigen::VectorXd& b, 28 | Eigen::SparseMatrix& Aeq, const Eigen::VectorXd& beq, 29 | Eigen::SparseMatrix& Aineq, const Eigen::VectorXd& bineq, 30 | Eigen::VectorXd& v); 31 | 32 | }; 33 | 34 | #endif -------------------------------------------------------------------------------- /src/BrenderManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: Gustavo Lopez 10-21-17 3 | * 4 | * @version: 1.0 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class Brenderable; 15 | 16 | class BrenderManager 17 | { 18 | private: 19 | static bool instanceFlag; 20 | static BrenderManager *manager; 21 | int frame; 22 | std::string EXPORT_DIR; 23 | std::vector > brenderables; 24 | BrenderManager() 25 | { 26 | //private constructor 27 | EXPORT_DIR = "."; 28 | frame = 0; 29 | } 30 | public: 31 | static BrenderManager* getInstance(); 32 | void setExportDir(std::string export_dir); 33 | int getFrame() const; 34 | void exportBrender(double time = 0.0); 35 | void add(std::shared_ptr brenderable); 36 | ~BrenderManager() 37 | { 38 | instanceFlag = false; 39 | } 40 | }; -------------------------------------------------------------------------------- /src/ComputeBending.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __ComputeBending__ 3 | #define __ComputeBending__ 4 | 5 | void ComputeBending( 6 | const double *x0, // [input 3x1] World position of vertex 0 7 | const double *x1, // [input 3x1] World position of vertex 1 8 | const double *x2, // [input 3x1] World position of vertex 2 9 | const double *x3, // [input 3x1] World position of vertex 3 10 | const double *X0, // [input 2x1] Material position of vertex 0 11 | const double *X1, // [input 2x1] Material position of vertex 1 12 | const double *X2, // [input 2x1] Material position of vertex 2 13 | const double *X3, // [input 2x1] Material position of vertex 3 14 | double beta, // [input 1x1] Bending stiffness 15 | double *W, // [output 1x1] Bending potential energy 16 | double *f, // [output 12x1] Bending force vector 17 | double *K) // [output 12x12] Bending stiffness matrix 18 | ; 19 | 20 | #endif -------------------------------------------------------------------------------- /src/ComputeMembrane.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __ComputeMembrane__ 3 | #define __ComputeMembrane__ 4 | 5 | void ComputeMembrane( 6 | const double *xa, // [input 3x1] World position of vertex A 7 | const double *xb, // [input 3x1] World position of vertex B 8 | const double *xc, // [input 3x1] World position of vertex C 9 | const double *Xa, // [input 2x1] Material position of vertex A 10 | const double *Xb, // [input 2x1] Material position of vertex B 11 | const double *Xc, // [input 2x1] Material position of vertex C 12 | double e, // [input 1x1] Young's modulus -pascals 13 | double nu, // [input 1x1] Poisson's ratio 0.3 or 0.2 14 | const double *P, // [input 2x3] Projection matrix (column major) 15 | const double *Q, // [input 2x2] Polar decomposition of \bar{F} (column major) 16 | double *W, // [output 1x1] Membrane potential energy 17 | double *f, // [output 9x1] Membrane force vector 18 | double *K) // [output 9x9] Membrane stiffness matrix 19 | ; 20 | 21 | #endif -------------------------------------------------------------------------------- /src/genSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __genSet__ 3 | #define __getSet__ 4 | 5 | #include 6 | #include 7 | 8 | class genSet 9 | { 10 | public: 11 | 12 | genSet() : online(false),exportObjs(false), RESOURCE_DIR(""), OUTPUT_DIR("") {}; 13 | virtual ~genSet() {}; 14 | 15 | bool online; 16 | bool exportObjs; 17 | bool exportTimings; 18 | std::string RESOURCE_DIR; 19 | std::string OUTPUT_DIR; 20 | 21 | void printGenSet() { 22 | std::cout << "General settings" << std::endl; 23 | std::cout << " online: " << printGenBool(online) << std::endl; 24 | std::cout << " exportObjs: " << printGenBool(exportObjs) << std::endl; 25 | std::cout << " exportTimings: " << printGenBool(exportTimings) << std::endl; 26 | std::cout << " RESOURCE_DIR: " << RESOURCE_DIR << std::endl; 27 | std::cout << " OUTPUT_DIR: " << OUTPUT_DIR << std::endl; 28 | } 29 | 30 | private: 31 | 32 | std::string printGenBool(bool b) { 33 | if (b) return "True"; 34 | return "False"; 35 | } 36 | 37 | }; 38 | 39 | #endif -------------------------------------------------------------------------------- /src/FixedList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __FixedList__ 3 | #define __FixedList__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define EIGEN_DONT_ALIGN_STATICALLY 10 | #include 11 | 12 | class FixedList 13 | { 14 | public: 15 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 16 | 17 | FixedList() : when(0.0) { 18 | c1 = Eigen::VectorXd::Zero(6); 19 | c2 = Eigen::VectorXd::Zero(6); 20 | c3 = Eigen::VectorXd::Zero(6); 21 | c4 = Eigen::VectorXd::Zero(6); 22 | 23 | c1c2 = Eigen::VectorXd::Zero(6); 24 | c2c4 = Eigen::VectorXd::Zero(6); 25 | c4c3 = Eigen::VectorXd::Zero(6); 26 | c3c1 = Eigen::VectorXd::Zero(6); 27 | }; 28 | virtual ~FixedList() {}; 29 | 30 | double when; 31 | 32 | int c1i, c2i, c3i, c4i; 33 | 34 | Eigen::VectorXd c1; 35 | Eigen::VectorXd c2; 36 | Eigen::VectorXd c3; 37 | Eigen::VectorXd c4; 38 | 39 | // I didn't impliment this here yet 40 | Eigen::VectorXd c1c2; 41 | Eigen::VectorXd c2c4; 42 | Eigen::VectorXd c4c3; 43 | Eigen::VectorXd c3c1; 44 | 45 | }; 46 | 47 | #endif -------------------------------------------------------------------------------- /src/Forces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Forces__ 3 | #define __Forces__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Cloth.h" 10 | 11 | #include "external\ArcSim\mesh.hpp" 12 | 13 | #define EIGEN_DONT_ALIGN_STATICALLY 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef EOLC_ONLINE 19 | class MatrixStack; 20 | class Program; 21 | #endif // EOLC_ONLINE 22 | 23 | //class Mesh; 24 | class Obstacles; 25 | 26 | class Forces 27 | { 28 | public: 29 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 30 | 31 | Forces() : EoL_cutoff(0) {}; 32 | virtual ~Forces() {}; 33 | 34 | Eigen::VectorXd f; 35 | Eigen::SparseMatrix M; 36 | Eigen::SparseMatrix MDK; 37 | 38 | int EoL_cutoff; 39 | 40 | void fill(const Mesh& mesh, const Material& mat, const Eigen::Vector3d& grav, double h); 41 | 42 | #ifdef EOLC_ONLINE 43 | void drawSimple(const Mesh& mesh, std::shared_ptr MV, const std::shared_ptr p) const; 44 | #endif // EOLC_ONLINE 45 | }; 46 | 47 | #endif -------------------------------------------------------------------------------- /src/online/Program.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Program__ 3 | #define __Program__ 4 | 5 | #include 6 | #include 7 | 8 | #define GLEW_STATIC 9 | #include 10 | 11 | /** 12 | * An OpenGL Program (vertex and fragment shaders) 13 | */ 14 | class Program 15 | { 16 | public: 17 | Program(); 18 | virtual ~Program(); 19 | 20 | void setVerbose(bool v) { verbose = v; } 21 | bool isVerbose() const { return verbose; } 22 | 23 | void setShaderNames(const std::string &v, const std::string &f); 24 | virtual bool init(); 25 | virtual void bind(); 26 | virtual void unbind(); 27 | 28 | void addAttribute(const std::string &name); 29 | void addUniform(const std::string &name); 30 | GLint getAttribute(const std::string &name) const; 31 | GLint getUniform(const std::string &name) const; 32 | 33 | protected: 34 | std::string vShaderName; 35 | std::string fShaderName; 36 | 37 | private: 38 | GLuint pid; 39 | std::map attributes; 40 | std::map uniforms; 41 | bool verbose; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/Rigid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _RIGID_H_ 3 | #define _RIGID_H_ 4 | 5 | #define EIGEN_DONT_ALIGN_STATICALLY 6 | #include 7 | #include 8 | 9 | typedef Eigen::Matrix Vector6d; 10 | typedef Eigen::Matrix Matrix6d; 11 | typedef Eigen::Matrix Matrix3x6d; 12 | typedef Eigen::Matrix Matrix6x3d; 13 | 14 | class Rigid 15 | { 16 | private: 17 | Rigid(); 18 | 19 | public: 20 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 21 | 22 | static Eigen::Matrix4d inverse(const Eigen::Matrix4d &E); 23 | static Matrix3x6d gamma(const Eigen::Vector3d &r); 24 | static Matrix6d adjoint(const Eigen::Matrix4d &E); 25 | static Eigen::Matrix3d bracket3(const Eigen::Vector3d &a); 26 | static Eigen::Matrix4d bracket6(const Vector6d &a); 27 | static Eigen::Vector3d unbracket3(const Eigen::Matrix3d &A); 28 | static Vector6d unbracket6(const Eigen::Matrix4d &A); 29 | static Eigen::Matrix4d integrate(const Eigen::Matrix4d &E0, const Eigen::VectorXd &phi, double h); 30 | static Vector6d log(const Eigen::Matrix4d &A); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/external/ArcSim/referenceshape.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REFERENCESHAPE_HPP 2 | #define REFERENCESHAPE_HPP 3 | 4 | #include "mesh.hpp" 5 | 6 | class ReferenceShape { 7 | public: 8 | virtual Vec3 closest_point (const Vec3& p) = 0; 9 | virtual bool raycast(Vec3& p, const Vec3& dir) = 0; 10 | }; 11 | 12 | class ReferenceSphere : public ReferenceShape { 13 | public: 14 | ReferenceSphere(const Vec3& center, double radius); 15 | ReferenceSphere(const Mesh& mesh); 16 | 17 | Vec3 closest_point (const Vec3& p); 18 | bool raycast(Vec3& p, const Vec3& dir); 19 | private: 20 | Vec3 center; 21 | double radius; 22 | }; 23 | 24 | class ReferenceLinear : public ReferenceShape { 25 | public: 26 | ReferenceLinear(const Mesh& mesh); 27 | 28 | Vec3 closest_point (const Vec3& p); 29 | bool raycast(Vec3& p, const Vec3& dir); 30 | }; 31 | 32 | class ReferenceMesh : public ReferenceShape { 33 | public: 34 | ReferenceMesh(const Mesh& mesh, const std::string& filename); 35 | 36 | Vec3 closest_point (const Vec3& p); 37 | bool raycast(Vec3& p, const Vec3& dir); 38 | }; 39 | 40 | 41 | #endif -------------------------------------------------------------------------------- /src/Obstacles.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Obstacles__ 3 | #define __Obstacles__ 4 | 5 | #define EIGEN_DONT_ALIGN_STATICALLY 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "BrenderManager.h" 12 | 13 | class Points; 14 | class Box; 15 | class Shape; 16 | 17 | #ifdef EOLC_ONLINE 18 | class MatrixStack; 19 | class Program; 20 | #endif // EOLC_ONLINE 21 | 22 | class Obstacles 23 | { 24 | public: 25 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 26 | 27 | Obstacles(); 28 | virtual ~Obstacles() {}; 29 | 30 | int num_boxes; 31 | double cdthreshold; 32 | std::shared_ptr points; 33 | std::vector > boxes; 34 | std::vector > shapes; 35 | 36 | void load(const std::string &RESOURCE_DIR); 37 | void step(double h); 38 | 39 | void addExport(BrenderManager *brender); 40 | 41 | #ifdef EOLC_ONLINE 42 | void draw(std::shared_ptr MV, const std::shared_ptr p) const; 43 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 44 | void init(); 45 | #endif // EOLC_ONLINE 46 | 47 | 48 | 49 | private: 50 | 51 | }; 52 | 53 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shinjiro Sueda, Nicholas J. Weidner, David I.W. Levin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/matlabOutputs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __matlabOutputs__ 3 | #define __matlabOutputs__ 4 | 5 | #include "external\ArcSim\mesh.hpp" 6 | 7 | #define EIGEN_DONT_ALIGN_STATICALLY 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | void mat_s2s_file(const Eigen::SparseMatrix& mat, const std::string &var_name, const std::string &file_name, const bool& overwrite); 14 | 15 | void mat_to_file(const Eigen::MatrixXd& mat, const std::string &var_name, const std::string &file_name, const bool &overwrite); 16 | 17 | void mat_to_file(const Eigen::MatrixXi& mat, const std::string &var_name, const std::string &file_name, const bool &overwrite); 18 | 19 | void vec_to_file(const Eigen::VectorXd& vec, const std::string &var_name, const std::string &file_name, const bool &overwrite); 20 | 21 | void vec_to_file(const Eigen::VectorXi& vec, const std::string &var_name, const std::string &file_name, const bool &overwrite); 22 | 23 | void mesh2m(const Mesh& mesh, const std::string &file_name, const bool &overwrite); 24 | 25 | void double_to_file(double d, const std::string &var_name, const std::string &file_name, const bool &overwrite); 26 | 27 | #endif -------------------------------------------------------------------------------- /src/Shape.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _SHAPE_H_ 3 | #define _SHAPE_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #define EIGEN_DONT_ALIGN_STATICALLY 9 | #include 10 | 11 | #ifdef EOLC_ONLINE 12 | class Program; 13 | #endif 14 | 15 | /** 16 | * A shape defined by a list of triangles 17 | * - posBuf should be of length 3*ntris 18 | * - norBuf should be of length 3*ntris (if normals are available) 19 | * - texBuf should be of length 2*ntris (if texture coords are available) 20 | * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. 21 | */ 22 | class Shape 23 | { 24 | public: 25 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 26 | 27 | Shape(); 28 | virtual ~Shape(); 29 | void loadMesh(const std::string &meshName); 30 | void exportBrender(const Eigen::Matrix4d& E, std::ofstream& outfile) const; 31 | 32 | #ifdef EOLC_ONLINE 33 | void init(); 34 | void draw(const std::shared_ptr prog) const; 35 | #endif // EOLC_ONLINE 36 | 37 | 38 | private: 39 | std::vector posBuf; 40 | std::vector norBuf; 41 | std::vector texBuf; 42 | unsigned posBufID; 43 | unsigned norBufID; 44 | unsigned texBufID; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/online/GLSL.h: -------------------------------------------------------------------------------- 1 | // 2 | // Many useful helper functions for GLSL shaders - gleaned from various sources including orange book 3 | // Created by zwood on 2/21/10. 4 | // Modified by sueda 10/15/15. 5 | // 6 | 7 | #pragma once 8 | #ifndef __GLSL__ 9 | #define __GLSL__ 10 | 11 | #define GLEW_STATIC 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // For printing out the current file and line number // 16 | /////////////////////////////////////////////////////////////////////////////// 17 | #include 18 | 19 | template 20 | std::string NumberToString(T x) 21 | { 22 | std::ostringstream ss; 23 | ss << x; 24 | return ss.str(); 25 | } 26 | 27 | #define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() 28 | /////////////////////////////////////////////////////////////////////////////// 29 | 30 | namespace GLSL { 31 | 32 | void checkVersion(); 33 | void checkError(const char *str = 0); 34 | void printProgramInfoLog(GLuint program); 35 | void printShaderInfoLog(GLuint shader); 36 | int textFileWrite(const char *filename, const char *s); 37 | char *textFileRead(const char *filename); 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/external/ArcSim/magic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "magic.hpp" 28 | 29 | Magic magic; 30 | -------------------------------------------------------------------------------- /src/online/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Camera__ 3 | #define __Camera__ 4 | 5 | #include 6 | 7 | #define GLM_FORCE_RADIANS 8 | #include 9 | 10 | class MatrixStack; 11 | 12 | class Camera 13 | { 14 | public: 15 | enum { 16 | ROTATE = 0, 17 | TRANSLATE, 18 | SCALE 19 | }; 20 | 21 | Camera(); 22 | virtual ~Camera(); 23 | void setInitDistance(float z) { translations.z = -std::abs(z); } 24 | void setAspect(float a) { aspect = a; }; 25 | void setFovy(float f) { fovy = f; }; 26 | void setZnear(float z) { znear = z; }; 27 | void setZfar(float z) { zfar = z; }; 28 | void setRotationFactor(float f) { rfactor = f; }; 29 | void setTranslationFactor(float f) { tfactor = f; }; 30 | void setScaleFactor(float f) { sfactor = f; }; 31 | void mouseClicked(float x, float y, bool shift, bool ctrl, bool alt); 32 | void mouseMoved(float x, float y); 33 | void toggleFlatView(); 34 | void mouseClickedFlat(float x, float y, bool shift, bool ctrl, bool alt); 35 | void mouseMovedFlat(float x, float y); 36 | void applyProjectionMatrix(std::shared_ptr P) const; 37 | void applyViewMatrix(std::shared_ptr MV) const; 38 | 39 | private: 40 | float aspect; 41 | float fovy; 42 | float znear; 43 | float zfar; 44 | glm::vec2 rotations; 45 | glm::vec3 translations; 46 | glm::vec2 mousePrev; 47 | int state; 48 | bool flat; 49 | float rfactor; 50 | float tfactor; 51 | float sfactor; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/Constraints.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Constraints__ 3 | #define __Constraints__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "external\ArcSim\mesh.hpp" 10 | 11 | #define EIGEN_DONT_ALIGN_STATICALLY 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef EOLC_ONLINE 17 | class MatrixStack; 18 | class Program; 19 | #endif // EOLC_ONLINE 20 | 21 | //class Mesh; 22 | class Obstacles; 23 | class FixedList; 24 | 25 | class Constraints 26 | { 27 | public: 28 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 29 | 30 | Constraints(); 31 | virtual ~Constraints() {}; 32 | 33 | bool hasFixed; 34 | bool hasCollisions; 35 | 36 | Eigen::SparseMatrix Aeq; 37 | Eigen::SparseMatrix Aineq; 38 | 39 | std::vector > drawAineq; 40 | std::vector > drawAeq; 41 | 42 | Eigen::VectorXd beq; 43 | Eigen::VectorXd bineq; 44 | 45 | Eigen::MatrixXd constraintTable; 46 | 47 | void init(const std::shared_ptr obs); 48 | void updateTable(const std::shared_ptr obs); 49 | void fill(const Mesh& mesh, const std::shared_ptr obs, const std::shared_ptr fs, double h, const bool& online); 50 | 51 | #ifdef EOLC_ONLINE 52 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 53 | #endif // EOLC_ONLINE 54 | }; 55 | 56 | #endif -------------------------------------------------------------------------------- /src/Scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Scene__ 3 | #define __Scene__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define EIGEN_DONT_ALIGN_STATICALLY 10 | #include 11 | 12 | #include "boxTriCollision.h" 13 | #include "BrenderManager.h" 14 | 15 | class Cloth; 16 | class Obstacles; 17 | class Constraints; 18 | class Shape; 19 | class GeneralizedSolver; 20 | 21 | #ifdef EOLC_ONLINE 22 | class MatrixStack; 23 | class Program; 24 | #endif // EOLC_ONLINE 25 | 26 | class Scene 27 | { 28 | public: 29 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 30 | 31 | Scene(); 32 | virtual ~Scene() {}; 33 | 34 | void load(const std::string &RESOURCE_DIR); 35 | void init(const bool& online, const bool& exportObjs, const std::string& OUTPUT_DIR); 36 | void reset(); 37 | void step(const bool& online, const bool& exportObjs); 38 | void partialStep(); 39 | 40 | #ifdef EOLC_ONLINE 41 | void draw(std::shared_ptr MV, const std::shared_ptr p) const; 42 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 43 | #endif // EOLC_ONLINE 44 | 45 | double h; 46 | 47 | Eigen::Vector3d grav; 48 | 49 | bool EOLon; 50 | bool REMESHon; 51 | 52 | int part; 53 | 54 | std::shared_ptr GS; 55 | 56 | std::shared_ptr cloth; 57 | std::shared_ptr obs; 58 | std::vector > cls; 59 | 60 | private: 61 | 62 | double t; 63 | 64 | // Export 65 | BrenderManager *brender; 66 | 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/external/SolverWrappers/Mosek/QuadProg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __QuadProg_H__ 3 | #define __QuadProg_H__ 4 | 5 | #include 6 | #include 7 | 8 | // Calling convention: 9 | // https://www.mathworks.com/help/optim/ug/quadprog.html 10 | class QuadProg 11 | { 12 | public: 13 | QuadProg() {} 14 | virtual ~QuadProg() {} 15 | 16 | virtual void setNumberOfVariables(int numVars) = 0; 17 | virtual void setNumberOfInequalities(int numIneq) = 0; 18 | virtual void setNumberOfEqualities(int numEq) = 0; 19 | 20 | virtual void setObjectiveMatrix(const Eigen::SparseMatrix & mat) = 0; 21 | virtual void setObjectiveVector(const Eigen::VectorXd & vector) = 0; 22 | virtual void setObjectiveConstant(double constant) = 0; 23 | 24 | virtual void setLowerVariableBound(const Eigen::VectorXd & bounds) = 0; 25 | virtual void setUpperVariableBound(const Eigen::VectorXd & bounds) = 0; 26 | 27 | virtual void setInequalityMatrix(const Eigen::SparseMatrix & mat) = 0; 28 | virtual void setInequalityVector(const Eigen::VectorXd & vector) = 0; 29 | 30 | virtual void setEqualityMatrix(const Eigen::SparseMatrix & mat) = 0; 31 | virtual void setEqualityVector(const Eigen::VectorXd & vector) = 0; 32 | 33 | virtual bool solve() = 0; 34 | 35 | virtual Eigen::VectorXd getPrimalSolution() = 0; 36 | virtual Eigen::VectorXd getDualInequality() = 0; 37 | virtual Eigen::VectorXd getDualEquality() = 0; 38 | virtual Eigen::VectorXd getDualLower() = 0; 39 | virtual Eigen::VectorXd getDualUpper() = 0; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/Obstacles.cpp: -------------------------------------------------------------------------------- 1 | #include "Obstacles.h" 2 | #include "Points.h" 3 | #include "Box.h" 4 | #include "Shape.h" 5 | 6 | #ifdef EOLC_ONLINE 7 | #include "online\MatrixStack.h" 8 | #include "online\Program.h" 9 | #endif // EOLC_ONLINE 10 | 11 | using namespace std; 12 | using namespace Eigen; 13 | 14 | Obstacles::Obstacles() : 15 | num_boxes(0) 16 | { 17 | points = std::make_shared(); 18 | } 19 | 20 | void Obstacles::load(const std::string &RESOURCE_DIR) 21 | { 22 | auto box_shape = make_shared(); 23 | box_shape->loadMesh(RESOURCE_DIR + "box.obj"); 24 | shapes.push_back(box_shape); 25 | } 26 | 27 | void Obstacles::step(double h) 28 | { 29 | for (int i = 0; i < boxes.size(); i++) { 30 | boxes[i]->step(h); 31 | } 32 | } 33 | 34 | void Obstacles::addExport(BrenderManager *brender) 35 | { 36 | for (int b = 0; b < num_boxes; b++) { 37 | brender->add(boxes[b]); 38 | } 39 | } 40 | 41 | #ifdef EOLC_ONLINE 42 | void Obstacles::init() 43 | { 44 | for (int i = 0; i < boxes.size(); i++) { 45 | boxes[i]->init(); 46 | } 47 | } 48 | 49 | void Obstacles::draw(std::shared_ptr MV, const std::shared_ptr p) const 50 | { 51 | glUniform3fv(p->getUniform("kdFront"), 1, Vector3f(0.0, 1.0, 1.0).data()); 52 | for (int i = 0; i < boxes.size(); i++) { 53 | boxes[i]->draw(MV,p); 54 | } 55 | } 56 | 57 | void Obstacles::drawSimple(std::shared_ptr MV, const std::shared_ptr p) const 58 | { 59 | //for (int i = 0; i < boxes.size(); i++) { 60 | // //boxes[i]->drawSimple(MV, p); 61 | //} 62 | points->drawSimple(MV, p); 63 | } 64 | #endif // EOLC_ONLINE 65 | 66 | -------------------------------------------------------------------------------- /src/external/ArcSim/tensormax.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef TENSORMAX_HPP 28 | #define TENSORMAX_HPP 29 | 30 | #include "vectors.hpp" 31 | #include 32 | 33 | Mat2x2 tensor_max (const std::vector &Ms); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/Box.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Box__ 3 | #define __Box__ 4 | 5 | #include 6 | #include 7 | 8 | #define EIGEN_DONT_ALIGN_STATICALLY 9 | #include 10 | 11 | #include "Brenderable.h" 12 | 13 | #ifdef EOLC_ONLINE 14 | class MatrixStack; 15 | class Program; 16 | #endif // EOLC_ONLINE 17 | 18 | class Shape; 19 | class Rigid; 20 | 21 | class Box : public Brenderable 22 | { 23 | public: 24 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 25 | 26 | std::shared_ptr rigid; 27 | 28 | Box(const std::shared_ptr shape, std::string en); 29 | virtual ~Box(); 30 | void step(const double h); 31 | 32 | #ifdef EOLC_ONLINE 33 | void draw(std::shared_ptr MV, const std::shared_ptr p) const; 34 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 35 | void init(); 36 | #endif // EOLC_ONLINE 37 | 38 | int num_points; 39 | int num_edges; 40 | 41 | Eigen::Vector3d dim; 42 | Eigen::Vector3d rot; 43 | Eigen::Vector3d x; // position 44 | Eigen::Matrix4d E1; 45 | Eigen::Matrix4d E1inv; 46 | Eigen::VectorXd v; 47 | Eigen::MatrixXd adjoint; 48 | 49 | // These are used for constraints 50 | Eigen::MatrixXd faceNorms; 51 | Eigen::MatrixXi edgeFaces; 52 | Eigen::VectorXi edgeTan; 53 | Eigen::MatrixXi vertEdges1; 54 | 55 | 56 | // Export 57 | std::string exportName; 58 | int getBrenderCount() const; 59 | std::vector getBrenderNames() const; 60 | void exportBrender(std::vector< std::shared_ptr< std::ofstream > > outfiles) const; 61 | 62 | private: 63 | void generateConstraints(); 64 | 65 | const std::shared_ptr boxShape; 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/online/MatrixStack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _MatrixStack_H_ 3 | #define _MatrixStack_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | class MatrixStack 10 | { 11 | public: 12 | MatrixStack(); 13 | virtual ~MatrixStack(); 14 | 15 | // glPushMatrix(): Copies the current matrix and adds it to the top of the stack 16 | void pushMatrix(); 17 | // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top 18 | void popMatrix(); 19 | 20 | // glLoadIdentity(): Sets the top matrix to be the identity 21 | void loadIdentity(); 22 | // glMultMatrix(): Right multiplies the top matrix 23 | void multMatrix(const glm::mat4 &matrix); 24 | 25 | // glTranslate(): Right multiplies the top matrix by a translation matrix 26 | void translate(const glm::vec3 &trans); 27 | void translate(float x, float y, float z); 28 | // glScale(): Right multiplies the top matrix by a scaling matrix 29 | void scale(const glm::vec3 &scale); 30 | void scale(float x, float y, float z); 31 | // glScale(): Right multiplies the top matrix by a scaling matrix 32 | void scale(float size); 33 | // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) 34 | void rotate(float angle, const glm::vec3 &axis); 35 | void rotate(float angle, float x, float y, float z); 36 | 37 | // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix 38 | const glm::mat4 &topMatrix() const; 39 | 40 | // Prints out the specified matrix 41 | static void print(const glm::mat4 &mat, const char *name = 0); 42 | // Prints out the top matrix 43 | void print(const char *name = 0) const; 44 | 45 | private: 46 | std::shared_ptr< std::stack > mstack; 47 | 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/external/ArcSim/referenceshape.cpp: -------------------------------------------------------------------------------- 1 | #include "referenceshape.hpp" 2 | 3 | using namespace std; 4 | 5 | ReferenceSphere::ReferenceSphere(const Vec3& _center, double _radius) : center(_center), radius(_radius) { 6 | } 7 | 8 | // assume mesh is a discretized sphere; find center and radius using LSQ 9 | ReferenceSphere::ReferenceSphere(const Mesh& mesh) { 10 | Mat3x3 M(0); 11 | Vec3 b(0); 12 | for (size_t i=0; ix; 14 | for (size_t j=0; jx; 16 | for (int k=0; k<3; k++) M.col(k) += pi[k]*(pj-pi); 17 | b += 0.5*pi*(norm2(pj)-norm2(pi)); 18 | } 19 | } 20 | center = M.inv() * b; 21 | double R2 = 0; 22 | for (size_t i=0; ix); 24 | } 25 | radius = sqrt(R2/mesh.nodes.size()); 26 | } 27 | 28 | Vec3 ReferenceSphere::closest_point(const Vec3& p) { 29 | return center + radius * normalize(p - center); 30 | } 31 | 32 | bool ReferenceSphere::raycast(Vec3& p, const Vec3& dir) { 33 | p = normalize(p-center) * radius + center; 34 | return true; 35 | } 36 | 37 | ReferenceLinear::ReferenceLinear(const Mesh& mesh) { 38 | } 39 | 40 | 41 | Vec3 ReferenceLinear::closest_point(const Vec3& p) { 42 | return p; 43 | } 44 | 45 | bool ReferenceLinear::raycast(Vec3& p, const Vec3& dir) { 46 | return true; 47 | } 48 | 49 | ReferenceMesh::ReferenceMesh(const Mesh& mesh, const string& filename) { 50 | cout << "Reference mesh lookup not implemented here." << endl; 51 | exit(1); 52 | } 53 | 54 | Vec3 ReferenceMesh::closest_point(const Vec3& p) { 55 | return p; 56 | } 57 | 58 | bool ReferenceMesh::raycast(Vec3& p, const Vec3& dir) { 59 | return false; 60 | } 61 | -------------------------------------------------------------------------------- /src/external/ArcSim/dynamicremesh.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef DYNAMICREMESH_HPP 28 | #define DYNAMICREMESH_HPP 29 | 30 | #include 31 | #include "../../Cloth.h" 32 | //#include "nearobs.hpp" 33 | 34 | class MeshSubset; 35 | 36 | void static_remesh(Mesh& mesh); 37 | 38 | void dynamic_remesh(Mesh& mesh); 39 | void dynamic_remesh(MeshSubset& subset, const std::map &planes); 40 | 41 | Mat3x3 compute_face_sizing(Remeshing& remeshing, const Face *face, 42 | const std::map &planes, bool debug = false); 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/UtilEOL.cpp: -------------------------------------------------------------------------------- 1 | #include "UtilEOL.h" 2 | 3 | #include "external\ArcSim\geometry.hpp" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace Eigen; 12 | 13 | MatrixXd deform_grad(const Face *f) 14 | { 15 | MatrixXd Dx(3, 2); 16 | Dx(0, 0) = f->v[1]->node->x[0] - f->v[0]->node->x[0]; 17 | Dx(0, 1) = f->v[2]->node->x[0] - f->v[0]->node->x[0]; 18 | Dx(1, 0) = f->v[1]->node->x[1] - f->v[0]->node->x[1]; 19 | Dx(1, 1) = f->v[2]->node->x[1] - f->v[0]->node->x[1]; 20 | Dx(2, 0) = f->v[1]->node->x[2] - f->v[0]->node->x[2]; 21 | Dx(2, 1) = f->v[2]->node->x[2] - f->v[0]->node->x[2]; 22 | Matrix2d DX; 23 | DX(0, 0) = f->v[1]->u[0] - f->v[0]->u[0]; 24 | DX(0, 1) = f->v[2]->u[0] - f->v[0]->u[0]; 25 | DX(1, 0) = f->v[1]->u[1] - f->v[0]->u[1]; 26 | DX(1, 1) = f->v[2]->u[1] - f->v[0]->u[1]; 27 | return Dx * DX.inverse(); 28 | } 29 | 30 | MatrixXd deform_grad_v(const Vert* v) 31 | { 32 | double tot_ang = 0.0; 33 | Matrix3d Q = Matrix3d::Zero(); 34 | Matrix2d P = Matrix2d::Zero(); 35 | 36 | for (int f = 0; f < v->adjf.size(); f++) { 37 | Face* face = v->adjf[f]; 38 | 39 | MatrixXd F = deform_grad(face); 40 | JacobiSVD svd(F, ComputeFullU | ComputeFullV); 41 | 42 | MatrixXd V3(2, 3); 43 | V3 << svd.matrixV(), Vector2d::Zero(); 44 | 45 | MatrixXd Qx = svd.matrixU() * V3.transpose(); 46 | Matrix3d Qxrot; 47 | Qxrot << Qx.col(0), Qx.col(1), Qx.block<3,1>(0,0).cross(Qx.block<3,1>(0,1)); 48 | 49 | Matrix2d S2; 50 | S2 << svd.singularValues(), svd.singularValues(); 51 | 52 | Matrix2d Px = svd.matrixV() * S2 * svd.matrixV().transpose(); 53 | 54 | Q += incedent_angle(v, face) * Qxrot.log(); 55 | 56 | P += incedent_angle(v, face) * Px; 57 | 58 | tot_ang += incedent_angle(v, face); 59 | } 60 | 61 | Q /= tot_ang; 62 | Q = Q.exp(); 63 | 64 | P /= tot_ang; 65 | 66 | return Q.block<3, 2>(0, 0) * P; 67 | } -------------------------------------------------------------------------------- /src/external/ArcSim/io.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef IO_HPP 28 | #define IO_HPP 29 | 30 | #include "mesh.hpp" 31 | #include "util.hpp" 32 | //#include 33 | 34 | static double angle(const Vec3 &x0, const Vec3 &x1, const Vec3 &x2); 35 | std::vector triangulateARC(const std::vector &verts); 36 | 37 | void triangle_to_obj(const std::string &infile, const std::string &outfile); 38 | 39 | void load_obj(Mesh &mesh, const std::string &filename); 40 | void load_objs(std::vector &meshes, const std::string &prefix); 41 | 42 | void load_cloth_obj(Mesh &mesh, const std::string &filename); 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/external/ArcSim/subset.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef SUBSET_HPP 28 | #define SUBSET_HPP 29 | 30 | #include "mesh.hpp" 31 | #include "util.hpp" 32 | #include 33 | 34 | class MeshSubset { 35 | public: 36 | std::vector active_nodes; 37 | std::vector support_nodes; 38 | 39 | std::vector get_faces(); 40 | std::vector get_verts(); 41 | std::vector get_edges(); 42 | std::vector get_all_nodes(); 43 | 44 | void grow(int rings); 45 | void rebuild_faces(); 46 | void update_support(); 47 | void set_flag(int flag); 48 | void clear_flag(int flag); 49 | 50 | void debug(); 51 | 52 | private: 53 | void recompute_support(std::map& acc); 54 | }; 55 | 56 | #endif -------------------------------------------------------------------------------- /src/online/Camera.cpp: -------------------------------------------------------------------------------- 1 | #define _USE_MATH_DEFINES 2 | #include 3 | #include 4 | #include 5 | #include "Camera.h" 6 | #include "MatrixStack.h" 7 | 8 | Camera::Camera() : 9 | aspect(1.0f), 10 | fovy((float)(45.0*M_PI/180.0)), 11 | znear(0.01f), 12 | zfar(1000.0f), 13 | rotations(0.0, 0.0), 14 | translations(0.0f, 0.0f, -5.0f), 15 | rfactor(0.01f), 16 | tfactor(0.001f), 17 | sfactor(0.005f), 18 | flat(false) 19 | { 20 | } 21 | 22 | Camera::~Camera() 23 | { 24 | } 25 | 26 | void Camera::mouseClicked(float x, float y, bool shift, bool ctrl, bool alt) 27 | { 28 | mousePrev.x = x; 29 | mousePrev.y = y; 30 | if(shift) { 31 | state = Camera::TRANSLATE; 32 | } else if(ctrl) { 33 | state = Camera::SCALE; 34 | } else { 35 | if (flat) state = Camera::TRANSLATE; 36 | else state = Camera::ROTATE; 37 | } 38 | } 39 | 40 | void Camera::mouseMoved(float x, float y) 41 | { 42 | glm::vec2 mouseCurr(x, y); 43 | glm::vec2 dv = mouseCurr - mousePrev; 44 | switch(state) { 45 | case Camera::ROTATE: 46 | rotations += rfactor * dv; 47 | break; 48 | case Camera::TRANSLATE: 49 | translations.x -= translations.z * tfactor * dv.x; 50 | translations.y += translations.z * tfactor * dv.y; 51 | break; 52 | case Camera::SCALE: 53 | translations.z *= (1.0f - sfactor * dv.y); 54 | break; 55 | } 56 | mousePrev = mouseCurr; 57 | } 58 | 59 | void Camera::toggleFlatView() 60 | { 61 | if (flat) { 62 | flat = !flat; 63 | rotations = glm::vec2(0.0, 0.0); 64 | translations = glm::vec3(0.0f, 0.0f, -2.0f); 65 | } 66 | else { 67 | flat = !flat; 68 | rotations = glm::vec2(0.0, M_PI/2); 69 | translations = glm::vec3(-0.5f, -0.5f, -1.5f); 70 | } 71 | } 72 | 73 | void Camera::applyProjectionMatrix(std::shared_ptr P) const 74 | { 75 | // Modify provided MatrixStack 76 | P->multMatrix(glm::perspective(fovy, aspect, znear, zfar)); 77 | } 78 | 79 | void Camera::applyViewMatrix(std::shared_ptr MV) const 80 | { 81 | MV->translate(translations); 82 | MV->rotate(-M_PI*0.5, 1.0f, 0.0f, 0.0f); 83 | MV->rotate(rotations.y, glm::vec3(1.0f, 0.0f, 0.0f)); 84 | MV->rotate(rotations.x, glm::vec3(0.0f, 0.0f, 1.0f)); 85 | } 86 | -------------------------------------------------------------------------------- /src/external/ArcSim/magic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef MAGIC_HPP 28 | #define MAGIC_HPP 29 | 30 | // Magic numbers and other hacks 31 | 32 | struct Magic { 33 | bool fixed_high_res_mesh; 34 | double handle_stiffness, collision_stiffness; 35 | double repulsion_thickness, projection_thickness; 36 | double edge_flip_threshold; 37 | double rib_stiffening; 38 | bool combine_tensors; 39 | bool preserve_creases; 40 | bool add_jitter; 41 | double separation_step_size; 42 | int relax_method, max_cracks; 43 | bool enable_localopt; 44 | Magic() : 45 | fixed_high_res_mesh(false), 46 | handle_stiffness(1e3), 47 | collision_stiffness(1e9), 48 | repulsion_thickness(1e-3), 49 | projection_thickness(1e-4), 50 | edge_flip_threshold(1e-2), 51 | rib_stiffening(1), 52 | combine_tensors(true), 53 | preserve_creases(false), 54 | add_jitter(false), 55 | separation_step_size(1e-2), 56 | relax_method(0), 57 | max_cracks(100), 58 | enable_localopt(false) 59 | {} 60 | }; 61 | 62 | extern Magic magic; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/external/SolverWrappers/Mosek/QuadProgMosek.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef ____MosekQuadProgram__ 3 | #define ____MosekQuadProgram__ 4 | 5 | #include "QuadProg.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct MosekVarBounds; 12 | struct MosekObjectiveMatrix; 13 | struct MosekObjectiveVector; 14 | struct MosekConstraintMatrix; 15 | struct MosekConstraintVector; 16 | 17 | class QuadProgMosek : public QuadProg { 18 | private: 19 | 20 | int numVars, numCons, numIneqs, numEqs; 21 | std::shared_ptr bounds; 22 | 23 | std::shared_ptr objectiveMat; 24 | std::shared_ptr objectiveVec; 25 | double objectiveConstant; 26 | 27 | std::shared_ptr inequalityMat; 28 | std::shared_ptr inequalityVec; 29 | 30 | std::shared_ptr equalityMat; 31 | std::shared_ptr equalityVec; 32 | 33 | std::shared_ptr lowerVariableBound; 34 | std::shared_ptr upperVariableBound; 35 | 36 | std::map paramsInt; 37 | std::map paramsDouble; 38 | 39 | public: 40 | 41 | QuadProgMosek(); 42 | virtual ~QuadProgMosek(); 43 | 44 | virtual void setNumberOfVariables(int numVars); 45 | virtual void setNumberOfInequalities(int numIneq); 46 | virtual void setNumberOfEqualities(int numEq); 47 | 48 | virtual void setObjectiveMatrix(const Eigen::SparseMatrix & mat); 49 | virtual void setObjectiveVector(const Eigen::VectorXd & vector); 50 | virtual void setObjectiveConstant(double constant); 51 | 52 | virtual void setLowerVariableBound(const Eigen::VectorXd & bounds); 53 | virtual void setUpperVariableBound(const Eigen::VectorXd & bounds); 54 | 55 | virtual void setInequalityMatrix(const Eigen::SparseMatrix & mat); 56 | virtual void setInequalityVector(const Eigen::VectorXd & vector); 57 | 58 | virtual void setEqualityMatrix(const Eigen::SparseMatrix & mat); 59 | virtual void setEqualityVector(const Eigen::VectorXd & vector); 60 | 61 | virtual bool solve(); 62 | 63 | virtual Eigen::VectorXd getPrimalSolution(); 64 | virtual Eigen::VectorXd getDualInequality(); 65 | virtual Eigen::VectorXd getDualEquality(); 66 | virtual Eigen::VectorXd getDualLower(); 67 | virtual Eigen::VectorXd getDualUpper(); 68 | 69 | bool setParamInt(int name, int value); 70 | bool setParamDouble(int name, double value); 71 | }; 72 | 73 | #endif // ____MosekQuadProgram__ -------------------------------------------------------------------------------- /src/BrenderManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: Gustavo Lopez 10-21-17 3 | * 4 | * @version: 1.0 5 | */ 6 | 7 | #include "BrenderManager.h" 8 | #include "Brenderable.h" 9 | 10 | 11 | using namespace std; 12 | 13 | bool BrenderManager::instanceFlag = false; 14 | BrenderManager* BrenderManager::manager = NULL; 15 | BrenderManager* BrenderManager::getInstance() 16 | { 17 | if (!instanceFlag) 18 | { 19 | manager = new BrenderManager(); 20 | instanceFlag = true; 21 | return manager; 22 | } 23 | else 24 | { 25 | return manager; 26 | } 27 | } 28 | 29 | int BrenderManager::getFrame() const 30 | { 31 | return frame; 32 | } 33 | 34 | void BrenderManager::exportBrender(double time) 35 | { 36 | int objNum = 1; 37 | for (auto brenderable : brenderables) { 38 | vector names = brenderable->getBrenderNames(); 39 | vector< shared_ptr< ofstream > > outfiles; 40 | // Initialize files 41 | for (int i = 0; i < brenderable->getBrenderCount(); ++i) { 42 | auto outfile = make_shared(); 43 | outfiles.push_back(outfile); 44 | 45 | char filename[512]; 46 | 47 | //if object has not been given name 48 | if (names[i].compare("") == 0) { 49 | sprintf(filename, "%s/%06d_Object%d.obj", EXPORT_DIR.c_str(), frame, objNum); 50 | } 51 | //if object has been given specific name 52 | else { 53 | sprintf(filename, "%s/%06d_%s.obj", EXPORT_DIR.c_str(), frame, names[i].c_str()); 54 | } 55 | //open file 56 | outfile->open(filename); 57 | //frame string 58 | char framestring[50]; 59 | sprintf(framestring, "# frame %06d \n", frame); 60 | *outfile << framestring; 61 | //frame time 62 | char timeval[50]; 63 | sprintf(timeval, "# time %f \n", time); 64 | *outfile << timeval; 65 | //obj name 66 | //if object has not been given name 67 | if (names[i].compare("") == 0) { 68 | *outfile << "# name Object" + to_string(objNum) + " \n"; 69 | } 70 | //if object has been given specific name 71 | else { 72 | *outfile << "# name " + names[i] + " \n"; 73 | } 74 | } 75 | // Write to files 76 | brenderable->exportBrender(outfiles); 77 | // Close files 78 | for (int i = 0; i < brenderable->getBrenderCount(); ++i) { 79 | outfiles[i]->close(); 80 | } 81 | objNum++; 82 | } 83 | //Only time frame should be changed/modified 84 | frame++; 85 | } 86 | 87 | void BrenderManager::add(shared_ptr brenderable) 88 | { 89 | brenderables.push_back(brenderable); 90 | } 91 | 92 | void BrenderManager::setExportDir(string export_dir) 93 | { 94 | EXPORT_DIR = export_dir; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/online/MatrixStack.cpp: -------------------------------------------------------------------------------- 1 | #include "MatrixStack.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define GLM_FORCE_RADIANS 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | MatrixStack::MatrixStack() 14 | { 15 | mstack = make_shared< stack >(); 16 | mstack->push(glm::mat4(1.0)); 17 | } 18 | 19 | MatrixStack::~MatrixStack() 20 | { 21 | } 22 | 23 | void MatrixStack::pushMatrix() 24 | { 25 | const glm::mat4 &top = mstack->top(); 26 | mstack->push(top); 27 | assert(mstack->size() < 100); 28 | } 29 | 30 | void MatrixStack::popMatrix() 31 | { 32 | assert(!mstack->empty()); 33 | mstack->pop(); 34 | // There should always be one matrix left. 35 | assert(!mstack->empty()); 36 | } 37 | 38 | void MatrixStack::loadIdentity() 39 | { 40 | glm::mat4 &top = mstack->top(); 41 | top = glm::mat4(1.0); 42 | } 43 | 44 | void MatrixStack::translate(const glm::vec3 &t) 45 | { 46 | glm::mat4 &top = mstack->top(); 47 | top *= glm::translate(t); 48 | } 49 | 50 | void MatrixStack::translate(float x, float y, float z) 51 | { 52 | translate(glm::vec3(x, y, z)); 53 | } 54 | 55 | void MatrixStack::scale(const glm::vec3 &s) 56 | { 57 | glm::mat4 &top = mstack->top(); 58 | top *= glm::scale(s); 59 | } 60 | 61 | void MatrixStack::scale(float x, float y, float z) 62 | { 63 | scale(glm::vec3(x, y, z)); 64 | } 65 | 66 | void MatrixStack::scale(float s) 67 | { 68 | scale(glm::vec3(s, s, s)); 69 | } 70 | 71 | void MatrixStack::rotate(float angle, const glm::vec3 &axis) 72 | { 73 | glm::mat4 &top = mstack->top(); 74 | top *= glm::rotate(angle, axis); 75 | } 76 | 77 | void MatrixStack::rotate(float angle, float x, float y, float z) 78 | { 79 | rotate(angle, glm::vec3(x, y, z)); 80 | } 81 | 82 | void MatrixStack::multMatrix(const glm::mat4 &matrix) 83 | { 84 | glm::mat4 &top = mstack->top(); 85 | top *= matrix; 86 | } 87 | 88 | const glm::mat4 &MatrixStack::topMatrix() const 89 | { 90 | return mstack->top(); 91 | } 92 | 93 | void MatrixStack::print(const glm::mat4 &mat, const char *name) 94 | { 95 | if(name) { 96 | printf("%s = [\n", name); 97 | } 98 | for(int i = 0; i < 4; ++i) { 99 | for(int j = 0; j < 4; ++j) { 100 | // mat[j] returns the jth column 101 | printf("%- 5.2f ", mat[j][i]); 102 | } 103 | printf("\n"); 104 | } 105 | if(name) { 106 | printf("];"); 107 | } 108 | printf("\n"); 109 | } 110 | 111 | void MatrixStack::print(const char *name) const 112 | { 113 | print(mstack->top(), name); 114 | } 115 | -------------------------------------------------------------------------------- /src/external/ArcSim/remesh.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef REMESH_HPP 28 | #define REMESH_HPP 29 | 30 | #include "mesh.hpp" 31 | 32 | // Pointers are owned by the RemeshOp. 33 | // Use done() and/or inverse().done() to free. 34 | 35 | struct RemeshOp { 36 | std::vector added_verts, removed_verts; 37 | std::vector added_nodes, removed_nodes; 38 | std::vector added_edges, removed_edges; 39 | std::vector added_faces, removed_faces; 40 | bool empty() { return added_faces.empty() && removed_faces.empty(); } 41 | RemeshOp inverse() const; 42 | void apply(Mesh &mesh) const; 43 | void done() const; // frees removed data 44 | void cancel(); // aborts operations, resets RemeshOp 45 | 46 | void set_null(std::vector& v); 47 | void update(std::vector& v); 48 | void update(std::vector& v); 49 | void update(std::vector& v); 50 | }; 51 | std::ostream &operator<< (std::ostream &out, const RemeshOp &op); 52 | 53 | // These do not change the mesh directly, 54 | // they return a RemeshOp that you can apply() to the mesh 55 | 56 | void project_vertex(Vert *vnew, Edge* edge, int s, double d); 57 | 58 | bool try_move_node(Node* node, Edge* edge, double d); 59 | 60 | RemeshOp split_edge(Edge *edge, double d); 61 | 62 | RemeshOp collapse_edge(Edge *edge, int which); // which end to delete 63 | 64 | RemeshOp flip_edge(Edge *edge); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/external/ArcSim/winport.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef WINPORT_HPP 28 | #define WINPORT_HPP 29 | // MS Windows bindings, etc 30 | 31 | #if defined(_WIN32) && !defined(__CYGWIN__) 32 | 33 | #pragma warning(disable:4018) // signed/unsigned mismatch 34 | #pragma warning(disable:4244) // conversion from 'double' to 'float', possible loss of data 35 | #pragma warning(disable:4996) // this function or variable may be unsafe 36 | #pragma warning(disable:4251) // class needs to have dll-interface to be used by clients 37 | #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' 38 | #pragma warning(disable:161) // unrecognized #pragma 39 | 40 | #define _USE_MATH_DEFINES // just to have M_PI 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #undef min 47 | #undef max 48 | #include 49 | #include 50 | #define snprintf _snprintf 51 | 52 | //#include 53 | //template inline bool isfinite(const T& number) { return boost::math::isfinite(number); } 54 | //template inline bool finite(const T& number) { return boost::math::isfinite(number); } 55 | 56 | inline double sqrt(int n) { return sqrt(double(n)); } 57 | 58 | template inline T log2(const T& number) { return log(number)/log(T(2)); } 59 | 60 | extern std::ostream cdbg; 61 | 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/external/ArcSim/blockvectors.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef BLOCKVECTORS_HPP 28 | #define BLOCKVECTORS_HPP 29 | 30 | #include "vectors.hpp" 31 | 32 | template 33 | Vec mat_to_vec (const Mat &A) { 34 | Vec a; 35 | for (int i = 0; i < m; i++) 36 | for (int j = 0; j < n; j++) 37 | a[i+j*m] = A(i,j); 38 | return a; 39 | } 40 | 41 | template 42 | Mat vec_to_mat (const Vec &a) { 43 | Mat A; 44 | for (int i = 0; i < m; i++) 45 | for (int j = 0; j < n; j++) 46 | A(i,j) = a[i+j*m]; 47 | return A; 48 | } 49 | 50 | template Mat blockdiag (const Mat &A) { 51 | Mat B = 0; 52 | for (int b = 0; b < bn; b++) 53 | for (int i = 0; i < m; i++) 54 | for (int j = 0; j < n; j++) 55 | B(b*m+i, b*n+j) = A(i,j); 56 | return B; 57 | } 58 | 59 | template Mat transpose () { 60 | Mat T = 0; 61 | for (int i = 0; i < m; i++) 62 | for (int j = 0; j < n; j++) 63 | T(n*i+j, i+j*m) = 1; 64 | return T; 65 | } 66 | 67 | template Mat symmetrize (); 68 | 69 | template <> inline Mat<3,4> symmetrize<2> () { 70 | Mat<3,4> S = Mat<3,4>(0); 71 | S(0,0) = 1.f; 72 | S(1,3) = 1.f; 73 | S(2,1) = S(2,2) = 1/2.f; 74 | return S; 75 | } 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/Cloth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __Cloth__ 3 | #define __Cloth__ 4 | 5 | #include 6 | #include 7 | 8 | #define EIGEN_DONT_ALIGN_STATICALLY 9 | #include 10 | #include 11 | 12 | // ArcSim 13 | #include "external/ArcSim//mesh.hpp" 14 | 15 | #include "Brenderable.h" 16 | 17 | class Obstacles; 18 | class FixedList; 19 | class Constraints; 20 | class Forces; 21 | class GeneralizedSolver; 22 | 23 | #ifdef EOLC_ONLINE 24 | class MatrixStack; 25 | class Program; 26 | #endif 27 | 28 | extern struct Material { 29 | double density; // area density 30 | double e; 31 | double nu; 32 | double beta; 33 | double dampingA; 34 | double dampingB; 35 | }; 36 | 37 | extern struct Remeshing { 38 | double refine_angle, refine_compression, refine_velocity; 39 | double size_min, size_max; // size limits 40 | double aspect_min; // aspect ratio control 41 | }; 42 | 43 | class Cloth : public Brenderable 44 | { 45 | public: 46 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 47 | 48 | Mesh mesh; 49 | Remeshing remeshing; 50 | Material material; 51 | 52 | Mesh last_mesh; 53 | 54 | std::vector > fs; 55 | 56 | std::shared_ptr consts; 57 | std::shared_ptr myForces; 58 | 59 | Eigen::MatrixXd boundaries; 60 | 61 | Cloth(); 62 | virtual ~Cloth() {}; 63 | 64 | void build(const Eigen::Vector2i res, 65 | const Eigen::VectorXd &p00, 66 | const Eigen::VectorXd &p01, 67 | const Eigen::VectorXd &p10, 68 | const Eigen::VectorXd &p11); 69 | void build(const std::string &filename); 70 | void updatePosNor(); 71 | void updateBuffers(); 72 | 73 | void updatePreviousMesh(); 74 | void velocityTransfer(); 75 | void step(std::shared_ptr gs, std::shared_ptr obs, const Eigen::Vector3d& grav, double h, const bool& REMESHon, const bool& online); 76 | void solve(std::shared_ptr gs, double h); 77 | void updateFix(double t); 78 | 79 | #ifdef EOLC_ONLINE 80 | void init(); 81 | void draw(std::shared_ptr MV, const std::shared_ptr p) const; 82 | void drawSimple(std::shared_ptr MV, const std::shared_ptr p) const; 83 | #endif // EOLC_ONLINE 84 | 85 | // Exporting 86 | int getBrenderCount() const; 87 | std::vector getBrenderNames() const; 88 | void exportBrender(std::vector< std::shared_ptr< std::ofstream > > outfiles) const; 89 | 90 | private: 91 | 92 | int fsindex; 93 | 94 | Eigen::VectorXd v_old; 95 | Eigen::VectorXd v; 96 | Eigen::VectorXd f; 97 | 98 | std::vector eleBuf; 99 | std::vector posBuf; 100 | std::vector norBuf; 101 | std::vector texBuf; 102 | 103 | #ifdef EOLC_ONLINE 104 | unsigned eleBufID; 105 | unsigned posBufID; 106 | unsigned norBufID; 107 | unsigned texBufID; 108 | #endif // EOLC_ONLINE 109 | 110 | }; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/online/Program.cpp: -------------------------------------------------------------------------------- 1 | #include "Program.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "GLSL.h" 7 | 8 | using namespace std; 9 | 10 | Program::Program() : 11 | vShaderName(""), 12 | fShaderName(""), 13 | pid(0), 14 | verbose(true) 15 | { 16 | 17 | } 18 | 19 | Program::~Program() 20 | { 21 | 22 | } 23 | 24 | void Program::setShaderNames(const string &v, const string &f) 25 | { 26 | vShaderName = v; 27 | fShaderName = f; 28 | } 29 | 30 | bool Program::init() 31 | { 32 | GLint rc; 33 | 34 | // Create shader handles 35 | GLuint VS = glCreateShader(GL_VERTEX_SHADER); 36 | GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); 37 | 38 | // Read shader sources 39 | const char *vshader = GLSL::textFileRead(vShaderName.c_str()); 40 | const char *fshader = GLSL::textFileRead(fShaderName.c_str()); 41 | glShaderSource(VS, 1, &vshader, NULL); 42 | glShaderSource(FS, 1, &fshader, NULL); 43 | 44 | // Compile vertex shader 45 | glCompileShader(VS); 46 | glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); 47 | if(!rc) { 48 | if(isVerbose()) { 49 | GLSL::printShaderInfoLog(VS); 50 | cout << "Error compiling vertex shader " << vShaderName << endl; 51 | } 52 | return false; 53 | } 54 | 55 | // Compile fragment shader 56 | glCompileShader(FS); 57 | glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); 58 | if(!rc) { 59 | if(isVerbose()) { 60 | GLSL::printShaderInfoLog(FS); 61 | cout << "Error compiling fragment shader " << fShaderName << endl; 62 | } 63 | return false; 64 | } 65 | 66 | // Create the program and link 67 | pid = glCreateProgram(); 68 | glAttachShader(pid, VS); 69 | glAttachShader(pid, FS); 70 | glLinkProgram(pid); 71 | glGetProgramiv(pid, GL_LINK_STATUS, &rc); 72 | if(!rc) { 73 | if(isVerbose()) { 74 | GLSL::printProgramInfoLog(pid); 75 | cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; 76 | } 77 | return false; 78 | } 79 | 80 | GLSL::checkError(GET_FILE_LINE); 81 | return true; 82 | } 83 | 84 | void Program::bind() 85 | { 86 | glUseProgram(pid); 87 | } 88 | 89 | void Program::unbind() 90 | { 91 | glUseProgram(0); 92 | } 93 | 94 | void Program::addAttribute(const string &name) 95 | { 96 | attributes[name] = glGetAttribLocation(pid, name.c_str()); 97 | } 98 | 99 | void Program::addUniform(const string &name) 100 | { 101 | uniforms[name] = glGetUniformLocation(pid, name.c_str()); 102 | } 103 | 104 | GLint Program::getAttribute(const string &name) const 105 | { 106 | map::const_iterator attribute = attributes.find(name.c_str()); 107 | if(attribute == attributes.end()) { 108 | if(isVerbose()) { 109 | cout << name << " is not an attribute variable" << endl; 110 | } 111 | return -1; 112 | } 113 | return attribute->second; 114 | } 115 | 116 | GLint Program::getUniform(const string &name) const 117 | { 118 | map::const_iterator uniform = uniforms.find(name.c_str()); 119 | if(uniform == uniforms.end()) { 120 | if(isVerbose()) { 121 | cout << name << " is not a uniform variable" << endl; 122 | } 123 | return -1; 124 | } 125 | return uniform->second; 126 | } 127 | -------------------------------------------------------------------------------- /simulationSettingsBox.json: -------------------------------------------------------------------------------- 1 | // EOL Cloth simulation settings 2 | // Not including a setting will fall back to its default 3 | { 4 | // Use either "mosek" or "gurobi". Make sure you've compiiled with the specified solver enabled 5 | // This can be left undefined in which case Eigen solvers will be used, but simulations must be collision free 6 | "solver": "gurobi", 7 | 8 | "timestep": 0.5e-2, // Defaults to 0.5e-2 9 | 10 | "gravity": [0.0, 0.0, -9.8], // Defaults to -9.8 in the Z direction 11 | 12 | "REMESH": true, // Defaults to false. The remeshing settings should be set if this is on. 13 | 14 | "EOL": true, // Defaults to false. This on forces Remeshing on 15 | 16 | // The default cloth is 1m x 1m, centerd at (0.5,0.5,0.0), with a 2 points x 2 points resolution 17 | "Cloth": { 18 | // Only 3 corners of format [x ,y, z, X, Y] 19 | "init": { 20 | "initial_cloth_res": [3, 3], 21 | "corner1": [0.0, 0.0, 0.0, 0.0, 0.0], 22 | "corner2": [1.0, 0.0, 0.0, 1.0, 0.0], 23 | "corner3": [0.0, 1.0, 0.0, 0.0, 1.0], 24 | "corner4": [1.0, 1.0, 0.0, 1.0, 1.0] 25 | }, 26 | 27 | "Material": { 28 | "density": 0.05, // Kg 29 | "youngs": 50.0, 30 | "poissons": 0.01, 31 | "stiffness": 1.0e-5, 32 | "damping": [0.0, 1.0] 33 | }, 34 | 35 | // The inclusion of Remeshing in the settings file means to sim with it 36 | "Remeshing": { 37 | "refine_angle": 0.3, 38 | "refine_compression": 0.005, 39 | "refine_velocity": 0.5, 40 | "size": [320e-3, 350e-3], // These are the main bounds that changes the overall resolution 41 | "aspect_min": 0.2 42 | }, 43 | 44 | // The corner points can be fixed or given a scripted motion 45 | // 1 for the first three values turns on fix/script along the x,y,z axis 46 | // The number of the second three values is the set velocity of that point along that axis, i.e. 0 is fixed 47 | // "When" is the time in simulation seconds the fixed parameters should change 48 | "Fixed": { 49 | "0": { 50 | "when": 0, 51 | //"corner1": [1, 1, 1, 0, 0, 0], 52 | //"corner2": [1, 1, 1, 0, 0, 0], 53 | "corner3": [1, 1, 1, 0, 0, 0], 54 | "corner4": [1, 1, 1, 0, 0, 0] 55 | }, 56 | "1": { 57 | "when": 0.35, 58 | //"corner1": [1, 1, 1, 0, 0, 0], 59 | //"corner2": [1, 1, 1, 0, 0, 0], 60 | "corner3": [1, 1, 1, 0.1, 0, 0], 61 | "corner4": [1, 1, 1, 0.1, 0, 0] 62 | } 63 | } 64 | }, 65 | 66 | // Obstacles can include points, boxes, or both 67 | // Either can be loaded from an external file, defined here, or both 68 | "Obstacles": { 69 | // Collision threshold 70 | "threshold": 5e-3, 71 | 72 | // Point definitions comma seperated 73 | // Each instance of a point follows the structure [x y z xn yn zn] 74 | // The x,y,z values are the location of the point 75 | // The xn,yn,zn values are the points normal direction 76 | "points": [ 77 | 78 | ], 79 | 80 | // Box definitions comma seperated 81 | // Each instance of a box follows the structure [x y z xs xy xz xv yv zv xw yw zw] 82 | // The x,y,z values are the center of the point 83 | // The xs,ys,zs values are the scale along each local axis 84 | // The xv,yv,zv values are the velocity along that local axis 85 | // The xw,yw,zw values are the angular velocity around that local axis 86 | "boxes": [ 87 | [1.2, 1.5, 1.0, 88 | 0.9175, 0.4425, -0.549, 89 | 0.0, 0.0, 0.0, 90 | 0.0, 0.0, 0.0] 91 | ] 92 | 93 | } 94 | } -------------------------------------------------------------------------------- /src/Collisions.cpp: -------------------------------------------------------------------------------- 1 | #include "Collisions.h" 2 | #include "Box.h" 3 | #include "Points.h" 4 | 5 | #define EIGEN_DONT_ALIGN_STATICALLY 6 | #include 7 | 8 | using namespace std; 9 | using namespace Eigen; 10 | 11 | void CD(const Mesh& mesh, const shared_ptr obs, std::vector > &cls) 12 | { 13 | MatrixXd verts2(3, mesh.nodes.size()); 14 | MatrixXi faces2(3, mesh.faces.size()); 15 | //VectorXi EoLs(1, mesh.nodes.size()); 16 | VectorXi EoLs; 17 | EoLs.resize(mesh.nodes.size()); 18 | 19 | 20 | 21 | for (int i = 0; i < mesh.nodes.size(); i++) { 22 | verts2.col(i) = Vector3d(mesh.nodes[i]->x[0], mesh.nodes[i]->x[1], mesh.nodes[i]->x[2]); 23 | if (mesh.nodes[i]->EoL) EoLs(i) = 1; 24 | } 25 | for (int i = 0; i < mesh.faces.size(); i++) { 26 | faces2.col(i) = Vector3i(mesh.faces[i]->v[0]->node->index, mesh.faces[i]->v[1]->node->index, mesh.faces[i]->v[2]->node->index); 27 | } 28 | 29 | // Compute these first so they form the base of our collision list 30 | btc::pointTriCollision(cls, obs->cdthreshold, obs->points->pxyz, obs->points->norms, verts2, faces2, true); 31 | 32 | int c = cls.size(); 33 | for (int b = 0; b < obs->num_boxes; b++) { 34 | vector > clst; 35 | btc::boxTriCollision(clst, obs->cdthreshold, obs->boxes[b]->dim, obs->boxes[b]->E1, verts2, faces2, EoLs, false); 36 | cls.insert(cls.end(), clst.begin(), clst.end()); 37 | // We need to augment the indices of the box geometry by the object number 38 | // TODO:: Internally? 39 | for (c; c < cls.size(); c++) { 40 | if (cls[c]->count1 == 1 && cls[c]->count2 == 3) { 41 | //cls[c]->verts1(0) = obs->points->num_points + (obs->boxes[b]->num_points * b) + cls[c]->verts1(0); 42 | cls[c]->verts1(0) = obs->points->num_points + (b* obs->boxes[b]->num_points) + (b* obs->boxes[b]->num_edges) + cls[c]->verts1(0); 43 | } 44 | for (int e = 0; e < cls[c]->edge1.size(); e++) { 45 | //cls[c]->edge1[e] = obs->points->num_points + (obs->boxes[b]->num_edges * b) + cls[c]->edge1[e]; 46 | //cls[c]->edge1[e] = (obs->boxes[b]->num_edges * b) + cls[c]->edge1[e]; 47 | cls[c]->edge1[e] = obs->points->num_points + (b* obs->boxes[b]->num_points) + (b* obs->boxes[b]->num_edges) + (obs->boxes[b]->num_points + cls[c]->edge1[e]); 48 | } 49 | } 50 | } 51 | 52 | 53 | } 54 | 55 | void CD2(const Mesh& mesh, const shared_ptr obs, std::vector > &cls) 56 | { 57 | MatrixXd verts2(3, mesh.nodes.size()); 58 | MatrixXi faces2(3, mesh.faces.size()); 59 | VectorXi EoLs; 60 | EoLs.resize(mesh.nodes.size()); 61 | 62 | for (int i = 0; i < mesh.nodes.size(); i++) { 63 | verts2.col(i) = Vector3d(mesh.nodes[i]->x[0], mesh.nodes[i]->x[1], mesh.nodes[i]->x[2]); 64 | if (mesh.nodes[i]->EoL) EoLs(i) = 1; 65 | } 66 | for (int i = 0; i < mesh.faces.size(); i++) { 67 | faces2.col(i) = Vector3i(mesh.faces[i]->v[0]->node->index, mesh.faces[i]->v[1]->node->index, mesh.faces[i]->v[2]->node->index); 68 | } 69 | 70 | // Compute these first so they form the base of our collision list 71 | btc::pointTriCollision(cls, obs->cdthreshold, obs->points->pxyz, obs->points->norms, verts2, faces2, false); 72 | 73 | for (int b = 0; b < obs->num_boxes; b++) { 74 | vector > clst; 75 | btc::boxTriCollision(clst, obs->cdthreshold, obs->boxes[b]->dim, obs->boxes[b]->E1, verts2, faces2, EoLs, false); 76 | cls.insert(cls.end(), clst.begin(), clst.end()); 77 | } 78 | } -------------------------------------------------------------------------------- /simulationSettings.json: -------------------------------------------------------------------------------- 1 | // EOL Cloth simulation settings 2 | // Not including a setting will fall back to its default 3 | { 4 | // Use either "mosek" or "gurobi". Make sure you've compiiled with the specified solver enabled 5 | // This can be left undefined in which case Eigen solvers will be used, but simulations must be collision free 6 | "solver": "mosek", 7 | 8 | "timestep": 0.5e-2, // Defaults to 0.5e-2 9 | 10 | "gravity": [0.0, 0.0, -9.8], // Defaults to -9.8 in the Z direction 11 | 12 | "REMESH": true, // Defaults to false. The remeshing settings should be set if this is on. 13 | 14 | "EOL": true, // Defaults to false. This on forces Remeshing on 15 | 16 | // The default cloth is 1m x 1m, centerd at (0.5,0.5,0.0), with a 2 points x 2 points resolution 17 | "Cloth": { 18 | // Only 3 corners of format [x ,y, z, X, Y] 19 | "init": { 20 | "initial_cloth_res": [3, 3], 21 | "corner1": [0.0, 0.0, 0.0, 0.0, 0.0], 22 | "corner2": [1.0, 0.0, 0.0, 1.0, 0.0], 23 | "corner3": [0.0, 1.0, 0.0, 0.0, 1.0], 24 | "corner4": [1.0, 1.0, 0.0, 1.0, 1.0] 25 | }, 26 | 27 | "Material": { 28 | "density": 0.05, // Kg 29 | "youngs": 50.0, 30 | "poissons": 0.01, 31 | "stiffness": 1.0e-5, 32 | "damping": [0.0, 1.0] 33 | }, 34 | 35 | // The inclusion of Remeshing in the settings file means to sim with it 36 | "Remeshing": { 37 | "refine_angle": 0.3, 38 | "refine_compression": 0.005, 39 | "refine_velocity": 0.5, 40 | "size": [320e-3, 350e-3], // These are the main bounds that changes the overall resolution 41 | "aspect_min": 0.2 42 | }, 43 | 44 | // The corner points can be fixed or given a scripted motion 45 | // 1 for the first three values turns on fix/script along the x,y,z axis 46 | // The number of the second three values is the set velocity of that point along that axis, i.e. 0 is fixed 47 | // "When" is the time in simulation seconds the fixed parameters should change 48 | "Fixed": { 49 | "0": { 50 | "when": 0, 51 | //"corner1": [1, 1, 1, 0, 0, 0], 52 | //"corner2": [1, 1, 1, 0, 0, 0], 53 | "corner3": [1, 1, 1, 0, 0, 0], 54 | "corner4": [1, 1, 1, 0, 0, 0] 55 | }, 56 | "1": { 57 | "when": 0.25, 58 | //"corner1": [1, 1, 1, 0, 0, 0], 59 | //"corner2": [1, 1, 1, 0, 0, 0], 60 | "corner3": [1, 1, 1, 0.1, 0, 0], 61 | "corner4": [1, 1, 1, 0.1, 0, 0] 62 | } 63 | } 64 | }, 65 | 66 | // Obstacles can include points, boxes, or both 67 | // Either can be loaded from an external file, defined here, or both 68 | "Obstacles": { 69 | // Collision threshold 70 | "threshold": 5e-3, 71 | 72 | // Point definitions comma seperated 73 | // Each instance of a point follows the structure [x y z xn yn zn] 74 | // The x,y,z values are the location of the point 75 | // The xn,yn,zn values are the points normal direction 76 | "points": [ 77 | [0.751, 0.751, -0.005, 78 | 0.0, 0.0, 1.0], 79 | [0.71, 0.22, -0.005, 80 | 0.0, 0.0, 1.0], 81 | [0.27, 0.51, -0.005, 82 | 0.0, 0.0, 1.0] 83 | 84 | ], 85 | 86 | // Box definitions comma seperated 87 | // Each instance of a box follows the structure [x y z xs xy xz xv yv zv xw yw zw] 88 | // The x,y,z values are the center of the point 89 | // The xs,ys,zs values are the scale along each local axis 90 | // The xv,yv,zv values are the velocity along that local axis 91 | // The xw,yw,zw values are the angular velocity around that local axis 92 | The 93 | "boxes": [ 94 | 95 | ] 96 | 97 | } 98 | } -------------------------------------------------------------------------------- /src/external/ArcSim/transformation.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef TRANSFORMATION_HPP 28 | #define TRANSFORMATION_HPP 29 | 30 | //#include "spline.hpp" 31 | #include "vectors.hpp" 32 | #include 33 | 34 | // Transform the mesh 35 | struct Quaternion { 36 | double s; 37 | Vec3 v; 38 | Vec3 rotate (const Vec3 &point) const; 39 | static Quaternion from_axisangle(const Vec3 &axis, double angle); 40 | std::pair to_axisangle() const; 41 | Quaternion operator+(const Quaternion& q) const; 42 | Quaternion operator-(const Quaternion& q) const; 43 | Quaternion operator-() const; 44 | Quaternion operator*(const Quaternion& q) const; 45 | Quaternion operator*(double scalar) const; 46 | Quaternion operator/(double scalar) const; 47 | }; 48 | 49 | Quaternion normalize (const Quaternion &q); 50 | Quaternion inverse(const Quaternion &q); 51 | double norm2(const Quaternion &q); 52 | inline std::ostream &operator<< (std::ostream &out, const Quaternion &q) {out << "(" << q.s << ", " << q.v << ")"; return out;} 53 | 54 | struct Transformation { 55 | Vec3 translation; 56 | double scale; 57 | Quaternion rotation; 58 | Transformation (double factor=1); 59 | Vec3 apply (const Vec3 &point) const; 60 | Vec3 apply_vec (const Vec3 &vec) const; 61 | Transformation operator+(const Transformation& t) const; 62 | Transformation operator-(const Transformation& t) const; 63 | Transformation operator*(const Transformation& t) const; 64 | Transformation operator*(double scalar) const; 65 | Transformation operator/(double scalar) const; 66 | }; 67 | 68 | namespace tform { 69 | Transformation identity(); 70 | } 71 | Transformation inverse(const Transformation &tr); 72 | inline std::ostream &operator<< (std::ostream &out, const Transformation &t) {out << "(translation: " << t.translation << ", rotation: " << t.rotation << ", scale: " << t.scale << ")"; return out;} 73 | 74 | //typedef Spline Motion; 75 | typedef std::pair DTransformation; 76 | 77 | //void clean_up_quaternions (Motion &motion); // remove sign flips 78 | 79 | //Transformation get_trans (const Motion &motion, double t); 80 | //DTransformation get_dtrans (const Motion &motion, double t); 81 | //Vec3 apply_dtrans (const DTransformation &dT, const Vec3 &x0, Vec3 *vel=NULL); 82 | //Vec3 apply_dtrans_vec (const DTransformation &dT, const Vec3 &v0); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/Scene.cpp: -------------------------------------------------------------------------------- 1 | #include "Scene.h" 2 | #include "Cloth.h" 3 | #include "Obstacles.h" 4 | #include "Shape.h" 5 | #include "Preprocessor.h" 6 | #include "Collisions.h" 7 | #include "Constraints.h" 8 | #include "GeneralizedSolver.h" 9 | #include "matlabOutputs.h" 10 | 11 | #include "external\ArcSim\dynamicremesh.hpp" 12 | 13 | #ifdef EOLC_ONLINE 14 | #include "online\MatrixStack.h" 15 | #include "online\Program.h" 16 | #endif // EOLC_ONLINE 17 | 18 | 19 | using namespace std; 20 | using namespace Eigen; 21 | 22 | Scene::Scene() : 23 | t(0.0), 24 | h(0.005), 25 | grav(Vector3d(0.0,0.0,-9.8)), 26 | part(0) 27 | { 28 | cloth = make_shared(); 29 | obs = make_shared(); 30 | GS = make_shared(); 31 | } 32 | 33 | void Scene::load(const string &RESOURCE_DIR) 34 | { 35 | obs->load(RESOURCE_DIR); 36 | } 37 | 38 | void Scene::init(const bool& online, const bool& exportObjs, const string& OUTPUT_DIR) 39 | { 40 | #ifdef EOLC_ONLINE 41 | if (online) { 42 | cloth->init(); 43 | obs->init(); 44 | } 45 | #endif 46 | 47 | if (REMESHon) { 48 | dynamic_remesh(cloth->mesh); 49 | set_indices(cloth->mesh); 50 | } 51 | 52 | cloth->consts->init(obs); 53 | 54 | if (exportObjs) { 55 | brender = BrenderManager::getInstance(); 56 | brender->setExportDir(OUTPUT_DIR); 57 | brender->add(cloth); 58 | obs->addExport(brender); 59 | brender->exportBrender(t); 60 | } 61 | } 62 | 63 | void printstate(Mesh& mesh) 64 | { 65 | for (int n = 0; n < mesh.nodes.size(); n++) { 66 | if (mesh.nodes[n]->EoL) { 67 | cout << mesh.nodes[n]->EoL_state << endl; 68 | } 69 | } 70 | } 71 | 72 | void Scene::step(const bool& online, const bool& exportObjs) 73 | { 74 | cout << "Sim time: " << t << endl; 75 | 76 | if (part != 0) { 77 | cout << "Please finish the partial step before making a full step" << endl; 78 | return; 79 | } 80 | cloth->updateFix(t); 81 | if (EOLon) { 82 | cloth->updatePreviousMesh(); 83 | CD(cloth->mesh, obs, cls); 84 | preprocess(cloth->mesh, cloth->boundaries, cls); 85 | //cout << "pre" << endl; 86 | } 87 | if (REMESHon) { 88 | dynamic_remesh(cloth->mesh); 89 | set_indices(cloth->mesh); 90 | } 91 | cloth->step(GS, obs, grav, h, REMESHon, online); 92 | obs->step(h); 93 | cls.clear(); 94 | //mesh2m(cloth->mesh, "mesh.m", true); 95 | if (exportObjs) brender->exportBrender(t); 96 | //cout << "step" << endl; 97 | t += h; 98 | } 99 | 100 | void Scene::partialStep() 101 | { 102 | if (part == 0) { 103 | cloth->updatePreviousMesh(); 104 | cloth->updateFix(t); 105 | CD(cloth->mesh, obs, cls); 106 | cout << "CD" << endl; 107 | } 108 | else if (part >= 1 && part < 8) { 109 | preprocessPart(cloth->mesh, cloth->boundaries, cls, part); 110 | set_indices(cloth->mesh); 111 | cloth->updateBuffers(); 112 | mesh2m(cloth->mesh, "mesh.m", true); 113 | } 114 | else if (part == 8) { 115 | dynamic_remesh(cloth->mesh); 116 | set_indices(cloth->mesh); 117 | cloth->updateBuffers(); 118 | } 119 | else if (part == 9) { 120 | cloth->step(GS, obs, grav, h, REMESHon, true); 121 | obs->step(h); 122 | cout << "Finished step" << endl; 123 | cls.clear(); 124 | part = -1; 125 | } 126 | part++; 127 | } 128 | 129 | #ifdef EOLC_ONLINE 130 | void Scene::draw(std::shared_ptr MV, const std::shared_ptr p) const 131 | { 132 | obs->draw(MV,p); 133 | 134 | glUniform3fv(p->getUniform("kdFront"), 1, Vector3f(1.0, 0.5, 0.5).data()); 135 | glUniform3fv(p->getUniform("kdBack"), 1, Vector3f(1.0, 0.5, 0.5).data()); 136 | cloth->draw(MV, p); 137 | } 138 | 139 | void Scene::drawSimple(std::shared_ptr MV, const std::shared_ptr p) const 140 | { 141 | obs->drawSimple(MV, p); 142 | cloth->drawSimple(MV, p); 143 | } 144 | #endif // EOLC_ONLINE 145 | -------------------------------------------------------------------------------- /src/external/SolverWrappers/Gurobi/Gurobi.h: -------------------------------------------------------------------------------- 1 | // This file is part of EigenQP. 2 | // 3 | // EigenQP is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU Lesser General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // EigenQP is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU Lesser General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU Lesser General Public License 14 | // along with EigenQP. If not, see . 15 | 16 | #pragma once 17 | 18 | // includes 19 | // Eigen 20 | #include 21 | #include 22 | 23 | //Gurobi 24 | #include 25 | 26 | // eigen-quadprog 27 | #include "eigen_gurobi_api.h" 28 | 29 | namespace Eigen 30 | { 31 | 32 | class GurobiCommon 33 | { 34 | public: 35 | enum class WarmStatus : int 36 | { 37 | DEFAULT = -1, 38 | PRIMAL = 0, 39 | DUAL = 1, 40 | NONE = 2 41 | }; 42 | 43 | public: 44 | EIGEN_GUROBI_API GurobiCommon(); 45 | 46 | EIGEN_GUROBI_API int iter() const; 47 | EIGEN_GUROBI_API int fail() const; 48 | 49 | EIGEN_GUROBI_API const VectorXd& result() const; 50 | 51 | EIGEN_GUROBI_API GurobiCommon::WarmStatus warmStart() const; 52 | EIGEN_GUROBI_API void warmStart(GurobiCommon::WarmStatus warmStatus); 53 | 54 | EIGEN_GUROBI_API void inform() const; 55 | EIGEN_GUROBI_API void displayOutput(bool doDisplay); 56 | 57 | EIGEN_GUROBI_API double feasibilityTolerance() const; 58 | EIGEN_GUROBI_API void feasibilityTolerance(double tol); 59 | 60 | EIGEN_GUROBI_API double optimalityTolerance() const; 61 | EIGEN_GUROBI_API void optimalityTolerance(double tol); 62 | 63 | EIGEN_GUROBI_API void problem(int nrvar, int nreq, int nrineq); 64 | 65 | protected: 66 | MatrixXd Q_; 67 | VectorXd C_, Beq_, Bineq_, X_; 68 | int fail_, nrvar_, nreq_, nrineq_, iter_; 69 | 70 | GRBEnv env_; 71 | GRBModel model_; 72 | 73 | GRBVar* vars_; 74 | std::vector lvars_, rvars_, eqvars_, ineqvars_; 75 | GRBConstr* eqconstr_; 76 | GRBConstr* ineqconstr_; 77 | }; 78 | 79 | 80 | class GurobiDense : public GurobiCommon 81 | { 82 | public: 83 | EIGEN_GUROBI_API GurobiDense(); 84 | EIGEN_GUROBI_API GurobiDense(int nrvar, int nreq, int nrineq); 85 | 86 | EIGEN_GUROBI_API void problem(int nrvar, int nreq, int nrineq); 87 | 88 | EIGEN_GUROBI_API bool solve(const MatrixXd& Q, const VectorXd& C, 89 | const MatrixXd& Aeq, const VectorXd& Beq, 90 | const MatrixXd& Aineq, const VectorXd& Bineq, 91 | const VectorXd& XL, const VectorXd& XU); 92 | 93 | private: 94 | void updateConstr(GRBConstr* constrs, const std::vector& vars, 95 | const Eigen::MatrixXd& A, const Eigen::VectorXd& b, int len); 96 | 97 | }; 98 | 99 | 100 | class GurobiSparse : public GurobiCommon 101 | { 102 | public: 103 | EIGEN_GUROBI_API GurobiSparse(); 104 | EIGEN_GUROBI_API GurobiSparse(int nrvar, int nreq, int nrineq); 105 | 106 | EIGEN_GUROBI_API void problem(int nrvar, int nreq, int nrineq); 107 | 108 | EIGEN_GUROBI_API bool solve(const SparseMatrix& Q, const SparseVector& C, 109 | const SparseMatrix& Aeq, const SparseVector& Beq, 110 | const SparseMatrix& Aineq, const SparseVector& Bineq, 111 | const VectorXd& XL, const VectorXd& XU); 112 | 113 | private: 114 | void updateConstr(GRBConstr* constrs, const std::vector& vars, 115 | const Eigen::SparseMatrix& A, const Eigen::SparseVector& b, int len); 116 | }; 117 | 118 | } // namespace Eigen 119 | -------------------------------------------------------------------------------- /src/online/GLSL.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Many useful helper functions for GLSL shaders - gleaned from various sources including orange book 3 | // Created by zwood on 2/21/10. 4 | // Modified by sueda 10/15/15. 5 | // 6 | 7 | #include "GLSL.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | namespace GLSL { 16 | 17 | const char * errorString(GLenum err) 18 | { 19 | switch(err) { 20 | case GL_NO_ERROR: 21 | return "No error"; 22 | case GL_INVALID_ENUM: 23 | return "Invalid enum"; 24 | case GL_INVALID_VALUE: 25 | return "Invalid value"; 26 | case GL_INVALID_OPERATION: 27 | return "Invalid operation"; 28 | case GL_STACK_OVERFLOW: 29 | return "Stack overflow"; 30 | case GL_STACK_UNDERFLOW: 31 | return "Stack underflow"; 32 | case GL_OUT_OF_MEMORY: 33 | return "Out of memory"; 34 | default: 35 | return "No error"; 36 | } 37 | } 38 | 39 | void checkVersion() 40 | { 41 | int major, minor; 42 | major = minor = 0; 43 | const char *verstr = (const char *)glGetString(GL_VERSION); 44 | 45 | if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { 46 | printf("Invalid GL_VERSION format %d.%d\n", major, minor); 47 | } 48 | if(major < 2) { 49 | printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); 50 | exit(0); 51 | } 52 | } 53 | 54 | void checkError(const char *str) 55 | { 56 | GLenum glErr = glGetError(); 57 | if(glErr != GL_NO_ERROR) { 58 | if(str) { 59 | printf("%s: ", str); 60 | } 61 | printf("GL_ERROR = %s.\n", errorString(glErr)); 62 | assert(false); 63 | } 64 | } 65 | 66 | void printShaderInfoLog(GLuint shader) 67 | { 68 | GLint infologLength = 0; 69 | GLint charsWritten = 0; 70 | GLchar *infoLog = 0; 71 | 72 | checkError(GET_FILE_LINE); 73 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); 74 | checkError(GET_FILE_LINE); 75 | 76 | if(infologLength > 0) { 77 | infoLog = (GLchar *)malloc(infologLength); 78 | if(infoLog == NULL) { 79 | puts("ERROR: Could not allocate InfoLog buffer"); 80 | exit(1); 81 | } 82 | glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); 83 | checkError(GET_FILE_LINE); 84 | printf("Shader InfoLog:\n%s\n\n", infoLog); 85 | free(infoLog); 86 | } 87 | } 88 | 89 | void printProgramInfoLog(GLuint program) 90 | { 91 | GLint infologLength = 0; 92 | GLint charsWritten = 0; 93 | GLchar *infoLog = 0; 94 | 95 | checkError(GET_FILE_LINE); 96 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); 97 | checkError(GET_FILE_LINE); 98 | 99 | if(infologLength > 0) { 100 | infoLog = (GLchar *)malloc(infologLength); 101 | if(infoLog == NULL) { 102 | puts("ERROR: Could not allocate InfoLog buffer"); 103 | exit(1); 104 | } 105 | glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); 106 | checkError(GET_FILE_LINE); 107 | printf("Program InfoLog:\n%s\n\n", infoLog); 108 | free(infoLog); 109 | } 110 | } 111 | 112 | char *textFileRead(const char *fn) 113 | { 114 | FILE *fp; 115 | char *content = NULL; 116 | int count = 0; 117 | if(fn != NULL) { 118 | fp = fopen(fn,"rt"); 119 | if(fp != NULL) { 120 | fseek(fp, 0, SEEK_END); 121 | count = (int)ftell(fp); 122 | rewind(fp); 123 | if(count > 0) { 124 | content = (char *)malloc(sizeof(char) * (count+1)); 125 | count = (int)fread(content,sizeof(char),count,fp); 126 | content[count] = '\0'; 127 | } 128 | fclose(fp); 129 | } else { 130 | printf("error loading %s\n", fn); 131 | } 132 | } 133 | return content; 134 | } 135 | 136 | int textFileWrite(const char *fn, const char *s) 137 | { 138 | FILE *fp; 139 | int status = 0; 140 | if(fn != NULL) { 141 | fp = fopen(fn,"w"); 142 | if(fp != NULL) { 143 | if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { 144 | status = 1; 145 | } 146 | fclose(fp); 147 | } 148 | } 149 | return(status); 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/Box.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef EOLC_ONLINE 4 | #define GLEW_STATIC 5 | #include 6 | #include 7 | 8 | #define GLM_FORCE_RADIANS 9 | #include 10 | #include 11 | #include "glm/ext.hpp" 12 | 13 | #include "online/Program.h" 14 | #include "online/MatrixStack.h" 15 | #endif // EOLC_ONLINE 16 | 17 | #include 18 | 19 | #include "Box.h" 20 | #include "Shape.h" 21 | #include "Rigid.h" 22 | 23 | using namespace std; 24 | 25 | double faceNorm_data[] = { 26 | 1.0, 0.0, 0.0, 27 | -1.0, 0.0, 0.0, 28 | 0.0, 1.0, 0.0, 29 | 0.0, -1.0, 0.0, 30 | 0.0, 0.0, 1.0, 31 | 0.0, 0.0, -1.0 32 | }; 33 | 34 | int edgeFaces_data[] = { 35 | 1,3, 36 | 1,5, 37 | 1,4, 38 | 1,2, 39 | 3,5, 40 | 3,4, 41 | 0,3, 42 | 2,5, 43 | 0,5, 44 | 2,4, 45 | 0,4, 46 | 0,2 47 | }; 48 | 49 | int edgeTan_data[] = { 50 | 4, 51 | 2, 52 | 2, 53 | 4, 54 | 0, 55 | 0, 56 | 4, 57 | 0, 58 | 2, 59 | 0, 60 | 2, 61 | 4 62 | }; 63 | 64 | int vertsEdge1_data[] = { 65 | 0, 1, 4, 66 | 0, 2, 5, 67 | 1, 3, 7, 68 | 2, 3, 9, 69 | 4, 6, 8, 70 | 5, 6, 10, 71 | 7, 8, 11, 72 | 9, 10, 11 73 | }; 74 | 75 | Box::Box(const shared_ptr s, string en) : 76 | num_points(8), 77 | num_edges(12), 78 | dim(1.0, 1.0, 1.0), 79 | x(0.0, 0.0, 0.0), 80 | E1(Eigen::Matrix4d::Identity()), 81 | E1inv(Eigen::Matrix4d::Identity()), 82 | adjoint(Eigen::Matrix::Identity()), 83 | v(Eigen::Matrix::Zero()), 84 | boxShape(s), 85 | exportName(en) 86 | { 87 | Eigen::Map > faceNorms_(faceNorm_data); 88 | faceNorms = E1.block<3, 3>(0, 0) * faceNorms_; 89 | Eigen::Map > edgeFaces1_(edgeFaces_data); 90 | edgeFaces = edgeFaces1_; 91 | Eigen::Map > edgeTan_(edgeTan_data); 92 | edgeTan = edgeTan_; 93 | Eigen::Map > vertEdges1_(vertsEdge1_data); 94 | vertEdges1 = vertEdges1_; 95 | } 96 | 97 | Box::~Box() 98 | { 99 | } 100 | 101 | 102 | 103 | void Box::step(const double h) 104 | { 105 | //adjoint = rigid->adjoint(E1inv); 106 | adjoint = Matrix6d::Identity(); 107 | adjoint.block<3, 3>(0, 0) = E1.block<3, 3>(0, 0).transpose(); 108 | adjoint.block<3, 3>(3, 3) = E1.block<3, 3>(0, 0).transpose(); 109 | E1 = rigid->integrate(E1, adjoint*v, h); 110 | E1inv = E1.inverse(); 111 | 112 | Eigen::Map > faceNorms_(faceNorm_data); 113 | faceNorms = E1.block<3, 3>(0, 0) * faceNorms_; 114 | } 115 | 116 | #ifdef EOLC_ONLINE 117 | 118 | void Box::init() 119 | { 120 | boxShape->init(); 121 | } 122 | 123 | void Box::draw(shared_ptr MV, const shared_ptr prog) const 124 | { 125 | MV->pushMatrix(); 126 | //MV->translate(E1(0,3), E1(1,3), E1(2,3)); 127 | 128 | Eigen::Matrix4d E1row = Eigen::Matrix4d::Identity(); 129 | E1row.block<3, 3>(0, 0) = E1.block<3, 3>(0, 0); 130 | glm::mat4 bbb = glm::make_mat4(E1.data()); 131 | MV->multMatrix(bbb); 132 | 133 | MV->scale(dim(0), dim(1), dim(2)); 134 | 135 | glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix())); 136 | boxShape->draw(prog); 137 | MV->popMatrix(); 138 | } 139 | 140 | void Box::drawSimple(shared_ptr MV, const shared_ptr prog) const 141 | { 142 | for (int i = 0; i < faceNorms.cols(); i++) { 143 | glColor3f(1.0f, 0.0f, 1.0f); 144 | glBegin(GL_LINES); 145 | glVertex3f(E1(0,3), E1(1, 3), E1(2, 3)); 146 | glVertex3f(E1(0, 3) + faceNorms(0,i), E1(1, 3) + faceNorms(1, i), E1(2, 3) + faceNorms(2, i)); 147 | glEnd(); 148 | } 149 | } 150 | 151 | #endif // EOLC_ONLINE 152 | 153 | // Export 154 | int Box::getBrenderCount() const 155 | { 156 | return 1; 157 | } 158 | 159 | vector Box::getBrenderNames() const 160 | { 161 | vector names; 162 | names.push_back(exportName); 163 | return names; 164 | } 165 | 166 | void Box::exportBrender(vector< shared_ptr< ofstream > > outfiles) const 167 | { 168 | ofstream &outfile = *outfiles[0]; 169 | 170 | Eigen::Matrix4d T, S; 171 | S.setIdentity(); 172 | S(0, 0) = dim(0); 173 | S(1, 1) = dim(1); 174 | S(2, 2) = dim(2); 175 | //T.setIdentity(); 176 | //T.block<3, 1>(0, 3) = x; 177 | 178 | boxShape->exportBrender(E1*S, outfile); 179 | 180 | 181 | } -------------------------------------------------------------------------------- /src/external/ArcSim/subset.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "subset.hpp" 28 | #include "mesh.hpp" 29 | //#include "display.hpp" 30 | 31 | using namespace std; 32 | 33 | vector MeshSubset::get_all_nodes() { 34 | vector nodes; 35 | nodes.reserve(active_nodes.size() + support_nodes.size()); 36 | nodes.insert(nodes.end(), active_nodes.begin(), active_nodes.end()); 37 | nodes.insert(nodes.end(), support_nodes.begin(), support_nodes.end()); 38 | return nodes; 39 | } 40 | 41 | vector MeshSubset::get_verts() { 42 | vector verts; 43 | for (size_t i = 0; iverts.size(); j++) 45 | include(active_nodes[i]->verts[j], verts); 46 | return verts; 47 | } 48 | 49 | vector MeshSubset::get_faces() { 50 | vector faces; 51 | for (size_t i = 0; i& verts = active_nodes[i]->verts; 53 | for (size_t j = 0; j& f = verts[j]->adjf; 55 | for (size_t k = 0; k MeshSubset::get_edges() { 63 | vector edges; 64 | for (size_t i = 0; iadje.size(); j++) 66 | include(active_nodes[i]->adje[j], edges); 67 | 68 | return edges; 69 | } 70 | 71 | void MeshSubset::recompute_support(map& acc) { 72 | support_nodes.clear(); 73 | for (vector::iterator i = active_nodes.begin(); i != active_nodes.end(); ++i) 74 | for (vector::iterator j = (*i)->adje.begin(); j != (*i)->adje.end(); ++j) { 75 | Node* node = other_node(*j, *i); 76 | if (!acc[node]) { 77 | support_nodes.push_back(node); 78 | acc[node] = 1; 79 | } 80 | } 81 | } 82 | 83 | void MeshSubset::update_support() { 84 | map acc; 85 | for (size_t i=0; i acc; 93 | for (size_t i=0; iflag |= flag; 107 | } 108 | 109 | void MeshSubset::clear_flag(int flag) { 110 | for(size_t i=0; iflag &= ~flag; 112 | } 113 | 114 | //void MeshSubset::debug() { 115 | // for (size_t i=0; iflag & Node::FlagMayBreak) ? Vec3(0,0.4,0) : Vec3(0.8,0,0.8)); 119 | // wait_key(); 120 | //} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EOL-Cloth 2 | Eulerian-on-Lagrangian Cloth Simulation 3 | 4 | ACM Transactions on Graphics, 37 (4) 50:1-50:11 (SIGGRAPH), 2018. 5 | 6 | [Nicholas J. Weidner](http://weidnern.github.io), [Kyle Piddington](https://www.linkedin.com/in/kyle-piddington-5870b4106/), [David I.W. Levin](http://diwlevin.webfactional.com/researchdb/), [Shinjiro Sueda](http://faculty.cs.tamu.edu/sueda/) 7 | 8 | ## Info 9 | EOL-Cloth is a simulation tool for simulating the phenomenon of cloth sliding over sharp geometric features such as boxes and points. It was developed at Texas A&M University and the coinciding publication was presented at SIGGRAPH 2018. 10 | 11 | Check out the project page [here](http://faculty.cs.tamu.edu/sueda/projects/eol-cloth/ "EOL-Cloth"). 12 | 13 | ## Installing 14 | #### Dependencies 15 | * [CMake](https://cmake.org/ "CMake") 16 | * [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page "Eigen") 17 | 18 | Technically the code will run with just these two libraries, but simulations must be collision free and nothing will render. 19 | 20 | * [GLM](https://glm.g-truc.net/0.9.9/index.html "GLM") 21 | * [GLFW](http://www.glfw.org/ "GLFW") 22 | * [GLEW](http://glew.sourceforge.net/ "GLEW") 23 | 24 | To run the simulation "online" with rendered output these three libraries must be installed 25 | 26 | * [MOSEK](https://www.mosek.com/ "Mosek") 27 | OR 28 | * [GUROBI](http://www.gurobi.com/ "Gurobi") 29 | 30 | To handle collisions and in turn the EOL dynamics of the simulation, a quadratic program (QP) must be used. The Mosek and Gurobi libraries are currently supported using corresponding QP wrappers from [here](http://www.google.com/ "Mosek QP Wrapper") and [here](https://github.com/jrl-umi3218/eigen-gurobi "Gurobi QP Wrapper") respectively. These wrappers do not need to be installed seperately, they are already a part of the EOL-Cloth src. 31 | 32 | While it does not need to be seperetely installed, we use a modified version of [ARCSim](http://graphics.berkeley.edu/resources/ARCSim/ "ARCSim") to handle our remeshing. Feel free to look into some of the great work that has been done with it. 33 | 34 | #### Building 35 | ```sh 36 | git clone https://github.com/sueda/eol-cloth 37 | cd eol-cloth 38 | mkdir build 39 | ``` 40 | Before building with CMake, open the CMakeLists.txt file with a text editor (I know this is bad practice). While the build options can be set when we run CMake, for each option turned ON the corresponding dependency file path must be set. I do this for ease of use with multiple external library versions installed. Set the paths as shown to match the machine. Note some of the binaries are defined for the solvers which are platform specific. 41 | ```sh 42 | cd build 43 | cmake [options] .. 44 | make 45 | ``` 46 | 47 | Where the options, if not already changed in the CMakeLists.txt, are: 48 | * `-DCMAKE_BUIlD_TYPE=Release` Build in Release mode 49 | * `-DONLINE=ON` default is `OFF` 50 | * `-DMOSEK=ON` default is `OFF` 51 | * `-DGUROBI=ON` default is `OFF` 52 | 53 | ## Running 54 | ```sh 55 | ./eol-cloth 56 | ``` 57 | Settings are defined using json files and their file paths are passed as the two command line arguments. 58 | #### General Settings 59 | * `online` : `true/false` 60 | * `exportObjs` : `true/false` 61 | * `RESOURCE_DIR` : path the the directories with rendering shaders 62 | * `OUTPUT_DIR` : path to export location 63 | 64 | Fairly self explanatory. 65 | #### Simultion Settings 66 | Most of these settings are described better in the actuall example simulationSettings json files, but as a quick overview: 67 | * `solver` : `none/mosek/gurobi` 68 | * `remeshing` : `true/false` which equates to on/off 69 | * `EOL` : `true/false` which equates to on/off 70 | * `Cloth` : These settings cover initial cloth `shape, resolution, and position`, `materials`, `remeshing parameters`, and `fixed points` 71 | * `Obstacles` : These settings cover `collision threshold` and a basic definition structure for building `points` and `boxes` 72 | 73 | ## Exporting 74 | To export our objects we use an in lab developed tool we call Brender. After defining an export directory and turning on export, Brender will generate an obj file for each object in the scene snapshotted at every time step. These can be used as desired, but we usually import them into blender for nicer looking renders than what tour basi OpenGL settup provides. 75 | 76 | **NOTE**: The export directory must already exist in the file system, the simulation will not generate a directory for you. 77 | 78 | ## Contact 79 | If you would like to contact us for anything regarding EOL-Cloth free to email us. 80 | If you have any code specific comments or find any bugs, please specifically contact Nick Weidner via [GitHub](https://github.com/weidnern "Nick Weidner GitHub") or Email 81 | 82 | -------------------------------------------------------------------------------- /src/matlabOutputs.cpp: -------------------------------------------------------------------------------- 1 | #include "matlabOutputs.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace Eigen; 8 | 9 | 10 | // This gets the job done for now 11 | // TODO:: Traverse sparse structure 12 | void mat_s2s_file(const SparseMatrix& mat, const string &var_name, const string &file_name, const bool& overwrite) 13 | { 14 | ofstream ofs; 15 | if (overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 16 | else ofs.open(file_name, ofstream::out | ofstream::app); 17 | 18 | MatrixXd dMat = MatrixXd(mat); 19 | 20 | ofs << setprecision(20); 21 | 22 | ofs << "i = [ "; 23 | 24 | for (int i = 0; i < dMat.rows(); i++) { 25 | for (int j = 0; j < dMat.cols(); j++) { 26 | if (dMat(i, j) != 0.0) { 27 | ofs << i + 1 << " "; 28 | } 29 | } 30 | } 31 | 32 | ofs << "]';\n"; 33 | 34 | ofs << "j = [ "; 35 | 36 | for (int i = 0; i < dMat.rows(); i++) { 37 | for (int j = 0; j < dMat.cols(); j++) { 38 | if (dMat(i, j) != 0.0) { 39 | ofs << j + 1 << " "; 40 | } 41 | } 42 | } 43 | 44 | ofs << "]';\n"; 45 | 46 | ofs << "v = [ "; 47 | 48 | for (int i = 0; i < dMat.rows(); i++) { 49 | for (int j = 0; j < dMat.cols(); j++) { 50 | if (dMat(i, j) != 0.0) { 51 | ofs << setprecision(16) << dMat(i, j) << " "; 52 | } 53 | } 54 | } 55 | 56 | ofs << "]';\n"; 57 | 58 | ofs << var_name; 59 | ofs << " = sparse(i,j,v,"; 60 | ofs << dMat.rows() << "," << dMat.cols() << ");\n\n"; 61 | 62 | ofs.close(); 63 | } 64 | 65 | void mat_to_file(const Eigen::MatrixXd& mat, const string &var_name, const string &file_name, const bool &overwrite) 66 | { 67 | ofstream ofs; 68 | if(overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 69 | else ofs.open(file_name, ofstream::out | ofstream::app); 70 | 71 | ofs << setprecision(20); 72 | 73 | ofs << var_name; 74 | ofs << " = ["; 75 | ofs << mat; 76 | ofs << "];\n\n"; 77 | 78 | ofs.close(); 79 | } 80 | 81 | void mat_to_file(const Eigen::MatrixXi& mat, const string &var_name, const string &file_name, const bool &overwrite) 82 | { 83 | ofstream ofs; 84 | if (overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 85 | else ofs.open(file_name, ofstream::out | ofstream::app); 86 | 87 | ofs << setprecision(20); 88 | 89 | ofs << var_name; 90 | ofs << " = ["; 91 | ofs << mat; 92 | ofs << "];\n\n"; 93 | 94 | ofs.close(); 95 | } 96 | 97 | void vec_to_file(const Eigen::VectorXd& vec, const string &var_name, const string &file_name, const bool &overwrite) 98 | { 99 | ofstream ofs; 100 | if (overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 101 | else ofs.open(file_name, ofstream::out | ofstream::app); 102 | 103 | ofs << setprecision(20); 104 | 105 | ofs << var_name; 106 | ofs << " = [\n"; 107 | ofs << vec; 108 | ofs << "\n];\n\n"; 109 | 110 | ofs.close(); 111 | } 112 | 113 | void vec_to_file(const Eigen::VectorXi& vec, const string &var_name, const string &file_name, const bool &overwrite) 114 | { 115 | ofstream ofs; 116 | if (overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 117 | else ofs.open(file_name, ofstream::out | ofstream::app); 118 | 119 | ofs << setprecision(20); 120 | 121 | ofs << var_name; 122 | ofs << " = [\n"; 123 | ofs << vec; 124 | ofs << "\n];\n\n"; 125 | 126 | ofs.close(); 127 | } 128 | 129 | void mesh2m(const Mesh& mesh, const string &file_name, const bool &overwrite) 130 | { 131 | MatrixXd x_X(mesh.nodes.size(), 5); 132 | MatrixXi faces2(3, mesh.faces.size()); 133 | VectorXi isEOL(mesh.nodes.size()); 134 | for (int i = 0; i < mesh.nodes.size(); i++) { 135 | 136 | if (mesh.nodes[i]->EoL) isEOL(i) = 1; 137 | else isEOL(i) = 0; 138 | x_X(i, 0) = mesh.nodes[i]->x[0]; 139 | x_X(i, 1) = mesh.nodes[i]->x[1]; 140 | x_X(i, 2) = mesh.nodes[i]->x[2]; 141 | x_X(i, 3) = mesh.nodes[i]->verts[0]->u[0]; 142 | x_X(i, 4) = mesh.nodes[i]->verts[0]->u[1]; 143 | } 144 | 145 | for (int i = 0; i < mesh.faces.size(); i++) { 146 | faces2.col(i) = Vector3i(mesh.faces[i]->v[0]->node->index, mesh.faces[i]->v[1]->node->index, mesh.faces[i]->v[2]->node->index); 147 | } 148 | 149 | mat_to_file(x_X, "x_X", file_name, overwrite); 150 | vec_to_file(isEOL, "isEol", file_name, false); 151 | VectorXi vvv(3); 152 | vvv << 1, 1, 1; 153 | mat_to_file(faces2.colwise() += vvv, "faces", file_name, false); 154 | } 155 | 156 | void double_to_file(double d, const string &var_name, const string &file_name, const bool &overwrite) 157 | { 158 | ofstream ofs; 159 | if (overwrite) ofs.open(file_name, ofstream::out | ofstream::trunc); 160 | else ofs.open(file_name, ofstream::out | ofstream::app); 161 | 162 | ofs << setprecision(20); 163 | 164 | ofs << var_name; 165 | ofs << " = "; 166 | ofs << d; 167 | ofs << ";\n\n"; 168 | 169 | ofs.close(); 170 | } -------------------------------------------------------------------------------- /src/external/ArcSim/geometry.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef GEOMETRY_HPP 28 | #define GEOMETRY_HPP 29 | 30 | #include "mesh.hpp" 31 | #include "util.hpp" 32 | 33 | double signed_vf_distance(const Vec3 &x, 34 | const Vec3 &y0, const Vec3 &y1, const Vec3 &y2, 35 | Vec3 *n, double *w); 36 | 37 | double signed_ee_distance(const Vec3 &x0, const Vec3 &x1, 38 | const Vec3 &y0, const Vec3 &y1, 39 | Vec3 *n, double *w); 40 | 41 | double unsigned_vf_distance(const Vec3 &x, 42 | const Vec3 &y0, const Vec3 &y1, const Vec3 &y2, 43 | Vec3 *n, double *w); 44 | 45 | double unsigned_ee_distance(const Vec3 &x0, const Vec3 &x1, 46 | const Vec3 &y0, const Vec3 &y1, 47 | Vec3 *n, double *w); 48 | 49 | double signed_ve_distance(const Vec3 &x, const Vec3 &y0, const Vec3 &y1, 50 | Vec3* n, double *w); 51 | 52 | // NICK 53 | double unsigned_vv_distance(const Vec3 &x, const Vec3 &y); 54 | double incedent_angle(const Vert* v, const Face* f); 55 | 56 | Vec3 get_barycentric_coords(const Vec2 &point, const Face *face); 57 | 58 | Face* get_enclosing_face(const Mesh& mesh, const Vec2& u, 59 | Face *starting_face_hint = NULL); 60 | 61 | enum Space { MS, PS, WS }; // material space, plastic space, world space 62 | 63 | template const Vec3 &pos(const Node *node); 64 | template inline Vec3 &pos(Node *node); 65 | template const Vec3 &pos(const Vert *vert); 66 | template inline Vec3 &pos(Vert *vert); 67 | template Vec3 normal(const Face *face); 68 | template Vec3 normal(const Node* node); 69 | template double dihedral_angle(const Edge *edge); 70 | double dihedral_angle(const Vec3& p0, const Vec3& p1, const Vec3& n0, const Vec3& n1); 71 | template Mat3x3 curvature(const Face *face); 72 | template Mat2x2 projected_curvature(const Face *face, const Mat2x3& base); 73 | 74 | inline double area(const Vec3& u0, const Vec3& u1, const Vec3& u2) { return 0.5*norm(cross(u1 - u0, u2 - u0)); } 75 | inline double area(const Face* face) { return area(face->v[0]->u, face->v[1]->u, face->v[2]->u); } 76 | double aspect(const Vec3& u0, const Vec3& u1, const Vec3& u2); 77 | inline double aspect(const Face* face) { return aspect(face->v[0]->u, face->v[1]->u, face->v[2]->u); } 78 | double get_angle(const Vec3& u, const Vec3& v); 79 | 80 | // Nick 81 | inline double edge_length(const Edge* edge) { return sqrt(pow(edge->n[0]->verts[0]->u[0] - edge->n[1]->verts[0]->u[0], 2) + pow(edge->n[0]->verts[0]->u[1] - edge->n[1]->verts[0]->u[1], 2)); } 82 | inline double edge_length3D(const Edge* edge) { return sqrt(pow(edge->n[0]->x[0] - edge->n[1]->x[0], 2) + pow(edge->n[0]->x[1] - edge->n[1]->x[1], 2) + pow(edge->n[0]->x[2] - edge->n[1]->x[2], 2)); } 83 | 84 | template Plane plane_fit(const Mesh& mesh); 85 | 86 | Mat3x3 local_base(const Vec3& normal); 87 | 88 | bool triangle_ray_test(const Vec3 &x0, const Vec3& x1, const Vec3& x2, 89 | const Vec3 &s, const Vec3& d, double& z, Vec3* bary = 0); 90 | 91 | // ----------------------------------------------------------------------------- 92 | // IMPLEMENTATION 93 | // 94 | 95 | template <> inline const Vec3 &pos(const Node *node) { return node->y; } 96 | template <> inline const Vec3 &pos(const Node *node) { return node->x; } 97 | template <> inline Vec3 &pos(Node *node) { return node->y; } 98 | template <> inline Vec3 &pos(Node *node) { return node->x; } 99 | template <> inline const Vec3 &pos(const Vert *vert) { return vert->u; } 100 | template <> inline const Vec3 &pos(const Vert *vert) { return vert->node->y; } 101 | template <> inline const Vec3 &pos(const Vert *vert) { return vert->node->x; } 102 | template <> inline Vec3 &pos(Vert *vert) { return vert->u; } 103 | template <> inline Vec3 &pos(Vert *vert) { return vert->node->y; } 104 | template <> inline Vec3 &pos(Vert *vert) { return vert->node->x; } 105 | 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/Rigid.cpp: -------------------------------------------------------------------------------- 1 | #include "Rigid.h" 2 | #define _USE_MATH_DEFINES 3 | #include 4 | #include 5 | 6 | #define EIGEN_DONT_ALIGN_STATICALLY 7 | #define EIGEN_NO_STATIC_ASSERT 8 | using namespace Eigen; 9 | 10 | Matrix4d Rigid::inverse(const Matrix4d &E) 11 | { 12 | Matrix4d Einv = Matrix4d::Identity(); 13 | Matrix3d R = E.block<3,3>(0,0); 14 | Vector3d p = E.block<3,1>(0,3); 15 | Matrix3d Rt = R.transpose(); 16 | Einv.block<3,3>(0,0) = Rt; 17 | Einv.block<3,1>(0,3) = -Rt * p; 18 | return Einv; 19 | } 20 | 21 | Matrix3x6d Rigid::gamma(const Eigen::Vector3d &r) 22 | { 23 | Matrix3x6d G = Matrix3x6d::Zero(); 24 | G.block<3,3>(0,0) = bracket3(r).transpose(); 25 | G.block<3,3>(0,3) = Matrix3d::Identity(); 26 | return G; 27 | } 28 | 29 | Matrix6d Rigid::adjoint(const Matrix4d &E) 30 | { 31 | Matrix6d Ad = Matrix6d::Zero(); 32 | Matrix3d R = E.block<3,3>(0,0); 33 | Vector3d p = E.block<3,1>(0,3); 34 | Ad.block(0,0,3,3) = R; 35 | Ad.block(3,0,3,3) = bracket3(p) * R; 36 | Ad.block(3,3,3,3) = R; 37 | return Ad; 38 | } 39 | 40 | Matrix3d Rigid::bracket3(const Vector3d &a) 41 | { 42 | Matrix3d A = Matrix3d::Zero(); 43 | A(0,1) = -a(2); 44 | A(0,2) = a(1); 45 | A(1,0) = a(2); 46 | A(1,2) = -a(0); 47 | A(2,0) = -a(1); 48 | A(2,1) = a(0); 49 | return A; 50 | } 51 | 52 | Matrix4d Rigid::bracket6(const Vector6d &a) 53 | { 54 | Matrix4d A = Matrix4d::Zero(); 55 | A.block<3,3>(0,0) = bracket3(a.segment<3>(0)); 56 | A.block<3,1>(0,3) = a.segment<3>(3); 57 | return A; 58 | } 59 | 60 | Vector3d Rigid::unbracket3(const Matrix3d &A) 61 | { 62 | Vector3d a; 63 | a(0) = A(2,1); 64 | a(1) = A(0,2); 65 | a(2) = A(1,0); 66 | return a; 67 | } 68 | 69 | Vector6d Rigid::unbracket6(const Matrix4d &A) 70 | { 71 | Vector6d a; 72 | a.segment<3>(0) = unbracket3(A.block<3,3>(0,0)); 73 | a(3) = A(0,3); 74 | a(4) = A(1,3); 75 | a(5) = A(2,3); 76 | return a; 77 | } 78 | 79 | Matrix4d Rigid::integrate(const Matrix4d &E0, const VectorXd &phi, double h) 80 | { 81 | Matrix3d I = Matrix3d::Identity(); 82 | Vector3d w = phi.segment<3>(0); 83 | Vector3d v = phi.segment<3>(3); 84 | Matrix4d phib = Matrix4d::Identity(); 85 | phib.block<3,1>(0,3) = h*v; 86 | double wlen = w.norm(); 87 | if(wlen > 1e-10) { 88 | w /= wlen; 89 | v /= wlen; 90 | // Rodrigues formula %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 91 | double wX = w(0); 92 | double wY = w(1); 93 | double wZ = w(2); 94 | double c = cos(wlen * h); 95 | double s = sin(wlen * h); 96 | double c1 = 1.0 - c; 97 | Matrix3d R; 98 | R << c + wX * wX * c1, -wZ * s + wX * wY * c1, wY * s + wX * wZ * c1, 99 | wZ * s + wX * wY * c1, c + wY * wY * c1, -wX * s + wY * wZ * c1, 100 | -wY * s + wX * wZ * c1, wX * s + wY * wZ * c1, c + wZ * wZ * c1; 101 | //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 102 | Matrix3d A = I - R; 103 | Vector3d cc = w.cross(v); 104 | Vector3d d = A * cc; 105 | double wv = w.dot(v); 106 | Vector3d p = (wv * wlen * h) * w + d; 107 | phib.block<3,3>(0,0) = R; 108 | phib.block<3,1>(0,3) = p; 109 | //cout << phib << endl; 110 | } 111 | return E0 * phib; 112 | } 113 | 114 | Vector6d Rigid::log(const Eigen::Matrix4d & A) 115 | { 116 | Matrix3d R = A.block<3,3>(0,0); 117 | Vector3d p = A.block<3,1>(0,3); 118 | Vector6d phi; 119 | 120 | double cosTheta = 0.5*(R.trace() - 1); 121 | double theta = acos(cosTheta); 122 | 123 | if (cosTheta > 0.999999999999) 124 | theta = 0; 125 | else if (cosTheta < -0.999999999999) 126 | theta = M_PI; 127 | 128 | if (abs(theta) < 1e-8) 129 | { 130 | phi.segment<3>(0) << 0.0, 0.0, 0.0; 131 | phi.segment<3>(3) = p; 132 | } 133 | else 134 | { 135 | double sinTheta = sin(theta); 136 | Matrix3d wBracket = theta / (2 * sinTheta)*(R - R.transpose()); 137 | phi.segment<3>(0) = unbracket3(wBracket); 138 | Matrix3d V = Matrix3d::Identity() + ((1 - cosTheta) / (theta * theta) * wBracket) + ((theta - sinTheta) / (theta * theta * theta) * wBracket*wBracket); 139 | phi.segment<3>(3) = V.colPivHouseholderQr().solve(p); 140 | } 141 | 142 | return phi; 143 | } 144 | 145 | 146 | // #include 147 | // using namespace std; 148 | // int main(int argc, char **argv) 149 | // { 150 | // Matrix4d E = Matrix4d::Identity(); 151 | // E << -0.1817, 0.7236, 0.6658, 2.7694, 152 | // -0.6198, -0.6100, 0.4938, -1.3499, 153 | // 0.7634, -0.3230, 0.5594, 3.0349, 154 | // 0, 0, 0, 1.0000; 155 | // cout << E << endl << endl; 156 | // cout << Rigid::inverse(E) << endl << endl; 157 | // Vector3d r; 158 | // r << 0.7254, -0.0631, 0.7147; 159 | // cout << Rigid::gamma(r) << endl << endl; 160 | // cout << Rigid::adjoint(E) << endl << endl; 161 | // Vector6d p; 162 | // p << -0.2050, -0.1241, 1.4897, 1.4090, 1.4172, 0.6715; 163 | // cout << Rigid::bracket6(p) << endl << endl; 164 | // Vector3d ax; 165 | // ax << -1.2075, 0.7172, 1.6302; 166 | // double a = 0.4889; 167 | // cout << Rigid::aaToMat(ax, a) << endl << endl; 168 | // cout << Rigid::aaToMat(Vector3d(1, 0, 0), a) << endl << endl; 169 | // cout << Rigid::aaToMat(Vector3d(0, 1, 0), a) << endl << endl; 170 | // cout << Rigid::aaToMat(Vector3d(0, 0, 1), a) << endl << endl; 171 | // } 172 | -------------------------------------------------------------------------------- /src/GeneralizedSolver.cpp: -------------------------------------------------------------------------------- 1 | #include "GeneralizedSolver.h" 2 | 3 | #include "matlabOutputs.h" 4 | 5 | #include 6 | 7 | #ifdef EOLC_MOSEK 8 | #include "external\SolverWrappers\Mosek\QuadProgMosek.h" 9 | #endif 10 | 11 | #ifdef EOLC_GUROBI 12 | #include "external\SolverWrappers\Gurobi\Gurobi.h" 13 | #endif 14 | 15 | using namespace std; 16 | using namespace Eigen; 17 | 18 | GeneralizedSolver::GeneralizedSolver() : 19 | whichSolver(GeneralizedSolver::NoSolver) 20 | { 21 | 22 | } 23 | 24 | void generateMatlab(const SparseMatrix& MDK, const VectorXd& b, 25 | const SparseMatrix& Aeq, const VectorXd& beq, 26 | const SparseMatrix& Aineq, const VectorXd& bineq, 27 | VectorXd& v) 28 | { 29 | mat_s2s_file(MDK, "MDK", "solver.m", true); 30 | vec_to_file(b, "b", "solver.m", false); 31 | mat_s2s_file(Aeq, "Aeq", "solver.m", false); 32 | vec_to_file(beq, "beq", "solver.m", false); 33 | mat_s2s_file(Aineq, "Aineq", "solver.m", false); 34 | vec_to_file(bineq, "bineq", "solver.m", false); 35 | vec_to_file(v, "v_input", "solver.m", false); 36 | } 37 | 38 | #ifdef EOLC_MOSEK 39 | bool mosekSolve(const SparseMatrix& MDK, const VectorXd& b, 40 | const SparseMatrix& Aeq, const VectorXd& beq, 41 | const SparseMatrix& Aineq, const VectorXd& bineq, 42 | VectorXd& v) 43 | { 44 | QuadProgMosek *program = new QuadProgMosek(); 45 | double inf = numeric_limits::infinity(); 46 | 47 | VectorXd xl; 48 | VectorXd xu; 49 | xl.setConstant(b.size(), -inf); 50 | xu.setConstant(b.size(), inf); 51 | 52 | program->setNumberOfVariables(b.size()); 53 | program->setNumberOfEqualities(beq.size()); 54 | program->setNumberOfInequalities(bineq.size()); 55 | 56 | program->setObjectiveMatrix(MDK); 57 | program->setObjectiveVector(b); 58 | 59 | program->setInequalityMatrix(Aineq); 60 | program->setInequalityVector(bineq); 61 | 62 | program->setEqualityMatrix(Aeq); 63 | program->setEqualityVector(beq); 64 | 65 | bool success = program->solve(); 66 | 67 | v = program->getPrimalSolution(); 68 | 69 | return success; 70 | } 71 | #endif 72 | 73 | #ifdef EOLC_GUROBI 74 | bool gurobiSolve(SparseMatrix& MDK, const VectorXd& b, 75 | SparseMatrix& Aeq, const VectorXd& beq, 76 | SparseMatrix& Aineq, const VectorXd& bineq, 77 | VectorXd& v) 78 | { 79 | GurobiSparse qp(b.size(), beq.size(), bineq.size()); 80 | qp.displayOutput(false); 81 | 82 | SparseMatrix Sb(b.sparseView()); 83 | SparseVector Sbeq(beq.sparseView()); 84 | SparseVector Sbineq(bineq.sparseView()); 85 | 86 | MDK.makeCompressed(); 87 | Sb.makeCompressed(); 88 | Aeq.makeCompressed(); 89 | Aineq.makeCompressed(); 90 | 91 | VectorXd XL, XU; 92 | double inf = numeric_limits::infinity(); 93 | XL.setConstant(b.size(), -inf); 94 | XU.setConstant(b.size(), inf); 95 | 96 | bool success = qp.solve(MDK, Sb, 97 | Aeq, Sbeq, 98 | Aineq, Sbineq, 99 | XL, XU); 100 | 101 | v = qp.result(); 102 | 103 | return success; 104 | } 105 | #endif 106 | 107 | bool GeneralizedSolver::velocitySolve(const bool& fixedPoints, const bool& collisions, 108 | SparseMatrix& MDK, const VectorXd& b, 109 | SparseMatrix& Aeq, const VectorXd& beq, 110 | SparseMatrix& Aineq, const VectorXd& bineq, 111 | VectorXd& v) 112 | { 113 | //if (true) { 114 | // generateMatlab(MDK, b, 115 | // Aeq, beq, 116 | // Aineq, bineq, 117 | // v); 118 | //} 119 | 120 | if (!collisions && false) { 121 | // Simplest case, a cloth with no fixed points and no collisions 122 | if (!fixedPoints) { 123 | ConjugateGradient, Lower | Upper> cg; 124 | cg.compute(MDK); 125 | v = cg.solve(-b); 126 | //cout << v << endl; 127 | return true; 128 | } 129 | else { 130 | // If there are fixed points we can use KKT which is faster than solving a quadprog 131 | // the assumption is made that MDK and b have been built properly uppon making it here 132 | LeastSquaresConjugateGradient > lscg; 133 | lscg.compute(MDK); 134 | v = lscg.solve(-b); 135 | return true; 136 | } 137 | } 138 | else { 139 | if (whichSolver == GeneralizedSolver::NoSolver) { 140 | cout << "The simulation has encountered a collision, but a quadratic programming solver has not been specified." << endl; 141 | cout << "Please either set an external quadratic programming solver, or avoid collisions in your simulation." << endl; 142 | abort(); 143 | } 144 | else if (whichSolver == GeneralizedSolver::Mosek) { 145 | #ifdef EOLC_MOSEK 146 | bool success = mosekSolve(MDK, b, 147 | Aeq, beq, 148 | Aineq, bineq, 149 | v); 150 | return success; 151 | #else 152 | cout << "ERROR:" << endl; 153 | cout << "Attempting to use the mosek solver without mosek support enabled" << endl; 154 | abort(); 155 | #endif 156 | } 157 | else if (whichSolver == GeneralizedSolver::Gurobi) { 158 | #ifdef EOLC_GUROBI 159 | bool success = gurobiSolve(MDK, b, 160 | Aeq, beq, 161 | Aineq, bineq, 162 | v); 163 | return success; 164 | #else 165 | cout << "ERROR:" << endl; 166 | cout << "Attempting to use the gurobi solver without gurobi support enabled" << endl; 167 | abort(); 168 | #endif 169 | } 170 | } 171 | 172 | return false; 173 | } -------------------------------------------------------------------------------- /src/ComputeInertial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | void ComputeInertial( 3 | const double *xa, // [input 3x1] World position of vertex A 4 | const double *xb, // [input 3x1] World position of vertex B 5 | const double *xc, // [input 3x1] World position of vertex C 6 | const double *Xa, // [input 2x1] Material position of vertex A 7 | const double *Xb, // [input 2x1] Material position of vertex B 8 | const double *Xc, // [input 2x1] Material position of vertex C 9 | const double *g, // [input 3x1] 3D gravity vector 10 | double rho, // [input 1x1] Density (mass per area) 11 | double *W, // [output 1x1] Gravitational potential energy 12 | double *f, // [output 9x1] Gravity force vector 13 | double *M) // [output 9x9] Inertia matrix 14 | { 15 | double xax = xa[0]; 16 | double xay = xa[1]; 17 | double xaz = xa[2]; 18 | double xbx = xb[0]; 19 | double xby = xb[1]; 20 | double xbz = xb[2]; 21 | double xcx = xc[0]; 22 | double xcy = xc[1]; 23 | double xcz = xc[2]; 24 | double Xax = Xa[0]; 25 | double Xay = Xa[1]; 26 | double Xbx = Xb[0]; 27 | double Xby = Xb[1]; 28 | double Xcx = Xc[0]; 29 | double Xcy = Xc[1]; 30 | double gx = g[0]; 31 | double gy = g[1]; 32 | double gz = g[2]; 33 | double t8 = rho * (Xax * Xby - Xax * Xcy - Xbx * Xay + Xcx * Xay + Xbx * Xcy - Xcx * Xby); 34 | double W00 = -t8 * (gx * (xbx - xcx) / 6 + gy * (xby - xcy) / 6 + gz * (xbz - xcz) / 6 + gx * (xax - xcx) / 6 + gy * (xay - xcy) / 6 + gz * (xaz - xcz) / 6 + gx * xcx / 2 + gy * xcy / 2 + gz * xcz / 2); 35 | double f01 = t8 * gx / 6; 36 | double f02 = t8 * gy / 6; 37 | double f03 = t8 * gz / 6; 38 | double f04 = f01; 39 | double f05 = f02; 40 | double f06 = f03; 41 | double f07 = f04; 42 | double f08 = f05; 43 | double f09 = f06; 44 | double M0101 = t8 / 12; 45 | double M0102 = 0; 46 | double M0103 = 0; 47 | double M0104 = t8 / 24; 48 | double M0105 = 0; 49 | double M0106 = 0; 50 | double M0107 = M0104; 51 | double M0108 = 0; 52 | double M0109 = 0; 53 | double M0201 = 0; 54 | double M0202 = M0101; 55 | double M0203 = 0; 56 | double M0204 = 0; 57 | double M0205 = M0107; 58 | double M0206 = 0; 59 | double M0207 = 0; 60 | double M0208 = M0205; 61 | double M0209 = 0; 62 | double M0301 = 0; 63 | double M0302 = 0; 64 | double M0303 = M0202; 65 | double M0304 = 0; 66 | double M0305 = 0; 67 | double M0306 = M0208; 68 | double M0307 = 0; 69 | double M0308 = 0; 70 | double M0309 = M0306; 71 | double M0401 = M0309; 72 | double M0402 = 0; 73 | double M0403 = 0; 74 | double M0404 = M0303; 75 | double M0405 = 0; 76 | double M0406 = 0; 77 | double M0407 = M0401; 78 | double M0408 = 0; 79 | double M0409 = 0; 80 | double M0501 = 0; 81 | double M0502 = M0407; 82 | double M0503 = 0; 83 | double M0504 = 0; 84 | double M0505 = M0404; 85 | double M0506 = 0; 86 | double M0507 = 0; 87 | double M0508 = M0502; 88 | double M0509 = 0; 89 | double M0601 = 0; 90 | double M0602 = 0; 91 | double M0603 = M0508; 92 | double M0604 = 0; 93 | double M0605 = 0; 94 | double M0606 = M0505; 95 | double M0607 = 0; 96 | double M0608 = 0; 97 | double M0609 = M0603; 98 | double M0701 = M0609; 99 | double M0702 = 0; 100 | double M0703 = 0; 101 | double M0704 = M0701; 102 | double M0705 = 0; 103 | double M0706 = 0; 104 | double M0707 = M0606; 105 | double M0708 = 0; 106 | double M0709 = 0; 107 | double M0801 = 0; 108 | double M0802 = M0704; 109 | double M0803 = 0; 110 | double M0804 = 0; 111 | double M0805 = M0802; 112 | double M0806 = 0; 113 | double M0807 = 0; 114 | double M0808 = M0707; 115 | double M0809 = 0; 116 | double M0901 = 0; 117 | double M0902 = 0; 118 | double M0903 = M0805; 119 | double M0904 = 0; 120 | double M0905 = 0; 121 | double M0906 = M0903; 122 | double M0907 = 0; 123 | double M0908 = 0; 124 | double M0909 = M0808; 125 | W[0]=W00; 126 | f[0]=f01; f[1]=f02; f[2]=f03; f[3]=f04; f[4]=f05; f[5]=f06; f[6]=f07; f[7]=f08; f[8]=f09; 127 | M[ 0*9+ 0]=M0101; M[ 0*9+ 1]=M0102; M[ 0*9+ 2]=M0103; M[ 0*9+ 3]=M0104; M[ 0*9+ 4]=M0105; M[ 0*9+ 5]=M0106; M[ 0*9+ 6]=M0107; M[ 0*9+ 7]=M0108; M[ 0*9+ 8]=M0109; 128 | M[ 1*9+ 0]=M0201; M[ 1*9+ 1]=M0202; M[ 1*9+ 2]=M0203; M[ 1*9+ 3]=M0204; M[ 1*9+ 4]=M0205; M[ 1*9+ 5]=M0206; M[ 1*9+ 6]=M0207; M[ 1*9+ 7]=M0208; M[ 1*9+ 8]=M0209; 129 | M[ 2*9+ 0]=M0301; M[ 2*9+ 1]=M0302; M[ 2*9+ 2]=M0303; M[ 2*9+ 3]=M0304; M[ 2*9+ 4]=M0305; M[ 2*9+ 5]=M0306; M[ 2*9+ 6]=M0307; M[ 2*9+ 7]=M0308; M[ 2*9+ 8]=M0309; 130 | M[ 3*9+ 0]=M0401; M[ 3*9+ 1]=M0402; M[ 3*9+ 2]=M0403; M[ 3*9+ 3]=M0404; M[ 3*9+ 4]=M0405; M[ 3*9+ 5]=M0406; M[ 3*9+ 6]=M0407; M[ 3*9+ 7]=M0408; M[ 3*9+ 8]=M0409; 131 | M[ 4*9+ 0]=M0501; M[ 4*9+ 1]=M0502; M[ 4*9+ 2]=M0503; M[ 4*9+ 3]=M0504; M[ 4*9+ 4]=M0505; M[ 4*9+ 5]=M0506; M[ 4*9+ 6]=M0507; M[ 4*9+ 7]=M0508; M[ 4*9+ 8]=M0509; 132 | M[ 5*9+ 0]=M0601; M[ 5*9+ 1]=M0602; M[ 5*9+ 2]=M0603; M[ 5*9+ 3]=M0604; M[ 5*9+ 4]=M0605; M[ 5*9+ 5]=M0606; M[ 5*9+ 6]=M0607; M[ 5*9+ 7]=M0608; M[ 5*9+ 8]=M0609; 133 | M[ 6*9+ 0]=M0701; M[ 6*9+ 1]=M0702; M[ 6*9+ 2]=M0703; M[ 6*9+ 3]=M0704; M[ 6*9+ 4]=M0705; M[ 6*9+ 5]=M0706; M[ 6*9+ 6]=M0707; M[ 6*9+ 7]=M0708; M[ 6*9+ 8]=M0709; 134 | M[ 7*9+ 0]=M0801; M[ 7*9+ 1]=M0802; M[ 7*9+ 2]=M0803; M[ 7*9+ 3]=M0804; M[ 7*9+ 4]=M0805; M[ 7*9+ 5]=M0806; M[ 7*9+ 6]=M0807; M[ 7*9+ 7]=M0808; M[ 7*9+ 8]=M0809; 135 | M[ 8*9+ 0]=M0901; M[ 8*9+ 1]=M0902; M[ 8*9+ 2]=M0903; M[ 8*9+ 3]=M0904; M[ 8*9+ 4]=M0905; M[ 8*9+ 5]=M0906; M[ 8*9+ 6]=M0907; M[ 8*9+ 7]=M0908; M[ 8*9+ 8]=M0909; 136 | } 137 | -------------------------------------------------------------------------------- /src/boxTriCollision.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef BOXTRICOLLISION_H_ 3 | #define BOXTRICOLLISION_H_ 4 | 5 | #include 6 | #include 7 | #define EIGEN_DONT_ALIGN_STATICALLY 8 | #include 9 | 10 | // Throughout this code, `1` refers to the box and `2` refers to the cloth. 11 | // For example, `pos1` is the collision point on the box, and `pos2` is the 12 | // collision point on the cloth. 13 | 14 | namespace btc 15 | { 16 | 17 | /** 18 | * The vertex ordering is as follows: 19 | * 20 | * x2 21 | * / \ 22 | * / t0 \ 23 | * / \ 24 | * x0--edge--x1 25 | * \ / 26 | * \ t1 / 27 | * \ / 28 | * x3 29 | */ 30 | class Edge 31 | { 32 | public: 33 | Edge(); 34 | virtual ~Edge(); 35 | 36 | Eigen::Vector4i verts; 37 | Eigen::Vector2i faces; 38 | bool internal; 39 | double angle; 40 | Eigen::Vector3d normals[2]; 41 | }; 42 | 43 | void createEdges( 44 | std::vector > &edges, // output 45 | const Eigen::MatrixXi &faces, // input 46 | const Eigen::MatrixXd &verts // input 47 | ); 48 | 49 | class Collision 50 | { 51 | public: 52 | Collision(); 53 | virtual ~Collision(); 54 | 55 | // The collision can be Vert-Face, Face-Vert, or Edge-Edge. 56 | // Vert-Face: 57 | // count1 = 1 58 | // count2 = 3 59 | // verts1 = [i -1 -1], where i is the vertex index for box 60 | // verts2 = [i j k], where i, j, k are the vertex indices for cloth 61 | // weights1 = [a 0 0], where a is the box vertex weight for i 62 | // weights2 = [a b c], where a, b, c, are the cloth vertex weights for i, j, k 63 | // tri1 = -1 64 | // tri2 = i, where i is the triangle index for cloth 65 | // edge1 = [a b c ...], wher a, b, c, etc. are the edge indices of the surrounding edges 66 | // edge2 = -1 67 | // edgeDir = [0 0 0] 68 | // Edge-Edge: 69 | // count1 = 2 70 | // count2 = 2 71 | // verts1 = [i j -1], where i, j are the vertex indices for box 72 | // verts2 = [i j -1], where i, j are the vertex indices for cloth 73 | // weights1 = [a b 0], where a, b are the box vertex weight for i, j 74 | // weights2 = [a b 0], where a, b are the cloth vertex weights for i, j 75 | // tri1 = -1 76 | // tri2 = -1 77 | // edge1 = [i], where i is the edge index for box 78 | // edge2 = i, where i is the edge index for cloth 79 | // edgeDir = [x y z] where this vector represents the box edge direction 80 | // Face-Vert: 81 | // count1 = 3 82 | // count2 = 1 83 | // verts1 = [i j k], where i, j, k are the vertex indices for box 84 | // verts2 = [i -1 -1], where i is the vertex index for cloth 85 | // weights1 = [a b c], where a, b, c, are the cloth vertex weights for i, j, k 86 | // weights2 = [a 0 0], where a is the box vertex weight for i 87 | // tri1 = i, where i is the triangle index for box 88 | // tri2 = -1 89 | // edge1 = [] 90 | // edge2 = -1 91 | // edgeDir = [0 0 0] 92 | 93 | double dist; // distance 94 | Eigen::Vector3d nor1; // normal 95 | Eigen::Vector3d nor2; // normal on cloth 96 | Eigen::Vector3d pos1; // position on box 97 | Eigen::Vector3d pos2; // position on cloth 98 | Eigen::Vector3d pos1_; // position on box offset to be slightly inside 99 | int count1; // Collision type for box: 1=vert, 2=edge, 3=face 100 | int count2; // Collision type for cloth: 1=vert, 2=edge, 3=face 101 | Eigen::Vector3i verts1; // The collided vertices on box 102 | Eigen::Vector3i verts2; // The collided vertices on cloth 103 | Eigen::Vector3d weights1; // The vertex weights on box 104 | Eigen::Vector3d weights2; // The vertex weights on cloth 105 | int tri1; // Triangle index for box 106 | int tri2; // Triangle index for cloth 107 | std::vector edge1; // all surrounding edge indices for he box 108 | int edge2; // edge index for cloth 109 | Eigen::Vector3d edgeDir; // Direction of box edge TODO:: This a better way 110 | }; 111 | 112 | /** 113 | * Main function 114 | * OUTPUT 115 | * collisions: a vector of detected collisions 116 | * INPUT 117 | * threshold: detection threshold (e.g., 1e-5) 118 | * whd1: box dimensions 119 | * E1: box frame 120 | * verts2: 3xn matrix of cloth vertices 121 | * faces2: 3xm matrix of cloth faces 122 | */ 123 | void boxTriCollision( 124 | std::vector > &collisions, 125 | double threshold, 126 | const Eigen::Vector3d &whd1, 127 | const Eigen::Matrix4d &E1, 128 | const Eigen::MatrixXd &verts2, 129 | const Eigen::MatrixXi &faces2, 130 | const Eigen::VectorXi &isEOL2, 131 | bool EOL); 132 | 133 | /** 134 | * Same as above, but doesn't create the edge structure. If the edge structure 135 | * is already created, then call this function. Otherwise, call the function 136 | * above, which creates the edge structure based on verts2 and faces2. 137 | */ 138 | void boxTriCollision( 139 | std::vector > &collisions, 140 | double threshold, 141 | const Eigen::Vector3d &whd1, 142 | const Eigen::Matrix4d &E1, 143 | const Eigen::MatrixXd &verts2, 144 | const Eigen::MatrixXi &faces2, 145 | const Eigen::VectorXi &isEOL2, 146 | bool EOL, 147 | const std::vector > &edges2); 148 | 149 | /////////////////////////////////////////////////////////////////////////////// 150 | 151 | void pointTriCollision( 152 | std::vector > &collisions, 153 | double threshold, 154 | const Eigen::MatrixXd &verts1, 155 | const Eigen::MatrixXd &norms1, 156 | const Eigen::MatrixXd &verts2, 157 | const Eigen::MatrixXi &faces2, 158 | bool EOL); 159 | 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /src/external/ArcSim/util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "util.hpp" 28 | #include "io.hpp" 29 | #include "mesh.hpp" 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | using namespace std; 39 | 40 | void Stats::add(double x) { 41 | xs.push_back(x); 42 | sum += x; 43 | sorted = false; 44 | } 45 | 46 | void Stats::sort() const { 47 | if (sorted) return; 48 | std::sort(xs.begin(), xs.end()); 49 | sorted = true; 50 | } 51 | 52 | double Stats::min() const { sort(); return xs.front(); } 53 | double Stats::max() const { sort(); return xs.back(); } 54 | double Stats::mean() const { return sum / xs.size(); } 55 | double Stats::median() const { return quantile(0.5); } 56 | double Stats::quantile(double q) const { sort(); return xs[(int)(q*xs.size())]; } 57 | 58 | ostream &operator<< (ostream &out, const Stats &stats) { 59 | if (stats.xs.empty()) 60 | out << "no data"; 61 | else 62 | out << stats.min() << " " << stats.quantile(0.05) << " " 63 | << stats.quantile(0.25) << " " << stats.median() << " " 64 | << stats.quantile(0.75) << " " << stats.quantile(0.95) << " " 65 | << stats.max(); 66 | return out; 67 | } 68 | 69 | inline string stringf(const string &format, ...) { 70 | char buf[256]; 71 | va_list args; 72 | va_start(args, format); 73 | vsnprintf(buf, 256, format.c_str(), args); 74 | va_end(args); 75 | return std::string(buf); 76 | } 77 | 78 | template string name(const T *p) { 79 | stringstream ss; 80 | ss << setw(3) << setfill('0') << hex << ((size_t)p / sizeof(T)) % 0xfff; 81 | return ss.str(); 82 | } 83 | 84 | ostream &operator<< (ostream &out, const Vert *vert) { 85 | if (!vert) 86 | out << "v:none"; 87 | else 88 | out << "v:" << name(vert); 89 | return out; 90 | } 91 | 92 | ostream &operator<< (ostream &out, const Node *node) { 93 | if (!node) 94 | out << "n:none"; 95 | else 96 | out << "n:" << name(node) << node->verts; 97 | return out; 98 | } 99 | 100 | ostream &operator<< (ostream &out, const Edge *edge) { 101 | if (!edge) 102 | out << "e:none"; 103 | else 104 | out << "e:" << name(edge) << "(" << edge->n[0] << "-" << edge->n[1] << ")"; 105 | return out; 106 | } 107 | 108 | ostream &operator<< (ostream &out, const Face *face) { 109 | if (!face) 110 | out << "f:none"; 111 | else 112 | out << "f:" << name(face) << "(" << face->v[0] << "-" << face->v[1] << "-" << face->v[2] << ")"; return out; 113 | } 114 | 115 | const double infinity = numeric_limits::infinity(); 116 | 117 | int solve_quadratic(double a, double b, double c, double x[2]) { 118 | // http://en.wikipedia.org/wiki/Quadratic_formula#Floating_point_implementation 119 | double d = b*b - 4 * a*c; 120 | if (d < 0) { 121 | x[0] = -b / (2 * a); 122 | return 0; 123 | } 124 | double q = -(b + sgn(b)*sqrt(d)) / 2; 125 | int i = 0; 126 | if (abs(a) > 1e-12*abs(q)) 127 | x[i++] = q / a; 128 | if (abs(q) > 1e-12*abs(c)) 129 | x[i++] = c / q; 130 | if (i == 2 && x[0] > x[1]) 131 | swap(x[0], x[1]); 132 | return i; 133 | } 134 | 135 | bool is_seam_or_boundary(const Vert *v) { 136 | return is_seam_or_boundary(v->node); 137 | } 138 | 139 | bool is_seam_or_boundary(const Node *n) { 140 | for (int e = 0; e < (int)n->adje.size(); e++) 141 | if (is_seam_or_boundary(n->adje[e])) 142 | return true; 143 | return false; 144 | } 145 | 146 | bool is_seam_or_boundary(const Edge *e) { 147 | return !e->adjf[0] || !e->adjf[1] 148 | || edge_vert(e, 0, 0) != edge_vert(e, 1, 0) 149 | || edge_vert(e, 0, 1) != edge_vert(e, 1, 1); 150 | } 151 | 152 | bool is_seam_or_boundary(const Face *f) { 153 | return is_seam_or_boundary(f->adje[0]) 154 | || is_seam_or_boundary(f->adje[1]) 155 | || is_seam_or_boundary(f->adje[2]); 156 | } 157 | 158 | bool is_seam(const Edge* e) { 159 | return e->adjf[0] && e->adjf[1] 160 | && (edge_vert(e, 0, 0) != edge_vert(e, 1, 0) 161 | || edge_vert(e, 0, 1) != edge_vert(e, 1, 1)); 162 | } 163 | 164 | void build_node_lookup(map& nodemap, const vector& meshes) { 165 | for (size_t i = 0; inodes.size(); j++) 167 | nodemap[meshes[i]->nodes[j]] = meshes[i]->nodes[j]->x; 168 | } 169 | 170 | 171 | void segfault() { 172 | raise(SIGSEGV); 173 | } -------------------------------------------------------------------------------- /src/external/ArcSim/optimization.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef OPTIMIZATION_HPP 28 | #define OPTIMIZATION_HPP 29 | 30 | //#include "sparse.hpp" 31 | #include "vectors.hpp" 32 | 33 | // Problems 34 | 35 | struct NLOpt { // nonlinear optimization problem 36 | // minimize objective 37 | int nvar; 38 | virtual void initialize (double *x) const = 0; 39 | //virtual double objective (const double *x) const = 0; 40 | //virtual void precompute (const double *x) const {} 41 | //virtual void gradient (const double *x, double *g) const = 0; 42 | //virtual bool hessian (const double *x, SpMat &H) const { 43 | // return false; // should return true if implemented 44 | //}; 45 | virtual void finalize (const double *x) const = 0; 46 | }; 47 | 48 | struct NLConOpt { // nonlinear constrained optimization problem 49 | // minimize objective s.t. constraints = or <= 0 50 | int nvar, ncon; 51 | virtual void initialize (double *x) const = 0; 52 | virtual void precompute (const double *x) const {} 53 | virtual double objective (const double *x) const = 0; 54 | virtual void obj_grad (const double *x, double *grad) const = 0; // set 55 | virtual double constraint (const double *x, int j, int &sign) const = 0; 56 | virtual void con_grad (const double *x, int j, double factor, 57 | double *grad) const = 0; // add factor*gradient 58 | virtual void finalize (const double *x) const = 0; 59 | }; 60 | 61 | // Algorithms 62 | 63 | struct OptOptions { 64 | int _max_iter; 65 | double _eps_x, _eps_f, _eps_g; 66 | OptOptions (): _max_iter(100), _eps_x(1e-6), _eps_f(1e-12), _eps_g(1e-6) {} 67 | // Named parameter idiom 68 | // http://www.parashift.com/c++-faq-lite/named-parameter-idiom.html 69 | OptOptions &max_iter (int n) {_max_iter = n; return *this;} 70 | OptOptions &eps_x (double e) {_eps_x = e; return *this;} 71 | OptOptions &eps_f (double e) {_eps_f = e; return *this;} 72 | OptOptions &eps_g (double e) {_eps_g = e; return *this;} 73 | int max_iter () {return _max_iter;} 74 | double eps_x () {return _eps_x;} 75 | double eps_f () {return _eps_f;} 76 | double eps_g () {return _eps_g;} 77 | }; 78 | 79 | void l_bfgs_method (const NLOpt &problem, 80 | OptOptions opts=OptOptions(), 81 | bool verbose=false); 82 | 83 | void line_search_newtons_method (const NLOpt &problem, 84 | OptOptions opts=OptOptions(), 85 | bool verbose=false); 86 | 87 | void nonlinear_conjugate_gradient_method (const NLOpt &problem, 88 | OptOptions opts=OptOptions(), 89 | bool verbose=false); 90 | 91 | void trust_region_method (const NLOpt &problem, 92 | OptOptions opts=OptOptions(), 93 | bool verbose=false); 94 | 95 | void augmented_lagrangian_method (const NLConOpt &problem, 96 | OptOptions opts=OptOptions(), 97 | bool verbose=false); 98 | 99 | // convenience functions for when optimization variables are Vec3-valued 100 | 101 | inline Vec3 get_subvec (const double *x, int i) { 102 | return Vec3(x[i*3+0], x[i*3+1], x[i*3+2]);} 103 | inline void set_subvec (double *x, int i, const Vec3 &xi) { 104 | for (int j = 0; j < 3; j++) x[i*3+j] = xi[j];} 105 | inline void add_subvec (double *x, int i, const Vec3 &xi) { 106 | for (int j = 0; j < 3; j++) x[i*3+j] += xi[j];} 107 | 108 | template Vec get_subvec (const double *x, int i) { 109 | Vec v; for (int j = 0; j < n; j++) v[j] = x[i*n+j]; return v;} 110 | template void set_subvec (double *x, int i, const Vec &xi) { 111 | for (int j = 0; j < n; j++) x[i*n+j] = xi[j];} 112 | template void add_subvec (double *x, int i, const Vec &xi) { 113 | for (int j = 0; j < n; j++) x[i*n+j] += xi[j];} 114 | 115 | //inline Mat3x3 get_submat (SpMat &A, int i, int j) { 116 | // Mat3x3 Aij; 117 | // for (int ii = 0; ii < 3; ii++) for (int jj = 0; jj < 3; jj++) 118 | // Aij(ii,jj) = A(i*3+ii, j*3+jj); 119 | // return Aij; 120 | //} 121 | //inline void set_submat (SpMat &A, int i, int j, const Mat3x3 &Aij) { 122 | // for (int ii = 0; ii < 3; ii++) for (int jj = 0; jj < 3; jj++) 123 | // A(i*3+ii, j*3+jj) = Aij(ii,jj); 124 | //} 125 | //inline void add_submat (SpMat &A, int i, int j, const Mat3x3 &Aij) { 126 | // for (int ii = 0; ii < 3; ii++) for (int jj = 0; jj < 3; jj++) 127 | // A(i*3+ii, j*3+jj) += Aij(ii,jj); 128 | //} 129 | 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/remeshExtension.cpp: -------------------------------------------------------------------------------- 1 | #include "remeshExtension.h" 2 | 3 | #include "external\ArcSim\util.hpp" 4 | #include "external\ArcSim\blockvectors.hpp" 5 | #include "external\ArcSim\geometry.hpp" 6 | 7 | RemeshOp split_edgeForced(Edge* edge, double d, double thresh) { 8 | Mesh& mesh = *edge->n[0]->mesh; 9 | RemeshOp op; 10 | Node *node0 = edge->n[0], 11 | *node1 = edge->n[1], 12 | *node = new Node((1 - d)*node0->y + d*node1->y, 13 | (1 - d)*node0->x + d*node1->x, 14 | (1 - d)*node0->v + d*node1->v, 15 | 0, //node0->label & node1->label, 16 | node0->flag & node1->flag, 17 | false); 18 | node->acceleration = (1 - d)*node0->acceleration + d*node1->acceleration; 19 | op.added_nodes.push_back(node); 20 | op.removed_edges.push_back(edge); 21 | op.added_edges.push_back(new Edge(node0, node, edge->theta_ideal, 22 | edge->preserve)); 23 | op.added_edges.push_back(new Edge(node, node1, edge->theta_ideal, 24 | edge->preserve)); 25 | Vert *vnew[2] = { NULL, NULL }; 26 | for (int s = 0; s < 2; s++) { 27 | if (!edge->adjf[s]) 28 | continue; 29 | Vert *v0 = edge_vert(edge, s, s), 30 | *v1 = edge_vert(edge, s, 1 - s), 31 | *v2 = edge_opp_vert(edge, s); 32 | if (s == 0 || is_seam_or_boundary(edge)) { 33 | vnew[s] = new Vert(Vec3(0), Vec3(0)); 34 | project_vertex(vnew[s], edge, s, d); 35 | connect(vnew[s], node); 36 | op.added_verts.push_back(vnew[s]); 37 | } 38 | else 39 | vnew[s] = vnew[0]; 40 | op.added_edges.push_back(new Edge(v2->node, node, 0, 0)); 41 | Face *f = edge->adjf[s]; 42 | op.removed_faces.push_back(f); 43 | Face* nf0 = new Face(v0, vnew[s], v2, f->Sp_str, f->Sp_bend, f->material, f->damage); 44 | Face* nf1 = new Face(vnew[s], v1, v2, f->Sp_str, f->Sp_bend, f->material, f->damage); 45 | 46 | 47 | 48 | op.added_faces.push_back(nf0); 49 | op.added_faces.push_back(nf1); 50 | } 51 | 52 | bool make_worse = true; 53 | if (thresh > 0) { 54 | for (size_t n = 0; n < op.added_nodes.size(); n++) { 55 | for (int adje = 0; adje < op.added_edges.size(); adje++) { 56 | if (edge_length(op.added_edges[adje]) < thresh) make_worse = false; 57 | } 58 | } 59 | } 60 | else { 61 | make_worse = false; 62 | } 63 | 64 | if (make_worse) { 65 | op.cancel(); 66 | } 67 | else { 68 | op.apply(mesh); 69 | node->y = (1 - d)*node0->y + d*node1->y; 70 | } 71 | return op; 72 | } 73 | 74 | RemeshOp collapse_edgeForced(Edge* edge, int i) { 75 | /*if (is_seam_or_boundary(edge)) { 76 | Annotation::add(edge); 77 | cout << "collapse" << endl; 78 | cout << edge->n[i]->preserve << endl; 79 | wait_key(); 80 | }*/ 81 | Mesh& mesh = *edge->n[0]->mesh; 82 | RemeshOp op; 83 | Node *node0 = edge->n[i], *node1 = edge->n[1 - i]; 84 | op.removed_nodes.push_back(node0); 85 | for (size_t e = 0; e < node0->adje.size(); e++) { 86 | Edge *edge1 = node0->adje[e]; 87 | op.removed_edges.push_back(edge1); 88 | Node *node2 = (edge1->n[0] != node0) ? edge1->n[0] : edge1->n[1]; 89 | if (node2 != node1 && !get_edge(node1, node2)) 90 | op.added_edges.push_back(new Edge(node1, node2, edge1->theta_ideal, 91 | edge1->preserve)); 92 | // Preserve in weird situations 93 | //if (node2 != node1 && (get_edge(node1, node2) != NULL && get_edge(node0, node2) != NULL)) { 94 | // if (get_edge(node0, node2)->preserve) { 95 | // get_edge(node1, node2)->preserve = true; 96 | // } 97 | //} 98 | } 99 | for (int s = 0; s < 2; s++) { 100 | Vert *vert0 = edge_vert(edge, s, i), *vert1 = edge_vert(edge, s, 1 - i); 101 | if (!vert0 || (s == 1 && vert0 == edge_vert(edge, 0, i))) 102 | continue; 103 | op.removed_verts.push_back(vert0); 104 | for (size_t f = 0; f < vert0->adjf.size(); f++) { 105 | Face *face = vert0->adjf[f]; 106 | op.removed_faces.push_back(face); 107 | if (!is_in(vert1, face->v)) { 108 | Vert *verts[3] = { face->v[0], face->v[1], face->v[2] }; 109 | replace(vert0, vert1, verts); 110 | Face* new_face = new Face(verts[0], verts[1], verts[2], 111 | face->Sp_str, face->Sp_bend, face->material, face->damage); 112 | op.added_faces.push_back(new_face); 113 | // inversion test 114 | if (dot(normal(face), normal(new_face)) < 0) { 115 | op.cancel(); 116 | return RemeshOp(); 117 | } 118 | if (area(new_face) == 0) { 119 | op.cancel(); 120 | return RemeshOp(); 121 | } 122 | } 123 | } 124 | } 125 | op.apply(mesh); 126 | return op; 127 | } 128 | 129 | RemeshOp split_face(Face* face, Vec3 b) { 130 | Mesh& mesh = *face->v[0]->node->mesh; 131 | RemeshOp op; 132 | Node *node0 = face->v[0]->node, 133 | *node1 = face->v[1]->node, 134 | *node2 = face->v[2]->node, 135 | *node = new Node(b[0] * node0->y + b[1] * node1->y + b[2] * node2->y, 136 | b[0] * node0->x + b[1] * node1->x + b[2] * node2->x, 137 | b[0] * node0->v + b[1] * node1->v + b[2] * node2->v, 138 | 0, 139 | node0->flag & node1->flag & node2->flag, 140 | false); 141 | node->acceleration = b[0] * node0->acceleration + b[1] * node1->acceleration + b[2] * node2->acceleration; 142 | op.added_nodes.push_back(node); 143 | op.added_edges.push_back(new Edge(node0, node, 0.0, 144 | false)); 145 | op.added_edges.push_back(new Edge(node1, node, 0.0, 146 | false)); 147 | op.added_edges.push_back(new Edge(node2, node, 0.0, 148 | false)); 149 | Vert *v0 = face->v[0], 150 | *v1 = face->v[1], 151 | *v2 = face->v[2]; 152 | Vert *v = new Vert(b[0] * v0->u + b[1] * v1->u + b[2] * v2->u, 153 | b[0] * v0->v + b[1] * v1->v + b[2] * v2->v); 154 | v->sizing = b[0] * v0->sizing + b[1] * v1->sizing + b[2] * v2->sizing; 155 | connect(v, node); 156 | op.added_verts.push_back(v); 157 | op.removed_faces.push_back(face); 158 | Face* nf0 = new Face(v0, v1, v, face->Sp_str, face->Sp_bend, face->material, face->damage); 159 | Face* nf1 = new Face(v1, v2, v, face->Sp_str, face->Sp_bend, face->material, face->damage); 160 | Face* nf2 = new Face(v2, v0, v, face->Sp_str, face->Sp_bend, face->material, face->damage); 161 | 162 | op.added_faces.push_back(nf0); 163 | op.added_faces.push_back(nf1); 164 | op.added_faces.push_back(nf2); 165 | 166 | op.apply(mesh); 167 | return op; 168 | } -------------------------------------------------------------------------------- /src/external/ArcSim/tensormax.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "tensormax.hpp" 28 | #include "util.hpp" 29 | using namespace std; 30 | 31 | struct Disk { 32 | Vec2 c; 33 | double r; 34 | Disk (): c(Vec2(0)), r(0) {} 35 | Disk (const Vec2 &c, double r): c(c), r(r) {} 36 | }; 37 | ostream &operator<< (ostream &out, const Disk &disk) {out << "Circle[{" << disk.c[0] << "," << disk.c[1] << "}," << disk.r << "]"; return out;} 38 | 39 | // Welzl, Smallest enclosing disks..., 1991 40 | Disk welzls_algorithm (const vector &disks); 41 | 42 | Mat2x2 tensor_max (const vector &Ms) { 43 | int n = Ms.size(); 44 | vector disks; 45 | for (int i = 0; i < n; i++) { 46 | const Mat2x2 &M = Ms[i]; 47 | if (trace(M) == 0) 48 | continue; 49 | disks.push_back(Disk(Vec2((M(0,0)-M(1,1))/2, (M(0,1)+M(1,0))/2), 50 | (M(0,0)+M(1,1))/2)); 51 | } 52 | Disk disk = welzls_algorithm(disks); 53 | return disk.c[0]*Mat2x2(Vec2(1,0),Vec2(0,-1)) 54 | + disk.c[1]*Mat2x2(Vec2(0,1),Vec2(1,0)) 55 | + disk.r*Mat2x2(Vec2(1,0),Vec2(0,1)); 56 | } 57 | 58 | Disk minidisk (const vector &P); 59 | Disk b_minidisk (const vector &P, const vector &R); 60 | Disk b_md (const vector &R); 61 | 62 | Disk welzls_algorithm (const vector &disks) { 63 | return minidisk(disks); 64 | } 65 | 66 | bool enclosed (const Disk &disk0, const Disk &disk1); 67 | template T head (const vector &v); 68 | template vector tail (const vector &v); 69 | template vector cons (const T &x, const vector &v); 70 | 71 | Disk minidisk (const vector &P) { 72 | if (P.empty()) 73 | return Disk(); 74 | Disk p = head(P); 75 | vector P_ = tail(P); 76 | Disk D = minidisk(P_); 77 | if (enclosed(p, D)) 78 | return D; 79 | else 80 | return b_minidisk(P_, vector(1,p)); 81 | } 82 | 83 | Disk b_minidisk (const vector &P, const vector &R) { 84 | if (P.empty() || R.size() == 3) 85 | return b_md(R); 86 | Disk p = head(P); 87 | vector P_ = tail(P); 88 | Disk D = b_minidisk(P_, R); 89 | if (enclosed(p, D)) 90 | return D; 91 | else 92 | return b_minidisk(P_, cons(p, R)); 93 | } 94 | 95 | Disk apollonius (const Disk &disk1, const Disk &disk2, const Disk &disk3); 96 | 97 | Disk b_md (const vector &R) { 98 | if (R.empty()) 99 | return Disk(); 100 | else if (R.size() == 1) 101 | return head(R); 102 | else if (R.size() == 2) { 103 | double d = norm(R[0].c - R[1].c); 104 | double r = (R[0].r + d + R[1].r)/2; 105 | double t = (r - R[0].r)/d; 106 | return Disk(R[0].c + t*(R[1].c - R[0].c), r); 107 | } else 108 | return apollonius(R[0], R[1], R[2]); 109 | } 110 | 111 | Disk apollonius (const Disk &disk1, const Disk &disk2, const Disk &disk3) { 112 | // nicked from http://rosettacode.org/mw/index.php?title=Problem_of_Apollonius&oldid=88212 113 | #define DEFXYR(N) double x##N = disk##N.c[0]; \ 114 | double y##N = disk##N.c[1]; \ 115 | double r##N = disk##N.r; 116 | DEFXYR(1); DEFXYR(2); DEFXYR(3); 117 | #undef DEFXYR 118 | int s1 = 1, s2 = 1, s3 = 1; 119 | double v11 = 2*x2 - 2*x1; 120 | double v12 = 2*y2 - 2*y1; 121 | double v13 = x1*x1 - x2*x2 + y1*y1 - y2*y2 - r1*r1 + r2*r2; 122 | double v14 = 2*s2*r2 - 2*s1*r1; 123 | double v21 = 2*x3 - 2*x2; 124 | double v22 = 2*y3 - 2*y2; 125 | double v23 = x2*x2 - x3*x3 + y2*y2 - y3*y3 - r2*r2 + r3*r3; 126 | double v24 = 2*s3*r3 - 2*s2*r2; 127 | double w12 = v12/v11; 128 | double w13 = v13/v11; 129 | double w14 = v14/v11; 130 | double w22 = v22/v21-w12; 131 | double w23 = v23/v21-w13; 132 | double w24 = v24/v21-w14; 133 | double P = -w23/w22; 134 | double Q = w24/w22; 135 | double M = -w12*P-w13; 136 | double N = w14 - w12*Q; 137 | double a = N*N + Q*Q - 1; 138 | double b = 2*M*N - 2*N*x1 + 2*P*Q - 2*Q*y1 + 2*s1*r1; 139 | double c = x1*x1 + M*M - 2*M*x1 + P*P + y1*y1 - 2*P*y1 - r1*r1; 140 | double D = b*b-4*a*c; 141 | double rs = (-b-sqrt(D))/(2*a); 142 | double xs = M+N*rs; 143 | double ys = P+Q*rs; 144 | return Disk(Vec2(xs,ys), rs); 145 | } 146 | 147 | bool enclosed (const Disk &disk0, const Disk &disk1) { 148 | return norm(disk0.c-disk1.c) + disk0.r <= disk1.r + 1e-6; 149 | } 150 | 151 | template T head (const vector &v) { 152 | return v.front(); 153 | } 154 | 155 | template vector tail (const vector &v) { 156 | vector w(v.size()-1); 157 | for (int i = 0; i < w.size(); i++) 158 | w[i] = v[i+1]; 159 | return w; 160 | } 161 | 162 | template vector cons (const T &x, const vector &v) { 163 | vector w(v.size()+1); 164 | w[0] = x; 165 | for (int i = 1; i < w.size(); i++) 166 | w[i] = v[i-1]; 167 | return w; 168 | } 169 | -------------------------------------------------------------------------------- /src/Shape.cpp: -------------------------------------------------------------------------------- 1 | #include "Shape.h" 2 | #include 3 | 4 | #ifdef EOLC_ONLINE 5 | #include "online/GLSL.h" 6 | #include "online/Program.h" 7 | #endif // EOLC_ONLINE 8 | 9 | #define TINYOBJLOADER_IMPLEMENTATION 10 | #include "tiny_obj_loader.h" 11 | 12 | using namespace std; 13 | 14 | Shape::Shape() : 15 | posBufID(0), 16 | norBufID(0), 17 | texBufID(0) 18 | { 19 | } 20 | 21 | Shape::~Shape() 22 | { 23 | } 24 | 25 | void Shape::loadMesh(const string &meshName) 26 | { 27 | // Load geometry 28 | tinyobj::attrib_t attrib; 29 | std::vector shapes; 30 | std::vector materials; 31 | string errStr; 32 | bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); 33 | if(!rc) { 34 | cerr << errStr << endl; 35 | } else { 36 | // Some OBJ files have different indices for vertex positions, normals, 37 | // and texture coordinates. For example, a cube corner vertex may have 38 | // three different normals. Here, we are going to duplicate all such 39 | // vertices. 40 | // Loop over shapes 41 | for(size_t s = 0; s < shapes.size(); s++) { 42 | // Loop over faces (polygons) 43 | size_t index_offset = 0; 44 | for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { 45 | size_t fv = shapes[s].mesh.num_face_vertices[f]; 46 | // Loop over vertices in the face. 47 | for(size_t v = 0; v < fv; v++) { 48 | // access to vertex 49 | tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; 50 | posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); 51 | posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); 52 | posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); 53 | if(!attrib.normals.empty()) { 54 | norBuf.push_back(attrib.normals[3*idx.normal_index+0]); 55 | norBuf.push_back(attrib.normals[3*idx.normal_index+1]); 56 | norBuf.push_back(attrib.normals[3*idx.normal_index+2]); 57 | } 58 | if(!attrib.texcoords.empty()) { 59 | texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); 60 | texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); 61 | } 62 | } 63 | index_offset += fv; 64 | // per-face material (IGNORE) 65 | shapes[s].mesh.material_ids[f]; 66 | } 67 | } 68 | } 69 | } 70 | 71 | #ifdef EOLC_ONLINE 72 | 73 | void Shape::init() 74 | { 75 | // Send the position array to the GPU 76 | glGenBuffers(1, &posBufID); 77 | glBindBuffer(GL_ARRAY_BUFFER, posBufID); 78 | glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); 79 | 80 | // Send the normal array to the GPU 81 | if(!norBuf.empty()) { 82 | glGenBuffers(1, &norBufID); 83 | glBindBuffer(GL_ARRAY_BUFFER, norBufID); 84 | glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); 85 | } 86 | 87 | // Send the texture array to the GPU 88 | if(!texBuf.empty()) { 89 | glGenBuffers(1, &texBufID); 90 | glBindBuffer(GL_ARRAY_BUFFER, texBufID); 91 | glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); 92 | } 93 | 94 | // Unbind the arrays 95 | glBindBuffer(GL_ARRAY_BUFFER, 0); 96 | 97 | GLSL::checkError(GET_FILE_LINE); 98 | } 99 | 100 | void Shape::draw(const shared_ptr prog) const 101 | { 102 | GLSL::checkError(GET_FILE_LINE); 103 | // Bind position buffer 104 | int h_pos = prog->getAttribute("aPos"); 105 | glEnableVertexAttribArray(h_pos); 106 | glBindBuffer(GL_ARRAY_BUFFER, posBufID); 107 | glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); 108 | 109 | // Bind normal buffer 110 | int h_nor = prog->getAttribute("aNor"); 111 | if(h_nor != -1 && norBufID != 0) { 112 | glEnableVertexAttribArray(h_nor); 113 | glBindBuffer(GL_ARRAY_BUFFER, norBufID); 114 | glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); 115 | } 116 | 117 | // Bind texcoords buffer 118 | //int h_tex = prog->getAttribute("aTex"); 119 | //if(h_tex != -1 && texBufID != 0) { 120 | // glEnableVertexAttribArray(h_tex); 121 | // glBindBuffer(GL_ARRAY_BUFFER, texBufID); 122 | // glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); 123 | //} 124 | 125 | // Draw 126 | int count = posBuf.size()/3; // number of indices to be rendered 127 | glDrawArrays(GL_TRIANGLES, 0, count); 128 | 129 | // Disable and unbind 130 | //if(h_tex != -1) { 131 | // glDisableVertexAttribArray(h_tex); 132 | //} 133 | if(h_nor != -1) { 134 | glDisableVertexAttribArray(h_nor); 135 | } 136 | glDisableVertexAttribArray(h_pos); 137 | glBindBuffer(GL_ARRAY_BUFFER, 0); 138 | 139 | GLSL::checkError(GET_FILE_LINE); 140 | } 141 | 142 | #endif // EOLC_ONLINE 143 | 144 | void Shape::exportBrender(const Eigen::Matrix4d &E, std::ofstream& outfile) const { 145 | //Make transformation conversions 146 | // //multiply E by each p(x,y,z) where p is point in shape 147 | 148 | //vertex positions 149 | for (int i = 0; i < posBuf.size(); i = i + 3) { 150 | Eigen::Vector4d pos(posBuf[i], posBuf[i + 1], posBuf[i + 2], 1.0); //double check if it should be zero or 1 151 | // apply transformation 152 | Eigen::Vector4d trans_pos = E * pos; 153 | char vert[50]; 154 | //sprintf(vert, "v %f %f %f\n", posBuf[i], posBuf[i + 1], posBuf[i + 2]); 155 | sprintf(vert, "v %f %f %f\n", trans_pos(0), trans_pos(1), trans_pos(2)); 156 | outfile << vert; 157 | } 158 | //texture coordinates 159 | for (int i = 0; i < texBuf.size(); i = i + 2) { 160 | char vtex[50]; 161 | sprintf(vtex, "vt %f %f\n", texBuf[i], texBuf[i + 1]); 162 | outfile << vtex; 163 | } 164 | //normal vectors 165 | for (int i = 0; i < norBuf.size(); i = i + 3) { 166 | Eigen::Vector4d nor(norBuf[i], norBuf[i + 1], norBuf[i + 2], 0.0); 167 | // apply transformation 168 | Eigen::Vector4d trans_nor = E * nor; 169 | char norm[50]; 170 | sprintf(norm, "vn %f %f %f\n", trans_nor(0), trans_nor(1), trans_nor(2)); 171 | outfile << norm; 172 | } 173 | 174 | //face 175 | //f vertex/texture/normal1 vertex/texture/normal2 vertex/texture/normal3 176 | // posbuf holds all vertices. each face has 3 vertices. 177 | for (int i = 1; i < (posBuf.size() / 3); i = i + 3) { 178 | char face[50]; 179 | int f1, f2, f3; 180 | f1 = i; 181 | f2 = i + 1; 182 | f3 = i + 2; 183 | 184 | sprintf(face, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", f1, f1, f1, f2, f2, f2, f3, f3, f3); 185 | outfile << face; 186 | } 187 | } -------------------------------------------------------------------------------- /src/external/ArcSim/transformation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "transformation.hpp" 28 | 29 | using namespace std; 30 | 31 | Transformation tform::identity () { 32 | return Transformation(); 33 | } 34 | 35 | Transformation inverse(const Transformation &tr) { 36 | Transformation in; 37 | in.scale = 1.f / tr.scale; 38 | in.rotation = inverse(tr.rotation); 39 | in.translation = Vec3(0.) - 40 | in.rotation.rotate( 41 | in.scale * ( 42 | tr.translation 43 | ) 44 | ); 45 | return in; 46 | } 47 | 48 | Quaternion inverse(const Quaternion &q) { 49 | Quaternion in; 50 | double divisor = norm2(q); 51 | in.s = q.s / divisor; 52 | in.v = -q.v / divisor; 53 | return in; 54 | } 55 | 56 | Quaternion Quaternion::from_axisangle(const Vec3 &axis, double angle) { 57 | Quaternion q; 58 | if (angle == 0) { 59 | q.s = 1; 60 | q.v = Vec3(0); 61 | } else { 62 | q.s = cos(angle/2); 63 | q.v = sin(angle/2)*normalize(axis); 64 | } 65 | return q; 66 | } 67 | 68 | pair Quaternion::to_axisangle() const { 69 | double angle = 2 * acos(s); 70 | Vec3 axis; 71 | if(angle == 0) { 72 | axis = Vec3(1); 73 | } else { 74 | axis = v / sqrt(1.0-s*s); 75 | } 76 | return pair(axis, angle); 77 | } 78 | 79 | Transformation::Transformation(double factor) { 80 | translation = Vec3(0); 81 | scale = factor; 82 | rotation = Quaternion::from_axisangle(Vec3(1), 0)*factor; 83 | } 84 | 85 | Transformation Transformation::operator-(const Transformation& other) const { 86 | Transformation t; 87 | t.scale = this->scale - other.scale; 88 | t.translation = this->translation - other.translation; 89 | t.rotation = this->rotation - other.rotation; 90 | return t; 91 | } 92 | 93 | Transformation Transformation::operator+(const Transformation& other) const { 94 | Transformation t; 95 | t.scale = this->scale + other.scale; 96 | t.translation = this->translation + other.translation; 97 | t.rotation = this->rotation + other.rotation; 98 | return t; 99 | } 100 | 101 | Transformation Transformation::operator*(const Transformation& other) const { 102 | Transformation t; 103 | t.scale = this->scale * other.scale; 104 | t.translation = this->translation + 105 | this->rotation.rotate(other.translation * this->scale); 106 | t.rotation = this->rotation * other.rotation; 107 | return t; 108 | } 109 | 110 | Transformation Transformation::operator*(double s) const { 111 | Transformation t; 112 | t.scale = this->scale * s; 113 | t.translation = this->translation * s; 114 | t.rotation = this->rotation * s; 115 | return t; 116 | } 117 | 118 | Transformation Transformation::operator/(double s) const { 119 | return (*this)*(1./s); 120 | } 121 | 122 | Quaternion Quaternion::operator+(const Quaternion& other) const { 123 | Quaternion q; 124 | q.v = this->v + other.v; 125 | q.s = this->s + other.s; 126 | return q; 127 | } 128 | 129 | Quaternion Quaternion::operator-(const Quaternion& other) const { 130 | Quaternion q; 131 | q.v = this->v - other.v; 132 | q.s = this->s - other.s; 133 | return q; 134 | } 135 | 136 | Quaternion Quaternion::operator-() const { 137 | Quaternion q; 138 | q.v = -this->v; 139 | q.s = -this->s; 140 | return q; 141 | } 142 | 143 | Quaternion Quaternion::operator*(const Quaternion& other) const { 144 | Quaternion q; 145 | q.v = (this->s * other.v) + (other.s * this->v) + 146 | cross(this->v, other.v); 147 | q.s = (this->s * other.s) - dot(this->v, other.v); 148 | return q; 149 | } 150 | 151 | Quaternion Quaternion::operator*(double s) const { 152 | Quaternion q; 153 | q.v = this->v * s; 154 | q.s = this->s * s; 155 | return q; 156 | } 157 | 158 | Quaternion Quaternion::operator/(double s) const { 159 | return (*this)*(1./s); 160 | } 161 | 162 | Vec3 Quaternion::rotate (const Vec3 &x) const { 163 | return x*(sq(s) - dot(v,v)) + 164 | 2.*v*dot(v,x) + 2.*cross(v,x)*s; 165 | } 166 | 167 | Vec3 Transformation::apply (const Vec3 &x) const { 168 | return translation + scale*rotation.rotate(x); 169 | } 170 | 171 | Vec3 Transformation::apply_vec (const Vec3 &v) const { 172 | return rotation.rotate(v); 173 | } 174 | 175 | double norm2(const Quaternion &q) { 176 | return sq(q.s) + norm2(q.v); 177 | } 178 | 179 | Quaternion normalize (const Quaternion &q) { 180 | double norm = sqrt(norm2(q)); 181 | Quaternion p; 182 | p.s = q.s/norm; 183 | p.v = q.v/norm; 184 | return p; 185 | } 186 | 187 | //void clean_up_quaternions (Motion &motion) { 188 | // for (int p = 1; p < motion.points.size(); p++) { 189 | // const Quaternion &q0 = motion.points[p-1].x.rotation; 190 | // Quaternion &q1 = motion.points[p].x.rotation; 191 | // double d = dot(q0.v, q1.v) + q0.s*q1.s; 192 | // if (d < 0) 193 | // q1 = -q1; 194 | // } 195 | //} 196 | 197 | //Transformation get_trans (const Motion &motion, double t) { 198 | // Transformation T = motion.pos(t); 199 | // T.rotation = normalize(T.rotation); 200 | // return T; 201 | //} 202 | // 203 | //DTransformation get_dtrans (const Motion &motion, double t) { 204 | // Transformation T = motion.pos(t), dT = motion.vel(t); 205 | // Quaternion q = T.rotation, dq = dT.rotation; 206 | // double qq = sq(q.s) + norm2(q.v), 207 | // qdq = q.s*dq.s + dot(q.v, dq.v); 208 | // double normq = sqrt(qq); 209 | // T.rotation = q/normq; 210 | // dT.rotation = dq/normq - q/normq*qdq/qq; 211 | // return make_pair(T, dT); 212 | //} 213 | 214 | //Vec3 apply_dtrans (const DTransformation &dtrans, const Vec3 &x0, Vec3 *vel) { 215 | // const Transformation &T = dtrans.first, &dT = dtrans.second; 216 | // Vec3 x = T.apply(x0); 217 | // if (vel) { 218 | // Vec3 w = 2.*(dT.rotation*inverse(T.rotation)).v; 219 | // *vel = dT.translation + dT.scale*T.rotation.rotate(x0) 220 | // + T.scale*cross(w, T.rotation.rotate(x0)); 221 | // } 222 | // return x; 223 | //} 224 | // 225 | //Vec3 apply_dtrans_vec (const DTransformation &dtrans, const Vec3 &v0) { 226 | // return dtrans.first.apply_vec(v0); 227 | //} 228 | -------------------------------------------------------------------------------- /src/external/ArcSim/util.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #ifndef UTIL_HPP 28 | #define UTIL_HPP 29 | 30 | #include // aa: win 31 | #include "mesh.hpp" 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define EPSILON 1e-7f 39 | 40 | // i+1 and i-1 modulo 3 41 | // This way of computing it tends to be faster than using % 42 | #define NEXT(i) ((i)<2 ? (i)+1 : (i)-2) 43 | #define PREV(i) ((i)>0 ? (i)-1 : (i)+2) 44 | 45 | typedef unsigned int uint; 46 | 47 | struct Transformation; 48 | 49 | // Quick-and easy statistics 50 | 51 | struct Stats { 52 | mutable std::vector xs; 53 | double sum; 54 | mutable bool sorted; 55 | Stats() : sum(0) {} 56 | void add(double x); 57 | void sort() const; 58 | double min() const, max() const, mean() const, median() const, 59 | quantile(double) const; 60 | }; 61 | std::ostream &operator<< (std::ostream &out, const Stats &stats); 62 | 63 | // sprintf for std::strings 64 | 65 | std::string stringf(const std::string &format, ...); 66 | 67 | // Easy reporting of vertices and faces 68 | 69 | std::ostream &operator<< (std::ostream &out, const Vert *vert); 70 | std::ostream &operator<< (std::ostream &out, const Node *node); 71 | std::ostream &operator<< (std::ostream &out, const Edge *edge); 72 | std::ostream &operator<< (std::ostream &out, const Face *face); 73 | 74 | // Math utilities 75 | 76 | extern const double infinity; 77 | 78 | template T sqr(const T& x) { return x*x; } 79 | 80 | template T clamp(const T &x, const T &a, const T &b) { 81 | return std::min(std::max(x, a), b); 82 | } 83 | 84 | template T min(const T &a, const T &b, const T &c) { 85 | return std::min(a, std::min(b, c)); 86 | } 87 | template T min(const T &a, const T &b, const T &c, const T &d) { 88 | return std::min(std::min(a, b), std::min(c, d)); 89 | } 90 | 91 | template T max(const T &a, const T &b, const T &c) { 92 | return std::max(a, std::max(b, c)); 93 | } 94 | template T max(const T &a, const T &b, const T &c, const T &d) { 95 | return std::max(std::max(a, b), std::max(c, d)); 96 | } 97 | 98 | template T sgn(const T &x) { return x<0 ? -1 : 1; } 99 | 100 | inline bool is_finite(double x) { return x > -1e300 && x < 1e300; } 101 | 102 | int solve_quadratic(double a, double b, double c, double x[2]); 103 | 104 | // Find, replace, and all that jazz 105 | 106 | template inline int find(const T *x, T* const *xs, int n = 3) { 107 | for (int i = 0; i < n; i++) if (xs[i] == x) return i; return -1; 108 | } 109 | 110 | template inline int find(const T &x, const T *xs, int n = 3) { 111 | for (int i = 0; i < n; i++) if (xs[i] == x) return i; return -1; 112 | } 113 | 114 | template inline int find(const T &x, const std::vector &xs) { 115 | for (int i = 0; i < xs.size(); i++) if (xs[i] == x) return i; return -1; 116 | } 117 | 118 | template inline bool is_in(const T *x, T* const *xs, int n = 3) { 119 | return find(x, xs, n) != -1; 120 | } 121 | 122 | template inline bool is_in(const T &x, const T *xs, int n = 3) { 123 | return find(x, xs, n) != -1; 124 | } 125 | 126 | template inline bool is_in(const T &x, const std::vector &xs) { 127 | return find(x, xs) != -1; 128 | } 129 | 130 | template inline void include(const T &x, std::vector &xs) { 131 | if (!is_in(x, xs)) xs.push_back(x); 132 | } 133 | 134 | template inline void remove(int i, std::vector &xs) { 135 | xs[i] = xs.back(); xs.pop_back(); 136 | } 137 | 138 | template inline void exclude(const T &x, std::vector &xs) { 139 | int i = find(x, xs); if (i != -1) remove(i, xs); 140 | } 141 | 142 | template inline void replace(const T &v0, const T &v1, T vs[3]) { 143 | int i = find(v0, vs); if (i != -1) vs[i] = v1; 144 | } 145 | 146 | template 147 | inline void replace(const T &x0, const T &x1, std::vector &xs) { 148 | int i = find(x0, xs); if (i != -1) xs[i] = x1; 149 | } 150 | 151 | template 152 | inline bool subset(const std::vector &xs, const std::vector &ys) { 153 | for (int i = 0; i < xs.size(); i++) if (!is_in(xs[i], ys)) return false; 154 | return true; 155 | } 156 | 157 | template 158 | inline void append(std::vector &xs, const std::vector &ys) { 159 | xs.insert(xs.end(), ys.begin(), ys.end()); 160 | } 161 | 162 | // Comparisons on vectors 163 | 164 | #define VEC_CMP(op) \ 165 | template \ 166 | bool operator op (const Vec &u, const Vec &v) { \ 167 | for (int i = 0; i < n; i++) if (!(u[i] op v[i])) return false; \ 168 | return true;} \ 169 | 170 | VEC_CMP(<) 171 | VEC_CMP(<= ) 172 | VEC_CMP(>) 173 | VEC_CMP(>= ) 174 | 175 | #undef VEC_CMP 176 | 177 | template 178 | Vec vec_min(const Vec &u, const Vec &v) { 179 | Vec m; for (int i = 0; i < n; i++) m[i] = std::min(u[i], v[i]); 180 | return m; 181 | } 182 | 183 | template 184 | Vec vec_max(const Vec &u, const Vec &v) { 185 | Vec m; for (int i = 0; i < n; i++) m[i] = std::max(u[i], v[i]); 186 | return m; 187 | } 188 | 189 | // Mesh utilities 190 | 191 | bool is_seam_or_boundary(const Vert *v); 192 | bool is_seam_or_boundary(const Node *n); 193 | bool is_seam_or_boundary(const Edge *e); 194 | bool is_seam_or_boundary(const Face *f); 195 | bool is_seam(const Edge* e); 196 | 197 | void build_node_lookup(std::map& nodemap, const std::vector& meshes); 198 | 199 | // Debugging 200 | 201 | void segfault(); 202 | void debug_save_mesh(const Mesh &mesh, const std::string &name, int n = -1); 203 | void debug_save_meshes(const std::vector &meshes, 204 | const std::string &name, int n = -1); 205 | 206 | template 207 | std::ostream &operator<< (std::ostream &out, const std::vector &v) { 208 | out << "["; 209 | for (int i = 0; i < v.size(); i++) 210 | out << (i == 0 ? "" : ", ") << v[i]; 211 | out << "]"; 212 | return out; 213 | } 214 | 215 | #define ECHO(x) std::cout << #x << std::endl 216 | 217 | #define REPORT(x) std::cout << #x << " = " << (x) << std::endl 218 | 219 | #define REPORT_ARRAY(x,n) std::cout << #x << "[" << #n << "] = " << vector(&(x)[0], &(x)[n]) << std::endl 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /src/runner.cpp: -------------------------------------------------------------------------------- 1 | #include "runner.h" 2 | 3 | #ifdef EOLC_ONLINE 4 | 5 | #ifndef _GLIBCXX_USE_NANOSLEEP 6 | #define _GLIBCXX_USE_NANOSLEEP 7 | #endif 8 | #include 9 | 10 | #define GLEW_STATIC 11 | #include 12 | #include 13 | 14 | #define GLM_FORCE_RADIANS 15 | #include 16 | #include 17 | 18 | #include "online\Camera.h" 19 | #include "online\Program.h" 20 | #include "online\MatrixStack.h" 21 | #include "online\GLSL.h" 22 | 23 | #endif // EOL_ONLINE 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "parseParams.h"; 31 | #include "genSet.h"; 32 | #include "Scene.h" 33 | 34 | using namespace std; 35 | using namespace Eigen; 36 | 37 | shared_ptr gs; 38 | shared_ptr scene; 39 | 40 | #ifdef EOLC_ONLINE 41 | bool keyToggles[256] = { false }; // only for English keyboards! 42 | 43 | GLFWwindow *window; // Main application window 44 | 45 | shared_ptr camera; 46 | shared_ptr progPhong; 47 | shared_ptr progSimple; 48 | #endif // EOLC_ONLINE 49 | 50 | void init_offline(const string &SIMSET_FILE) 51 | { 52 | scene = make_shared(); 53 | scene->load(gs->RESOURCE_DIR); 54 | load_simset(scene, SIMSET_FILE); 55 | scene->init(gs->online, gs->exportObjs, gs->OUTPUT_DIR); 56 | } 57 | 58 | void run_offline() 59 | { 60 | while (true) { 61 | scene->step(gs->online, gs->exportObjs); 62 | } 63 | } 64 | 65 | #ifdef EOLC_ONLINE 66 | 67 | static void error_callback(int error, const char *description) 68 | { 69 | cerr << description << endl; 70 | } 71 | 72 | static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) 73 | { 74 | if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { 75 | glfwSetWindowShouldClose(window, GL_TRUE); 76 | } 77 | } 78 | 79 | static void char_callback(GLFWwindow *window, unsigned int key) 80 | { 81 | keyToggles[key] = !keyToggles[key]; 82 | switch (key) { 83 | case 'h': 84 | scene->step(gs->online, gs->exportObjs); 85 | break; 86 | case 'r': 87 | //scene->reset(); 88 | break; 89 | case 'p': 90 | scene->partialStep(); 91 | break; 92 | case 'v': 93 | camera->toggleFlatView(); 94 | } 95 | } 96 | 97 | static void cursor_position_callback(GLFWwindow* window, double xmouse, double ymouse) 98 | { 99 | int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); 100 | if (state == GLFW_PRESS) { 101 | camera->mouseMoved(xmouse, ymouse); 102 | } 103 | } 104 | 105 | void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) 106 | { 107 | // Get the current mouse position. 108 | double xmouse, ymouse; 109 | glfwGetCursorPos(window, &xmouse, &ymouse); 110 | // Get current window size. 111 | int width, height; 112 | glfwGetWindowSize(window, &width, &height); 113 | if (action == GLFW_PRESS) { 114 | bool shift = mods & GLFW_MOD_SHIFT; 115 | bool ctrl = mods & GLFW_MOD_CONTROL; 116 | bool alt = mods & GLFW_MOD_ALT; 117 | camera->mouseClicked(xmouse, ymouse, shift, ctrl, alt); 118 | } 119 | } 120 | 121 | void stepperFunc() 122 | { 123 | while (true) { 124 | if (keyToggles[(unsigned)' ']) { 125 | scene->step(gs->online, gs->exportObjs); 126 | } 127 | this_thread::sleep_for(chrono::microseconds(1)); 128 | } 129 | } 130 | 131 | bool init_online(const string &SIMSET_FILE) 132 | { 133 | // Set error callback. 134 | glfwSetErrorCallback(error_callback); 135 | // Initialize the library. 136 | if (!glfwInit()) { 137 | return false; 138 | } 139 | // Create a windowed mode window and its OpenGL context. 140 | window = glfwCreateWindow(1280, 720, "EOL Cloth", NULL, NULL); 141 | if (!window) { 142 | glfwTerminate(); 143 | return false; 144 | } 145 | // Make the window's context current. 146 | glfwMakeContextCurrent(window); 147 | // Initialize GLEW. 148 | glewExperimental = true; 149 | if (glewInit() != GLEW_OK) { 150 | cerr << "Failed to initialize GLEW" << endl; 151 | return false; 152 | } 153 | 154 | glGetError(); // A bug in glewInit() causes an error that we can safely ignore. 155 | cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; 156 | cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; 157 | // Set vsync. 158 | glfwSwapInterval(1); 159 | // Set keyboard callback. 160 | glfwSetKeyCallback(window, key_callback); 161 | // Set char callback. 162 | glfwSetCharCallback(window, char_callback); 163 | // Set cursor position callback. 164 | glfwSetCursorPosCallback(window, cursor_position_callback); 165 | // Set mouse button callback. 166 | glfwSetMouseButtonCallback(window, mouse_button_callback); 167 | 168 | GLSL::checkVersion(); 169 | 170 | // Set background color 171 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 172 | // Enable z-buffer test 173 | glEnable(GL_DEPTH_TEST); 174 | // Enable alpha blending 175 | glEnable(GL_BLEND); 176 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 177 | 178 | progSimple = make_shared(); 179 | progSimple->setShaderNames(gs->RESOURCE_DIR + "simple_vert.glsl", gs->RESOURCE_DIR + "simple_frag.glsl"); 180 | progSimple->setVerbose(true); // Set this to true when debugging. 181 | progSimple->init(); 182 | progSimple->addUniform("P"); 183 | progSimple->addUniform("MV"); 184 | //progSimple->setVerbose(false); 185 | 186 | progPhong = make_shared(); 187 | progPhong->setVerbose(true); // Set this to true when debugging. 188 | progPhong->setShaderNames(gs->RESOURCE_DIR + "phong_vert.glsl", gs->RESOURCE_DIR + "phong_frag.glsl"); 189 | progPhong->init(); 190 | progPhong->addUniform("P"); 191 | progPhong->addUniform("MV"); 192 | progPhong->addUniform("kdFront"); 193 | progPhong->addUniform("kdBack"); 194 | progPhong->addAttribute("aPos"); 195 | progPhong->addAttribute("aNor"); 196 | //prog->setVerbose(false); 197 | 198 | camera = make_shared(); 199 | camera->setInitDistance(2.0f); 200 | 201 | scene = make_shared(); 202 | scene->load(gs->RESOURCE_DIR); 203 | load_simset(scene, SIMSET_FILE); 204 | scene->init(gs->online, gs->exportObjs, gs->OUTPUT_DIR); 205 | 206 | // If there were any OpenGL errors, this will print something. 207 | GLSL::checkError(GET_FILE_LINE); 208 | 209 | return true; 210 | } 211 | 212 | void render() 213 | { 214 | // Get current frame buffer size. 215 | int width, height; 216 | glfwGetFramebufferSize(window, &width, &height); 217 | glViewport(0, 0, width, height); 218 | 219 | // Use the window size for camera. 220 | glfwGetWindowSize(window, &width, &height); 221 | camera->setAspect((float)width / (float)height); 222 | 223 | // Clear buffers 224 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 225 | if (keyToggles[(unsigned)'c']) { 226 | glEnable(GL_CULL_FACE); 227 | } 228 | else { 229 | glDisable(GL_CULL_FACE); 230 | } 231 | if (keyToggles[(unsigned)'l']) { 232 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 233 | } 234 | else { 235 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 236 | } 237 | 238 | auto P = make_shared(); 239 | auto MV = make_shared(); 240 | 241 | // Apply camera transforms 242 | P->pushMatrix(); 243 | camera->applyProjectionMatrix(P); 244 | MV->pushMatrix(); 245 | camera->applyViewMatrix(MV); 246 | 247 | progSimple->bind(); 248 | glUniformMatrix4fv(progSimple->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix())); 249 | glUniformMatrix4fv(progSimple->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix())); 250 | 251 | scene->drawSimple(MV, progSimple); 252 | 253 | progSimple->unbind(); 254 | 255 | progPhong->bind(); 256 | glUniformMatrix4fv(progPhong->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix())); 257 | MV->pushMatrix(); 258 | scene->draw(MV, progPhong); 259 | MV->popMatrix(); 260 | progPhong->unbind(); 261 | 262 | MV->popMatrix(); 263 | P->popMatrix(); 264 | 265 | GLSL::checkError(GET_FILE_LINE); 266 | } 267 | 268 | void run_online() 269 | { 270 | // Start simulation thread. 271 | thread stepperThread(stepperFunc); 272 | 273 | while (!glfwWindowShouldClose(window)) { 274 | render(); 275 | // Swap front and back buffers. 276 | glfwSwapBuffers(window); 277 | // Poll for and process events. 278 | glfwPollEvents(); 279 | } 280 | stepperThread.detach(); 281 | glfwDestroyWindow(window); 282 | glfwTerminate(); 283 | } 284 | 285 | #endif // EOL_ONLINE 286 | 287 | void start_running(const string &GENSET_FILE, const string &SIMSET_FILE) 288 | { 289 | gs = make_shared(); 290 | load_genset(gs, GENSET_FILE); 291 | 292 | if (gs->online) { 293 | #ifdef EOLC_ONLINE 294 | init_online(SIMSET_FILE); 295 | run_online(); 296 | #else 297 | cout << "ERROR: Attempting to run in online mode without building the online libraries." << endl; 298 | #endif // EOL_ONLINE 299 | } 300 | else { 301 | init_offline(SIMSET_FILE); 302 | run_offline(); 303 | } 304 | } 305 | 306 | 307 | -------------------------------------------------------------------------------- /src/external/ArcSim/io.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ©2013 The Regents of the University of California 3 | (Regents). All Rights Reserved. Permission to use, copy, modify, and 4 | distribute this software and its documentation for educational, 5 | research, and not-for-profit purposes, without fee and without a 6 | signed licensing agreement, is hereby granted, provided that the 7 | above copyright notice, this paragraph and the following two 8 | paragraphs appear in all copies, modifications, and 9 | distributions. Contact The Office of Technology Licensing, UC 10 | Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 11 | (510) 643-7201, for commercial licensing opportunities. 12 | 13 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, 14 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 15 | LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 16 | DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY 17 | OF SUCH DAMAGE. 18 | 19 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING 22 | DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS 23 | IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 24 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | */ 26 | 27 | #include "io.hpp" 28 | 29 | #include "util.hpp" 30 | #include 31 | #include 32 | #include 33 | #include 34 | using namespace std; 35 | 36 | 37 | const int FILE_VERSION = 1; 38 | 39 | 40 | // OBJ meshes 41 | 42 | void get_valid_line(istream &in, string &line) { 43 | do 44 | getline(in, line); 45 | while (in && (line.length() == 0 || line[0] == '#')); 46 | } 47 | 48 | void triangle_to_obj(const string &inname, const string &outname) { 49 | fstream outfile(outname.c_str(), ios::out); 50 | { // nodes 51 | string filename = inname + ".node"; 52 | fstream file(filename.c_str(), ios::in); 53 | string line; 54 | get_valid_line(file, line); 55 | stringstream linestream(line); 56 | int nv, dim, na, nb; 57 | linestream >> nv >> dim >> na >> nb; 58 | for (int i = 0; i < nv; i++) { 59 | get_valid_line(file, line); 60 | stringstream linestream(line); 61 | int index; 62 | linestream >> index; 63 | Vec2 u; 64 | linestream >> u[0] >> u[1]; 65 | outfile << "v " << u[0] << " " << u[1] << " " << 0 << endl; 66 | } 67 | } 68 | { // eles 69 | string filename = inname + ".ele"; 70 | fstream file(filename.c_str(), ios::in); 71 | string line; 72 | get_valid_line(file, line); 73 | stringstream linestream(line); 74 | int nt, nn, na; 75 | linestream >> nt >> nn >> na; 76 | for (int i = 0; i < nt; i++) { 77 | get_valid_line(file, line); 78 | stringstream linestream(line); 79 | int index; 80 | linestream >> index; 81 | int v0, v1, v2; 82 | linestream >> v0 >> v1 >> v2; 83 | outfile << "f " << v0 + 1 << " " << v1 + 1 << " " << v2 + 1 << endl; 84 | } 85 | } 86 | } 87 | 88 | vector triangulateARC(const vector &verts); 89 | 90 | void load_obj(Mesh &mesh, const string &filename) { 91 | delete_mesh(mesh); 92 | fstream file(filename.c_str(), ios::in); 93 | if (!file) { 94 | cout << "Error: failed to open file " << filename << endl; 95 | return; 96 | } 97 | while (file) { 98 | string line; 99 | get_valid_line(file, line); 100 | stringstream linestream(line); 101 | string keyword; 102 | linestream >> keyword; 103 | if (keyword == "vt") { 104 | Vec2 u; 105 | linestream >> u[0] >> u[1]; 106 | mesh.add(new Vert(expand_xy(u), Vec3(0))); 107 | } 108 | else if (keyword == "ms") { 109 | Vec3 u; 110 | linestream >> u[0] >> u[1] >> u[2]; 111 | mesh.add(new Vert(u, Vec3(0))); 112 | } 113 | else if (keyword == "v") { 114 | Vec3 x; 115 | linestream >> x[0] >> x[1] >> x[2]; 116 | mesh.add(new Node(x, x, Vec3(0), 0, 0, false)); 117 | } 118 | else if (keyword == "ny") { 119 | Vec3 &y = mesh.nodes.back()->y; 120 | linestream >> y[0] >> y[1] >> y[2]; 121 | } 122 | else if (keyword == "nv") { 123 | Vec3 &v = mesh.nodes.back()->v; 124 | linestream >> v[0] >> v[1] >> v[2]; 125 | } 126 | else if (keyword == "nl") { 127 | linestream >> mesh.nodes.back()->label; 128 | } 129 | else if (keyword == "e") { 130 | int n0, n1; 131 | linestream >> n0 >> n1; 132 | mesh.add(new Edge(mesh.nodes[n0 - 1], mesh.nodes[n1 - 1], 0, 0)); 133 | } 134 | else if (keyword == "ea") { 135 | linestream >> mesh.edges.back()->theta_ideal; 136 | } 137 | else if (keyword == "ed") { 138 | linestream >> mesh.edges.back()->damage; 139 | } 140 | else if (keyword == "ep") { 141 | linestream >> mesh.edges.back()->preserve; 142 | } 143 | else if (keyword == "f") { 144 | vector verts; 145 | vector nodes; 146 | string w; 147 | while (linestream >> w) { 148 | stringstream wstream(w); 149 | int v, n; 150 | char c; 151 | wstream >> n >> c >> v; 152 | nodes.push_back(mesh.nodes[n - 1]); 153 | if (wstream) { 154 | verts.push_back(mesh.verts[v - 1]); 155 | } 156 | else if (!nodes.back()->verts.empty()) { 157 | verts.push_back(nodes.back()->verts[0]); 158 | } 159 | else { 160 | verts.push_back(new Vert(nodes.back()->x0, Vec3(0))); 161 | mesh.add(verts.back()); 162 | } 163 | } 164 | for (int v = 0; v < (int)verts.size(); v++) 165 | connect(verts[v], nodes[v]); 166 | vector faces = triangulateARC(verts); 167 | for (int f = 0; f < (int)faces.size(); f++) 168 | mesh.add(faces[f]); 169 | } 170 | else if (keyword == "tm") { 171 | linestream >> mesh.faces.back()->flag; 172 | } 173 | else if (keyword == "tp") { 174 | Mat3x3 &S = mesh.faces.back()->Sp_bend; 175 | for (int i = 0; i<3; i++) for (int j = 0; j<3; j++) 176 | linestream >> S(i, j); 177 | } 178 | else if (keyword == "ts") { 179 | Mat3x3 &S = mesh.faces.back()->Sp_str; 180 | for (int i = 0; i<3; i++) for (int j = 0; j<3; j++) 181 | linestream >> S(i, j); 182 | } 183 | else if (keyword == "td") { 184 | linestream >> mesh.faces.back()->damage; 185 | } 186 | } 187 | mark_nodes_to_preserve(mesh); 188 | compute_ms_data(mesh); 189 | } 190 | 191 | // Added by Nick for cloth obj loading 192 | void load_cloth_obj(Mesh &mesh, const string &filename) { 193 | delete_mesh(mesh); 194 | fstream file(filename.c_str(), ios::in); 195 | if (!file) { 196 | cout << "Error: failed to open file " << filename << endl; 197 | return; 198 | } 199 | while (file) { 200 | string line; 201 | get_valid_line(file, line); 202 | stringstream linestream(line); 203 | string keyword; 204 | linestream >> keyword; 205 | if (keyword == "v") { 206 | Vec3 x; 207 | linestream >> x[0] >> x[1] >> x[2]; 208 | x[0] += 0.5; 209 | x[1] += 0.5; 210 | if (x[0] <= 0.015) x[0] = 0.0; 211 | if (x[0] >= 0.985) x[0] = 1.0; 212 | if (x[1] <= 0.015) x[1] = 0.0; 213 | if (x[1] >= 0.985) x[1] = 1.0; 214 | Vec3 ver = Vec3(x[0], x[1], 0.0); 215 | mesh.add(new Node(x, x, Vec3(0), 0, 0, false)); 216 | mesh.add(new Vert(ver, Vec3(0))); 217 | } 218 | else if (keyword == "f") { 219 | vector verts; 220 | vector nodes; 221 | string w; 222 | while (linestream >> w) { 223 | stringstream wstream(w); 224 | int n; 225 | wstream >> n; 226 | nodes.push_back(mesh.nodes[n - 1]); 227 | verts.push_back(mesh.verts[n - 1]); 228 | } 229 | for (int v = 0; v < (int)verts.size(); v++) 230 | connect(verts[v], nodes[v]); 231 | vector faces = triangulateARC(verts); 232 | for (int f = 0; f < (int)faces.size(); f++) 233 | mesh.add(faces[f]); 234 | } 235 | } 236 | } 237 | 238 | static double angle(const Vec3 &x0, const Vec3 &x1, const Vec3 &x2) { 239 | Vec3 e1 = normalize(x1 - x0); 240 | Vec3 e2 = normalize(x2 - x0); 241 | return acos(clamp(dot(e1, e2), -1., 1.)); 242 | } 243 | 244 | vector triangulateARC(const vector &verts) { 245 | int n = verts.size(); 246 | double best_min_angle = 0; 247 | int best_root = -1; 248 | for (int i = 0; i < n; i++) { 249 | double min_angle = infinity; 250 | const Vert *vert0 = verts[i]; 251 | for (int j = 2; j < n; j++) { 252 | const Vert *vert1 = verts[(i + j - 1) % n], *vert2 = verts[(i + j) % n]; 253 | min_angle = min(min_angle, 254 | angle(vert0->node->x, vert1->node->x, vert2->node->x), 255 | angle(vert1->node->x, vert2->node->x, vert0->node->x), 256 | angle(vert2->node->x, vert0->node->x, vert1->node->x)); 257 | } 258 | if (min_angle > best_min_angle) { 259 | best_min_angle = min_angle; 260 | best_root = i; 261 | } 262 | } 263 | int i = best_root; 264 | Vert* vert0 = verts[i]; 265 | vector tris; 266 | for (int j = 2; j < n; j++) { 267 | Vert *vert1 = verts[(i + j - 1) % n], *vert2 = verts[(i + j) % n]; 268 | tris.push_back(new Face(vert0, vert1, vert2, Mat3x3(1), Mat3x3(0), 0, 0)); 269 | } 270 | return tris; 271 | } -------------------------------------------------------------------------------- /src/raytri.cpp: -------------------------------------------------------------------------------- 1 | /* Ray-Triangle Intersection Test Routines */ 2 | /* Different optimizations of my and Ben Trumbore's */ 3 | /* code from journals of graphics tools (JGT) */ 4 | /* http://www.acm.org/jgt/ */ 5 | /* by Tomas Moller, May 2000 */ 6 | 7 | #include 8 | 9 | #define EPSILON 1e-6 10 | #define CROSS(dest,v1,v2) \ 11 | dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ 12 | dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ 13 | dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; 14 | #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) 15 | #define SUB(dest,v1,v2) \ 16 | dest[0]=v1[0]-v2[0]; \ 17 | dest[1]=v1[1]-v2[1]; \ 18 | dest[2]=v1[2]-v2[2]; 19 | 20 | /* the original jgt code */ 21 | int intersect_triangle(double orig[3], double dir[3], 22 | double vert0[3], double vert1[3], double vert2[3], 23 | double *t, double *u, double *v) 24 | { 25 | double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; 26 | double det,inv_det; 27 | 28 | /* find vectors for two edges sharing vert0 */ 29 | SUB(edge1, vert1, vert0); 30 | SUB(edge2, vert2, vert0); 31 | 32 | /* begin calculating determinant - also used to calculate U parameter */ 33 | CROSS(pvec, dir, edge2); 34 | 35 | /* if determinant is near zero, ray lies in plane of triangle */ 36 | det = DOT(edge1, pvec); 37 | 38 | if (det > -EPSILON && det < EPSILON) 39 | return 0; 40 | inv_det = 1.0 / det; 41 | 42 | /* calculate distance from vert0 to ray origin */ 43 | SUB(tvec, orig, vert0); 44 | 45 | /* calculate U parameter and test bounds */ 46 | *u = DOT(tvec, pvec) * inv_det; 47 | if (*u < 0.0 || *u > 1.0) 48 | return 0; 49 | 50 | /* prepare to test V parameter */ 51 | CROSS(qvec, tvec, edge1); 52 | 53 | /* calculate V parameter and test bounds */ 54 | *v = DOT(dir, qvec) * inv_det; 55 | if (*v < 0.0 || *u + *v > 1.0) 56 | return 0; 57 | 58 | /* calculate t, ray intersects triangle */ 59 | *t = DOT(edge2, qvec) * inv_det; 60 | 61 | return 1; 62 | } 63 | 64 | 65 | /* code rewritten to do tests on the sign of the determinant */ 66 | /* the division is at the end in the code */ 67 | int intersect_triangle1(double orig[3], double dir[3], 68 | double vert0[3], double vert1[3], double vert2[3], 69 | double *t, double *u, double *v) 70 | { 71 | double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; 72 | double det,inv_det; 73 | 74 | /* find vectors for two edges sharing vert0 */ 75 | SUB(edge1, vert1, vert0); 76 | SUB(edge2, vert2, vert0); 77 | 78 | /* begin calculating determinant - also used to calculate U parameter */ 79 | CROSS(pvec, dir, edge2); 80 | 81 | /* if determinant is near zero, ray lies in plane of triangle */ 82 | det = DOT(edge1, pvec); 83 | 84 | if (det > EPSILON) 85 | { 86 | /* calculate distance from vert0 to ray origin */ 87 | SUB(tvec, orig, vert0); 88 | 89 | /* calculate U parameter and test bounds */ 90 | *u = DOT(tvec, pvec); 91 | if (*u < 0.0 || *u > det) 92 | return 0; 93 | 94 | /* prepare to test V parameter */ 95 | CROSS(qvec, tvec, edge1); 96 | 97 | /* calculate V parameter and test bounds */ 98 | *v = DOT(dir, qvec); 99 | if (*v < 0.0 || *u + *v > det) 100 | return 0; 101 | 102 | } 103 | else if(det < -EPSILON) 104 | { 105 | /* calculate distance from vert0 to ray origin */ 106 | SUB(tvec, orig, vert0); 107 | 108 | /* calculate U parameter and test bounds */ 109 | *u = DOT(tvec, pvec); 110 | /* printf("*u=%f\n",(float)*u); */ 111 | /* printf("det=%f\n",det); */ 112 | if (*u > 0.0 || *u < det) 113 | return 0; 114 | 115 | /* prepare to test V parameter */ 116 | CROSS(qvec, tvec, edge1); 117 | 118 | /* calculate V parameter and test bounds */ 119 | *v = DOT(dir, qvec) ; 120 | if (*v > 0.0 || *u + *v < det) 121 | return 0; 122 | } 123 | else return 0; /* ray is parallell to the plane of the triangle */ 124 | 125 | 126 | inv_det = 1.0 / det; 127 | 128 | /* calculate t, ray intersects triangle */ 129 | *t = DOT(edge2, qvec) * inv_det; 130 | (*u) *= inv_det; 131 | (*v) *= inv_det; 132 | 133 | return 1; 134 | } 135 | 136 | /* code rewritten to do tests on the sign of the determinant */ 137 | /* the division is before the test of the sign of the det */ 138 | int intersect_triangle2(double orig[3], double dir[3], 139 | double vert0[3], double vert1[3], double vert2[3], 140 | double *t, double *u, double *v) 141 | { 142 | double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; 143 | double det,inv_det; 144 | 145 | /* find vectors for two edges sharing vert0 */ 146 | SUB(edge1, vert1, vert0); 147 | SUB(edge2, vert2, vert0); 148 | 149 | /* begin calculating determinant - also used to calculate U parameter */ 150 | CROSS(pvec, dir, edge2); 151 | 152 | /* if determinant is near zero, ray lies in plane of triangle */ 153 | det = DOT(edge1, pvec); 154 | 155 | /* calculate distance from vert0 to ray origin */ 156 | SUB(tvec, orig, vert0); 157 | inv_det = 1.0 / det; 158 | 159 | if (det > EPSILON) 160 | { 161 | /* calculate U parameter and test bounds */ 162 | *u = DOT(tvec, pvec); 163 | if (*u < 0.0 || *u > det) 164 | return 0; 165 | 166 | /* prepare to test V parameter */ 167 | CROSS(qvec, tvec, edge1); 168 | 169 | /* calculate V parameter and test bounds */ 170 | *v = DOT(dir, qvec); 171 | if (*v < 0.0 || *u + *v > det) 172 | return 0; 173 | 174 | } 175 | else if(det < -EPSILON) 176 | { 177 | /* calculate U parameter and test bounds */ 178 | *u = DOT(tvec, pvec); 179 | if (*u > 0.0 || *u < det) 180 | return 0; 181 | 182 | /* prepare to test V parameter */ 183 | CROSS(qvec, tvec, edge1); 184 | 185 | /* calculate V parameter and test bounds */ 186 | *v = DOT(dir, qvec) ; 187 | if (*v > 0.0 || *u + *v < det) 188 | return 0; 189 | } 190 | else return 0; /* ray is parallell to the plane of the triangle */ 191 | 192 | /* calculate t, ray intersects triangle */ 193 | *t = DOT(edge2, qvec) * inv_det; 194 | (*u) *= inv_det; 195 | (*v) *= inv_det; 196 | 197 | return 1; 198 | } 199 | 200 | /* code rewritten to do tests on the sign of the determinant */ 201 | /* the division is before the test of the sign of the det */ 202 | /* and one CROSS has been moved out from the if-else if-else */ 203 | int intersect_triangle3(double orig[3], double dir[3], 204 | double vert0[3], double vert1[3], double vert2[3], 205 | double *t, double *u, double *v) 206 | { 207 | double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; 208 | double det,inv_det; 209 | 210 | /* find vectors for two edges sharing vert0 */ 211 | SUB(edge1, vert1, vert0); 212 | SUB(edge2, vert2, vert0); 213 | 214 | /* begin calculating determinant - also used to calculate U parameter */ 215 | CROSS(pvec, dir, edge2); 216 | 217 | /* if determinant is near zero, ray lies in plane of triangle */ 218 | det = DOT(edge1, pvec); 219 | 220 | /* calculate distance from vert0 to ray origin */ 221 | SUB(tvec, orig, vert0); 222 | inv_det = 1.0 / det; 223 | 224 | CROSS(qvec, tvec, edge1); 225 | 226 | if (det > EPSILON) 227 | { 228 | *u = DOT(tvec, pvec); 229 | if (*u < 0.0 || *u > det) 230 | return 0; 231 | 232 | /* calculate V parameter and test bounds */ 233 | *v = DOT(dir, qvec); 234 | if (*v < 0.0 || *u + *v > det) 235 | return 0; 236 | 237 | } 238 | else if(det < -EPSILON) 239 | { 240 | /* calculate U parameter and test bounds */ 241 | *u = DOT(tvec, pvec); 242 | if (*u > 0.0 || *u < det) 243 | return 0; 244 | 245 | /* calculate V parameter and test bounds */ 246 | *v = DOT(dir, qvec) ; 247 | if (*v > 0.0 || *u + *v < det) 248 | return 0; 249 | } 250 | else return 0; /* ray is parallell to the plane of the triangle */ 251 | 252 | *t = DOT(edge2, qvec) * inv_det; 253 | (*u) *= inv_det; 254 | (*v) *= inv_det; 255 | 256 | return 1; 257 | } 258 | 259 | /* Sueda: inclusive borders */ 260 | #define ZERO -EPSILON 261 | int intersect_triangle3_inc( 262 | const double *orig, const double *dir, 263 | const double *vert0, const double *vert1, const double *vert2, 264 | double *t, double *u, double *v) 265 | { 266 | double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; 267 | double det,inv_det; 268 | 269 | /* find vectors for two edges sharing vert0 */ 270 | SUB(edge1, vert1, vert0); 271 | SUB(edge2, vert2, vert0); 272 | 273 | /* begin calculating determinant - also used to calculate U parameter */ 274 | CROSS(pvec, dir, edge2); 275 | 276 | /* if determinant is near zero, ray lies in plane of triangle */ 277 | det = DOT(edge1, pvec); 278 | 279 | /* calculate distance from vert0 to ray origin */ 280 | SUB(tvec, orig, vert0); 281 | inv_det = 1.0 / det; 282 | 283 | CROSS(qvec, tvec, edge1); 284 | 285 | if (det > EPSILON) 286 | { 287 | *u = DOT(tvec, pvec); 288 | if (*u < -ZERO || *u > det + ZERO) 289 | return 0; 290 | 291 | /* calculate V parameter and test bounds */ 292 | *v = DOT(dir, qvec); 293 | if (*v < -ZERO || *u + *v > det + ZERO) 294 | return 0; 295 | 296 | } 297 | else if(det < -EPSILON) 298 | { 299 | /* calculate U parameter and test bounds */ 300 | *u = DOT(tvec, pvec); 301 | if (*u > ZERO || *u < det - ZERO) 302 | return 0; 303 | 304 | /* calculate V parameter and test bounds */ 305 | *v = DOT(dir, qvec) ; 306 | if (*v > ZERO || *u + *v < det - ZERO) 307 | return 0; 308 | } 309 | else return 0; /* ray is parallell to the plane of the triangle */ 310 | 311 | *t = DOT(edge2, qvec) * inv_det; 312 | (*u) *= inv_det; 313 | (*v) *= inv_det; 314 | 315 | return 1; 316 | } 317 | --------------------------------------------------------------------------------