水涟漪效应中的错误(Java Open GL)

水涟漪效应中的错误(Java Open GL),java,opengl,Java,Opengl,我试图在多边形模型/线框上实现水波效应。我遵循了这两个非常清晰的指南:和 按照这些指南,我最终得到了(按此顺序) 在我的应用程序启动后,两个浮点数数组充满了零,期望其中一个会产生涟漪效应 float[][] heightMapPrev = new float[101][101]; float[][] heightMapCurr = new float[101][101]; // ... filling both arrays with 0.0f ... heightMapCurr[30][

我试图在多边形模型/线框上实现水波效应。我遵循了这两个非常清晰的指南:和

按照这些指南,我最终得到了(按此顺序)
  • 在我的应用程序启动后,两个浮点数数组充满了零,期望其中一个会产生涟漪效应
  • float[][] heightMapPrev = new float[101][101];
    float[][] heightMapCurr = new float[101][101];
    
    // ... filling both arrays with 0.0f ...
    
    heightMapCurr[30][40] = -0.5f; // changing one value to start a water wave
    
    // Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
    for (int i = 1; i < 100; i++) {
        for (int j = 1; j < 100; j++) {    
            // Count new vertical position of each vertex
            heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
                                   heightMapPrev[i-1][j] + 
                                   heightMapPrev[i][j+1] + 
                                   heightMapPrev[i][j-1]) % 2.0f - 
                                   heightMapCurr[i][j];
            // Count water vertical velocity
            float velocity = -heightMapCurr[i][j];
            // Smooth buffers every frame to waves spread out the waves 
            float smoothed = (heightMapPrev[i+1][j] + 
                              heightMapPrev[i-1][j] + 
                              heightMapPrev[i][j+1] + 
                              heightMapPrev[i][j-1]) / 4.0f; 
            // Calculate new height of the water; reduce the effect with *2
            heightMapCurr[i][j] =  smoothed * 2 + velocity;
    
            // Damp ripples to make them loose energy                     
            heightMapCurr[i][j] *= damping;
        }
    }
    
  • 变量,用于定义波浪前进时的阻尼
  • float damping = 0.4f;
    
  • 算法本身。我循环遍历所有顶点,计算它们的新y位置并平滑/阻尼效果
  • float[][] heightMapPrev = new float[101][101];
    float[][] heightMapCurr = new float[101][101];
    
    // ... filling both arrays with 0.0f ...
    
    heightMapCurr[30][40] = -0.5f; // changing one value to start a water wave
    
    // Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
    for (int i = 1; i < 100; i++) {
        for (int j = 1; j < 100; j++) {    
            // Count new vertical position of each vertex
            heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
                                   heightMapPrev[i-1][j] + 
                                   heightMapPrev[i][j+1] + 
                                   heightMapPrev[i][j-1]) % 2.0f - 
                                   heightMapCurr[i][j];
            // Count water vertical velocity
            float velocity = -heightMapCurr[i][j];
            // Smooth buffers every frame to waves spread out the waves 
            float smoothed = (heightMapPrev[i+1][j] + 
                              heightMapPrev[i-1][j] + 
                              heightMapPrev[i][j+1] + 
                              heightMapPrev[i][j-1]) / 4.0f; 
            // Calculate new height of the water; reduce the effect with *2
            heightMapCurr[i][j] =  smoothed * 2 + velocity;
    
            // Damp ripples to make them loose energy                     
            heightMapCurr[i][j] *= damping;
        }
    }
    
  • 最后,正如指南告诉我的,我交换两个数组中的值-waveMapPrev中的值现在在waveMapCurr中,反之亦然
  • for (int i = 0; i < 101; i++) {
        for (int j = 0; j < 101; j++) {
            temp[i][j] = heightMapPrev[i][j];
            heightMapPrev[i][j] = heightMapCurr[i][j];
            heightMapCurr[i][j] = temp[i][j];
        }
    }
    
    for(int i=0;i<101;i++){
    对于(int j=0;j<101;j++){
    temp[i][j]=高度映射prev[i][j];
    heightMapPrev[i][j]=heightMapCurr[i][j];
    heightMapCurr[i][j]=温度[i][j];
    }
    }
    

    我想我很清楚那里发生了什么,但显然我不清楚,因为我的算法有问题。波从某一点传播到远处,保持圆形,这是可以的。然而,水在圈的中间也保持“鼓泡”,一旦水波纹到达边界,一切都“沸腾”,它永不停止。涟漪甚至可能不会触及所有边界。

    你能告诉/解释我做错了什么以及如何纠正错误吗?我尝试了几个小时来更改值(阻尼…、运算符(%for/、+for-)和平滑函数,但没有成功


    更新:// 在上面的代码中,我使用模数运算符(%)而不是(/)。这是因为我总是得到完全错误的heightMap值,波浪开始向各个方向传播,包括天空中的某个地方,再也不会向下传播,如下图所示。
    我想我发现了你的问题。将模数运算符
    %
    替换为简单的除法
    /
    ,因为您提供的两个链接都建议并查看其作用。

    解决方案甚至比指南建议的更简单。我找到了

    根据后面提供的指南,这是整个算法的主体,甚至比任何人预期的都要简单

    // Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
    for (int i = 1; i < 100; i++) {
        for (int j = 1; j < 100; j++) {    
            // Count new vertical position of each vertex
            heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
                                   heightMapPrev[i-1][j] + 
                                   heightMapPrev[i][j+1] + 
                                   heightMapPrev[i][j-1]) / 2.0f - 
                                   heightMapCurr[i][j];
    
            // Damp ripples to make them loose energy                    
            heightMapCurr[i][j] -= heightMapCurr[i][j] * damping;
        }
    }
    
    //循环遍历所有顶点,并根据其周围顶点的垂直位置更新其垂直位置值
    对于(int i=1;i<100;i++){
    对于(int j=1;j<100;j++){
    //计算每个顶点的新垂直位置
    heightMapCurr[i][j]=(heightMapPrev[i+1][j]+
    heightMapPrev[i-1][j]+
    heightMapPrev[i][j+1]+
    高度MAPPREV[i][j-1])/2.0f-
    heightMapCurr[i][j];
    //湿润涟漪,使其失去能量
    heightMapCurr[i][j]=heightMapCurr[i][j]*阻尼;
    }
    }
    
    尝试将内环中的数学代码与常规C++代码对齐,即,在新行、缩进等上加上括号。这将使数学上实际发生的事情更清楚。你会发现你可以重构代码很多(使用局部变量,删除多余的大括号,用一个简单的
    /2
    或者甚至
    *0.5
    替换
    /4*2
    )。此外,你混合了整数和浮点运算,所以尝试将数学部分中的所有相关常数改为双精度(例如
    /2.0
    ).我想从那里你会自己发现错误:)我只是照你说的做了,但把一切都放在浮点数里。我必须将数组更改为不必要的双精度数组。我认为缓冲区的逻辑或计算新位置时有问题,但我看不到。我不是说你应该使用
    double
    而不是
    float
    ,只是你不应该在浮点数学中使用
    int
    类型常量,所以你的新代码很好(虽然您错过了一个,可能不是很重要,但只使用浮点将阻止编译器进行任何中间类型转换)。而且像这样可读性更高,+1仅此而已!:)我很高兴您对此感到满意:)。我仍然看不出问题出在哪里:/有点奇怪,我想我做的一切都完全按照导游说的。这基本上和老师告诉我的一样,只是一些小细节使阻尼不起作用。这是我已经尝试过的事情之一。关于这一点,当阻尼=0.4f,顶点的初始垂直位置很小时,我想在没有任何变化的情况下开始一个涟漪。用更高的阻尼(如0.8f)进行实验,会有效果,但所有东西都会立即阻尼,就像没有能量一样。此外,为了能够看到效果,我必须将初始顶点的位置设置为至少20f。也许我现在可以降低阻尼,我想我必须要做很多实验。我更新了答案,让你知道为什么我要使用模数而不是标准除法。最后,你是正确的-谢谢:)我在这里找到了一个更简单阻尼过程的指南,它最终按预期工作。