add render rotation
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
Center Delay
|
||||||
|
count velocity x y theta_i theta_f color start end decayrate
|
||||||
|
===================================================
|
||||||
|
s
|
||||||
|
18000 65 0.5 0.5 0 360 cyan 1 0 0
|
||||||
|
18000 65 0.5 0.5 0 360 magenta 2.075 0 0
|
||||||
|
18000 65 0.5 0.5 0 360 yellow 4.931 0 0
|
||||||
|
5000 65 0.78127 0.5 -45 45 white 4.931 10 2
|
||||||
|
5000 65 0.21873 0.5 135 225 white 4.931 10 2
|
||||||
+3
-3
@@ -2,6 +2,6 @@ Center Delay
|
|||||||
count velocity x y theta_i theta_f color start end decayrate
|
count velocity x y theta_i theta_f color start end decayrate
|
||||||
===================================================
|
===================================================
|
||||||
s
|
s
|
||||||
20000 70 0.4 0.5 0 360 cyan 0 0 0
|
20000 68 0.5 0.5 0 360 cyan 1 0 0
|
||||||
20000 70 0.5 0.5 0 360 yellow 0 0 0
|
20000 68 0.5 0.5 0 360 magenta 2.075 0 0
|
||||||
20000 70 0.6 0.5 0 360 magenta 0 0 0
|
20000 68 0.5 0.5 0 360 yellow 4.931 0 0
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Center Delay
|
||||||
|
count velocity x y theta_i theta_f color start end decayrate
|
||||||
|
===================================================
|
||||||
|
s
|
||||||
|
20000 70 0.4 0.5 0 360 cyan 0 0 0
|
||||||
|
20000 70 0.5 0.5 0 360 yellow 0 0 0
|
||||||
|
20000 70 0.6 0.5 0 360 magenta 0 0 0
|
||||||
+8
-8
@@ -1,9 +1,9 @@
|
|||||||
Square (relative)
|
Big Diamond (relative)
|
||||||
x y (remember to dupe first entry for final entry)
|
x y
|
||||||
==================================================
|
==================
|
||||||
r
|
r
|
||||||
0.275 0.1
|
0.5 0.0
|
||||||
0.725 0.1
|
0.78125 0.5
|
||||||
0.725 0.9
|
0.5 1.0
|
||||||
0.275 0.9
|
0.21875 0.5
|
||||||
0.275 0.1
|
0.5 0.0
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ void main()
|
|||||||
|
|
||||||
vec4 color = texture(texture0, fragTexCoord) * weight[0];
|
vec4 color = texture(texture0, fragTexCoord) * weight[0];
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 5; i++) {
|
||||||
vec2 offset = texel * float(i);
|
vec2 offset = texel * float(i);
|
||||||
color += texture(texture0, fragTexCoord + offset) * weight[i];
|
color += texture(texture0, fragTexCoord + offset) * weight[i];
|
||||||
color += texture(texture0, fragTexCoord - offset) * weight[i];
|
color += texture(texture0, fragTexCoord - offset) * weight[i];
|
||||||
|
|||||||
+21
-5
@@ -16,8 +16,9 @@ int main(int argc, char* argv[]) {
|
|||||||
const int screenWidth = 1920;
|
const int screenWidth = 1920;
|
||||||
const int screenHeight = 1080;
|
const int screenHeight = 1080;
|
||||||
int rotFrame = 0;
|
int rotFrame = 0;
|
||||||
float angle = 0.05;
|
float rotSpeed = -0.1f;
|
||||||
float d_interval_pct = 0.00001;
|
float rotAngle = 0.0f;
|
||||||
|
float d_interval_pct = 0.00001f;
|
||||||
bool rotate = false;
|
bool rotate = false;
|
||||||
bool drawLines = true;
|
bool drawLines = true;
|
||||||
bool drawFPS = false;
|
bool drawFPS = false;
|
||||||
@@ -67,6 +68,8 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
int resXY = blurShader.GetLocation("resolution");
|
int resXY = blurShader.GetLocation("resolution");
|
||||||
int dirXY = blurShader.GetLocation("direction");
|
int dirXY = blurShader.GetLocation("direction");
|
||||||
|
int angleGL = rotShader.GetLocation("angle");
|
||||||
|
int resRotGL = rotShader.GetLocation("resolution");
|
||||||
float resolution[2] = { float(screenWidth), float(screenHeight)};
|
float resolution[2] = { float(screenWidth), float(screenHeight)};
|
||||||
blurShader.SetValue(resXY, resolution, RL_SHADER_UNIFORM_VEC2);
|
blurShader.SetValue(resXY, resolution, RL_SHADER_UNIFORM_VEC2);
|
||||||
noBlur.SetValue(resXY, resolution, RL_SHADER_UNIFORM_VEC2);
|
noBlur.SetValue(resXY, resolution, RL_SHADER_UNIFORM_VEC2);
|
||||||
@@ -77,14 +80,21 @@ int main(int argc, char* argv[]) {
|
|||||||
if (IsKeyPressed(KEY_R)) rotate = !rotate;
|
if (IsKeyPressed(KEY_R)) rotate = !rotate;
|
||||||
if (IsKeyPressed(KEY_L)) drawLines = !drawLines;
|
if (IsKeyPressed(KEY_L)) drawLines = !drawLines;
|
||||||
if (IsKeyPressed(KEY_F)) drawFPS = !drawFPS;
|
if (IsKeyPressed(KEY_F)) drawFPS = !drawFPS;
|
||||||
if (IsKeyPressed(KEY_D)) angle *= -1;
|
if (IsKeyPressed(KEY_D)) rotSpeed *= -1;
|
||||||
if (IsKeyPressed(KEY_B)) useShader = !useShader;
|
if (IsKeyPressed(KEY_B)) useShader = !useShader;
|
||||||
if (IsKeyPressed(KEY_SPACE)) paused = !paused;
|
if (IsKeyPressed(KEY_SPACE)) paused = !paused;
|
||||||
if (IsKeyPressed(KEY_T)) sim.reverseInterval();
|
if (IsKeyPressed(KEY_T)) sim.reverseInterval();
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
sim.updateFields(window.GetTime());
|
sim.updateFields(window.GetTime());
|
||||||
if (rotate) {
|
if (rotate) {
|
||||||
|
if (rotSpeed > 0) {
|
||||||
rotFrame++;
|
rotFrame++;
|
||||||
|
} else if (rotSpeed < 0 ) {
|
||||||
|
rotFrame--;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotAngle += rotSpeed * window.GetFrameTime();
|
||||||
|
rotAngle = std::fmod(rotAngle, 2.0f * PI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//for(const auto& item : sim.getCorners()) lines.push_back({item[0], item[1]});
|
//for(const auto& item : sim.getCorners()) lines.push_back({item[0], item[1]});
|
||||||
@@ -123,10 +133,13 @@ int main(int argc, char* argv[]) {
|
|||||||
blurShader.SetValue(dirXY, dirV, SHADER_UNIFORM_VEC2);
|
blurShader.SetValue(dirXY, dirV, SHADER_UNIFORM_VEC2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rotShader.SetValue(angleGL, &rotAngle, SHADER_UNIFORM_FLOAT);
|
||||||
|
rotShader.SetValue(resRotGL, resolution, SHADER_UNIFORM_VEC2);
|
||||||
|
|
||||||
while(window.Drawing()) {
|
while(window.Drawing()) {
|
||||||
window.ClearBackground(BLACK);
|
window.ClearBackground(BLACK);
|
||||||
|
|
||||||
//rot.BeginMode();
|
rot.BeginMode();
|
||||||
ClearBackground(BLACK);
|
ClearBackground(BLACK);
|
||||||
if (useShader) {
|
if (useShader) {
|
||||||
blurShader.BeginMode();
|
blurShader.BeginMode();
|
||||||
@@ -137,7 +150,10 @@ int main(int argc, char* argv[]) {
|
|||||||
DrawTextureRec(renderTarget.texture, {0, 0, resolution[0], -resolution[1]}, {0,0}, WHITE);
|
DrawTextureRec(renderTarget.texture, {0, 0, resolution[0], -resolution[1]}, {0,0}, WHITE);
|
||||||
//noBlur.EndMode();
|
//noBlur.EndMode();
|
||||||
}
|
}
|
||||||
//rotShader.BeginMode();
|
rot.EndMode();
|
||||||
|
rotShader.BeginMode();
|
||||||
|
DrawTextureRec(rot.texture, {0, 0, resolution[0], -resolution[1]}, {0,0}, WHITE);
|
||||||
|
rotShader.EndMode();
|
||||||
|
|
||||||
if(drawFPS) window.DrawFPS(10,10);
|
if(drawFPS) window.DrawFPS(10,10);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,563 @@
|
|||||||
|
//use floats, not doubles, for 32-bit iGPUs
|
||||||
|
|
||||||
|
#include "polypartiCL.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
#include <sycl/sycl.hpp>
|
||||||
|
#include <exception>
|
||||||
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace sycl;
|
||||||
|
|
||||||
|
struct Polyparti::ParticleField::ColCode {
|
||||||
|
std::vector<XYVector> positions, velocities;
|
||||||
|
float t, lifeTime = 0, startTime = 0;
|
||||||
|
int count, decay = 0, originCounter = 0;
|
||||||
|
int color[4];
|
||||||
|
//float decay = 1.0f;
|
||||||
|
bool dies = false, dead = false;
|
||||||
|
|
||||||
|
// allocate only one queue so we don't reinitialize every step of the calculation
|
||||||
|
static queue& q_shared() {
|
||||||
|
static queue q{gpu_selector_v, property::queue::in_order()};
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkCollisions(std::vector<XYVector> verticies) {
|
||||||
|
queue& q = q_shared();
|
||||||
|
int len_points = positions.size();
|
||||||
|
|
||||||
|
//Pointers to malloc on GPU VRAM for calculations. malloc_shared pointers are entry/exit
|
||||||
|
//point for data in CPU RAM
|
||||||
|
float *v_ptr = malloc_shared<float>(2 * len_points, q);
|
||||||
|
float *d_ptr = malloc_shared<float>(2 * len_points, q);
|
||||||
|
float *c_ptr = malloc_shared<float>(2 * len_points, q);
|
||||||
|
float *ray_ptr = malloc_device<float>(2 * len_points, q);
|
||||||
|
float *det_ptr = malloc_device<float>(len_points, q);
|
||||||
|
float *bestA_ptr = malloc_device<float>(2 * len_points, q);
|
||||||
|
float *bestSlope_ptr = malloc_device<float>(2 * len_points, q);
|
||||||
|
float *r_ptr = malloc_device<float>(len_points, q);
|
||||||
|
float *s_ptr = malloc_device<float>(len_points, q);
|
||||||
|
float *rPref_ptr = malloc_device<float>(len_points, q);
|
||||||
|
float *sPref_ptr = malloc_device<float>(len_points, q);
|
||||||
|
float *nml_ptr = malloc_device<float>(len_points * 2, q);
|
||||||
|
float *dot_ptr = malloc_device<float>(len_points, q);
|
||||||
|
|
||||||
|
float *t_ptr = malloc_shared<float>(1, q);
|
||||||
|
std::vector<float> sPrefInit(len_points, float(1000000.0f));
|
||||||
|
|
||||||
|
XYVector A, B, borderSlope;
|
||||||
|
|
||||||
|
//Copy arrays from CPU RAM to shared pointer with GPU VRAM & CPU RAM
|
||||||
|
//SYCL can only handle one memcpy per kernel
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {h.memcpy(c_ptr, &positions[0], len_points * 2 * sizeof(float)); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {h.memcpy(v_ptr, &velocities[0], len_points * 2 * sizeof(float));});
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {h.memcpy(sPref_ptr, &sPrefInit[0], len_points * sizeof(float)); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) { h.memcpy(t_ptr, &t, sizeof(float)); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
|
||||||
|
//Calculate expected location of each particle after imminent time step, and vectorize the
|
||||||
|
//difference <dx, dy> from the current position. We will use Cramer's Rule with the
|
||||||
|
//vectorized boundary, also <dx, dy>, to check intersection
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {
|
||||||
|
h.parallel_for(len_points * 2, [=](id<1> i) {
|
||||||
|
d_ptr[i] = v_ptr[i] * *t_ptr + c_ptr[i];
|
||||||
|
ray_ptr[i] = d_ptr[i] - c_ptr[i];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
//Iterate over each room boundary in terms of their endpoints. Note that iterative and
|
||||||
|
//parallel computing concepts can work in tandem, with the next kernel executed
|
||||||
|
//sychronously within the for loop
|
||||||
|
|
||||||
|
for (int i = 1; i < verticies.size(); i++) {
|
||||||
|
A = verticies[i-1], B = verticies[i];
|
||||||
|
borderSlope[0] = B[0] - A[0];
|
||||||
|
borderSlope[1] = B[1] - A[1];
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {
|
||||||
|
h.parallel_for(len_points, [=](id<1> i) {
|
||||||
|
//Calculate determinant of 2x2 matrix of both vectors
|
||||||
|
det_ptr[i] = borderSlope[0] * ray_ptr[(i*2) + 1] - borderSlope[1] * ray_ptr[(i*2)];
|
||||||
|
if (fabs(det_ptr[i]) > float(1e-5) * hypot(borderSlope[0], borderSlope[1]) * hypot(ray_ptr[i*2], ray_ptr[(i*2) + 1])) {
|
||||||
|
//
|
||||||
|
r_ptr[i] = ((c_ptr[i*2] - A[0]) * ray_ptr[(i*2)+1] - (c_ptr[(2*i)+1] - A[1]) * ray_ptr[i*2]) / det_ptr[i];
|
||||||
|
s_ptr[i] = ((c_ptr[i*2] - A[0]) * borderSlope[1] - (c_ptr[(i*2) + 1] - A[1]) * borderSlope[0]) / det_ptr[i];
|
||||||
|
} else {
|
||||||
|
r_ptr[i] = float(-1.0f);
|
||||||
|
s_ptr[i] = float(-1.0f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {
|
||||||
|
h.parallel_for(len_points, [=](id<1> i) {
|
||||||
|
if (r_ptr[i] >= float(0.0) && r_ptr[i] <= float(1.0)
|
||||||
|
&& s_ptr[i] >= float(0.0) && s_ptr[i] <= float(1.0)) {
|
||||||
|
if (s_ptr[i] < sPref_ptr[i]) {
|
||||||
|
sPref_ptr[i] = s_ptr[i];
|
||||||
|
rPref_ptr[i] = r_ptr[i];
|
||||||
|
bestA_ptr[i*2] = A[0];
|
||||||
|
bestA_ptr[(i*2) + 1] = A[1];
|
||||||
|
bestSlope_ptr[i*2] = borderSlope[0];
|
||||||
|
bestSlope_ptr[(i*2) + 1] = borderSlope[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
q.wait();
|
||||||
|
}
|
||||||
|
q.submit([&](handler& h) {
|
||||||
|
h.parallel_for(len_points, [=](id<1> i) {
|
||||||
|
if (sPref_ptr[i] < float(1000000.0f)) {
|
||||||
|
nml_ptr[(i*2)] = (-1 * bestSlope_ptr[(i*2) + 1]) / hypot(bestSlope_ptr[i*2], bestSlope_ptr[(i*2) + 1]);
|
||||||
|
nml_ptr[(i*2) + 1] = bestSlope_ptr[i*2] / hypot(bestSlope_ptr[i*2], bestSlope_ptr[(i*2) + 1]);
|
||||||
|
|
||||||
|
dot_ptr[i] = (nml_ptr[i*2] * v_ptr[i*2]) + (nml_ptr[(i*2) + 1] * v_ptr[(i*2) + 1]);
|
||||||
|
|
||||||
|
if (dot_ptr[i] > 0) {
|
||||||
|
nml_ptr[i*2] = nml_ptr[i*2] * -1;
|
||||||
|
nml_ptr[(i*2) + 1] = nml_ptr[(i*2) + 1] * -1;
|
||||||
|
dot_ptr[i] *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
v_ptr[i*2] -= 2 * dot_ptr[i] * nml_ptr[i*2];
|
||||||
|
v_ptr[(i*2) + 1] -= 2 * dot_ptr[i] * nml_ptr[(i*2) + 1];
|
||||||
|
|
||||||
|
c_ptr[i*2] = bestA_ptr[i*2] + (rPref_ptr[i] * bestSlope_ptr[i*2]);
|
||||||
|
c_ptr[(i*2) + 1] = bestA_ptr[(i*2) + 1] + (rPref_ptr[i] * bestSlope_ptr[(i*2) + 1]);
|
||||||
|
|
||||||
|
c_ptr[i*2] -= nml_ptr[i*2] * 1e-4f;
|
||||||
|
c_ptr[(i*2) + 1] -= nml_ptr[(i*2) + 1] * 1e-4f;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
//Get the computed data back into pointers we can use
|
||||||
|
q.submit([&](handler& h) {h.memcpy(&positions[0], c_ptr, len_points * 2 * sizeof(float));});
|
||||||
|
q.submit([&](handler& h) {h.memcpy(&velocities[0], v_ptr, len_points * 2 * sizeof(float));});
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
free(c_ptr, q);
|
||||||
|
free(d_ptr, q);
|
||||||
|
free(v_ptr, q);
|
||||||
|
free(ray_ptr, q);
|
||||||
|
free(det_ptr, q);
|
||||||
|
free(bestA_ptr, q);
|
||||||
|
free(bestSlope_ptr, q);
|
||||||
|
free(r_ptr, q);
|
||||||
|
free(s_ptr, q);
|
||||||
|
free(rPref_ptr, q);
|
||||||
|
free(sPref_ptr, q);
|
||||||
|
free(nml_ptr, q);
|
||||||
|
free(dot_ptr, q);
|
||||||
|
free(t_ptr,q);
|
||||||
|
|
||||||
|
}
|
||||||
|
void moveParticles() {
|
||||||
|
queue& q = q_shared();
|
||||||
|
int len = positions.size();
|
||||||
|
float *v_ptr = malloc_shared<float>(2 * len, q);
|
||||||
|
float *p_ptr = malloc_shared<float>(2 * len, q);
|
||||||
|
float *t_ptr = malloc_shared<float>(1, q);
|
||||||
|
|
||||||
|
q.submit([&](handler& h) {
|
||||||
|
h.memcpy(p_ptr, &positions[0], len * 2 * sizeof(float));
|
||||||
|
});
|
||||||
|
q.wait();
|
||||||
|
q.submit([&](handler& h) { h.memcpy(v_ptr, &velocities[0], len * 2 * sizeof(float)); } );
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) { h.memcpy(t_ptr, &t, sizeof(float)); } );
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) { h.parallel_for(len * 2, [=](id<1> i) {
|
||||||
|
p_ptr[i] += v_ptr[i] * *t_ptr;
|
||||||
|
}); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) { h.memcpy(&positions[0], p_ptr, len * 2 * sizeof(float)); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
q.submit([&](handler& h) { h.memcpy(&velocities[0], v_ptr, len * 2 * sizeof(float)); });
|
||||||
|
q.wait();
|
||||||
|
|
||||||
|
free(p_ptr, q);
|
||||||
|
free(v_ptr, q);
|
||||||
|
free(t_ptr, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Polyparti::ParticleField::ParticleField() : colcode(std::make_unique<ColCode>()) { }
|
||||||
|
Polyparti::ParticleField::~ParticleField() = default;
|
||||||
|
Polyparti::ParticleField::ParticleField(const ParticleField& other)
|
||||||
|
: colcode(std::make_unique<ColCode>(*other.colcode)) {}
|
||||||
|
Polyparti::ParticleField::ParticleField(ParticleField&&) noexcept = default;
|
||||||
|
Polyparti::ParticleField& Polyparti::ParticleField::operator=(ParticleField&& other) noexcept = default;
|
||||||
|
Polyparti::ParticleField& Polyparti::ParticleField::operator=(const ParticleField& other) {
|
||||||
|
if (this != &other) { *colcode = *other.colcode; }
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::addParticle(float x, float y, float vx, float vy) {
|
||||||
|
colcode->positions.push_back({x, y});
|
||||||
|
colcode->velocities.push_back({vx, vy});
|
||||||
|
colcode->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::deleteParticle(int index) {
|
||||||
|
colcode->positions.erase(colcode->positions.begin() + index);
|
||||||
|
colcode->velocities.erase(colcode->velocities.begin() + index);
|
||||||
|
colcode->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::updateField(std::vector<XYVector> verticies, double time) {
|
||||||
|
if(colcode->t > 0) {
|
||||||
|
++colcode->originCounter;
|
||||||
|
} else if (colcode->t < 0) {
|
||||||
|
--colcode->originCounter;
|
||||||
|
}
|
||||||
|
if (colcode->dies) {
|
||||||
|
if (time >= colcode->lifeTime) {
|
||||||
|
colcode->color[3] -= colcode->decay;
|
||||||
|
}
|
||||||
|
if (colcode->color[3] <= 0) {
|
||||||
|
colcode->dead = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(colcode->originCounter >= 0) {
|
||||||
|
colcode->checkCollisions(verticies);
|
||||||
|
colcode->moveParticles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<XYVector>& Polyparti::ParticleField::getPositions() const {
|
||||||
|
return colcode->positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<XYVector>& Polyparti::ParticleField::getVelocities() const {
|
||||||
|
return colcode->velocities;
|
||||||
|
}
|
||||||
|
int Polyparti::ParticleField::getSize() {
|
||||||
|
return colcode->positions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::setColor(std::string newColor) {
|
||||||
|
colcode->color[3] = 255;
|
||||||
|
if (newColor == "red" ) {
|
||||||
|
colcode->color[0] = 255;
|
||||||
|
colcode->color[1] = 0;
|
||||||
|
colcode->color[2] = 0;
|
||||||
|
} else if (newColor == "orange") {
|
||||||
|
colcode->color[0] = 255;
|
||||||
|
colcode->color[1] = 127;
|
||||||
|
colcode->color[2] = 0;
|
||||||
|
} else if (newColor == "yellow") {
|
||||||
|
colcode->color[0] = 255;
|
||||||
|
colcode->color[1] = 255;
|
||||||
|
colcode->color[2] = 0;
|
||||||
|
} else if (newColor == "green") {
|
||||||
|
colcode->color[0] = 0;
|
||||||
|
colcode->color[1] = 255;
|
||||||
|
colcode->color[2] = 0;
|
||||||
|
} else if (newColor == "blue") {
|
||||||
|
colcode->color[0] = 0;
|
||||||
|
colcode->color[1] = 0;
|
||||||
|
colcode->color[2] = 255;
|
||||||
|
} else if (newColor == "indigo") {
|
||||||
|
colcode->color[0] = 31;
|
||||||
|
colcode->color[1] = 0;
|
||||||
|
colcode->color[2] = 127;
|
||||||
|
} else if (newColor == "violet") {
|
||||||
|
colcode->color[0] = 127;
|
||||||
|
colcode->color[1] = 0;
|
||||||
|
colcode->color[2] = 127;
|
||||||
|
} else if (newColor == "cyan") {
|
||||||
|
colcode->color[0] = 0;
|
||||||
|
colcode->color[1] = 255;
|
||||||
|
colcode->color[2] = 255;
|
||||||
|
} else if (newColor == "darkgreen") {
|
||||||
|
colcode->color[0] = 0;
|
||||||
|
colcode->color[1] = 127;
|
||||||
|
colcode->color[2] = 0;
|
||||||
|
} else if (newColor == "magenta") {
|
||||||
|
colcode->color[0] = 255;
|
||||||
|
colcode->color[1] = 0;
|
||||||
|
colcode->color[2] = 255;
|
||||||
|
} else {
|
||||||
|
colcode->color[0] = 255;
|
||||||
|
colcode->color[1] = 255;
|
||||||
|
colcode->color[2] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int* Polyparti::ParticleField::getColor() {
|
||||||
|
return colcode->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Polyparti::ParticleField::getCount() {
|
||||||
|
return colcode->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::setInterval(const float interval) {
|
||||||
|
colcode->t = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::ParticleField::setDecay(const float t, const float d) {
|
||||||
|
if (t != 0) {
|
||||||
|
colcode->dies = true;
|
||||||
|
colcode->lifeTime = t;
|
||||||
|
colcode->decay = static_cast<int>(fabs(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Polyparti::ParticleField::isDead() {
|
||||||
|
return colcode->dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Polyparti::ParticleField::willDie() {
|
||||||
|
return colcode->dies;
|
||||||
|
}
|
||||||
|
struct Polyparti::Room::ImplRoom {
|
||||||
|
std::vector<XYVector> corners;
|
||||||
|
XYVector midpoint;
|
||||||
|
// std::vector<ParticleField> field;
|
||||||
|
};
|
||||||
|
Polyparti::Room::Room() : implRoom(std::make_unique<ImplRoom>()) {}
|
||||||
|
|
||||||
|
Polyparti::Room::Room(int w, int h) : Room() { screenWidth = w; screenHeight = h;}
|
||||||
|
|
||||||
|
Polyparti::Room::Room(int w, int h, int fps) : Room() {
|
||||||
|
screenWidth = w;
|
||||||
|
screenHeight = h;
|
||||||
|
interval = 1.0f/fps;
|
||||||
|
}
|
||||||
|
Polyparti::Room::~Room() = default;
|
||||||
|
Polyparti::Room::Room(const Room& other)
|
||||||
|
: implRoom(std::make_unique<ImplRoom>(*other.implRoom)),
|
||||||
|
info(other.info),
|
||||||
|
field(other.field),
|
||||||
|
x_min(other.x_min),
|
||||||
|
x_max(other.x_max),
|
||||||
|
y_min(other.y_min),
|
||||||
|
y_max(other.y_max){}
|
||||||
|
Polyparti::Room::Room(Room&& other) noexcept = default;
|
||||||
|
Polyparti::Room& Polyparti::Room::operator=(const Room& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
*implRoom = *other.implRoom;
|
||||||
|
info = other.info;
|
||||||
|
field = other.field;
|
||||||
|
x_min = other.x_min;
|
||||||
|
x_max = other.x_max;
|
||||||
|
y_min = other.y_min;
|
||||||
|
y_max = other.y_max;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Polyparti::Room& Polyparti::Room::operator=(Room&& other) noexcept = default;
|
||||||
|
|
||||||
|
|
||||||
|
void Polyparti::Room::addCorner(float x, float y) { implRoom->corners.push_back({x,y}); }
|
||||||
|
|
||||||
|
void Polyparti::Room::checkCorners() {
|
||||||
|
if (implRoom->corners.front() != implRoom->corners.back()) { implRoom->corners.push_back(implRoom->corners.front()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<XYVector> Polyparti::Room::getCorners() {
|
||||||
|
return implRoom->corners;
|
||||||
|
}
|
||||||
|
void Polyparti::Room::loadRoom(std::string name) {
|
||||||
|
std::ifstream roomfile;
|
||||||
|
std::string roomName, temp;
|
||||||
|
bool relative = false;
|
||||||
|
float a, b, tot_x = 0, tot_y = 0;
|
||||||
|
int n = 0;
|
||||||
|
char check;
|
||||||
|
roomfile.open(name);
|
||||||
|
if (roomfile.is_open()) {
|
||||||
|
getline(roomfile, roomName);
|
||||||
|
getline(roomfile, temp);
|
||||||
|
getline(roomfile, temp);
|
||||||
|
check = roomfile.get();
|
||||||
|
this->name = roomName;
|
||||||
|
}
|
||||||
|
else { std::cout << "error" << std::endl;}
|
||||||
|
|
||||||
|
x_min = screenHeight;
|
||||||
|
y_min = screenWidth;
|
||||||
|
|
||||||
|
if (check == 'r') { relative = true; }
|
||||||
|
|
||||||
|
if (roomfile.is_open()) {
|
||||||
|
while (roomfile >> a >> b) {
|
||||||
|
if (relative) { a *= screenWidth; b *= screenHeight; }
|
||||||
|
addCorner(a,b);
|
||||||
|
tot_x += a;
|
||||||
|
tot_y += b;
|
||||||
|
n++;
|
||||||
|
|
||||||
|
if ( a > x_max) {x_max = a;}
|
||||||
|
if ( a < x_min) {x_min = a;}
|
||||||
|
if ( b > y_max) {y_max = b;}
|
||||||
|
if ( b < y_min) {y_min = b;}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "error: rooms/load.room not found" << '\n';
|
||||||
|
}
|
||||||
|
checkCorners();
|
||||||
|
roomfile.close();
|
||||||
|
|
||||||
|
implRoom->midpoint[0] = tot_x / n;
|
||||||
|
implRoom->midpoint[1] = tot_y / n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::Room::loadParticles(std::string name) {
|
||||||
|
fieldInfo newEntry;
|
||||||
|
std::ifstream partfile(name);
|
||||||
|
bool relativeScreen = false;
|
||||||
|
bool relativeRoom = false;
|
||||||
|
int count;
|
||||||
|
float velocity, x, y, deg_start, deg_end, start, life, decay;
|
||||||
|
std::string color, partName, temp;
|
||||||
|
|
||||||
|
getline(partfile, partName);
|
||||||
|
getline(partfile, temp);
|
||||||
|
getline(partfile, temp);
|
||||||
|
|
||||||
|
char check = partfile.get();
|
||||||
|
if (check =='s') { relativeScreen = true;}
|
||||||
|
else if (check == 'r') { relativeRoom = true; }
|
||||||
|
|
||||||
|
if (partfile.is_open()) {
|
||||||
|
while (partfile >> count >> velocity >> x >> y >> deg_start >> deg_end >> color >> start
|
||||||
|
>> life >> decay) {
|
||||||
|
if (relativeScreen) {
|
||||||
|
x *= screenWidth;
|
||||||
|
y *= screenHeight;
|
||||||
|
} else if (relativeRoom) {
|
||||||
|
x = implRoom->midpoint[0] + (x * (x_max - x_min) / 2);
|
||||||
|
y = implRoom->midpoint[1] + (y * (y_max - y_min) / 2);
|
||||||
|
}
|
||||||
|
newEntry.count = count;
|
||||||
|
newEntry.velocity = velocity;
|
||||||
|
newEntry.x = x;
|
||||||
|
newEntry.y = y;
|
||||||
|
newEntry.deg_start = deg_start;
|
||||||
|
newEntry.deg_end = deg_end;
|
||||||
|
newEntry.color = color;
|
||||||
|
newEntry.start = start;
|
||||||
|
newEntry.life = life;
|
||||||
|
newEntry.decayRate = decay;
|
||||||
|
|
||||||
|
if (start == 0) { this->info.push_back(newEntry); }
|
||||||
|
else {
|
||||||
|
++moreCount;
|
||||||
|
this->later.push_back(newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort later fields by descending order so they can be popped_back
|
||||||
|
std::sort(later.begin(), later.end(),
|
||||||
|
[] (const fieldInfo& a, const fieldInfo& b) { return a.start > b.start; });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "error: particles/load.prtc not found" << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void Polyparti::Room::initField(Polyparti::Room::fieldInfo info) {
|
||||||
|
ParticleField newField;
|
||||||
|
double rad = 4 * std::acos(0.0);
|
||||||
|
int passCount;
|
||||||
|
bool finalPass = false;
|
||||||
|
info.deg_start = (info.deg_start / 360) * rad;
|
||||||
|
info.deg_end = (info.deg_end/360) * rad;
|
||||||
|
|
||||||
|
newField.setColor(info.color);
|
||||||
|
newField.setInterval(interval);
|
||||||
|
newField.setDecay(info.life, info.decayRate);
|
||||||
|
|
||||||
|
for (int i = 0; i < passCount; i++) {
|
||||||
|
double angle = (float(i) / passCount) * (info.deg_end - info.deg_start);
|
||||||
|
newField.addParticle(info.x, info.y, info.velocity * (std::cos(angle + info.deg_start)), info.velocity * -(std::sin(angle + info.deg_start)));
|
||||||
|
}
|
||||||
|
|
||||||
|
field.push_back(std::move(newField));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::Room::rotateRoom(float degrees) {
|
||||||
|
float rad = (degrees / 360) * 4 * std::acos(0.0);
|
||||||
|
|
||||||
|
for (auto& point : implRoom->corners) {
|
||||||
|
float temp = point[0];
|
||||||
|
point[0] = ((temp - implRoom->midpoint[0]) * std::cos(rad) - (point[1] - (implRoom->midpoint[1])) * std::sin(rad));
|
||||||
|
point[1] = ((temp - implRoom->midpoint[0]) * std::sin(rad) + (point[1] - (implRoom->midpoint[1])) * std::cos(rad));
|
||||||
|
point[0] += implRoom->midpoint[0];
|
||||||
|
point[1] += implRoom->midpoint[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::Room::addFields() {
|
||||||
|
for (auto& i: info) initField(i);
|
||||||
|
|
||||||
|
/*for (auto& f: field) {
|
||||||
|
if (!f.willDie()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::Room::updateFields(double time) {
|
||||||
|
while (moreCount && later.back().start <= time) {
|
||||||
|
initField(later.back());
|
||||||
|
later.pop_back();
|
||||||
|
--moreCount;
|
||||||
|
}
|
||||||
|
for (auto& f : field) {
|
||||||
|
f.updateField(implRoom->corners, time);
|
||||||
|
}
|
||||||
|
field.erase(std::remove_if(field.begin(), field.end(), [](auto& f) { return f.isDead();}), field.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Polyparti::ParticleField& Polyparti::Room::getField(int index) { return field.at(index); }
|
||||||
|
|
||||||
|
void Polyparti::Room::adjustInterval(const float diff) {
|
||||||
|
//float diff = 1.0 + pct;
|
||||||
|
interval += diff;
|
||||||
|
for (auto &f : field) {
|
||||||
|
f.setInterval(diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polyparti::Room::reverseInterval() {
|
||||||
|
interval = -interval;
|
||||||
|
for (auto &f : field) {
|
||||||
|
f.setInterval(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int Polyparti::Room::getFieldCount() {
|
||||||
|
return field.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Polyparti::Room::getName() {
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user