Last active
June 28, 2017 07:42
-
-
Save dev001hajipro/0c1b43a1c8b9aa5edd5f44a0abb5ec8e to your computer and use it in GitHub Desktop.
flowfield with OpenSive3D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Siv3D.hpp> | |
#define _USE_MATH_DEFINES | |
#include <math.h> | |
// p5.js helper functions for OpenSiv3D | |
namespace p5h { | |
template <typename T> | |
inline T map(T n, T start1, T stop1, T start2, T stop2) noexcept { | |
return ((n - start1) / (stop1 - start1)) * (stop2 - start2) + start2; | |
} | |
inline void limit(Vec2& v, double a) noexcept { | |
double b = v.lengthSq(); | |
if (b > a*a) { | |
v /= sqrt((float)b); | |
} | |
v *= a; | |
} | |
inline double heading(Vec2& v) noexcept { | |
return atan2(v.y, v.x); | |
} | |
template <typename T> | |
inline auto radians(T d) noexcept { | |
return 2 * M_PI / 360 * d; // 2*PI=360 degrees. | |
} | |
template <typename T> | |
inline auto constrain(T n, T low, T high) noexcept { | |
return max(min(n, high), low); | |
} | |
} | |
using namespace std; | |
struct FlowField | |
{ | |
std::vector<std::vector<Vec2>> field; | |
int32_t resolution = 10; | |
int32_t cols; | |
int32_t rows; | |
double zoff = 0.0; // perlin noize offset. | |
FlowField() | |
{ | |
cols = Window::Width() / resolution; | |
rows = Window::Height() / resolution; | |
field.resize(cols); | |
initFieldNoize3(); | |
} | |
void initFieldNoize3() { | |
PerlinNoise noise(1234); // seed = 1234 | |
double xoff = 0.0; | |
for (int x = 0; x < cols; x++) { | |
field[x] = std::vector<Vec2>(rows); | |
double yoff = 0.0; | |
for (int y = 0; y < rows; y++) { | |
double n = noise.noise(xoff, yoff, zoff) + 1; | |
//_RPTN(_CRT_WARN, "n= %f\n", n); | |
double theta = p5h::map(n*0.5, 0.0, 1.0, 0.0, M_PI * 2); | |
field[x][y].x = cos(theta); | |
field[x][y].y = sin(theta); | |
yoff += 0.05; | |
} | |
xoff += 0.05; | |
} | |
zoff += 0.02; | |
} | |
Vec2 lookup(Vec2& src) | |
{ | |
int x = p5h::constrain((int)src.x / resolution, 0, cols - 1); | |
int y = p5h::constrain((int)src.y / resolution, 0, rows - 1); | |
return field[x][y]; | |
} | |
void display() { | |
for (int x = 0; x < cols; x++) { | |
for (int y = 0; y < rows; y++) { | |
Line(x* resolution, y* resolution, | |
x* resolution + field[x][y].x * resolution, | |
y* resolution + field[x][y].y * resolution).draw(Palette::Lightpink); | |
} | |
} | |
} | |
}; | |
struct Vehicle { | |
int mass = 1; | |
int r = 5; | |
double maxspeed = 4.0; | |
double maxforce = 0.1; | |
Vec2 position; | |
Vec2 velocity; | |
Vec2 acceleration; | |
Vehicle(): | |
position(Vec2(Random(0, Window::Width()), Random(0, Window::Height()))), | |
velocity(Vec2::Zero()), | |
acceleration(Vec2(Random(-1, 1), Random(-1, 1))) { | |
} | |
void applyForce(Vec2 force) { | |
Vec2 a = force / mass; | |
acceleration += a; | |
} | |
void follow(FlowField& flowField) { | |
Vec2 desired = flowField.lookup(position); | |
desired *= maxspeed; | |
Vec2 steer = desired - velocity; | |
p5h::limit(steer, maxforce); | |
applyForce(steer); | |
} | |
void update() { | |
velocity += acceleration; | |
position += velocity; | |
acceleration *= 0.0; | |
if (position.x < 0) { | |
position.x = Window::Width(); | |
} else if (position.x > Window::Width()) { | |
position.x = 0; | |
} | |
if (position.y < 0) { | |
position.y = Window::Height(); | |
} else if (position.y > Window::Height()) { | |
position.y = 0; | |
} | |
} | |
void display(const Texture& t) { | |
auto theta = p5h::heading(velocity) + M_PI / 2; | |
t.resize(30).rotate(theta).draw(position); | |
} | |
}; | |
void Main() | |
{ | |
Range(1, 13); | |
Window::Resize(1280, 720); | |
Graphics::SetBackground(Color(20, 20, 20)); | |
const Font font(20); | |
const Texture texture3(Emoji(L"🗻"), TextureDesc::Unmipped); | |
FlowField ff; | |
std::vector<Vehicle> vs(1000); | |
while (System::Update()) | |
{ | |
ff.initFieldNoize3(); | |
ff.display(); | |
for (auto& v : vs) { | |
v.follow(ff); | |
v.update(); | |
v.display(texture3); | |
} | |
font(L"OpenSiv3D!").drawAt(80, 20, Palette::Black); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment