2#include "HyperelasticBody.h"
4#include "Primitive/Primitive3D.h"
5#include "Topology/TetrahedronSet.h"
6#include "Mapping/PointSetToPointSet.h"
8#include "ParticleSystem/Module/ParticleIntegrator.h"
10#include "Primitive/Primitive3D.h"
13#include "Topology/DistanceField3D.h"
15#include "Module/SemiImplicitHyperelasticitySolver.h"
16#include "Module/CalculateNormalSDF.h"
18#include "Auxiliary/DataSource.h"
22 IMPLEMENT_TCLASS(HyperelasticBody, TDataType)
24 template<typename TDataType>
25 HyperelasticBody<TDataType>::HyperelasticBody()
26 : TetrahedralSystem<TDataType>()
28 auto horizon = std::make_shared<FloatingNumber<TDataType>>();
29 horizon->varValue()->setValue(0.0085f);
30 this->animationPipeline()->pushModule(horizon);
32 //四面体邻域大小,求解超弹性时需要访问的状态变量,不需要更新
33 //this->varHorizon()->setValue(0.0085);
35 auto integrator = std::make_shared<ParticleIntegrator<TDataType>>();
36 this->stateTimeStep()->connect(integrator->inTimeStep());
37 this->statePosition()->connect(integrator->inPosition());
38 this->stateVelocity()->connect(integrator->inVelocity());
39 this->stateAttribute()->connect(integrator->inAttribute());
40 this->animationPipeline()->pushModule(integrator);
42 auto hyperElasticity = std::make_shared<SemiImplicitHyperelasticitySolver<TDataType>>();
43 horizon->outFloating()->connect(hyperElasticity->inHorizon());
44 this->stateTimeStep()->connect(hyperElasticity->inTimeStep());
45 this->varEnergyType()->connect(hyperElasticity->inEnergyType());
46 this->varEnergyModel()->connect(hyperElasticity->inEnergyModels());
47 this->stateRestPosition()->connect(hyperElasticity->inX());
48 this->statePosition()->connect(hyperElasticity->inY());
49 this->stateVelocity()->connect(hyperElasticity->inVelocity());
50 this->stateVolume()->connect(hyperElasticity->inVolume());
51 this->stateBonds()->connect(hyperElasticity->inBonds());
52 this->stateAttribute()->connect(hyperElasticity->inAttribute());
53 this->stateVolumePair()->connect(hyperElasticity->inVolumePair());
54 this->varAlphaComputed()->connect(hyperElasticity->varIsAlphaComputed());
55 this->animationPipeline()->pushModule(hyperElasticity);
56 //弹性能量,求解超弹性时需要访问的状态变量,不需要更新
57 EnergyModels<Real> funcs;
58 funcs.linearModel = LinearModel<Real>(48000000, 12000000);
59 funcs.neohookeanModel = NeoHookeanModel<Real>(48000000, 12000000);
60 funcs.stvkModel = StVKModel<Real>(48000000, 12000000);
61 funcs.xuModel = XuModel<Real>(12000000);
62 this->varEnergyModel()->setValue(funcs);
66// auto CalcSDF = std::make_shared<CalculateNormalSDF<TDataType>>();
67// this->statePosition()->connect(CalcSDF->inPosition());
68// this->stateTets()->connect(CalcSDF->inTets());
69// this->stateDisranceSDF()->connect(CalcSDF->inDisranceSDF());
70// this->stateNormalSDF()->connect(CalcSDF->inNormalSDF());
71// this->animationPipeline()->pushModule(CalcSDF);
76// m_cSDF = std::make_shared<DistanceField3D<DataType3f>>();
77// m_cSDF->setSpace(lo - 0.025f, hi + 0.025f, 105, 105, 105);
78// m_cSDF->loadBox(lo, hi, true);
80 this->setDt(Real(0.001));
83 template<typename TDataType>
84 HyperelasticBody<TDataType>::~HyperelasticBody()
89 template<typename TDataType>
90 void HyperelasticBody<TDataType>::setEnergyModel(XuModel<Real> model)
92 this->varEnergyType()->setValue(Xuetal);
93 auto models = this->varEnergyModel()->getValue();
94 models.xuModel = model;
96 this->varEnergyModel()->setValue(models);
99 template<typename TDataType>
100 void HyperelasticBody<TDataType>::setEnergyModel(NeoHookeanModel<Real> model)
102 this->varEnergyType()->setValue(NeoHooekean);
103 auto models = this->varEnergyModel()->getValue();
104 models.neohookeanModel = model;
106 this->varEnergyModel()->setValue(models);
109 template<typename TDataType>
110 void HyperelasticBody<TDataType>::setEnergyModel(LinearModel<Real> model)
112 this->varEnergyType()->setValue(Linear);
113 auto models = this->varEnergyModel()->getValue();
114 models.linearModel = model;
116 this->varEnergyModel()->setValue(models);
119 template<typename TDataType>
120 void HyperelasticBody<TDataType>::setEnergyModel(StVKModel<Real> model)
122 this->varEnergyType()->setValue(StVK);
124 auto models = this->varEnergyModel()->getValue();
125 models.stvkModel = model;
127 this->varEnergyModel()->setValue(models);
130 template<typename TDataType>
131 bool HyperelasticBody<TDataType>::translate(Coord t)
133 auto triSet = this->stateTetrahedronSet()->getDataPtr();
134 triSet->translate(t);
139 template<typename TDataType>
140 bool HyperelasticBody<TDataType>::scale(Real s)
142 auto triSet = this->stateTetrahedronSet()->getDataPtr();
145 this->varHorizon()->setValue(s * this->varHorizon()->getData());
150 template<typename TDataType>
151 bool HyperelasticBody<TDataType>::scale(Coord s)
153 auto triSet = this->stateTetrahedronSet()->getDataPtr();
156 this->varHorizon()->setValue((s[0] + s[1] + s[2]) / 3.0f * this->varHorizon()->getData());
161 template<typename TDataType>
162 bool HyperelasticBody<TDataType>::rotate(Coord angle)
164 auto triSet = this->stateTetrahedronSet()->getDataPtr();
165 triSet->rotate(angle);
167 //TypeInfo::cast<TriangleSet<TDataType>>(m_surfaceNode->stateTopology()->getDataPtr())->rotate(angle);
172 template<typename TDataType>
173 bool HyperelasticBody<TDataType>::rotate(Quat<Real> angle)
175 auto ptSet = this->stateTetrahedronSet()->getDataPtr();
176 ptSet->rotate(angle);
181 template<typename Matrix>
182 __global__ void InitRotation(
185 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
186 if (pId >= rots.size()) return;
188 rots[pId] = Matrix::identityMatrix();
191 /*template<typename TDataType>
192 void HyperelasticBody<TDataType>::updateStates()
194 std::cout << "update:" << this->varFileName()->getValue().string() << std::endl;
196 template<typename TDataType>
197 void HyperelasticBody<TDataType>::resetStates()
199 std::cout << this->varFileName()->getValue().string() << std::endl;
200 if (this->varFileName()->getValue().string().length() > 1)
202 this->loadVertexFromGmshFile(this->varFileName()->getValue().string());
203 this->scale(this->varScale()->getValue());
204 this->translate(this->varLocation()->getValue());
205 //ParticleSystem::resetStates();
207 printf("inside reset States\n");
208 auto tetSet = TypeInfo::cast<TetrahedronSet<TDataType>>(this->stateTetrahedronSet()->getDataPtr());
209 if (tetSet == nullptr) return;
210 printf("host attribute\n");
212 CArray<Attribute> host_attribute;
213 host_attribute.resize(tetSet->getPoints().size());
214 for (int i = 0; i < tetSet->getPoints().size(); i++)
216 host_attribute[i] = Attribute();
219 CArray<Coord> tetPoints;
220 CArray<TopologyModule::Tetrahedron> tetIds;
222 tetPoints.resize(tetSet->getPoints().size());
223 tetPoints.assign(tetSet->getPoints());
225 tetIds.resize(tetSet->getTetrahedrons().size());
226 tetIds.assign(tetSet->getTetrahedrons());
229 this->stateTets()->resize(tetSet->getTetrahedrons().size());
230 this->stateTets()->getData().assign(tetSet->getTetrahedrons());
232 this->stateNormalSDF()->resize(tetSet->getTetrahedrons().size());
234 float global_min = 1000000;
235 float global_max = 0.0f;
236 for (int i = 0; i < tetIds.size(); i++)
238 auto tet = tetIds[i];
240 Vec3f v0 = tetPoints[tet[0]];
241 Vec3f v1 = tetPoints[tet[1]];
242 Vec3f v2 = tetPoints[tet[2]];
243 Vec3f v3 = tetPoints[tet[3]];
245 Vec3f min_v = v0.minimum(v1).minimum(v2.minimum(v3));
246 Vec3f max_v = v0.maximum(v1).maximum(v2.maximum(v3));
248 Vec3f bounding = max_v - min_v;
250 float max_edge = maximum(maximum(bounding[0], bounding[1]), bounding[2]);
252 global_min = max_edge < global_min ? max_edge : global_min;
253 global_max = max_edge > global_max ? max_edge : global_max;
258 this->varHorizon()->setValue(1.5 * global_max);
260 int vNum = tetSet->getPoints().size();
262 this->stateRestPosition()->resize(vNum);
263 //Function1Pt::copy(this->stateRestPosition()->getData(), tetSet->getPoints());
264 this->stateRestPosition()->getData().assign(tetSet->getPoints(), tetSet->getPoints().size());
266 this->statePosition()->resize(vNum);
267 this->statePosition()->getData().assign(tetSet->getPoints(), tetSet->getPoints().size());
269 this->stateVelocity()->resize(vNum);
270 this->stateVelocity()->getDataPtr()->reset();
271 this->stateForce()->resize(vNum);
274 this->stateAttribute()->resize(vNum);
275 //Function1Pt::copy(this->currentAttribute()->getData(), host_attribute);
276 this->stateAttribute()->getData().assign(host_attribute, host_attribute.size());
278 this->stateVertexRotation()->resize(vNum);
281 this->stateVertexRotation()->getData());
283 host_attribute.clear();
285 HyperelasticBody<TDataType>::updateVolume();
286 HyperelasticBody<TDataType>::updateRestShape();
290 __global__ void SetSize(
292 DArrayList<int> lists)
294 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
295 if (pId >= lists.size()) return;
297 //printf("size_0 %d\n", lists[pId].size() + 1);
298 index[pId] = lists[pId].size();
301 template<typename Coord, typename Bond, typename Tetrahedron>
302 __global__ void SetRestShape(
303 DArrayList<Bond> restShapes,
304 DArrayList<Real> volume,
305 DArrayList<int> ver2tet,
306 DArrayList<int> lists,
307 DArray<Coord> tetVertex,
308 DArray<Tetrahedron> tetIndex)
310 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
311 if (pId >= lists.size()) return;
313 Coord v_i = tetVertex[pId];
315 List<Bond>& list_i = restShapes[pId];
316 List<Real>& vol_i = volume[pId];
317 List<int>& tets_i = ver2tet[pId];
319 List<int> list = lists[pId];
320 for (auto it = list.begin(); it != list.end(); it++)
324 Real vol_ij = Real(0);
325 for (auto ik = tets_i.begin(); ik != tets_i.end(); ik++)
328 Tetrahedron t_k = tetIndex[k];
330 if (t_k[0] == j || t_k[1] == j || t_k[2] == j || t_k[3] == j)
332 TTet3D<Real> tet(tetVertex[t_k[0]], tetVertex[t_k[1]], tetVertex[t_k[2]], tetVertex[t_k[3]]);
334 vol_ij += abs(tet.volume());
338 Real minVol = Real(0.00001);
339 vol_ij = maximum(vol_ij, minVol); //0.000123;//
341 list_i.insert(Bond(j, tetVertex[j] - v_i));
342 vol_i.insert(vol_ij);
345 int size_i = restShapes[pId].size();
348 template<typename TDataType>
349 void HyperelasticBody<TDataType>::updateRestShape()
351 printf("updateRestShape1\n");
352 auto tetSet = TypeInfo::cast<TetrahedronSet<TDataType>>(this->stateTetrahedronSet()->getDataPtr());
353 if (tetSet == nullptr) return;
355 DArrayList<int> neighbors;
356 tetSet->requestPointNeighbors(neighbors);
358 auto ver2tet = tetSet->getVer2Tet();
360 auto& restPos = this->stateRestPosition()->getData();
362 //this->stateRestShape()->resize(restPos.size());
363 if(this->stateBonds()->isEmpty())
364 this->stateBonds()->allocate();
366 if (this->stateVolumePair()->isEmpty())
368 this->stateVolumePair()->allocate();
371 //printf("aaaaaaaa");
372 auto nbrPtr = this->stateBonds()->getDataPtr();
373 //printf("bbbbbbbb");
374 nbrPtr->resize(restPos.size());
376 auto index = this->stateBonds()->getData().index();
377 auto elements = this->stateBonds()->getData().elements();
379 DArray<uint> index_temp;
380 index_temp.resize(index.size());
382 cuExecute(neighbors.size(),
388 this->stateBonds()->getData().resize(index_temp);
389 this->stateVolumePair()->getDataPtr()->resize(index_temp);
391 cuExecute(neighbors.size(),
393 stateBonds()->getData(),
394 stateVolumePair()->getData(),
398 tetSet->getTetrahedrons());
403 template<typename Real, typename Coord, typename Tetrahedron>
404 __global__ void HB_CalculateVolume(
406 DArray<Coord> restPos,
407 DArray<Tetrahedron> tets,
408 DArrayList<int> lists)
410 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
411 if (pId >= volume.size()) return;
413 Real vol_i = Real(0);
415 List<int>& list_i = lists[pId];
416 int nbSize = list_i.size();
418 for (int i = 0; i < nbSize; i++)
420 int tetId = list_i[i];//lists.getElement(pId, i);
421 Tetrahedron tetIndex = tets[tetId];
423 TTet3D<Real> tet(restPos[tetIndex[0]], restPos[tetIndex[1]], restPos[tetIndex[2]], restPos[tetIndex[3]]);
425 vol_i += abs(tet.volume());
428 Real minVol = Real(0.00001);
429 volume[pId] = maximum(vol_i, minVol); //0.000123;//
431// printf("%f \n", volume[pId]);
434 template<typename TDataType>
435 void HyperelasticBody<TDataType>::updateVolume()
437 auto tetSet = TypeInfo::cast<TetrahedronSet<TDataType>>(this->stateTetrahedronSet()->getDataPtr());
438 if (tetSet == nullptr) return;
440 auto& ver2Tet = tetSet->getVer2Tet();
442 auto& restPos = this->stateRestPosition()->getData();
444 this->stateVolume()->resize(restPos.size());
446 cuExecute(restPos.size(),
448 this->stateVolume()->getData(),
450 tetSet->getTetrahedrons(),
453 auto& volume = this->stateVolume()->getData();
455 Reduction<Real> reduce;
456 Real max_vol = reduce.maximum(volume.begin(), volume.size());
457 Real min_vol = reduce.minimum(volume.begin(), volume.size());
459 printf("max vol: %f; min vol: %f \n", max_vol, min_vol);
463 template<typename Real, typename Coord, typename Tetrahedron, typename TDataType>
464 __global__ void K_InitTetCenterSDF(
465 DArray<Coord> posArr,
466 DArray<Tetrahedron> tets,
467 DistanceField3D<TDataType> df,
468 DArray<Real> distanceTetCenter)
470 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
471 if (pId >= tets.size()) return;
473 Coord posCenter = (posArr[tets[pId][0]] + posArr[tets[pId][1]] + posArr[tets[pId][2]] + posArr[tets[pId][3]]) / 4.0f;
476 df.getDistance(posCenter, dist, normal);
477 distanceTetCenter[pId] = dist;
481 template<typename Real, typename Coord, typename TDataType>
482 __global__ void K_InitTetVertexSDF(
483 DArray<Coord> posArr,
484 DistanceField3D<TDataType> df,
485 DArray<Real> distanceTetVertex)
487 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
488 if (pId >= posArr.size()) return;
490 Coord posCenter = posArr[pId];
493 df.getDistance(posCenter, dist, normal);
494 distanceTetVertex[pId] = dist;
502 template<typename TDataType>
503 void HyperelasticBody<TDataType>::loadSDF(std::string filename, bool inverted)
505// m_cSDF->loadSDF(filename, inverted);
507// auto tetSet = TypeInfo::cast<TetrahedronSet<TDataType>>(this->stateTetrahedronSet()->getDataPtr());
508// if (tetSet == nullptr) return;
510// //auto& ver2Tet = tetSet->getVer2Tet();
512// auto& restPos = tetSet->getPoints();
514// initDistance.resize(restPos.size());
516// cuExecute(restPos.size(),
517// K_InitTetVertexSDF,
522// printf("tet size = %d\n", tetSet->getTetrahedrons().size());
524// this->stateDisranceSDF()->resize(restPos.size());
525// this->stateDisranceSDF()->getData().assign(initDistance);
526// this->stateNormalSDF()->resize(tetSet->getTetrahedrons().size());
527// this->stateNormalSDF()->getData().reset();
528// this->varSDF()->setValue(true);
530 //printf("max vol: %f; min vol: %f \n", max_vol, min_vol);
533 DEFINE_CLASS(HyperelasticBody);