实现碰撞
实现了系统与N布料的碰撞。
![collision.gif](http://images0.cnblogs.com/blog/511610/201503/311823022329245.gif)
可以发现图中多了很多蓝色的小球,这些小球是吸附到网格顶点的n粒子,用于碰撞检测。
这是由于从头实现一个碰撞检测算法实在太麻烦,而且难以与maya原有的动力学系统兼容,所以利用n粒子作为"感应器",具体方法是:
1. 创建等于表面网格点数的n粒子
2. 利用goal命令,让每个n粒子与网格顶点一一对应
3. 让物体碰撞n粒子,再让n粒子把碰撞力传到模拟节点
4. 进行模拟,这样就可以实现带碰撞的效果了
这是模拟出来的弯曲程度轨迹曲线,可以发现在开头一段轨迹发生了扰动,这是由于棍子受到了圆管的碰撞。
![](http://images0.cnblogs.com/blog/511610/201503/311823067794456.png)
n粒子与模拟节点的连接方式如下,
collisionGeometryIndex是发生碰撞的几何体序号
collisionWorldForce是碰撞的力
![](http://images0.cnblogs.com/blog/511610/201503/311823076079569.png)
后来发现一个棘手的问题,就是在模拟过程中,粒子可以及时跟踪到网格顶点的新位置,但在播放模拟结果时,粒子总是慢一帧。经过调试,发现是由于粒子先于节点被求值,于是粒子goalGeometry获得的就是上一帧的网格。解决办法是新建一个time属性,连接到系统时间节点(这个节点默认就在,不能被删除,不能被改名),如图:
![](http://images0.cnblogs.com/blog/511610/201503/311823082325212.png)
这样每一帧由于time1自动更新,便会强制驱动模拟节点更新,随后才对粒子求值,于是粒子保持同步了。
顺带发现关于maya节点求值机制的一个很令人愤怒的问题,就是在节点的compute函数,一定要把一个属性Attribute依赖的所有输入都读取进来,即使实际上不需要这个输入。
这是因为maya节点的脏位传递机制会在一个“脏”的属性上终止。不被compute处理的那部分输入属性,会一直保持“脏”的状态。随后若这些属性依赖的其他属性更新了,则“脏”位的传递过程会被这些属性阻断,于是节点中被这些属性影响的输出属性没有被标记为“脏”。最后导致回溯求值的过程中节点被跳过。
以下是一个人的详细解释:
Your initialize code looks fine. Sounds like it might be an issue in your compute method. Can you show us your compute method implementation. One thing that gets new API users a lot is that they don't realize that they aren't clearing the dirty bit from their inputs so that during the subsequent dirty propagation it fails to dirty the output. The basic idea that you must understand is: Your compute method must always retrieve all inputs affecting the requested output plug, even if it does not need that input. Failure to do so can leave the DG in a bad state. Here's an example that people run into a lot: animNode.output -----> customNode.input || customNode::compute() || customNode.output ------> outputObject.input. When animNode.output is changed, it will trigger a DG dirty propagation, where anything downstream of the output is marked dirty. So, in this case, the dirtied elements are: animNode.output/customNode.input connection customNode.input customNode.output customNode.output/outputObject.input connection outputObject.input Let's say in your compute method you just hardcode so that it outputs the same thing without reading the customNode.input field. Then what will happen is the following items are cleaned: customNode.output customNode.output/outputObject.input connection outputObject.input This leaves customNode.input and its input connection still DIRTY. On any subsequent change in animNode.output, the dirty propagation will stop early because it only dirties as far as it needs to. It assumes the DG is in a clean state prior to the dirty propagation. It will assume that anything beyond customNode.input is still dirty - presumably marked dirty from a separate dirty propagation. This is a perf optim of the DG. As a result, the customNode.output will still be clean and the DG will never think to update it again. This may not be the case that is affecting you, but it is a common mistake that might help you figure out your issue until you're able to post your compute method. Alternately a way of debugging it is to simplify your compute method so that it only reads in the input and just spits out something basic (if it is too complicated to post). Just make sure that the underlying data propagation concepts of the DG are working properly. |