implement perlin noise render
This commit is contained in:
parent
e0d23c9a82
commit
e4b900e721
7 changed files with 207 additions and 38 deletions
28
includes/math/Vector2.hpp
Normal file
28
includes/math/Vector2.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef VECTPR2_HPP
|
||||
#define VECTOR2_HPP
|
||||
|
||||
class Vector2 {
|
||||
public:
|
||||
Vector2(int x, int y);
|
||||
Vector2(float x, float y);
|
||||
Vector2(double x, double y);
|
||||
Vector2();
|
||||
Vector2(const Vector2 &v);
|
||||
|
||||
~Vector2();
|
||||
|
||||
Vector2 &operator=(const Vector2 &v);
|
||||
Vector2 operator+(const Vector2 &v) const;
|
||||
Vector2 operator-(const Vector2 &v) const;
|
||||
Vector2 operator*(const Vector2 &v) const;
|
||||
|
||||
float dot(const Vector2 &v) const;
|
||||
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
private:
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
#endif
|
||||
20
includes/noise/perlin.hpp
Normal file
20
includes/noise/perlin.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
#ifndef PERLIN_HPP
|
||||
#define PERLIN_HPP
|
||||
#include "math/Vector2.hpp"
|
||||
|
||||
|
||||
class PerlinNoise {
|
||||
public:
|
||||
PerlinNoise();
|
||||
float noise(float x, float y);
|
||||
|
||||
private:
|
||||
void initializeGradients();
|
||||
Vector2 grad[256];
|
||||
Vector2 randoGradient(int ix, int iy);
|
||||
float dotGridGradient(int ix, int iy, float x, float y);
|
||||
float interpolate(float a, float a1, float w);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -4,18 +4,23 @@
|
|||
|
||||
#include <X11/Xlib.h>
|
||||
#include <mutex>
|
||||
#include <cstdint>
|
||||
#include "err.h"
|
||||
|
||||
class WindowManager {
|
||||
public:
|
||||
WindowManager(int width, int height);
|
||||
WindowManager(int width, int height, int (*)(u_int32_t *img));
|
||||
~WindowManager();
|
||||
|
||||
u_int32_t *get_image_addr() { return img; }
|
||||
|
||||
void display_image();
|
||||
void loop();
|
||||
private:
|
||||
void update_image(int (*)(u_int32_t *img));
|
||||
void display_image();
|
||||
void handle_events(XEvent &GeneralEvent);
|
||||
|
||||
int (*render)(u_int32_t *img);
|
||||
u_int32_t *img;
|
||||
int WindowX;
|
||||
int WindowY;
|
||||
|
|
@ -32,6 +37,7 @@ private:
|
|||
Window RootWindow;
|
||||
Atom wmDelete;
|
||||
bool isWindowOpen;
|
||||
bool isDisplayReady;
|
||||
};
|
||||
|
||||
#endif //NOISE_GENERATOR_WINDOWMANAGER_HPP
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
|
||||
#include <csignal>
|
||||
#include "windowManager/WindowManager.hpp"
|
||||
#include "noise/perlin.hpp"
|
||||
|
||||
#define WIDTH 500
|
||||
#define HEIGHT 800
|
||||
|
||||
int main() {
|
||||
WindowManager window(WIDTH, HEIGHT);
|
||||
u_int32_t *img = window.get_image_addr();
|
||||
#define WIDTH 720
|
||||
#define HEIGHT 420
|
||||
|
||||
int render(uint32_t *img) {
|
||||
static PerlinNoise PerlinNoise;
|
||||
static float time = 0.0;
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
img[y * WIDTH + x] = (y * 255 / HEIGHT) * 0x100 + (x * 255 / WIDTH);
|
||||
float n = (PerlinNoise.noise(x / 100.0 + time, (y / 100.0) + time));
|
||||
|
||||
int color = static_cast<int>((n + 1) * 127.5);
|
||||
img[y * WIDTH + x] = (color << 16) | (color << 8) | color ;
|
||||
}
|
||||
}
|
||||
time += 0.1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
WindowManager window(WIDTH, HEIGHT, render);
|
||||
|
||||
window.loop();
|
||||
return 0;
|
||||
|
|
|
|||
34
srcs/math/Vector2.cpp
Normal file
34
srcs/math/Vector2.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include "math/Vector2.hpp"
|
||||
|
||||
Vector2::Vector2(int x, int y) : x(x), y(y) {};
|
||||
Vector2::Vector2(float x, float y) : x(x), y(y) {};
|
||||
Vector2::Vector2() : x(0), y(0) {};
|
||||
Vector2::Vector2(const Vector2 &v) : x(v.x), y(v.y) {};
|
||||
Vector2::Vector2(double x, double y) : x(x), y(y) {};
|
||||
|
||||
float Vector2::getX() const { return x; }
|
||||
float Vector2::getY() const { return y; }
|
||||
|
||||
Vector2 &Vector2::operator=(const Vector2 &v) {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator+(const Vector2 &v) const {
|
||||
return Vector2(x + v.x, y + v.y);
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator-(const Vector2 &v) const {
|
||||
return Vector2(x - v.x, y - v.y);
|
||||
}
|
||||
|
||||
Vector2 Vector2::operator*(const Vector2 &v) const {
|
||||
return Vector2(x * v.x, y * v.y);
|
||||
}
|
||||
|
||||
float Vector2::dot(const Vector2 &v) const {
|
||||
return x * v.x + y * v.y;
|
||||
}
|
||||
|
||||
Vector2::~Vector2() {}
|
||||
57
srcs/noise/perlin.cpp
Normal file
57
srcs/noise/perlin.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include "noise/perlin.hpp"
|
||||
|
||||
|
||||
|
||||
PerlinNoise::PerlinNoise() {
|
||||
initializeGradients();
|
||||
}
|
||||
|
||||
void PerlinNoise::initializeGradients() {
|
||||
std::mt19937 gen(0);
|
||||
std::uniform_real_distribution<float> dis(0.0, 2 * M_PI);
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
float angle = dis(gen);
|
||||
grad[i] = Vector2(cos(angle), sin(angle));
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 PerlinNoise::randoGradient(int ix, int iy) {
|
||||
uint32_t hash = ix * 7385451 ^ iy * 19349663;
|
||||
return grad[hash & 0xFF];
|
||||
}
|
||||
|
||||
float PerlinNoise::dotGridGradient(int ix, int iy, float x, float y) {
|
||||
Vector2 gradient = randoGradient(ix, iy);
|
||||
float dx = x - (float)ix;
|
||||
float dy = y - (float)iy;
|
||||
return dx * gradient.getX() + dy * gradient.getY();
|
||||
}
|
||||
|
||||
float PerlinNoise::interpolate(float a, float a1, float w) {
|
||||
return (a1 - a) * (3.0 - w * 2.0) * w * w + a;
|
||||
}
|
||||
|
||||
float PerlinNoise::noise(float x, float y) {
|
||||
int x0 = (int)x;
|
||||
int y0 = (int)y;
|
||||
int x1 = x0 + 1;
|
||||
int y1 = y0 + 1;
|
||||
|
||||
float sx = x - (float)x0;
|
||||
float sy = y - (float)y0;
|
||||
|
||||
float n0 = dotGridGradient(x0, y0, x, y);
|
||||
float n1 = dotGridGradient(x1, y0, x, y);
|
||||
float ix0 = interpolate(n0, n1, sx);
|
||||
|
||||
n0 = dotGridGradient(x0, y1, x, y);
|
||||
n1 = dotGridGradient(x1, y1, x, y);
|
||||
float ix1 = interpolate(n0, n1, sx);
|
||||
|
||||
return interpolate(ix0, ix1, sy);
|
||||
}
|
||||
|
|
@ -1,24 +1,25 @@
|
|||
#include "windowManager/WindowManager.hpp"
|
||||
#include <string.h>
|
||||
#include "noise/perlin.hpp"
|
||||
#include <X11/Xutil.h>
|
||||
#include <iostream>
|
||||
#include <X11/Xlib.h>
|
||||
#include <csignal>
|
||||
#include <mutex>
|
||||
|
||||
WindowManager::WindowManager(int width, int height) :
|
||||
WindowManager::WindowManager(int width, int height, int (*render)(u_int32_t *img)) :
|
||||
render(render),
|
||||
WindowX(0), WindowY(0),
|
||||
WindowWidth(width), WindowHeight(height),
|
||||
BorderWidth(0),
|
||||
WindowDepth(CopyFromParent),
|
||||
WindowClass(CopyFromParent),
|
||||
WindowVisual(CopyFromParent),
|
||||
AttributeValueMask(CWBackPixel | CWEventMask)
|
||||
AttributeValueMask(CWBackPixel | CWEventMask),
|
||||
isDisplayReady(false)
|
||||
{
|
||||
img = new u_int32_t[width * height];
|
||||
MainDisplay = XOpenDisplay(0);
|
||||
RootWindow = XDefaultRootWindow(MainDisplay);
|
||||
bzero(&WindowAttributes, sizeof(XSetWindowAttributes));
|
||||
WindowAttributes = {};
|
||||
WindowAttributes.background_pixel = 0x0;
|
||||
WindowAttributes.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask;
|
||||
|
||||
|
|
@ -40,11 +41,7 @@ WindowManager::~WindowManager() {
|
|||
delete[] img;
|
||||
}
|
||||
|
||||
void WindowManager::loop() {
|
||||
while (isWindowOpen) {
|
||||
XEvent GeneralEvent = {};
|
||||
XNextEvent(this->MainDisplay, &GeneralEvent);
|
||||
|
||||
void WindowManager::handle_events(XEvent &GeneralEvent) {
|
||||
switch(GeneralEvent.type) {
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
|
|
@ -61,11 +58,26 @@ void WindowManager::loop() {
|
|||
} break;
|
||||
case Expose:
|
||||
{
|
||||
std::cout << "test" << std::endl;
|
||||
if (!isDisplayReady)
|
||||
isDisplayReady = true;
|
||||
display_image();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::loop() {
|
||||
while (isWindowOpen) {
|
||||
while (XPending(this->MainDisplay) > 0)
|
||||
{
|
||||
XEvent GeneralEvent = {};
|
||||
XNextEvent(this->MainDisplay, &GeneralEvent);
|
||||
handle_events(GeneralEvent);
|
||||
}
|
||||
if (isDisplayReady) {
|
||||
update_image(this->render);
|
||||
display_image();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::display_image() {
|
||||
|
|
@ -86,3 +98,9 @@ void WindowManager::display_image() {
|
|||
XPutImage(MainDisplay, MainWindow, DefaultGC(MainDisplay, 0), &image, 0, 0, 0, 0, WindowWidth, WindowHeight);
|
||||
XFlush(MainDisplay);
|
||||
}
|
||||
|
||||
void WindowManager::update_image(int (*func)(u_int32_t *img)) {
|
||||
if (func(this->img))
|
||||
this->isWindowOpen = false;
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue