【作业8】弹性固体fem仿真加渲染

作业8

作业描述

这次作业是固体仿真加渲染,用fem模拟了弹性固体物体自由落体在地面得效果;渲染是通过之前渲染作业得代码做的,最后将仿真及渲染结果合成了视频。

效果展示

渲染结果放到了这里(掉地上感觉太duang了,是不是参数设置的问题,或者网格不够细分…)

代码链接

代码在这里Code

我的大致步骤如下:
1、将原本得斑点牛表面三角形网格结构得模型转化为整体得四面体剖分结构得模型,在网上找了TetGen这个工具来做,先将原本小牛得obj格式文件用blender之类的软件转成stl;
再用TetGen将其转化为mesh格式的文件。
2、使用有限元方式模拟模型物体的自由落体,这里主要参考的作业代码,边界条件为y<=0,正好康纳尔盒子的地板也是y=0;
每一个time step我会生成一份obj,我一共生成了900份obj供后续渲染用;
3、对所有第二步生成的obj循环渲染生成png图片。
4、用python 的cv2模块将所有图片合成视频,其中根据模拟时time step 为16.7ms得出大概一秒会有60(为了加快渲染可以调整下timestep)张图片;

过程中遇到的难点及问题:
1、由于对四面体网格划分相关理论技术没有涉猎,查了很久才找到相关工具;然后有限元模拟自由落体部分很顺利;
2、对于表面三角形网格顶点法线的同步计算被困扰了很久,最开始按我的理解,顶点法线的变化更新应该和顶点相关的,共用同一份deformation gradient,
所以有根据其次坐标空间中的向量变换将3x3的F扩展成4x4矩阵然后叉乘原法线得出新法线;但是实际结果却不对,也搞不懂原因就只能找别的办法;
最后从顶点法向量的生成的角度解决了此问题,在每次time step完成更新过模型的数据后,再重新计算一下表面顶点的法向量,
即每个点的法向量等于模型表面上所有共用此点的所有三角形的面法向量与各个面的面积所占比例的加权求和(好像这种还比原来的效率更高)。最终解决了此问题
3、在渲染时发现我台式机每渲染7张图片就报错(笔记本不报错,但是发现渲染出来每60多张图片都一样)报错信息就是
论坛搜了下发现说是在kernel内定义field导致的,但是看报错的堆栈是在python作用域报的,是我的Scene类,在每次渲染时都要定义一遍模型相关的数据field最后导致的,但是这些定义每次也是不能避免的,因为每次的模型不一样,都要更新所有的bvh模型数据啥的,感觉似乎每次定义的field分配的显卡内存没有释放,执行多次后就不够了?不知道有没有什么解决办法;(所以几百张图片每渲染7张我就手动重新执行下程序,断断续续基本花了1天才渲染完)
4、发现循环给field赋值会很慢,用from_numpy的方式会更快一些;比如我有个100万长度的n=3的向量,循环赋值的时候我电脑要100多秒,然后用from_numpy就1m内就可以了。
最后,之前禹鹏老师说渲染的再优化下可以作为大作业了,那这个可以作为大作业吧,可以的话先拿这个保个底,后面学习流体的仿真渲染如果顺利的话再换;
对了上面说的报错信息如下:

[E 12/06/21 17:52:24.281 9688] [snode_tree_buffer_manager.cpp:taichi::lang::SNodeTreeBufferManager::allocate@44] LLVM backend supports up to 32 snode trees


