【问题标题】:An error in water ripple effect (Java Open GL)水波纹效果错误(Java Opengl)
【发布时间】:2014-05-20 07:08:39
【问题描述】:

我正在尝试在多边形模型/线框上实现水波纹效果。我遵循了这两个非常清楚的指南:2D Water 和 The Water Effect Explained

按照这些指南,我最终得到了(按此顺序)

  • 两个浮点数组,在我的应用启动后全为零,期望一个会启动涟漪效应
  • 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
    

  • 变量用于定义波在进一步传播时的阻尼
  • float damping = 0.4f;
    

  • 算法本身。我遍历所有顶点,计算它们的新 y 位置并平滑/阻尼效果
  • // 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;
        }
    }
    

  • (重新)在这两个 for 循环内绘制所有顶点
  • gl.glVertex3f((float)i, heightMapCurr[i][j], (float)j); // for each vertex
    

  • 最后,正如指南告诉我的那样,我交换了两个数组中的值 - 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];
        }
    }
    


    虽然我很清楚那里发生了什么,但显然我不是,因为我的算法有问题。波从某一点向远处传播,保持圆形,没关系。然而,水也在圆圈的中间不断“冒泡”,一旦水波纹到达边界,一切都在“冒泡”,并且永不停息。涟漪甚至可能不会触及所有边界。

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


    更新:// 在上面的代码中,我使用模运算符 (%) 而不是 (/)。这样做的原因只是因为我总是得到完全错误的 heightMap 值,波浪开始向各个方向传播,包括天空的某个地方,永远不会退缩 - 如下图所示。

    【问题讨论】:

    • 尝试将内部循环中的数学代码与常规 C++ 代码对齐,即新行上的大括号、缩进等。这应该可以更清楚地说明数学上实际发生的情况。你会发现你可以重构代码很多(使用局部变量,删除无关的大括号,用简单的/2 甚至*0.5 替换/4*2。此外,你正在混合整数和浮点运算,所以尝试将数学部分中的所有相关常量更改为双倍(例如/2.0)。我想从那里你会自己找出错误:)
    • 我只是按照你说的做了,但把所有东西都放在浮动中。我必须将数组更改为不需要的双精度数组。我认为缓冲区的逻辑或计算新位置存在问题 - 但看不到它。
    • 我并不是说你应该使用double而不是float,只是你不应该在浮点数学中使用int类型常量,所以你的新代码很好(你虽然错过了一个,可能不是那么重要,但只使用浮点数会阻止编译器进行任何中间类型转换)。像这样也更具可读性,为此+1! :)
    • 很高兴您对此感到满意 :)。我仍然看不出问题出在哪里:/这有点奇怪,尽管我完全按照指南所说的那样做。和老师说的基本一样,只是有些小细节让阻尼不起作用。

    标签: java opengl


    【解决方案1】:

    我想我找到了你的问题。将模运算符 % 替换为简单的除法 /,因为您提供的两个链接都建议并查看它的作用。

    【讨论】:

    • 这是我已经尝试过的事情之一。关于这一点的事情是,在阻尼 = 0.4f 和顶点的小初始垂直位置时,我想开始一个没有任何反应的波纹。尝试使用 0.8f 之类的更高阻尼,效果是有的,但一切都立即被阻尼,就像没有能量一样。此外,为了能够看到效果,我必须将初始顶点的位置设置为至少 20f。也许我现在可以降低阻尼,我猜必须尝试很多。
    • 我为你更新了答案,看看我为什么使用模数而不是标准除法。
    • 最后,你是对的 - 谢谢 :) 我在这里找到了另一个指南fabiensanglard.net/fluide,它的阻尼过程更简单,它最终可以按预期工作。
    【解决方案2】:

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

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

    // 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-01
      • 1970-01-01
      相关资源
      最近更新 更多