Fixed parameter passing logic
This commit is contained in:
@ -22,6 +22,9 @@ struct GerstnerWave {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
Tuto strukturu si můžete libovolně upravit a předat funkci například jako pole strutkur.
|
||||
|
||||
## Dokumentace
|
||||
|
||||
V dokumentaci **podrobně popište** postup optimalizace. Pro lepší přehlednost můžete využít:
|
||||
@ -61,7 +64,7 @@ Na poslední cvičení bude obhajoba projektu, cílem je ukázat, že projektu r
|
||||
|
||||
### Windows + VS Code
|
||||
|
||||
Projekt spusťte ve **VS Code** z **2. cvičení**, které obsahuje všechny potřebné knihovny.
|
||||
Projekt spusťte ve **VS Code** z **2. cvičení**, které obsahuje všechny potřebné knihovny. Jelikož šablona pro windows obsahuje relativní cesty k root složce archívu, musíte nakopírovat sloužku "windows" projektu do root složky ze cvičení.
|
||||
|
||||
### Linux
|
||||
|
||||
|
7
linux/.vscode/settings.json
vendored
7
linux/.vscode/settings.json
vendored
@ -58,6 +58,11 @@
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
"typeinfo": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"optional": "cpp",
|
||||
"typeindex": "cpp"
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.s
|
||||
# Clean target
|
||||
clean:
|
||||
rm $(BUILD_DIR)/*
|
||||
rm $(EXECUTABLE_PATH)
|
||||
|
||||
# Debug build target
|
||||
debug: CXXFLAGS += -DDEBUG -g
|
||||
|
@ -79,8 +79,8 @@ private:
|
||||
void generateGrid();
|
||||
void createBuffers(); // Create and populate VBOs and IBO
|
||||
void updateBuffers(const std::vector<glm::vec3>& updatedVertices, const std::vector<glm::vec3>& updatedNormals); // Update VBO data
|
||||
void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float time); // Update vertex Y positions based on wave function
|
||||
|
||||
//void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float time); // Update vertex Y positions based on wave function
|
||||
void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float * originalWorldX_, float * originalWorldZ_, int _grid_size, float time);
|
||||
#if ASM_TYPE==CLEAR_ASM
|
||||
#else
|
||||
void updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float time); // Modified signature for C++ as well (for consistency or if you want to use float arrays in C++ SIMD too)
|
||||
|
@ -5,11 +5,12 @@
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <x86intrin.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Helper function to check for OpenGL errors and print a message
|
||||
void checkGLError(const char* operation);
|
||||
float perlinNoise(float x, float y); // Placeholder declaration
|
||||
|
||||
void convert_vec3_to_float_array(const std::vector<glm::vec3>& src, float * dst);
|
||||
void convert_float_array_to_vec3(float * src, std::vector<glm::vec3>& dst);
|
||||
uint64_t rdtsc();
|
||||
#endif // UTILS_H
|
@ -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;
|
||||
}
|
@ -69,4 +69,25 @@ float perlinNoise(float x, float y) {
|
||||
frequency *= 2.0f; // Increase frequency for each octave
|
||||
}
|
||||
return value / maxAmplitude; // Normalize to [0, 1] range
|
||||
}
|
||||
}
|
||||
|
||||
void convert_vec3_to_float_array(const std::vector<glm::vec3>& src, float * dst) {
|
||||
// Ensure dst is the correct size (numVertices * 3) - should be handled by resize in constructor
|
||||
size_t numVertices = src.size();
|
||||
|
||||
for (size_t i = 0; i < numVertices; ++i) {
|
||||
dst[i * 3 + 0] = src[i].x;
|
||||
dst[i * 3 + 1] = src[i].y;
|
||||
dst[i * 3 + 2] = src[i].z;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_float_array_to_vec3(float * src, std::vector<glm::vec3>& dst) {
|
||||
size_t numVertices = dst.size(); // Assume dst has correct size already
|
||||
|
||||
for (size_t i = 0; i < numVertices; ++i) {
|
||||
dst[i].x = src[i * 3 + 0];
|
||||
dst[i].y = src[i * 3 + 1];
|
||||
dst[i].z = src[i * 3 + 2];
|
||||
}
|
||||
}
|
||||
|
@ -79,8 +79,8 @@ private:
|
||||
void generateGrid();
|
||||
void createBuffers(); // Create and populate VBOs and IBO
|
||||
void updateBuffers(const std::vector<glm::vec3>& updatedVertices, const std::vector<glm::vec3>& updatedNormals); // Update VBO data
|
||||
void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float time); // Update vertex Y positions based on wave function
|
||||
|
||||
//void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float time); // Update vertex Y positions based on wave function
|
||||
void updateVertices(std::vector<glm::vec3> * updatedVertices, std::vector<glm::vec3> * updatedNormals, float * originalWorldX_, float * originalWorldZ_, int _grid_size, float time);
|
||||
#if ASM_TYPE==CLEAR_ASM
|
||||
#else
|
||||
void updateVertices_simd(float* updatedVertices_array, float* updatedNormals_array, size_t numVertices, float time); // Modified signature for C++ as well (for consistency or if you want to use float arrays in C++ SIMD too)
|
||||
|
@ -5,11 +5,12 @@
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <x86intrin.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Helper function to check for OpenGL errors and print a message
|
||||
void checkGLError(const char* operation);
|
||||
float perlinNoise(float x, float y); // Placeholder declaration
|
||||
|
||||
void convert_vec3_to_float_array(const std::vector<glm::vec3>& src, float * dst);
|
||||
void convert_float_array_to_vec3(float * src, std::vector<glm::vec3>& dst);
|
||||
uint64_t rdtsc();
|
||||
#endif // UTILS_H
|
@ -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;
|
||||
}
|
@ -69,4 +69,25 @@ float perlinNoise(float x, float y) {
|
||||
frequency *= 2.0f; // Increase frequency for each octave
|
||||
}
|
||||
return value / maxAmplitude; // Normalize to [0, 1] range
|
||||
}
|
||||
}
|
||||
|
||||
void convert_vec3_to_float_array(const std::vector<glm::vec3>& src, float * dst) {
|
||||
// Ensure dst is the correct size (numVertices * 3) - should be handled by resize in constructor
|
||||
size_t numVertices = src.size();
|
||||
|
||||
for (size_t i = 0; i < numVertices; ++i) {
|
||||
dst[i * 3 + 0] = src[i].x;
|
||||
dst[i * 3 + 1] = src[i].y;
|
||||
dst[i * 3 + 2] = src[i].z;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_float_array_to_vec3(float * src, std::vector<glm::vec3>& dst) {
|
||||
size_t numVertices = dst.size(); // Assume dst has correct size already
|
||||
|
||||
for (size_t i = 0; i < numVertices; ++i) {
|
||||
dst[i].x = src[i * 3 + 0];
|
||||
dst[i].y = src[i * 3 + 1];
|
||||
dst[i].z = src[i * 3 + 2];
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user