1 修改CMakeLists.txt
位于
D:\codes\SPH\SPlisHSPlasH\SPlisHSPlasH\Simulator\CMakeLists.txt
增加两行
2 增加cpp和h文件
在SPlisHSPlasH\Viscosity下撰写自己的源文件
内容如下:
CPP文件
#include "MyViscosity.h"
namespace SPH{
MyViscosity::MyViscosity(FluidModel *model) :
ViscosityBase(model)
{
}
MyViscosity::~MyViscosity(void)
{
}
void MyViscosity::initParameters()
{
ViscosityBase::initParameters();
}
void MyViscosity::step()
{
}
void MyViscosity::reset()
{
}
}
h文件
#pragma once
#ifndef __MyViscosity_h__
#define __MyViscosity_h__
#include "SPlisHSPlasH/Common.h"
#include "SPlisHSPlasH/FluidModel.h"
#include "ViscosityBase.h"
namespace SPH
{
class MyViscosity : public ViscosityBase
{
protected:
virtual void initParameters();
public:
MyViscosity(FluidModel* model);
virtual ~MyViscosity(void);
static NonPressureForceBase* creator(FluidModel* model) { return new MyViscosity(model); }
virtual void step();
virtual void reset();
};
}
#endif
注意,以下四个函数是必须要写的
3 修改NonPressureForceRegistration.cpp
位于SPlisHSPlasH\
增加如下一行文字
addViscosityMethod("My viscosity method", MyViscosity::creator);
在头文件中增加
这一步为注册新方法。
要注意:
MyViscosity类中有这样一个静态方法 static NonPressureForceBase* creator(FluidModel* model) { return new MyViscosity(model); }。这个方法就是联系到NonPressureForceRegistration.cpp的。
这一步的作用是在GUI中可以显示新加的方法。在引号里面给出的字符串恰好就是GUI里面显示的。
运行CMake并重新编译
打开CMake,重新先Config,再Generate,然后点Open Project
再编译,即可
效果
额外内容
1 如何增加自定义场变量
仿照SPlisHSPlasH\Viscosity\Viscosity_Weiler2018.cpp
在构造函数和析构函数中分别添加:
model->addField({ "MyAddedField", FieldType::Vector3, [&](const unsigned int i) -> Real* { return &m_vDiff[i][0]; }, true });
和
m_model->removeFieldByName("MyAddedField");
前者是用来增加一个场变量的,后者是销毁自定义的场的。
可见这里增加了一个场变量,GUI中显示的名字是MyAddedField。
实际变量名是m_vDiff
所以我们要相对应地定义m_vDiff
拷贝Viscosity_Weiler2018.cpp中所有关于m_vDiff的内容。
即增加了这么几个地方
完整代码为
MyViscosity::MyViscosity(FluidModel *model) :
ViscosityBase(model), m_vDiff()
{
m_vDiff.resize(model->numParticles(), Vector3r::Zero());
model->addField({ "MyAddedField", FieldType::Vector3, [&](const unsigned int i) -> Real* { return &m_vDiff[i][0]; }, true });
}
MyViscosity::~MyViscosity(void)
{
m_model->removeFieldByName("MyAddedField");
m_vDiff.clear();
}
同时,要在h文件中添加相应的变量
还需要在头函数定义get和set函数
同样拷贝Weiler的代码
编译运行
然后在GUI中用鼠标左键框选粒子,再按按键"i"
TUI就会出现MyAddedField
由于我们没有给出值,所以都是0
增加延迟初始化
参考SPlisHSPlasH\Elasticity\Elasticity_Peer2018.h和cpp
在h文件中增加protected方法
virtual void deferredInit();
在cpp文件中增加
void MyViscosity::deferredInit()
{
initValues();
}
同时要增加void initValues();
在头文件protected方法中
void initValues();
在cpp文件中
void MyViscosity::initValues()
{
}
效果是在读完json之后,仍然能初始化参数,即调用initValues();
注释如下
/** This function is called after the simulation scene is loaded and all
parameters are initialized. While reading a scene file several parameters
can change. The deferred init function should initialize all values which
depend on these parameters.
*/
具体内容可见Elasticity_Peer2018.cpp中的initValues函数
附录 :常见错误
错误1 不允许使用抽象类类型…的对象
E0322 不允许使用抽象类类型 “SPH::MyElasticity” 的对象:
原因:有些函数在基类中定义为虚函数。即virtual开头的函数。而这里继承以后,没有实现这些虚函数。(存在虚函数的类叫抽象类)
更正:在函数中重载所有基类中virtual开头的函数。
比如step和reset函数。
错误2 未找到…符号
没有include头文件
错误3 “creator”: 不是 “SPH::MyVorticity” 的成员
没有加上creator函数。
这个函数是用来注册的。
错误4 非法成员初始化…不是基或成员
原因:拷贝了VorticityBase,它是继承自NonPressureForceBase的。但是我们增加MyVorticity的时候,要继承自VorticityBase
错误5 无法解析的外部符号
cpp文件里实现的时候没有指定好类作用域