【发布时间】: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;
// 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;
}
}
gl.glVertex3f((float)i, heightMapCurr[i][j], (float)j); // for each vertex
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! :) -
很高兴您对此感到满意 :)。我仍然看不出问题出在哪里:/这有点奇怪,尽管我完全按照指南所说的那样做。和老师说的基本一样,只是有些小细节让阻尼不起作用。