|
|
|
@ -17,12 +17,12 @@
|
|
|
|
|
|
|
|
|
|
#if ASM_TYPE==CLEAR_ASM
|
|
|
|
|
// Assembly version declaration (signature changed to float arrays)
|
|
|
|
|
extern "C" void updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float time);
|
|
|
|
|
extern "C" void updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float * originalWorldX_, float * originalWorldZ_, int _grid_size, float time);
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
// C++ implementation of SIMD version (now also taking float arrays for consistency)
|
|
|
|
|
void Ocean::updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float time)
|
|
|
|
|
void Ocean::updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float * originalWorldX_, float * originalWorldZ_, int _grid_size, float time)
|
|
|
|
|
{
|
|
|
|
|
// Placeholder C++ implementation using float arrays
|
|
|
|
|
//for (size_t i = 0; i < numVertices; ++i) {
|
|
|
|
@ -46,10 +46,7 @@ Ocean::Ocean(int gridSize) : time(0.0f),gridSize(gridSize), gridSpacing(1.0f),
|
|
|
|
|
//gerstnerWaves.push_back({0.5f, 1.2f, 2.0f, glm::normalize(glm::vec2(0.9f, 0.8f)), 0.0f});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ocean::~Ocean()
|
|
|
|
|
{
|
|
|
|
|
cleanup(); // Call cleanup to release OpenGL resources
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Ocean::init()
|
|
|
|
|
{
|
|
|
|
@ -59,29 +56,6 @@ bool Ocean::init()
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Ocean::cleanup()
|
|
|
|
|
{
|
|
|
|
|
// No dynamic memory allocation in this simple version
|
|
|
|
|
// Release OpenGL resources (VBOs, IBO, VAO)
|
|
|
|
|
glDeleteBuffers(1, &vertexBufferID);
|
|
|
|
|
glDeleteBuffers(1, &normalBufferID);
|
|
|
|
|
glDeleteBuffers(1, &texCoordBufferID);
|
|
|
|
|
glDeleteBuffers(1, &indexBufferID);
|
|
|
|
|
glDeleteVertexArrays(1, &vaoID);
|
|
|
|
|
vertexBufferID = 0;
|
|
|
|
|
normalBufferID = 0;
|
|
|
|
|
texCoordBufferID = 0;
|
|
|
|
|
indexBufferID = 0;
|
|
|
|
|
vaoID = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void add_sse(float* a, float* b, float* result) {
|
|
|
|
|
__m128 vec1 = _mm_loadu_ps(a); // Load 4 floats from a
|
|
|
|
|
__m128 vec2 = _mm_loadu_ps(b); // Load 4 floats from b
|
|
|
|
|
__m128 sum = _mm_add_ps(vec1, vec2); // Perform vector addition
|
|
|
|
|
_mm_storeu_ps(result, sum); // Store result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Ocean::update(float deltaTime)
|
|
|
|
|
{
|
|
|
|
@ -97,49 +71,40 @@ void Ocean::update(float deltaTime)
|
|
|
|
|
size_t numVertices = vertices.size();
|
|
|
|
|
size_t floatArraySize = numVertices * 3;
|
|
|
|
|
|
|
|
|
|
float* updatedVertices_array = new float[floatArraySize];
|
|
|
|
|
float* updatedNormals_array = new float[floatArraySize];
|
|
|
|
|
float* updatedVertices_simd_array = new float[floatArraySize]; // Array for SIMD function
|
|
|
|
|
float* updatedNormals_simd_array = new float[floatArraySize]; // Array for SIMD function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Convert vector of vec3 to float array (for both normal and simd versions)
|
|
|
|
|
for (size_t i = 0; i < numVertices; ++i) {
|
|
|
|
|
updatedVertices_array[i * 3 + 0] = updatedVertices_vec[i].x;
|
|
|
|
|
updatedVertices_array[i * 3 + 1] = updatedVertices_vec[i].y;
|
|
|
|
|
updatedVertices_array[i * 3 + 2] = updatedVertices_vec[i].z;
|
|
|
|
|
|
|
|
|
|
updatedNormals_array[i * 3 + 0] = updatedNormals_vec[i].x; // Normals init - adjust as needed
|
|
|
|
|
updatedNormals_array[i * 3 + 1] = updatedNormals_vec[i].y;
|
|
|
|
|
updatedNormals_array[i * 3 + 2] = updatedNormals_vec[i].z;
|
|
|
|
|
|
|
|
|
|
updatedVertices_simd_array[i * 3 + 0] = updatedVertices_simd_vec[i].x; // SIMD version init
|
|
|
|
|
updatedVertices_simd_array[i * 3 + 1] = updatedVertices_simd_vec[i].y;
|
|
|
|
|
updatedVertices_simd_array[i * 3 + 2] = updatedVertices_simd_vec[i].z;
|
|
|
|
|
|
|
|
|
|
updatedNormals_simd_array[i * 3 + 0] = updatedNormals_simd_vec[i].x; // SIMD normals init
|
|
|
|
|
updatedNormals_simd_array[i * 3 + 1] = updatedNormals_simd_vec[i].y;
|
|
|
|
|
updatedNormals_simd_array[i * 3 + 2] = updatedNormals_simd_vec[i].z;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//Reference C++ part
|
|
|
|
|
auto start_time = std::chrono::high_resolution_clock::now();
|
|
|
|
|
uint64_t start = rdtsc();
|
|
|
|
|
// --- Call C++ version for comparison (using vector) ---
|
|
|
|
|
updateVertices(&updatedVertices_vec, &updatedNormals_vec, time);
|
|
|
|
|
|
|
|
|
|
//updateVertices(&updatedVertices_vec, &updatedNormals_vec, time);
|
|
|
|
|
updateVertices(&updatedVertices_vec, &updatedNormals_vec, originalWorldX.data(), originalWorldZ.data(), gridSize, time);
|
|
|
|
|
updateBuffers(updatedVertices_vec, updatedNormals_vec); // Use vectors for updateBuffers
|
|
|
|
|
uint64_t end = rdtsc();
|
|
|
|
|
|
|
|
|
|
auto end_time = std::chrono::high_resolution_clock::now();
|
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
|
|
|
|
|
|
|
|
|
|
std::cout << "Ocean::update took " << duration.count() << "ns " << "CPU cycles: " << (end - start) << std::endl;
|
|
|
|
|
//End Reference C++ part
|
|
|
|
|
|
|
|
|
|
float* updatedVertices_simd_array = new float[floatArraySize]; // Array for SIMD function
|
|
|
|
|
float* updatedNormals_simd_array = new float[floatArraySize]; // Array for SIMD function
|
|
|
|
|
|
|
|
|
|
//Start SIMD part
|
|
|
|
|
// Convert vector of vec3 to float array (for both normal and simd versions)
|
|
|
|
|
|
|
|
|
|
convert_vec3_to_float_array(updatedVertices_simd_vec, updatedVertices_simd_array); // Convert base vertices
|
|
|
|
|
convert_vec3_to_float_array(updatedNormals_simd_vec, updatedNormals_simd_array); // Convert base vertices
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_time = std::chrono::high_resolution_clock::now();
|
|
|
|
|
start = rdtsc();
|
|
|
|
|
|
|
|
|
|
// --- Call SIMD version (now taking float arrays) ---
|
|
|
|
|
updateVertices_simd(updatedVertices_simd_array, updatedNormals_simd_array, numVertices, time);
|
|
|
|
|
// READ
|
|
|
|
|
// Extend function parameters by passing a reference to a structure with
|
|
|
|
|
// Gerstner wave properties, allowing customization through your own implementation.
|
|
|
|
|
updateVertices_simd(updatedVertices_simd_array, updatedNormals_simd_array, numVertices, originalWorldX.data(), originalWorldZ.data(), gridSize, time);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end = rdtsc();
|
|
|
|
|
|
|
|
|
|
end_time = std::chrono::high_resolution_clock::now();
|
|
|
|
@ -152,22 +117,23 @@ void Ocean::update(float deltaTime)
|
|
|
|
|
std::vector<glm::vec3> updatedVertices_vec_from_array(numVertices);
|
|
|
|
|
std::vector<glm::vec3> updatedNormals_vec_from_array(numVertices);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < numVertices; ++i) {
|
|
|
|
|
updatedVertices_vec_from_array[i].x = updatedVertices_simd_array[i * 3 + 0];
|
|
|
|
|
updatedVertices_vec_from_array[i].y = updatedVertices_simd_array[i * 3 + 1];
|
|
|
|
|
updatedVertices_vec_from_array[i].z = updatedVertices_simd_array[i * 3 + 2];
|
|
|
|
|
|
|
|
|
|
updatedNormals_vec_from_array[i].x = updatedNormals_simd_array[i * 3 + 0];
|
|
|
|
|
updatedNormals_vec_from_array[i].y = updatedNormals_simd_array[i * 3 + 1];
|
|
|
|
|
updatedNormals_vec_from_array[i].z = updatedNormals_simd_array[i * 3 + 2];
|
|
|
|
|
}
|
|
|
|
|
convert_float_array_to_vec3(updatedVertices_simd_array, updatedVertices_vec_from_array);
|
|
|
|
|
convert_float_array_to_vec3(updatedNormals_simd_array, updatedNormals_vec_from_array);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateBuffers(updatedVertices_vec_from_array, updatedNormals_vec_from_array); // Use vectors for updateBuffers
|
|
|
|
|
|
|
|
|
|
// READ
|
|
|
|
|
|
|
|
|
|
// THIS FUNCTION UPDATES THE VERTICES AND NORMALS. If updateVertices_simd doesn't work,
|
|
|
|
|
// the surface will remain flat. Uncomment this after implementing the update logic.
|
|
|
|
|
|
|
|
|
|
//updateBuffers(updatedVertices_vec_from_array, updatedNormals_vec_from_array); // Use vectors for updateBuffers
|
|
|
|
|
|
|
|
|
|
//End SIMD part
|
|
|
|
|
|
|
|
|
|
// --- Deallocate float arrays ---
|
|
|
|
|
|
|
|
|
|
delete[] updatedVertices_simd_array;
|
|
|
|
|
delete[] updatedNormals_simd_array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -193,6 +159,135 @@ void Ocean::generateGrid()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Ocean::updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float * originalWorldX_, float * originalWorldZ_, int _grid_size, float time)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
for (int x = 0; x < _grid_size; ++x)
|
|
|
|
|
{
|
|
|
|
|
for (int z = 0; z < _grid_size; ++z)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
glm::vec3 &vertex = (*updatedVertices)[x * _grid_size + z]; // Use reference to modify directly
|
|
|
|
|
float originalX = originalWorldX_[x * _grid_size + z];
|
|
|
|
|
float originalZ = originalWorldZ_[x * _grid_size + z];
|
|
|
|
|
vertex.y = getWaveHeight(vertex.x, vertex.z, time);
|
|
|
|
|
|
|
|
|
|
(*updatedNormals)[x * gridSize + z] = getWaveNormal(originalX, originalZ, time); // Calculate normal using original coords
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float Ocean::getWaveHeight(float x, float z, float time) const {
|
|
|
|
|
float totalHeight = 0.0f;
|
|
|
|
|
for (const auto& wave : gerstnerWaves) {
|
|
|
|
|
totalHeight += getGerstnerWaveHeight(wave, x, z, time);
|
|
|
|
|
}
|
|
|
|
|
return totalHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Ocean::getGerstnerWaveHeight(const GerstnerWave& wave, float x, float z, float time) const {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
float waveHeightValue = periodicAmplitude * sin(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
|
|
|
|
|
if (fabs(x) < 0.5f && fabs(z) < 0.5f) {
|
|
|
|
|
//std::cout << " getGerstnerWaveHeight - time: " << time << ", periodicAmplitude: " << periodicAmplitude << ", waveHeightValue: " << waveHeightValue << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return waveHeightValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getGerstnerWaveDisplacement(const GerstnerWave& wave, float x, float z, float time) const {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float cosTerm = cos(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
return glm::vec3(wave.direction.x * periodicAmplitude * cosTerm,
|
|
|
|
|
0.0f,
|
|
|
|
|
wave.direction.y * periodicAmplitude * cosTerm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getWaveNormal(float x, float z, float time) const {
|
|
|
|
|
glm::vec3 tangentX = glm::vec3(1.0f, 0.0f, 0.0f);
|
|
|
|
|
glm::vec3 tangentZ = glm::vec3(0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
for (const auto& wave : gerstnerWaves) {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float sinTerm = sin(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float cosTerm = cos(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
float modulatedAmplitude = periodicAmplitude;
|
|
|
|
|
|
|
|
|
|
// Calculate tangent vectors for EACH wave component and ACCUMULATE them directly
|
|
|
|
|
tangentX += glm::vec3(
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.x * k * sinTerm, // dx_dx
|
|
|
|
|
modulatedAmplitude * wave.direction.x * k * cosTerm, // dy_dx
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.y * k * sinTerm // dz_dx
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
tangentZ += glm::vec3(
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.y * k * sinTerm, // dx_dz
|
|
|
|
|
modulatedAmplitude * wave.direction.y * k * cosTerm, // dy_dz
|
|
|
|
|
-modulatedAmplitude * wave.direction.y * wave.direction.y * k * sinTerm // dz_dz
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return glm::normalize(glm::cross(tangentZ, tangentX));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Ocean::updateBuffers(const std::vector<glm::vec3> &updatedVertices, const std::vector<glm::vec3> &updatedNormals)
|
|
|
|
|
{
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, updatedVertices.size() * sizeof(glm::vec3), updatedVertices.data()); // Update vertex positions
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, normalBufferID);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, updatedNormals.size() * sizeof(glm::vec3), updatedNormals.data()); // Update normals
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getVertex(int x, int z) const
|
|
|
|
|
{
|
|
|
|
|
return vertices[x * gridSize + z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Ocean::setGridSize(int newGridSize)
|
|
|
|
|
{
|
|
|
|
|
gridSize = newGridSize;
|
|
|
|
|
generateGrid(); // Re-generate the grid with the new size
|
|
|
|
|
|
|
|
|
|
std::vector<glm::vec3> updatedVertices = vertices; // Create a copy to update
|
|
|
|
|
std::vector<glm::vec3> updatedNormals(vertices.size()); // Vector to store updated normals
|
|
|
|
|
|
|
|
|
|
updateVertices(&updatedVertices, &updatedNormals, originalWorldX.data(), originalWorldZ.data(), gridSize, time);
|
|
|
|
|
|
|
|
|
|
updateBuffers(updatedVertices, updatedNormals);
|
|
|
|
|
//updateVertices(); // Re-update vertices based on waves (optional, if needed immediately)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint Ocean::getVAO() const
|
|
|
|
|
{
|
|
|
|
|
return vaoID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint Ocean::getIndexCount() const
|
|
|
|
|
{
|
|
|
|
|
return indexCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Ocean::getGridIndex(int x, int z) const {
|
|
|
|
|
return x * gridSize + z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Ocean::createBuffers()
|
|
|
|
|
{
|
|
|
|
|
glGenVertexArrays(1, &vaoID);
|
|
|
|
@ -278,126 +373,23 @@ void Ocean::createBuffers()
|
|
|
|
|
indexCount = indices.size(); // Store index count for rendering
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Ocean::updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float time)
|
|
|
|
|
Ocean::~Ocean()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
for (int x = 0; x < gridSize; ++x)
|
|
|
|
|
{
|
|
|
|
|
for (int z = 0; z < gridSize; ++z)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
glm::vec3 &vertex = vertices[x * gridSize + z];
|
|
|
|
|
float originalX = originalWorldX[x * gridSize + z];
|
|
|
|
|
float originalZ = originalWorldZ[x * gridSize + z];
|
|
|
|
|
vertex.y = getWaveHeight(vertex.x, vertex.z, time);
|
|
|
|
|
|
|
|
|
|
(*updatedNormals)[x * gridSize + z] = getWaveNormal(originalX, originalZ, time); // Calculate normal using original coords
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//vertices = updatedVertices; // Assign the updated vertices back
|
|
|
|
|
//updateBuffers(updatedVertices, updatedNormals);
|
|
|
|
|
cleanup(); // Call cleanup to release OpenGL resources
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Ocean::updateBuffers(const std::vector<glm::vec3> &updatedVertices, const std::vector<glm::vec3> &updatedNormals)
|
|
|
|
|
void Ocean::cleanup()
|
|
|
|
|
{
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, updatedVertices.size() * sizeof(glm::vec3), updatedVertices.data()); // Update vertex positions
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, normalBufferID);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, updatedNormals.size() * sizeof(glm::vec3), updatedNormals.data()); // Update normals
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getVertex(int x, int z) const
|
|
|
|
|
{
|
|
|
|
|
return vertices[x * gridSize + z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Ocean::getWaveHeight(float x, float z, float time) const {
|
|
|
|
|
float totalHeight = 0.0f;
|
|
|
|
|
for (const auto& wave : gerstnerWaves) {
|
|
|
|
|
totalHeight += getGerstnerWaveHeight(wave, x, z, time);
|
|
|
|
|
}
|
|
|
|
|
return totalHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Ocean::getGerstnerWaveHeight(const GerstnerWave& wave, float x, float z, float time) const {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
float waveHeightValue = periodicAmplitude * sin(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
|
|
|
|
|
if (fabs(x) < 0.5f && fabs(z) < 0.5f) {
|
|
|
|
|
//std::cout << " getGerstnerWaveHeight - time: " << time << ", periodicAmplitude: " << periodicAmplitude << ", waveHeightValue: " << waveHeightValue << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return waveHeightValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getGerstnerWaveDisplacement(const GerstnerWave& wave, float x, float z, float time) const {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float cosTerm = cos(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
return glm::vec3(wave.direction.x * periodicAmplitude * cosTerm,
|
|
|
|
|
0.0f,
|
|
|
|
|
wave.direction.y * periodicAmplitude * cosTerm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glm::vec3 Ocean::getWaveNormal(float x, float z, float time) const {
|
|
|
|
|
glm::vec3 tangentX = glm::vec3(1.0f, 0.0f, 0.0f);
|
|
|
|
|
glm::vec3 tangentZ = glm::vec3(0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
for (const auto& wave : gerstnerWaves) {
|
|
|
|
|
float k = 2.0f * glm::pi<float>() / wave.wavelength;
|
|
|
|
|
float w = wave.speed * k;
|
|
|
|
|
float dotProduct = glm::dot(wave.direction, glm::vec2(x, z));
|
|
|
|
|
float sinTerm = sin(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float cosTerm = cos(k * dotProduct - w * time + wave.phase);
|
|
|
|
|
float periodicAmplitude = wave.amplitude * 0.5f * (1.0f + sin(2.0f * glm::pi<float>() * time / wave.wavelength));
|
|
|
|
|
float modulatedAmplitude = periodicAmplitude;
|
|
|
|
|
|
|
|
|
|
// Calculate tangent vectors for EACH wave component and ACCUMULATE them directly
|
|
|
|
|
tangentX += glm::vec3(
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.x * k * sinTerm, // dx_dx
|
|
|
|
|
modulatedAmplitude * wave.direction.x * k * cosTerm, // dy_dx
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.y * k * sinTerm // dz_dx
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
tangentZ += glm::vec3(
|
|
|
|
|
-modulatedAmplitude * wave.direction.x * wave.direction.y * k * sinTerm, // dx_dz
|
|
|
|
|
modulatedAmplitude * wave.direction.y * k * cosTerm, // dy_dz
|
|
|
|
|
-modulatedAmplitude * wave.direction.y * wave.direction.y * k * sinTerm // dz_dz
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return glm::normalize(glm::cross(tangentZ, tangentX));
|
|
|
|
|
}
|
|
|
|
|
void Ocean::setGridSize(int newGridSize)
|
|
|
|
|
{
|
|
|
|
|
gridSize = newGridSize;
|
|
|
|
|
generateGrid(); // Re-generate the grid with the new size
|
|
|
|
|
|
|
|
|
|
std::vector<glm::vec3> updatedVertices = vertices; // Create a copy to update
|
|
|
|
|
std::vector<glm::vec3> updatedNormals(vertices.size()); // Vector to store updated normals
|
|
|
|
|
|
|
|
|
|
updateVertices(&updatedVertices, &updatedNormals, time);
|
|
|
|
|
|
|
|
|
|
updateBuffers(updatedVertices, updatedNormals);
|
|
|
|
|
//updateVertices(); // Re-update vertices based on waves (optional, if needed immediately)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint Ocean::getVAO() const
|
|
|
|
|
{
|
|
|
|
|
return vaoID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint Ocean::getIndexCount() const
|
|
|
|
|
{
|
|
|
|
|
return indexCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Ocean::getGridIndex(int x, int z) const {
|
|
|
|
|
return x * gridSize + z;
|
|
|
|
|
}
|
|
|
|
|
// No dynamic memory allocation in this simple version
|
|
|
|
|
// Release OpenGL resources (VBOs, IBO, VAO)
|
|
|
|
|
glDeleteBuffers(1, &vertexBufferID);
|
|
|
|
|
glDeleteBuffers(1, &normalBufferID);
|
|
|
|
|
glDeleteBuffers(1, &texCoordBufferID);
|
|
|
|
|
glDeleteBuffers(1, &indexBufferID);
|
|
|
|
|
glDeleteVertexArrays(1, &vaoID);
|
|
|
|
|
vertexBufferID = 0;
|
|
|
|
|
normalBufferID = 0;
|
|
|
|
|
texCoordBufferID = 0;
|
|
|
|
|
indexBufferID = 0;
|
|
|
|
|
vaoID = 0;
|
|
|
|
|
}
|