***********************************
* Taichi Compiler Stack Traceback *
***********************************
0x7ffe9a7ecb4a: taichi::print_traceback in taichi_core.pyd
0x7ffe9a6bc1a9: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a7e4782: taichi::create_instance_unique_ctor<taichi::Task> in taichi_core.pyd
0x7ffe9a75494f: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a756e23: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a78689f: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a5f880b: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a57cdb6: PyInit_taichi_core in taichi_core.pyd
0x7ffe9a54715f: pybind11::error_already_set::discard_as_unraisable in taichi_core.pyd
0x6879b055: PyCFunction_FastCallDict in python36.dll
0x6879bae3: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x687991f6: PyErr_Occurred in python36.dll
0x6879bf5b: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x687991f6: PyErr_Occurred in python36.dll
0x687cc30a: PyUnicode_Compare in python36.dll
0x6879fa10: PyEval_EvalFrameDefault in python36.dll
0x687991f6: PyErr_Occurred in python36.dll
0x6879783e: PyFunction_FastCallDict in python36.dll
0x68797625: PyObject_Hash in python36.dll
0x6878d11b: PyList_New in python36.dll
0x6878ce9c: PySequence_Fast in python36.dll
0x6879e946: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x6879bcbe: PyObject_GenericGetAttr in python36.dll
0x6879d3ff: PyEval_EvalFrameDefault in python36.dll
0x687991f6: PyErr_Occurred in python36.dll
0x6878392e: PyEval_EvalCodeEx in python36.dll
0x68783899: PyEval_EvalCode in python36.dll
0x68783843: PyArena_Free in python36.dll
0x68912e19: PyRun_FileExFlags in python36.dll
0x68913555: PyRun_SimpleFileExFlags in python36.dll
0x68912cf7: PyRun_AnyFileExFlags in python36.dll
0x68864d1c: Py_hashtable_size in python36.dll
0x687f9fba: Py_FatalError in python36.dll
0x1c8a126d: Unknown Function in python.exe
0x7ffef23f84d4: BaseThreadInitThunk in KERNEL32.DLL
0x7ffef3b5e871: RtlUserThreadStart in ntdll.dll

Internal error occurred. Check out this page for possible solutions:
https://docs.taichi.graphics/lang/articles/misc/install
Traceback (most recent call last):
 File "D:/workspace/CG/taichi/fem_hw/fem_main.py", line 300, in <module>
   render.rende_image(obj_fname,img_fname)
 File "D:\workspace\CG\taichi\fem_hw\render.py", line 156, in rende_image
   self.set_moddel(obj_filename)
 File "D:\workspace\CG\taichi\fem_hw\render.py", line 133, in set_moddel
   self.scene.commit()
 File "D:\workspace\CG\taichi\fem_hw\scene.py", line 81, in commit
   self.light_num[None] = self._light_num
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\lang\util.py", line 207, in wrapped
   return func(*args, **kwargs)
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\lang\field.py", line 262, in __setitem__
   self.initialize_host_accessors()
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\lang\field.py", line 204, in initialize_host_accessors
   taichi.lang.impl.get_runtime().materialize()
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\lang\impl.py", line 322, in materialize
   self.materialize_root_fb(not self.materialized)
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\lang\impl.py", line 313, in materialize_root_fb
   root.finalize()
 File "D:\dev_install\Python3_6\lib\site-packages\taichi\snode\fields_builder.py", line 159, in finalize
   impl.get_runtime().prog))
RuntimeError: [snode_tree_buffer_manager.cpp:taichi::lang::SNodeTreeBufferManager::allocate@44] LLVM backend supports up to 32 snode trees

Process finished with exit code 1
5 个赞

感觉越来越有意思了哈,物体的材质可以设置的更硬一点试试。

问题1,2你已经解决了。

我没有细看你的代码,问题3中为什么每次都要定义field?按说只要更新field里的内容就可?如果实在是要创建临时的field,使用后销毁,也是可以的。可以看:here

问题4中,我写了一个小的测试例子,确实是这样的。我后面研究一下是怎么回事。

Again, 继续加油。很棒的作业。

1 个赞

@shihuan 问题4,我开了一个issue, 你可以看一下。

好的我先看下

老师,关于问题3我按照你给的方式试了下,我对我Scene和BVHS类都用了ti.FieldsBuilder(),然后在类的西沟方法中destroy(),但是执行能连续渲染10张图片,然后又报这个错误了RuntimeError: [snode_tree_buffer_manager.cpp:taichi::lang::SNodeTreeBufferManager::allocate@44] LLVM backend supports up to 32 snode trees
并且现在代码被我改的更乱了,也难得给你去看了 :cry:
还有渲染出的图片也奇怪,第一张正常后面九张都暗了, :scream:

用ti.reset()的方式算是解决了这个问题吧

1 个赞

Hi @shihuan, 可以把你的视频转成gif上传一下么?这样我们就可以用脚本自动搜集你的作业,未来展示给更多人。

Sorry,文件太大了传不了,我跳帧生成了一下,看可以不
spot_falling_s20

1 个赞

Thanks