zoukankan      html  css  js  c++  java
  • SPH液面重构过程中的问题

    使用粒子方法进行流体特效模拟需要进行液面重构,构造出流体的自由表面,液面重构方法也是一个独立的研究方向,针对其的研究已经有了很多成果,包括液面的平滑度、精度和并行效率等。

    在这里,主要是记录一下我在液面重构实现过程遇到的问题。

    SPH的液面重构部分,我使用的是有向距离场方法(Animating Sand as a Fluid),这是一种简单有效的液面重构方法。目前针对有向距离场方法已经有了一些改进方案,如A Unified Particle Model for Fluid-Solid Interactions等。

    这里的距离场是为了计算流体的隐式表面。

    关于这个方法,我在实现过程中遇到了一个问题,液面在某些情况下存在一些缺口,如下:

            

    流体上方出现了一个缺口,在低精度(单元格精度0.05)表面下可以明显看到。

    粒子视图下流体为:

       

    两个视图分别为流体第5次迭代和第800次迭代后的状态。

    为了定位这个BUG,在调试时,我对距离场网格进行了一些定制,如单元格边长设为0.05,距离场网格起点设为(-0.2,-0.2,-0.2),然后对距离场规模进行了控制。

    通过调试,我找到了出现问题的网格单元,并且发现单元格顶点存在问题,在8个单元格顶点中有4个缺失了。在我的实现过程中,是通过空间中的坐标进行单元格顶点的搜索的。

    单元格顶点缺失的原因是:通过对哈希表的遍历,对顶点进行索引时,未能找到哈希表中的此坐标下的顶点,但哈希表中确实存在这个顶点,即查找时未能辨明这个顶点。

    在更准确的定位问题点后,我发现错误的根本原因是数据的精度问题,即double值的精度问题。顶点坐标使用的是double类型数据,在查找顶点时,通过判断当前坐标是否等于哈希表中的顶点坐标,如果等于则表明此顶点是需要搜索的顶点。

    如下是出现BUG的位置:

            if (this->x == gc.x && this->y == gc.y && this->z == gc.z)
            {
                return false;
            }

    改进之后为:

            const double delt = 0.000000001;
            if (abs(this->x - gc.x) < delt && abs(this->y - gc.y) < delt && abs(this->z - gc.z) < delt)
            {
                return false;
            }

    使用double数据进行判断时,double值在计算累积过程中可能会出现精度缺失,通过设定一个阈值进行一定精度范围下的等于判断,可以在一定程度上解决这个问题。从整体来看,液面重构出现BUG的原因与算法本身是没有关系的,根本原因是数据精度的问题。

    改进后的液面(单元格精度0.008)如下:

        

    渲染(blender):

    这里暂时先省略液面重构实现方案的部分,只是记录一下偶然遇到的这个问题。

  • 相关阅读:
    太赞了!两个技巧帮你记住复杂 Linux 命令!
    Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)
    Spring Cloud 学习 之 Spring Cloud Eureka(架构)
    Spring Cloud 学习 之 Spring Cloud Eureka(搭建)
    Spring Cloud 学习 之 Spring Cloud Eureka(概述)
    Spring Boot学习 之 Spring Boot Actuator(一)
    java基础篇 之 final关键字
    spring学习笔记(九)事务学习(上)
    JAVA基础篇 之 类的初始化
    JAVA基础篇 之 finalize()方法的作用
  • 原文地址:https://www.cnblogs.com/esCharacter/p/6842721.html
Copyright © 2011-2022 走看看