Untitled
unknown
plain_text
5 months ago
7.8 kB
6
Indexable
#include "OceanGenerator.h" #include "geomVertexWriter.h" #include "geomVertexRewriter.h" #include "geomVertexFormat.h" #include "geomTriangles.h" #include "geomNode.h" #include "genericAsyncTask.h" #include "asyncTaskManager.h" #include "texturepool.h" #include "shader.h" #include <cmath> #include <memory> #include <QDebug> #include <QDir> PT(GeomVertexData) OceanGenerator::vertex_data = nullptr; float OceanGenerator::time_elapsed = 0.0f; const LVector2f OceanGenerator::wave1Direction(1.0f, 0.5f); const float OceanGenerator::wave1Speed = 1.0f; const float OceanGenerator::wave1Amplitude = 0.2f; const float OceanGenerator::wave1Frequency = 0.9f; const LVector2f OceanGenerator::wave2Direction(0.7f, -0.7f); const float OceanGenerator::wave2Speed = 0.5f; const float OceanGenerator::wave2Amplitude = 0.1f; const float OceanGenerator::wave2Frequency = 1.2f; OceanGenerator::OceanGenerator(WindowFramework* window) : window(window) {} OceanGenerator::~OceanGenerator() {} NodePath OceanGenerator::generate(int size, float spacing, const std::string& texture_path, const std::string& normal_map_path) { PT(GeomVertexFormat) format = const_cast<GeomVertexFormat*>(GeomVertexFormat::get_v3t2()); vertex_data = new GeomVertexData("wave_data", format, Geom::UH_dynamic); GeomVertexWriter vertex_writer(vertex_data, "vertex"); GeomVertexWriter texcoord_writer(vertex_data, "texcoord"); PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static); int idx = 0; for (int x = 0; x <= size; ++x) { for (int y = 0; y <= size; ++y) { vertex_writer.add_data3(x * spacing, y * spacing, 0.0f); texcoord_writer.add_data2(x / static_cast<float>(size), y / static_cast<float>(size)); if (x < size && y < size) { int top_left = idx; int top_right = idx + 1; int bottom_left = idx + size + 1; int bottom_right = idx + size + 2; triangles->add_vertices(top_left, bottom_left, bottom_right); triangles->add_vertices(top_left, bottom_right, top_right); } ++idx; } } PT(Geom) geom = new Geom(vertex_data); geom->add_primitive(triangles); PT(GeomNode) node = new GeomNode("ocean_grid"); node->add_geom(geom); NodePath grid = window->get_render().attach_new_node(node); PT(Texture) texture = TexturePool::load_texture(texture_path); PT(Texture) normal_map = TexturePool::load_texture(normal_map_path); grid.set_texture(texture); grid.set_shader_input("texture_map", texture); grid.set_shader_input("normal_map", normal_map); grid.set_shader_input("time_elapsed", LVecBase4(time_elapsed, 0, 0, 0)); PT(Shader) shader = Shader::load(Shader::SL_GLSL, "water_shader.vert", "water_shader.frag"); grid.set_shader(shader); grid.set_shader_input("texture_map", texture); grid.set_shader_input("normal_map", normal_map); grid.set_shader_input("light_pos", LVecBase3(10, 10, 10)); grid.set_shader_input("view_pos", window->get_camera_group().get_pos()); NodePath moving_object = window->get_render().attach_new_node("moving_object"); moving_object.set_pos(size * spacing / 2.0f, size * spacing / 2.0f, 0.0f); auto task_data = std::make_unique<std::pair<OceanGenerator*, NodePath>>(this, grid); AsyncTaskManager::get_global_ptr()->add(new GenericAsyncTask("update_wave", updateWave, task_data.release())); return grid; } float OceanGenerator::calculateWaveHeight(float x, float y) const { float projected_x1 = x * wave1Direction.get_x() + y * wave1Direction.get_y(); float projected_y1 = y * wave1Direction.get_x() - x * wave1Direction.get_y(); float projected_x2 = x * wave2Direction.get_x() + y * wave2Direction.get_y(); float projected_y2 = y * wave2Direction.get_x() - x * wave2Direction.get_y(); float wave1_height = std::sin(wave1Frequency * projected_x1 + time_elapsed) * std::cos(wave1Frequency * projected_y1 + time_elapsed) * wave1Amplitude; float wave2_height = std::sin(wave2Frequency * projected_x2 + time_elapsed) * std::cos(wave2Frequency * projected_y2 + time_elapsed) * wave2Amplitude; return wave1_height + wave2_height; } AsyncTask::DoneStatus OceanGenerator::updateWave(GenericAsyncTask* task, void* data) { float dt = ClockObject::get_global_clock()->get_dt(); time_elapsed += dt * wave1Speed; GeomVertexRewriter vertex_rewriter(vertex_data, "vertex"); while (!vertex_rewriter.is_at_end()) { LPoint3f vertex = vertex_rewriter.get_data3(); float projected_x1 = vertex.get_x() * wave1Direction.get_x() + vertex.get_y() * wave1Direction.get_y(); float projected_y1 = vertex.get_y() * wave1Direction.get_x() - vertex.get_x() * wave1Direction.get_y(); float projected_x2 = vertex.get_x() * wave2Direction.get_x() + vertex.get_y() * wave2Direction.get_y(); float projected_y2 = vertex.get_y() * wave2Direction.get_x() - vertex.get_x() * wave2Direction.get_y(); float wave1_height = std::sin(wave1Frequency * projected_x1 + time_elapsed) * std::cos(wave1Frequency * projected_y1 + time_elapsed) * wave1Amplitude; float wave2_height = std::sin(wave2Frequency * projected_x2 + time_elapsed) * std::cos(wave2Frequency * projected_y2 + time_elapsed) * wave2Amplitude; float wave_height = wave1_height + wave2_height; vertex.set_z(wave_height); vertex_rewriter.set_data3(vertex); } auto* ocean_data = static_cast<std::pair<OceanGenerator*, NodePath>*>(data); OceanGenerator* ocean = ocean_data->first; NodePath* grid = &ocean_data->second; grid->set_shader_input("time_elapsed", LVecBase4(time_elapsed, 0, 0, 0)); NodePath platform = grid->find("**/oil_rig"); if (!platform.is_empty()) { float obj_x = platform.get_x(); float obj_y = platform.get_y(); float new_z = ocean->calculateWaveHeight(obj_x, obj_y); platform.set_z(new_z); } return AsyncTask::DS_cont; } #ifndef OCEANGENERATOR_H #define OCEANGENERATOR_H #include "pandaFramework.h" #include "nodePath.h" #include "geomVertexData.h" #include <string> #include <utility> #include <memory> class OceanGenerator { struct size_spacing_data { OceanGenerator* ocean_generator; NodePath grid; int size; float spacing; }; public: OceanGenerator(WindowFramework* window); ~OceanGenerator(); NodePath generate(int size, float spacing, const std::string& texture_path, const std::string& normal_map_path); static AsyncTask::DoneStatus updateWave(GenericAsyncTask* task, void* data); private: WindowFramework* window; void* data = nullptr; static PT(GeomVertexData) vertex_data; static float time_elapsed; float calculateWaveHeight(float x, float y) const; static const float wave1Speed; static const float wave1Amplitude; static const float wave1Frequency; static const LVector2f wave1Direction; static const float wave2Speed; static const float wave2Amplitude; static const float wave2Frequency; static const LVector2f wave2Direction; int size = 10; float spacing = 10.0f; }; #endif // OCEANGENERATOR_H
Editor is loading...
Leave a Comment