mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 07:58:59 +02:00
Cleaning up particle code
This commit is contained in:
parent
bcb3e082f6
commit
58d6c4c97a
7 changed files with 55 additions and 108 deletions
|
@ -1988,7 +1988,9 @@ void Application::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate particle cloud movements
|
// Simulate particle cloud movements
|
||||||
_cloud.simulate(deltaTime);
|
if (Menu::getInstance()->isOptionChecked(MenuOption::ParticleCloud)) {
|
||||||
|
_cloud.simulate(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
// no transmitter drive implies transmitter pick
|
// no transmitter drive implies transmitter pick
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) {
|
||||||
|
@ -2508,8 +2510,9 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
//renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude());
|
//renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude());
|
||||||
}
|
}
|
||||||
// Draw Cloud Particles
|
// Draw Cloud Particles
|
||||||
_cloud.render();
|
if (Menu::getInstance()->isOptionChecked(MenuOption::ParticleCloud)) {
|
||||||
|
_cloud.render();
|
||||||
|
}
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
|
|
|
@ -20,12 +20,12 @@ const int NUM_PARTICLES = 20000;
|
||||||
Cloud::Cloud() {
|
Cloud::Cloud() {
|
||||||
// Create and initialize particles
|
// Create and initialize particles
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
glm::vec3 box = glm::vec3(WORLD_SIZE);
|
glm::vec3 box = glm::vec3(PARTICLE_WORLD_SIZE);
|
||||||
bounds = box;
|
bounds = box;
|
||||||
count = NUM_PARTICLES;
|
count = NUM_PARTICLES;
|
||||||
wrapBounds = false;
|
wrapBounds = false;
|
||||||
particles = new Particle[count];
|
particles = new Particle[count];
|
||||||
field = new Field();
|
field = new Field(PARTICLE_WORLD_SIZE);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
float x = randFloat()*box.x;
|
float x = randFloat()*box.x;
|
||||||
|
@ -37,12 +37,12 @@ Cloud::Cloud() {
|
||||||
|
|
||||||
const float INIT_VEL_SCALE = 0.10;
|
const float INIT_VEL_SCALE = 0.10;
|
||||||
particles[i].velocity = randVector();
|
particles[i].velocity = randVector();
|
||||||
particles[i].velocity *= WORLD_SIZE * INIT_VEL_SCALE;
|
particles[i].velocity *= PARTICLE_WORLD_SIZE * INIT_VEL_SCALE;
|
||||||
|
|
||||||
float color_mult = 1 - COLOR_MIN;
|
float color_mult = 1 - COLOR_MIN;
|
||||||
particles[i].color = glm::vec3(x*color_mult/WORLD_SIZE + COLOR_MIN,
|
particles[i].color = glm::vec3(x*color_mult/PARTICLE_WORLD_SIZE + COLOR_MIN,
|
||||||
y*color_mult/WORLD_SIZE + COLOR_MIN,
|
y*color_mult/PARTICLE_WORLD_SIZE + COLOR_MIN,
|
||||||
z*color_mult/WORLD_SIZE + COLOR_MIN);
|
z*color_mult/PARTICLE_WORLD_SIZE + COLOR_MIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "Field.h"
|
#include "Field.h"
|
||||||
|
|
||||||
|
#define PARTICLE_WORLD_SIZE 128.0
|
||||||
|
|
||||||
class Cloud {
|
class Cloud {
|
||||||
public:
|
public:
|
||||||
Cloud();
|
Cloud();
|
||||||
|
|
|
@ -9,13 +9,9 @@
|
||||||
#include "Field.h"
|
#include "Field.h"
|
||||||
|
|
||||||
#define FIELD_SCALE 0.00050
|
#define FIELD_SCALE 0.00050
|
||||||
#define FIELD_SCALEf 0.1f
|
|
||||||
#define COLOR_DRIFT_RATE 0.001f // per-frame drift of particle color towards field element color
|
#define COLOR_DRIFT_RATE 0.001f // per-frame drift of particle color towards field element color
|
||||||
#define COLOR_MIN 0.2f // minimum R/G/B value at 0,0,0 - also needs setting in cloud.cpp
|
#define COLOR_MIN 0.2f // minimum R/G/B value at 0,0,0 - also needs setting in cloud.cpp
|
||||||
|
|
||||||
#define USE_SCALAR 0
|
|
||||||
|
|
||||||
#define WORLD_SIZE 100.0
|
|
||||||
|
|
||||||
// A vector-valued field over an array of elements arranged as a 3D lattice
|
// A vector-valued field over an array of elements arranged as a 3D lattice
|
||||||
|
|
||||||
|
@ -23,9 +19,10 @@ int Field::value(float *value, float *pos)
|
||||||
// sets the vector value (3 floats) to field value at location pos in space.
|
// sets the vector value (3 floats) to field value at location pos in space.
|
||||||
// returns zero if the location is outside world bounds
|
// returns zero if the location is outside world bounds
|
||||||
{
|
{
|
||||||
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
|
int index = (int)(pos[0] / _worldSize * 10.0) +
|
||||||
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
|
(int)(pos[1] / _worldSize * 10.0) * 10 +
|
||||||
(int)(pos[2]/WORLD_SIZE*10.0)*100;
|
(int)(pos[2] / _worldSize * 10.0) * 100;
|
||||||
|
|
||||||
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
||||||
{
|
{
|
||||||
value[0] = field[index].val.x;
|
value[0] = field[index].val.x;
|
||||||
|
@ -36,24 +33,25 @@ int Field::value(float *value, float *pos)
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field::Field()
|
Field::Field(float worldSize)
|
||||||
// Initializes the field to some random values
|
// Initializes the field to some random values
|
||||||
{
|
{
|
||||||
|
_worldSize = worldSize;
|
||||||
int i;
|
int i;
|
||||||
float fx, fy, fz;
|
float fx, fy, fz;
|
||||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||||
{
|
{
|
||||||
field[i].val.x = (randFloat() - 0.5f)*FIELD_SCALEf * WORLD_SIZE;
|
const float FIELD_INITIAL_MAG = 0.3f;
|
||||||
field[i].val.y = (randFloat() - 0.5f)*FIELD_SCALEf * WORLD_SIZE;
|
field[i].val = randVector() * FIELD_INITIAL_MAG * _worldSize;
|
||||||
field[i].val.z = (randFloat() - 0.5f)*FIELD_SCALEf * WORLD_SIZE;
|
|
||||||
field[i].scalar = 0;
|
field[i].scalar = 0;
|
||||||
// Record center point for this field cell
|
// Record center point for this field cell
|
||||||
fx = static_cast<float>(i % 10);
|
fx = static_cast<float>(i % 10);
|
||||||
fy = static_cast<float>(i%100 / 10);
|
fy = static_cast<float>(i % 100 / 10);
|
||||||
fz = static_cast<float>(i / 100);
|
fz = static_cast<float>(i / 100);
|
||||||
field[i].center.x = fx + 0.5f;
|
field[i].center.x = (fx + 0.5f);
|
||||||
field[i].center.y = fy + 0.5f;
|
field[i].center.y = (fy + 0.5f);
|
||||||
field[i].center.z = fz + 0.5f;
|
field[i].center.z = (fz + 0.5f);
|
||||||
|
field[i].center *= _worldSize / 10.f;
|
||||||
|
|
||||||
// and set up the RGB values for each field element.
|
// and set up the RGB values for each field element.
|
||||||
float color_mult = 1 - COLOR_MIN;
|
float color_mult = 1 - COLOR_MIN;
|
||||||
|
@ -66,9 +64,10 @@ Field::Field()
|
||||||
void Field::add(float* add, float *pos)
|
void Field::add(float* add, float *pos)
|
||||||
// At location loc, add vector add to the field values
|
// At location loc, add vector add to the field values
|
||||||
{
|
{
|
||||||
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
|
int index = (int)(pos[0] / _worldSize * 10.0) +
|
||||||
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
|
(int)(pos[1] / _worldSize * 10.0)*10 +
|
||||||
(int)(pos[2]/WORLD_SIZE*10.0)*100;
|
(int)(pos[2] / _worldSize * 10.0)*100;
|
||||||
|
|
||||||
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
if ((index >= 0) && (index < FIELD_ELEMENTS))
|
||||||
{
|
{
|
||||||
field[index].val.x += add[0];
|
field[index].val.x += add[0];
|
||||||
|
@ -79,9 +78,9 @@ void Field::add(float* add, float *pos)
|
||||||
|
|
||||||
void Field::interact(float dt, glm::vec3 * pos, glm::vec3 * vel, glm::vec3 * color, float coupling) {
|
void Field::interact(float dt, glm::vec3 * pos, glm::vec3 * vel, glm::vec3 * color, float coupling) {
|
||||||
|
|
||||||
int index = (int)(pos->x/WORLD_SIZE*10.0) +
|
int index = (int)(pos->x/ _worldSize * 10.0) +
|
||||||
(int)(pos->y/WORLD_SIZE*10.0)*10 +
|
(int)(pos->y/_worldSize*10.0)*10 +
|
||||||
(int)(pos->z/WORLD_SIZE*10.0)*100;
|
(int)(pos->z/_worldSize*10.0)*100;
|
||||||
if ((index >= 0) && (index < FIELD_ELEMENTS)) {
|
if ((index >= 0) && (index < FIELD_ELEMENTS)) {
|
||||||
//
|
//
|
||||||
// Vector Coupling with particle velocity
|
// Vector Coupling with particle velocity
|
||||||
|
@ -95,13 +94,6 @@ void Field::interact(float dt, glm::vec3 * pos, glm::vec3 * vel, glm::vec3 * col
|
||||||
// Scalar coupling: Damp particle as function of local density
|
// Scalar coupling: Damp particle as function of local density
|
||||||
//
|
//
|
||||||
|
|
||||||
if (USE_SCALAR) {
|
|
||||||
//*vel *= (1.f + field[index].scalar*0.01*dt);
|
|
||||||
const float SCALAR_PARTICLE_ADD = 1.0;
|
|
||||||
field[index].scalar += SCALAR_PARTICLE_ADD*dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// add a fraction of the field color to the particle color
|
// add a fraction of the field color to the particle color
|
||||||
//*color = (*color * (1 - COLOR_DRIFT_RATE)) + (fieldcolors[index].rgb * COLOR_DRIFT_RATE);
|
//*color = (*color * (1 - COLOR_DRIFT_RATE)) + (fieldcolors[index].rgb * COLOR_DRIFT_RATE);
|
||||||
}
|
}
|
||||||
|
@ -134,80 +126,31 @@ void Field::avg_neighbors(int index, glm::vec3 * result) {
|
||||||
|
|
||||||
void Field::simulate(float dt) {
|
void Field::simulate(float dt) {
|
||||||
glm::vec3 neighbors, add, diff;
|
glm::vec3 neighbors, add, diff;
|
||||||
float size, distance;
|
|
||||||
int i, j;
|
for (int i = 0; i < FIELD_ELEMENTS; i++)
|
||||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
|
||||||
{
|
{
|
||||||
if (0) { //(randFloat() > 0.01) {
|
const float CONSTANT_DAMPING = 0.5;
|
||||||
avg_neighbors(i, &neighbors);
|
const float CONSTANT_SCALAR_DAMPING = 2.5;
|
||||||
size = powf(field[i].val.x*field[i].val.x +
|
field[i].val *= (1.f - CONSTANT_DAMPING*dt);
|
||||||
field[i].val.y*field[i].val.y +
|
field[i].scalar *= (1.f - CONSTANT_SCALAR_DAMPING*dt);
|
||||||
field[i].val.z*field[i].val.z, 0.5);
|
}
|
||||||
|
|
||||||
neighbors *= 0.0001;
|
|
||||||
field[i].val = glm::normalize(field[i].val);
|
|
||||||
field[i].val *= size * 0.99;
|
|
||||||
add = glm::normalize(neighbors);
|
|
||||||
add *= size * 0.01;
|
|
||||||
field[i].val += add;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const float CONSTANT_DAMPING = 0.5;
|
|
||||||
const float CONSTANT_SCALAR_DAMPING = 2.5;
|
|
||||||
field[i].val *= (1.f - CONSTANT_DAMPING*dt);
|
|
||||||
field[i].scalar *= (1.f - CONSTANT_SCALAR_DAMPING*dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (USE_SCALAR) {
|
|
||||||
//
|
|
||||||
// Compute a field value from sum of all other field values (electrostatics, etc)
|
|
||||||
//
|
|
||||||
field[i].fld.x = field[i].fld.y = field[i].fld.z = 0;
|
|
||||||
for (j = 0; j < FIELD_ELEMENTS; j++)
|
|
||||||
{
|
|
||||||
if (i != j) {
|
|
||||||
// Compute vector field from scalar densities
|
|
||||||
diff = field[j].center - field[i].center;
|
|
||||||
distance = glm::length(diff);
|
|
||||||
diff = glm::normalize(diff);
|
|
||||||
field[i].fld += diff*field[j].scalar*(1/distance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field::render()
|
void Field::render()
|
||||||
// Render the field lines
|
// Render the field lines
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float fx, fy, fz;
|
float scale_view = 0.05f * _worldSize;
|
||||||
float scale_view = 0.1f * WORLD_SIZE;
|
|
||||||
|
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||||
{
|
{
|
||||||
fx = field[i].center.x * WORLD_SIZE;
|
|
||||||
fy = field[i].center.y * WORLD_SIZE;
|
|
||||||
fz = field[i].center.z * WORLD_SIZE;
|
|
||||||
|
|
||||||
glColor3f(0, 1, 0);
|
glColor3f(0, 1, 0);
|
||||||
glVertex3f(fx, fy, fz);
|
glVertex3fv(&field[i].center.x);
|
||||||
glVertex3f(fx + field[i].val.x * scale_view,
|
glVertex3f(field[i].center.x + field[i].val.x * scale_view,
|
||||||
fy + field[i].val.y * scale_view,
|
field[i].center.y + field[i].val.y * scale_view,
|
||||||
fz + field[i].val.z * scale_view);
|
field[i].center.z + field[i].val.z * scale_view);
|
||||||
if (USE_SCALAR) {
|
|
||||||
glColor3f(1, 0, 0);
|
|
||||||
glVertex3f(fx, fy, fz);
|
|
||||||
glVertex3f(fx, fy+field[i].scalar*0.01f, fz);
|
|
||||||
glColor3f(1, 1, 0);
|
|
||||||
glVertex3f(fx, fy, fz);
|
|
||||||
glVertex3f(fx + field[i].fld.x*0.0001f,
|
|
||||||
fy + field[i].fld.y*0.0001f,
|
|
||||||
fz + field[i].fld.z*0.0001f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
|
@ -215,14 +158,9 @@ void Field::render()
|
||||||
glPointSize(4.0);
|
glPointSize(4.0);
|
||||||
glEnable(GL_POINT_SMOOTH);
|
glEnable(GL_POINT_SMOOTH);
|
||||||
glBegin(GL_POINTS);
|
glBegin(GL_POINTS);
|
||||||
|
|
||||||
for (i = 0; i < FIELD_ELEMENTS; i++)
|
for (i = 0; i < FIELD_ELEMENTS; i++)
|
||||||
{
|
{
|
||||||
fx = static_cast<float>(i % 10);
|
glVertex3fv(&field[i].center.x);
|
||||||
fy = static_cast<float>(i%100 / 10);
|
|
||||||
fz = static_cast<float>(i / 100);
|
|
||||||
|
|
||||||
glVertex3f(fx / 10.f * WORLD_SIZE, fy / 10.f * WORLD_SIZE, fz / 10.f * WORLD_SIZE);
|
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
#define WORLD_SIZE 100.0
|
|
||||||
|
|
||||||
// Field is a lattice of vectors uniformly distributed FIELD_ELEMENTS^(1/3) on side
|
// Field is a lattice of vectors uniformly distributed FIELD_ELEMENTS^(1/3) on side
|
||||||
const int FIELD_ELEMENTS = 1000;
|
const int FIELD_ELEMENTS = 1000;
|
||||||
|
|
||||||
|
@ -34,7 +32,8 @@ class Field {
|
||||||
glm::vec3 rgb;
|
glm::vec3 rgb;
|
||||||
} fieldcolors[FIELD_ELEMENTS];
|
} fieldcolors[FIELD_ELEMENTS];
|
||||||
|
|
||||||
Field();
|
Field(float worldSize);
|
||||||
|
|
||||||
int value(float *ret, float *pos);
|
int value(float *ret, float *pos);
|
||||||
void render();
|
void render();
|
||||||
void add(float* add, float *loc);
|
void add(float* add, float *loc);
|
||||||
|
@ -43,6 +42,7 @@ class Field {
|
||||||
glm::vec3 hsv2rgb(glm::vec3 in);
|
glm::vec3 hsv2rgb(glm::vec3 in);
|
||||||
private:
|
private:
|
||||||
void avg_neighbors(int index, glm::vec3 * result);
|
void avg_neighbors(int index, glm::vec3 * result);
|
||||||
|
float _worldSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -234,6 +234,9 @@ Menu::Menu() :
|
||||||
0,
|
0,
|
||||||
appInstance->getGlowEffect(),
|
appInstance->getGlowEffect(),
|
||||||
SLOT(cycleRenderMode()));
|
SLOT(cycleRenderMode()));
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ParticleCloud, 0, false);
|
||||||
|
|
||||||
|
|
||||||
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxel Options");
|
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxel Options");
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,7 @@ namespace MenuOption {
|
||||||
const QString GoHome = "Go Home";
|
const QString GoHome = "Go Home";
|
||||||
const QString Gravity = "Use Gravity";
|
const QString Gravity = "Use Gravity";
|
||||||
const QString GroundPlane = "Ground Plane";
|
const QString GroundPlane = "Ground Plane";
|
||||||
|
const QString ParticleCloud = "Particle Cloud";
|
||||||
const QString GyroLook = "Smooth Gyro Look";
|
const QString GyroLook = "Smooth Gyro Look";
|
||||||
const QString ListenModeNormal = "Listen Mode Normal";
|
const QString ListenModeNormal = "Listen Mode Normal";
|
||||||
const QString ListenModePoint = "Listen Mode Point";
|
const QString ListenModePoint = "Listen Mode Point";
|
||||||
|
|
Loading…
Reference in a new issue