#ifndef __FEM_WORLD_H__ #define __FEM_WORLD_H__ #include "Constraint/Constraint.h" #include #include #include namespace FEM { enum IntegrationMethod { NEWTON_METHOD, QUASI_STATIC, PROJECTIVE_DYNAMICS, PROJECTIVE_QUASI_STATIC }; class World { public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW void Initialize(); void TimeStepping(bool integrate = true); void AddBody(const Eigen::VectorXd& x0, const std::vector>& constraints, double m = 1.0); void AddConstraint(const std::shared_ptr& c); void RemoveConstraint(const std::shared_ptr& c); void Computedxda(Eigen::VectorXd& dx_da,const Eigen::VectorXd& dg_da); IntegrationMethod GetIntegrationMethod(){return mIntegrationMethod;} int GetMaxIteration() {return mMaxIteration;} int GetNumVertices(){return mNumVertices;} double GetTime() {return mTime;} double GetTimeStep() {return mTimeStep;} const Eigen::VectorXd& GetPositions() {return mPositions;} std::vector>& GetConstraints() {return mConstraints;} void SetTime(double t) {mTime = t;}; void SetPositions(const Eigen::VectorXd& X) {mPositions = X;}; World(const World& other) = delete; World& operator=(const World& other) = delete; std::shared_ptr Clone(); static std::shared_ptr Create( IntegrationMethod im = NEWTON_METHOD, double time_step = 1.0/120.0, int max_iteration = 100, const Eigen::Vector3d& gravity = Eigen::Vector3d(0,-9.81,0), double damping_coeff = 0.999); private: World( IntegrationMethod im = NEWTON_METHOD, double time_step = 1.0/120.0, int max_iteration = 100, const Eigen::Vector3d& gravity = Eigen::Vector3d(0,-9.81,0), double damping_coeff = 0.999); Eigen::VectorXd IntegrateNewtonMethod(); Eigen::VectorXd IntegrateQuasiStatic(); Eigen::VectorXd IntegrateProjectiveDynamics(); Eigen::VectorXd IntegrateProjectiveQuasiStatic(); void FactorizeLLT(const Eigen::SparseMatrix& A, Eigen::SimplicialLLT>& llt_solver); void FactorizeLDLT(const Eigen::SparseMatrix& A, Eigen::SimplicialLDLT>& ldlt_solver); //For Newton method, Quasi-static double EvaluateEnergy(const Eigen::VectorXd& x); void EvaluateGradient(const Eigen::VectorXd& x,Eigen::VectorXd& g); void EvaluateHessian(const Eigen::VectorXd& x,Eigen::SparseMatrix& H); double EvaluateConstraintsEnergy(const Eigen::VectorXd& x); void EvaluateConstraintsGradient(const Eigen::VectorXd& x,Eigen::VectorXd& g); void EvaluateConstraintsHessian(const Eigen::VectorXd& x,Eigen::SparseMatrix& H); double ComputeStepSize(const Eigen::VectorXd& x, const Eigen::VectorXd& g,const Eigen::VectorXd& d); //For Projective Dynamics, Projective Quasi-static void EvaluateDVector(const Eigen::VectorXd& x,Eigen::VectorXd& d); void EvaluateJMatrix(Eigen::SparseMatrix& J); void EvaluateLMatrix(Eigen::SparseMatrix& L); void Precompute(); //For detailing void InversionFree(Eigen::VectorXd& x); void IntegratePositionsAndVelocities(const Eigen::VectorXd& x_next); private: bool mIsInitialized; int mNumVertices; int mConstraintDofs; int mMaxIteration; double mTimeStep,mTime; double mDampingCoefficient; Eigen::Vector3d mGravity; IntegrationMethod mIntegrationMethod; std::vector mUnitMass; std::vector> mConstraints; Eigen::VectorXd mPositions,mVelocities; Eigen::VectorXd mExternalForces; Eigen::SparseMatrix mMassMatrix,mInvMassMatrix,mIdentityMatrix; //For Projective Dynamics, Projective Quasi-static Eigen::VectorXd mq; Eigen::SparseMatrix mJ,mL; Eigen::SimplicialLDLT> mSolver; }; }; #endif