Unity中的奇异流体模拟振荡

时间:2017-09-20 14:31:39

标签: c# unity3d fluid-dynamics

我正在尝试使用纸张Fast Hydraulic Erosion Simulation and Visualization on GPU作为模板来模拟水来实施流体表面模拟。但是,我得到这样的工件:

Wave artifacts

我的更新功能的代码如下所示,我已关注此问题another post,但更改没有帮助。

    private void updateHeight (float dt, float dx){
    float dhL, dhR, dhF, dhB, DV;
    float totalFlux;
    float updateConstant;
    float fluxConstant = dt*GRAVITY/(2*VISCOUSCOEFFICEINT*dx);
    //Update Flux
    for (int y=1; y<=N-1; y++){
        for(int x=1;x<=N-1;x++){
            dhL = this.height[x][y] - this.height[x-1][y];
            dhR = this.height[x][y] - this.height[x+1][y];
            dhF = this.height[x][y] - this.height[x][y+1];
            dhB = this.height[x][y] - this.height[x][y-1];

            if (Mathf.Abs(dhL) < 0.0001f){
                dhL=0.0f;
            }
            if (Mathf.Abs(dhR) < 0.0001f){
                dhR=0;
            }
            if (Mathf.Abs(dhF) < 0.0001f){
                dhF=0;
            }
            if (Mathf.Abs(dhB) < 0.0001f){
                dhB=0;
            }

            this.tempFluxArray[x][y].fluxL = Mathf.Max(0.0f, this.fluxArray[x][y].fluxL + fluxConstant*dhL);
            this.tempFluxArray[x][y].fluxR = Mathf.Max(0.0f, this.fluxArray[x][y].fluxR + fluxConstant*dhR);
            this.tempFluxArray[x][y].fluxF = Mathf.Max(0.0f, this.fluxArray[x][y].fluxF + fluxConstant*dhF);
            this.tempFluxArray[x][y].fluxB = Mathf.Max(0.0f, this.fluxArray[x][y].fluxB + fluxConstant*dhB);

            totalFlux = this.tempFluxArray[x][y].fluxL + this.tempFluxArray[x][y].fluxR + this.tempFluxArray[x][y].fluxF + this.tempFluxArray[x][y].fluxB;

            if(totalFlux > 0){
                updateConstant = Mathf.Min(1.0f, this.height[x][y]* dx*dx/(totalFlux * dt));
                this.tempFluxArray[x][y].fluxL = updateConstant * this.tempFluxArray[x][y].fluxL;
                this.tempFluxArray[x][y].fluxR = updateConstant * this.tempFluxArray[x][y].fluxR;
                this.tempFluxArray[x][y].fluxF = updateConstant * this.tempFluxArray[x][y].fluxF;
                this.tempFluxArray[x][y].fluxB = updateConstant * this.tempFluxArray[x][y].fluxB;
            }
        }
    }
    swap();
    //Height Calculation
    for (int y=1; y<=N-1; y++){
        for(int x=1;x<=N-1;x++){
            DV = dt*(this.fluxArray[x-1][y].fluxR + this.fluxArray[x][y-1].fluxF + this.fluxArray[x+1][y].fluxL + this.fluxArray[x][y+1].fluxB - this.fluxArray[x][y].fluxL - this.fluxArray[x][y].fluxR - this.fluxArray[x][y].fluxF - this.fluxArray[x][y].fluxB);
            this.height[x][y] = this.height[x][y] + DV/(dx*dx);
            if(this.height[x][y] < 1){
                // Debug.Log(x);
                // Debug.Log(y);
            }
        }
    }
}

是否应该使用此而不是ref?我与水面交互的方式如下所示。

    private void waterdrop(int x, int y){
    float sqrD = 0.8f*0.8f;
    for (int j = 1; j < N; j++) {
        for (int i = 1; i < N; i++) {
            float sqrDToVert = (float)0.2f*(i - x)*(i-x) + 0.2f*(j - y)*(j-y);
            if (sqrDToVert <= sqrD){
                float distanceCompensator = 1 - (sqrDToVert/sqrD);
                this.fluxArray[i][j].fluxL = this.fluxArray[i][j].fluxL + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxR = this.fluxArray[i][j].fluxR + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxF = this.fluxArray[i][j].fluxF + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxB = this.fluxArray[i][j].fluxB + (0.02f * distanceCompensator);
                //this.height[i][j] = this.height[i][j] - 1.0f * distanceCompensator;
                Debug.Log(this.height[i][j]);
            }
            //Debug.Log("x = "+i+"\n y = "+j+" height is "+this.height[i][j]);
        }
    }
}

即只改变所有方向某点的通量。

我尝试过的一些解决方案是改变高度,但这不起作用或仅限于小变化,但它只是建立了。边界条件是所有边界上的零通量,高度与最近点相同。

0 个答案:

没有答案