forked from yozlet/interface
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfield.cpp
More file actions
228 lines (195 loc) · 6.94 KB
/
Copy pathfield.cpp
File metadata and controls
228 lines (195 loc) · 6.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//
// 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();
}