Untitled
unknown
plain_text
a year ago
7.8 kB
7
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