上次我们探究了PBD是如何引入plishsplash的,以及其控制流。
https://blog.csdn.net/weixin_43940314/article/details/127569870
这次我们来讲如何在自己新建的类中控制PBD刚体。
上回说到
Simulator\PositionBasedDynamicsWrapper\PBDWrapper.cpp
中的
void PBDWrapper::timeStep()
函数是控制PBD的关键。
PBD刚体对象的指针为
PBD::SimulationModel::RigidBodyVector &rb = m_model.getRigidBodies();
于是我们操作rb指针即可。
我们首先要看看rb对象能干什么
点开rb[i]->getVelocity()函数,跳转到
build\extern\install\PositionBasedDynamics\include\Simulation\RigidBody.h
这个函数里面的所有public方法就是可操作的。
其中我们比较关注的当然是setPosition
于是我们测试一下是否可以让刚体在我们点击的时候移动到我们点击的位置。
获取点击位置
这一点我已经在下面的博文中说明了
https://chunleili.github.io/SPlisHSPlaSH/get_mouse
但是这还不是完整的。因为获取位置之后,我们不能单纯打印位置,而是应该将其传递给我们所需要的对象。因此我们新建一个类,叫做Interactive。让其获取鼠标位置。
对象和对象的数据传递方法请看
https://chunleili.github.io/cpp/data_transfer_OOP
这里我们采用单例模式的方法。
简单回顾下,就是在Simulator\GUI\imgui\Simulator_GUI_imgui.cpp之中
-
增加头文件,就是我们新建的类
-
在selection函数当中的最后一行,给interactive传递数据并调用它进行操作。
其中,get_inter是个单例静态函数
获取刚体位置
对应代码在
Simulator\PositionBasedDynamicsWrapper\PBDWrapper.cpp
运行结果:
按空格运行之后打印
可以发现y坐标确实是下降的
控制刚体位置
将刚体位置指针传递给Interactive
我们要做的首先是将刚体位置的指针传递给Interactive,并打印该位置和地址以确定获取正确。
仍然在 Simulator\PositionBasedDynamicsWrapper\PBDWrapper.cpp 中
调用Interactive类的我们自己写的新的方法
SPlisHSPlasH\My\Interactive\Interactive.h
打印结果
发现地址是正确的,因此我们已经获取了刚体位置指针。
控制物体位置
Simulator\PositionBasedDynamicsWrapper\PBDWrapper.cpp
void PBDWrapper::timeStep()
{
PBD::ParticleData &pd = m_model.getParticles();
PBD::SimulationModel::RigidBodyVector &rb = m_model.getRigidBodies();
PBD::TimeManager::getCurrent()->setTimeStepSize(SPH::TimeManager::getCurrent()->getTimeStepSize());
PBD::TimeManager::getCurrent()->setTime(SPH::TimeManager::getCurrent()->getTime());
m_timeStep->step(m_model);
for (unsigned int i = 0; i < pd.size(); i++)
{
pd.getVelocity(i) *= (static_cast<Real>(1.0) - m_dampingCoeff);
}
for (unsigned int i = 0; i < rb.size(); i++)
{
rb[i]->getVelocity() *= (static_cast<Real>(1.0) - m_dampingCoeff);
rb[i]->getAngularVelocity() *= (static_cast<Real>(1.0) - m_dampingCoeff);
}
//rb[0]是天空盒,所以rb[1]是第一个运动的刚体
Vector3r & rb_pos = rb[1]->getPosition();
Interactive::get_inter().set_rb_pos(rb_pos);
}
SPlisHSPlasH\My\Interactive\Interactive.h
#pragma once
#include "SPlisHSPlasH/Common.h"
//点击时获取鼠标位置
struct Interactive
{
Vector3r mouse_pos;
//a singleton method to get the object
static Interactive& get_inter()
{
static Interactive inter;
return inter;
}
void operation()
{
printf("mouse pos in Inter:(%.3f,\t%.3f,\t%.3f)\n", mouse_pos[0],mouse_pos[1],mouse_pos[2]);
}
//把mouse_pos从外界传递给Interactive内部
void get_mouse_pos(const Vector3r& rhs)
{
mouse_pos[0] = rhs[0];
mouse_pos[1] = rhs[1];
mouse_pos[2] = rhs[2];
}
//获取刚体的控制权。
void set_rb_pos(Vector3r& rb_pos)
{
(rb_pos) = mouse_pos; // 获取并设定位置
std::cout<< "rb_pos: "<< (rb_pos)<<"\n";
}
};
结果