overte-JulianGro/field.cpp
Philip Rosedale 8d74d5b4e9 Merge pull request #8 from yozlet/18784
Go fullscreen on startup
2012-12-03 16:08:06 -08:00

228 lines
6.9 KiB
C++

//
// field.cpp
// interface
//
// Created by Philip Rosedale on 8/23/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#include "field.h"
#include "glm/glm.hpp"
#define FIELD_SCALE 0.00050
#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 USE_SCALAR 0
// A vector-valued field over an array of elements arranged as a 3D lattice
int field_value(float *value, float *pos)
// sets the vector value (3 floats) to field value at location pos in space.
// returns zero if the location is outside world bounds
{
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
(int)(pos[2]/WORLD_SIZE*10.0)*100;
if ((index >= 0) && (index < FIELD_ELEMENTS))
{
value[0] = field[index].val.x;
value[1] = field[index].val.y;
value[2] = field[index].val.z;
return 1;
}
else return 0;
}
void field_init()
// Initializes the field to some random values
{
int i;
float fx, fy, fz;
for (i = 0; i < FIELD_ELEMENTS; i++)
{
field[i].val.x = (randFloat() - 0.5)*FIELD_SCALE;
field[i].val.y = (randFloat() - 0.5)*FIELD_SCALE;
field[i].val.z = (randFloat() - 0.5)*FIELD_SCALE;
field[i].scalar = 0;
// Record center point for this field cell
fx = (int)(i % 10);
fy = (int)(i%100 / 10);
fz = (int)(i / 100);
field[i].center.x = fx + 0.5;
field[i].center.y = fy + 0.5;
field[i].center.z = fz + 0.5;
// and set up the RGB values for each field element.
float color_mult = 1 - COLOR_MIN;
fieldcolors[i].rgb = glm::vec3(((i%10)*(color_mult/10.0f)) + COLOR_MIN,
((i%100)*(color_mult/100.0f)) + COLOR_MIN,
(i*(color_mult/1000.0f)) + COLOR_MIN);
}
}
void field_add(float* add, float *pos)
// At location loc, add vector add to the field values
{
int index = (int)(pos[0]/WORLD_SIZE*10.0) +
(int)(pos[1]/WORLD_SIZE*10.0)*10 +
(int)(pos[2]/WORLD_SIZE*10.0)*100;
if ((index >= 0) && (index < FIELD_ELEMENTS))
{
field[index].val.x += add[0];
field[index].val.y += add[1];
field[index].val.z += add[2];
}
}
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)(pos->y/WORLD_SIZE*10.0)*10 +
(int)(pos->z/WORLD_SIZE*10.0)*100;
if ((index >= 0) && (index < FIELD_ELEMENTS)) {
//
// Vector Coupling with particle velocity
//
*vel += field[index].val*dt; // Particle influenced by field
glm::vec3 temp = *vel*dt; // Field influenced by particle
temp *= coupling;
field[index].val += temp;
//
// 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
//*color = (*color * (1 - COLOR_DRIFT_RATE)) + (fieldcolors[index].rgb * COLOR_DRIFT_RATE);
}
}
void field_avg_neighbors(int index, glm::vec3 * result) {
// Given index to field element i, return neighbor field values
glm::vec3 neighbors(0,0,0);
int x,y,z;
x = (int)(index % 10);
y = (int)(index%100 / 10);
z = (int)(index / 100);
neighbors += field[(x+1)%10 + y*10 + z*100].val;
neighbors += field[(x-1)%10 + y*10 + z*100].val;
neighbors += field[x + ((y+1)%10)*10 + z*100].val;
neighbors += field[x + ((y-1)%10)*10 + z*100].val;
neighbors += field[x + y*10 + ((z+1)%10)*100].val;
neighbors += field[x%10 + y*10 + ((z-1)%10)*100].val;
neighbors /= 6;
result->x = neighbors.x;
result->y = neighbors.y;
result->z = neighbors.z;
}
void field_simulate(float dt) {
glm::vec3 neighbors, add, diff;
float size, distance;
int i, j;
for (i = 0; i < FIELD_ELEMENTS; i++)
{
if (0) { //(randFloat() > 0.01) {
field_avg_neighbors(i, &neighbors);
size = powf(field[i].val.x*field[i].val.x +
field[i].val.y*field[i].val.y +
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()
// Render the field lines
{
int i;
float fx, fy, fz;
float scale_view = 0.1;
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (i = 0; i < FIELD_ELEMENTS; i++)
{
fx = field[i].center.x;
fy = field[i].center.y;
fz = field[i].center.z;
glColor3f(0, 1, 0);
glVertex3f(fx, fy, fz);
glVertex3f(fx + field[i].val.x*scale_view,
fy + field[i].val.y*scale_view,
fz + field[i].val.z*scale_view);
if (USE_SCALAR) {
glColor3f(1, 0, 0);
glVertex3f(fx, fy, fz);
glVertex3f(fx, fy+field[i].scalar*0.01, fz);
glColor3f(1, 1, 0);
glVertex3f(fx, fy, fz);
glVertex3f(fx + field[i].fld.x*0.0001,
fy + field[i].fld.y*0.0001,
fz + field[i].fld.z*0.0001);
}
}
glEnd();
glColor3f(0, 1, 0);
glPointSize(4.0);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
for (i = 0; i < FIELD_ELEMENTS; i++)
{
fx = (int)(i % 10);
fy = (int)(i%100 / 10);
fz = (int)(i / 100);
glVertex3f(fx, fy, fz);
}
glEnd();
}