-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflowmetaball.cpp
More file actions
358 lines (284 loc) · 9.86 KB
/
Copy pathflowmetaball.cpp
File metadata and controls
358 lines (284 loc) · 9.86 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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//
// アプリケーション本体
//
// ウィンドウ関連の処理
#include "Window.h"
// 粒子群オブジェクト
#include "Blob.h"
// 標準ライブラリ
#include <memory>
#include <random>
//
// カメラ
//
// 位置
constexpr GLfloat cameraPosition[] = { 0.0f, 0.0f, 5.0f };
// 目標点
constexpr GLfloat cameraTarget[] = { 0.0f, 0.0f, 0.0f };
// 上方向
constexpr GLfloat cameraUp[] = { 0.0f, 1.0f, 0.0f };
// 画角
constexpr GLfloat cameraFovy(1.0f);
// 前方面の位置
constexpr GLfloat cameraNear(1.0f);
// 後方面の位置
constexpr GLfloat cameraFar(10.0f);
//
// 光源
//
// ambient 光源強度の環境光成分
// diffuse 光源強度の拡散反射光成分
// specular 光源強度の鏡面反射光成分
// position 光源の位置
constexpr GgSimpleShader::Light lightData =
{
{ 0.1f, 0.1f, 0.1f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
{ 3.0f, 4.0f, 5.0f, 1.0f }
};
//
// 材質
//
// ambient 環境光の反射係数
// diffuse 拡散反射係数
// specular 鏡面反射係数
// shininess 輝き係数
constexpr GgSimpleShader::Material materialData =
{
{ 0.6f, 0.6f, 0.6f, 1.0f },
{ 0.6f, 0.6f, 0.6f, 0.0f },
{ 0.4f, 0.4f, 0.4f, 0.0f },
30.0f
};
//
// 球
//
// 球の半径
constexpr float sphereRadius(0.5f);
// 球の分割数
constexpr int slices(32), stacks(16);
// 球の速度 (倍速の値)
constexpr float dSpeed(2.0f);
//
// 粒子群
//
// 生成する粒子群の数
constexpr int bCount(8);
// 生成する粒子群の中心位置の範囲
constexpr GLfloat bRange(0.8f);
// 一つの粒子群の粒子数
constexpr int pCount(2000);
// 一つの粒子群の中心からの距離の平均
constexpr GLfloat pMean(0.0f);
// 一つの粒子群の中心からの距離の標準偏差
constexpr GLfloat pDeviation(0.3f);
// アニメーションの繰り返し間隔
constexpr double interval(5.0);
//
// 粒子群の生成
//
// paticles 粒子群の格納先
// count 粒子群の粒子数
// cx, cy, cz 粒子群の中心位置
// rn メルセンヌツイスタ法による乱数
// mean 粒子の粒子群の中心からの距離の平均値
// deviation 粒子の粒子群の中心からの距離の標準偏差
//
void generateParticles(Particles &particles, int count,
GLfloat cx, GLfloat cy, GLfloat cz,
std::mt19937 &rn, GLfloat mean, GLfloat deviation)
{
// 一様実数分布
// [0, 2) の値の範囲で等確率に実数を生成する
std::uniform_real_distribution<GLfloat> uniform(0.0f, 2.0f);
// 正規分布
// 平均 mean、標準偏差 deviation で分布させる
std::normal_distribution<GLfloat> normal(mean, deviation);
// 格納先のメモリをあらかじめ確保しておく
particles.reserve(particles.size() + count);
// 原点中心に直径方向に正規分布する粒子群を発生する
for (int i = 0; i < count; ++i)
{
// 緯度方向
const GLfloat cp(uniform(rn) - 1.0f);
const GLfloat sp(sqrt(1.0f - cp * cp));
// 経度方向
const GLfloat t(3.1415927f * uniform(rn));
const GLfloat ct(cos(t)), st(sin(t));
// 粒子の粒子群の中心からの距離 (半径)
const GLfloat r(normal(rn));
// 粒子を追加する
// (静止した粒子をランダムに配置する場合)
particles.emplace_back(r * sp * ct + cx, r * sp * st + cy, r * cp + cz);
// (中心からランダムな方向に発射する場合)
//particles.emplace_back(cx, cy, cz, r * sp * ct, r * sp * st, r * cp);
}
}
//
// アプリケーションの実行
//
void app()
{
// ウィンドウを作成する
Window window("FlowMetaball");
//
// 粒子群オブジェクトの作成
//
// メルセンヌツイスタ法による乱数の系列を設定する
// (ハードウェア乱数を種に使って実行ごとに初期形状を変える場合)
//std::random_device seed;
//std::mt19937 rn(seed());
// (定数にして毎回同じ初期形状にする場合)
std::mt19937 rn(54321);
// 一様実数分布
// [-1.0, 1.0) の値の範囲で等確率に実数を生成する
std::uniform_real_distribution<GLfloat> center(-bRange, bRange);
// 粒子群データの初期値
Particles initial;
// 発生する粒子群の数だけ繰り返す
for (int i = 0; i < bCount; ++i)
{
// 点の玉中心位置
const GLfloat cx(center(rn)), cy(center(rn)), cz(center(rn));
// 中心からの距離に対して密度が正規分布に従う点の玉を生成する
generateParticles(initial, pCount, cx, cy, cz, rn, pMean, pDeviation);
}
// 粒子群オブジェクトを作成する
std::unique_ptr<const Blob> blob(new Blob(initial));
//
// 位置更新用のシェーダ
//
const GLuint updateShader(ggLoadComputeShader("update.comp"));
// 図形描画用のシェーダ
const GgSimpleShader simpleShader("simple.vert", "simple.frag");
// 図形描画用の光源
const GgSimpleShader::LightBuffer light(lightData);
//
// 物体
//
// 図形データ
//std::unique_ptr<const GgSimpleObj> object(new GgSimpleObj("AC_1038.obj", true));
//std::unique_ptr<const GgSimpleObj> object(new GgSimpleObj("bunny.obj", true);
//std::unique_ptr<const GgSimpleObj> object(new GgSimpleObj("box.obj", true);
// 球を生成する
std::unique_ptr<const GgElements> object(ggElementsSphere(sphereRadius, slices, stacks));
// 球の材質
const GgSimpleShader::MaterialBuffer material(materialData);
//
// 描画の設定
//
// ビュー変換行列
const GgMatrix view(ggLookat(cameraPosition, cameraTarget, cameraUp));
// 背面カリングを有効にする
glEnable(GL_CULL_FACE);
// デプスバッファを有効にする
glEnable(GL_DEPTH_TEST);
// 背景色を指定する
glClearColor(0.1f, 0.2f, 0.3f, 0.0f);
// 点のサイズはシェーダから変更する
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
/*
** レンダリング結果のブレンド
**
** glBlendFunc(GL_ONE, GL_ZERO); // 上書き(デフォルト)
** glBlendFunc(GL_ZERO, GL_ONE); // 描かない
** glBlendFunc(GL_ONE, GL_ONE); // 加算
** glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 通常のアルファブレンデング
** glBlendColor(0.01f, 0.01f, 0.01f, 0.0f); // 加算する定数
** glBlendFunc(GL_CONSTANT_COLOR, GL_ONE); // 定数を加算
*/
// フレームバッファに加算する
/**/
// ポイントスプライトの設定
// アルファブレンディングを設定する
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
#if !DEPTH
// デプスバッファは使わない
glDisable(GL_DEPTH_TEST);
#endif
// 時計をリセットする
double elapsed(0.0);
//
// 描画
//
while (window)
{
// ウィンドウを消去する
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 透視投影変換行列を求める
const GgMatrix projection(ggPerspective(cameraFovy, window.getAspect(), cameraNear, cameraFar));
// モデル変換行列を求める
static GLfloat angle(0.0f);
const GgMatrix model(window.getTrackball() * ggRotateY(angle));
// モデルビュー変換行列を求める
const GgMatrix modelview(view * model);
// 粒子群オブジェクトを描画する
//blob->draw(projection, modelview);
//メタボールの描画
blob->drawMetaball(projection, modelview, window, light);
//
// 球描画
//
// 初期位置
float sphereX = 0.0f;
float sphereY = 0.0f;
float sphereZ = 3.0f - static_cast<float>(glfwGetTime() - elapsed) * dSpeed;
// オブジェクトのシェーダプログラムの使用開始
simpleShader.use(projection, modelview.translate(sphereX, sphereY, sphereZ), light);
// アルファブレンディングを無効にして図形を描画する
glDisable(GL_BLEND);
material.select();
object->draw();
//
// ユーザインタフェース
//
ImGui::NewFrame();
ImGui::Begin("Control panel");
ImGui::Text("Position:%7.2f,%7.2f,%7.2f", sphereX, sphereY, sphereZ);
ImGui::SliderAngle("Angle", &angle, -180.0f, 180.0f);
static GLfloat equilibrium(0.2f);
ImGui::SliderFloat("Length", &equilibrium, 0.0f, 1.0f);
static GLfloat spring(1.0f);
ImGui::SliderFloat("Constant", &spring, 0.0f, 5.0f);
static GLfloat attenation(5.0f);
ImGui::SliderFloat("Attenation", &attenation, 0.0f, 10.0f);
static GLfloat weight(1.0f);
ImGui::SliderFloat("Weight", &weight, 0.01f, 5.0f);
static GLfloat range(0.5f);
ImGui::SliderFloat("Range", &range, 0.01f, 1.0f);
ImGui::Text("Frame rate: %6.2f fps", ImGui::GetIO().Framerate);
if (ImGui::Button("New cloud"))
{
// 粒子を捨てる
initial.clear();
// 発生する粒子群の数だけ繰り返す
for (int i = 0; i < bCount; ++i)
{
// 点の玉中心位置
const GLfloat cx(center(rn)), cy(center(rn)), cz(center(rn));
// 中心からの距離に対して密度が正規分布に従う点の玉を生成する
generateParticles(initial, pCount, cx, cy, cz, rn, pMean, pDeviation);
}
}
ImGui::SameLine();
if (ImGui::Button("Quit")) glfwSetWindowShouldClose(window.get(), GL_TRUE);
ImGui::End();
ImGui::Render();
// 粒子群オブジェクトを更新する
blob->update(sphereX, sphereY, sphereZ, sphereRadius,
equilibrium, spring, attenation, weight, range);
// カラーバッファを入れ替える
window.swapBuffers();
// 定期的に粒子群オブジェクトをリセットする
if (glfwGetTime() > elapsed + interval)
{
// 粒子の初期位置を変更する
blob->initialize(initial);
// 経過時間を更新する
elapsed += interval;
}
}
}