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 <X11/Xlib.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <cstdint>
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
|
||||||
class WindowManager {
|
class WindowManager {
|
||||||
public:
|
public:
|
||||||
WindowManager(int width, int height);
|
WindowManager(int width, int height, int (*)(u_int32_t *img));
|
||||||
~WindowManager();
|
~WindowManager();
|
||||||
|
|
||||||
u_int32_t *get_image_addr() { return img; }
|
u_int32_t *get_image_addr() { return img; }
|
||||||
|
|
||||||
void display_image();
|
|
||||||
void loop();
|
void loop();
|
||||||
private:
|
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;
|
u_int32_t *img;
|
||||||
int WindowX;
|
int WindowX;
|
||||||
int WindowY;
|
int WindowY;
|
||||||
|
|
@ -32,6 +37,7 @@ private:
|
||||||
Window RootWindow;
|
Window RootWindow;
|
||||||
Atom wmDelete;
|
Atom wmDelete;
|
||||||
bool isWindowOpen;
|
bool isWindowOpen;
|
||||||
|
bool isDisplayReady;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //NOISE_GENERATOR_WINDOWMANAGER_HPP
|
#endif //NOISE_GENERATOR_WINDOWMANAGER_HPP
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,27 @@
|
||||||
|
|
||||||
#include <csignal>
|
|
||||||
#include "windowManager/WindowManager.hpp"
|
#include "windowManager/WindowManager.hpp"
|
||||||
|
#include "noise/perlin.hpp"
|
||||||
|
|
||||||
#define WIDTH 500
|
#define WIDTH 720
|
||||||
#define HEIGHT 800
|
#define HEIGHT 420
|
||||||
|
|
||||||
int main() {
|
|
||||||
WindowManager window(WIDTH, HEIGHT);
|
|
||||||
u_int32_t *img = window.get_image_addr();
|
|
||||||
|
|
||||||
|
int render(uint32_t *img) {
|
||||||
|
static PerlinNoise PerlinNoise;
|
||||||
|
static float time = 0.0;
|
||||||
for (int y = 0; y < HEIGHT; y++) {
|
for (int y = 0; y < HEIGHT; y++) {
|
||||||
for (int x = 0; x < WIDTH; x++) {
|
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();
|
window.loop();
|
||||||
return 0;
|
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 "windowManager/WindowManager.hpp"
|
||||||
#include <string.h>
|
#include "noise/perlin.hpp"
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <csignal>
|
#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),
|
WindowX(0), WindowY(0),
|
||||||
WindowWidth(width), WindowHeight(height),
|
WindowWidth(width), WindowHeight(height),
|
||||||
BorderWidth(0),
|
BorderWidth(0),
|
||||||
WindowDepth(CopyFromParent),
|
WindowDepth(CopyFromParent),
|
||||||
WindowClass(CopyFromParent),
|
WindowClass(CopyFromParent),
|
||||||
WindowVisual(CopyFromParent),
|
WindowVisual(CopyFromParent),
|
||||||
AttributeValueMask(CWBackPixel | CWEventMask)
|
AttributeValueMask(CWBackPixel | CWEventMask),
|
||||||
|
isDisplayReady(false)
|
||||||
{
|
{
|
||||||
img = new u_int32_t[width * height];
|
img = new u_int32_t[width * height];
|
||||||
MainDisplay = XOpenDisplay(0);
|
MainDisplay = XOpenDisplay(0);
|
||||||
RootWindow = XDefaultRootWindow(MainDisplay);
|
RootWindow = XDefaultRootWindow(MainDisplay);
|
||||||
bzero(&WindowAttributes, sizeof(XSetWindowAttributes));
|
WindowAttributes = {};
|
||||||
WindowAttributes.background_pixel = 0x0;
|
WindowAttributes.background_pixel = 0x0;
|
||||||
WindowAttributes.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask;
|
WindowAttributes.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask;
|
||||||
|
|
||||||
|
|
@ -40,11 +41,7 @@ WindowManager::~WindowManager() {
|
||||||
delete[] img;
|
delete[] img;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::loop() {
|
void WindowManager::handle_events(XEvent &GeneralEvent) {
|
||||||
while (isWindowOpen) {
|
|
||||||
XEvent GeneralEvent = {};
|
|
||||||
XNextEvent(this->MainDisplay, &GeneralEvent);
|
|
||||||
|
|
||||||
switch(GeneralEvent.type) {
|
switch(GeneralEvent.type) {
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
|
|
@ -61,10 +58,25 @@ void WindowManager::loop() {
|
||||||
} break;
|
} break;
|
||||||
case Expose:
|
case Expose:
|
||||||
{
|
{
|
||||||
std::cout << "test" << std::endl;
|
if (!isDisplayReady)
|
||||||
|
isDisplayReady = true;
|
||||||
display_image();
|
display_image();
|
||||||
} break;
|
} 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,3 +98,9 @@ void WindowManager::display_image() {
|
||||||
XPutImage(MainDisplay, MainWindow, DefaultGC(MainDisplay, 0), &image, 0, 0, 0, 0, WindowWidth, WindowHeight);
|
XPutImage(MainDisplay, MainWindow, DefaultGC(MainDisplay, 0), &image, 0, 0, 0, 0, WindowWidth, WindowHeight);
|
||||||
XFlush(MainDisplay);
|
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