水涟漪效应中的错误(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;
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;
}
}
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。也许我现在可以降低阻尼,我想我必须要做很多实验。我更新了答案,让你知道为什么我要使用模数而不是标准除法。最后,你是正确的-谢谢:)我在这里找到了一个更简单阻尼过程的指南,它最终按预期工作。