rev |
line source |
nuclear@36
|
1 #include <random>
|
nuclear@36
|
2 #include <functional>
|
nuclear@36
|
3 #include <QTimer>
|
nuclear@24
|
4 #include <assert.h>
|
nuclear@18
|
5 #include <GL/glew.h>
|
nuclear@18
|
6 #include "demo.h"
|
nuclear@18
|
7 #include "sdr.h"
|
nuclear@18
|
8 #include "volray.h"
|
nuclear@36
|
9 #include "ui.h"
|
nuclear@18
|
10
|
nuclear@36
|
11 #define SZ 128
|
nuclear@36
|
12 #define TIMER_INTERVAL 33
|
nuclear@18
|
13
|
nuclear@18
|
14
|
nuclear@36
|
15 Demo::Demo()
|
nuclear@36
|
16 {
|
nuclear@36
|
17 vol = 0;
|
nuclear@36
|
18 sdr_mballs = 0;
|
nuclear@36
|
19 fbo = 0;
|
nuclear@36
|
20 timer = 0;
|
nuclear@36
|
21 balls = 0;
|
nuclear@36
|
22 tmsec = 0;
|
nuclear@36
|
23 }
|
nuclear@36
|
24
|
nuclear@36
|
25 Demo::~Demo()
|
nuclear@36
|
26 {
|
nuclear@36
|
27 glDeleteFramebuffersEXT(1, &fbo);
|
nuclear@36
|
28 free_program(sdr_mballs);
|
nuclear@36
|
29 delete vol;
|
nuclear@36
|
30 delete timer;
|
nuclear@36
|
31
|
nuclear@36
|
32 delete [] balls;
|
nuclear@36
|
33 }
|
nuclear@36
|
34
|
nuclear@36
|
35 void Demo::timer_func()
|
nuclear@36
|
36 {
|
nuclear@36
|
37 float tsec = tmsec / 1000.0;
|
nuclear@36
|
38 const float speed = 1.0;
|
nuclear@36
|
39
|
nuclear@36
|
40 for(int i=0; i<num_balls; i++) {
|
nuclear@36
|
41 float t = tsec * speed;
|
nuclear@36
|
42 int idx = (int)t % MB_PATH_SZ;
|
nuclear@36
|
43 t -= floor(t);
|
nuclear@36
|
44
|
nuclear@36
|
45 Vector3 a = balls[i].path[idx];
|
nuclear@36
|
46 Vector3 b = balls[i].path[(idx + 1) % MB_PATH_SZ];
|
nuclear@36
|
47 balls[i].pos = lerp(a, b, t);
|
nuclear@36
|
48
|
nuclear@36
|
49 char name[32];
|
nuclear@36
|
50
|
nuclear@36
|
51 sprintf(name, "pos[%d]", i);
|
nuclear@36
|
52 set_uniform_float3(sdr_mballs, name, balls[i].pos.x, balls[i].pos.y, balls[i].pos.z);
|
nuclear@36
|
53
|
nuclear@36
|
54 sprintf(name, "energy[%d]", i);
|
nuclear@36
|
55 set_uniform_float(sdr_mballs, name, balls[i].energy);
|
nuclear@36
|
56 }
|
nuclear@36
|
57
|
nuclear@36
|
58 post_redisplay();
|
nuclear@36
|
59
|
nuclear@36
|
60 tmsec += TIMER_INTERVAL;
|
nuclear@36
|
61 }
|
nuclear@36
|
62
|
nuclear@36
|
63 bool Demo::init()
|
nuclear@18
|
64 {
|
nuclear@18
|
65 if(!(sdr_mballs = create_program_load("sdr/demo.v.glsl", "sdr/demo.p.glsl"))) {
|
nuclear@18
|
66 return false;
|
nuclear@18
|
67 }
|
nuclear@18
|
68
|
nuclear@18
|
69 vol = new Volume;
|
nuclear@18
|
70 vol->create(SZ, SZ, SZ);
|
nuclear@18
|
71 volray_setvolume(vol);
|
nuclear@18
|
72
|
nuclear@24
|
73 assert(glGenFramebuffersEXT);
|
nuclear@24
|
74 assert(glBindFramebufferEXT);
|
nuclear@24
|
75 assert(glFramebufferTexture3DEXT);
|
nuclear@24
|
76 assert(glCheckFramebufferStatusEXT);
|
nuclear@24
|
77
|
nuclear@24
|
78 glGenFramebuffersEXT(1, &fbo);
|
nuclear@24
|
79 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
|
nuclear@24
|
80 glFramebufferTexture3DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
|
nuclear@18
|
81 vol->get_texture(), 0, 0);
|
nuclear@18
|
82
|
nuclear@24
|
83 unsigned int stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
|
nuclear@18
|
84 if(stat != GL_FRAMEBUFFER_COMPLETE) {
|
nuclear@18
|
85 printf("incomplete framebuffer: %u\n", stat);
|
nuclear@18
|
86 delete vol;
|
nuclear@18
|
87 return false;
|
nuclear@18
|
88 }
|
nuclear@24
|
89 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
|
nuclear@18
|
90
|
nuclear@36
|
91 // initialize metaballs
|
nuclear@36
|
92 auto rnd_energy = std::bind(std::uniform_real_distribution<float>(0.7, 1.6), std::mt19937());
|
nuclear@36
|
93 auto rnd_path = std::bind(std::uniform_real_distribution<float>(-0.5, 0.5), std::mt19937());
|
nuclear@36
|
94
|
nuclear@36
|
95 num_balls = 4;
|
nuclear@36
|
96 balls = new MetaBall[4];
|
nuclear@36
|
97
|
nuclear@36
|
98 for(int i=0; i<4; i++) {
|
nuclear@36
|
99 balls[i].energy = rnd_energy();
|
nuclear@36
|
100
|
nuclear@36
|
101 for(int j=0; j<MB_PATH_SZ; j++) {
|
nuclear@36
|
102 balls[i].path[j].x = rnd_path();
|
nuclear@36
|
103 balls[i].path[j].y = rnd_path();
|
nuclear@36
|
104 balls[i].path[j].z = rnd_path();
|
nuclear@36
|
105 }
|
nuclear@36
|
106 }
|
nuclear@36
|
107
|
nuclear@36
|
108 // update timer
|
nuclear@36
|
109 timer = new QTimer(this);
|
nuclear@36
|
110 timer->setSingleShot(false);
|
nuclear@36
|
111 connect(timer, SIGNAL(timeout()), this, SLOT(timer_func()));
|
nuclear@36
|
112 timer->start(TIMER_INTERVAL);
|
nuclear@36
|
113
|
nuclear@18
|
114 return true;
|
nuclear@18
|
115 }
|
nuclear@18
|
116
|
nuclear@36
|
117 void Demo::draw() const
|
nuclear@18
|
118 {
|
nuclear@18
|
119 if(volray_getvolume() != vol) {
|
nuclear@36
|
120 if(timer->isActive()) {
|
nuclear@36
|
121 timer->stop();
|
nuclear@36
|
122 }
|
nuclear@18
|
123 return;
|
nuclear@36
|
124 } else {
|
nuclear@36
|
125 if(!timer->isActive()) {
|
nuclear@36
|
126 timer->start(TIMER_INTERVAL);
|
nuclear@36
|
127 }
|
nuclear@18
|
128 }
|
nuclear@18
|
129
|
nuclear@21
|
130 glPushAttrib(GL_VIEWPORT_BIT);
|
nuclear@21
|
131 glViewport(0, 0, SZ, SZ);
|
nuclear@21
|
132
|
nuclear@24
|
133 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
|
nuclear@18
|
134 bind_program(sdr_mballs);
|
nuclear@18
|
135
|
nuclear@18
|
136 for(int i=0; i<SZ; i++) {
|
nuclear@24
|
137 glFramebufferTexture3DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
|
nuclear@18
|
138 vol->get_texture(), 0, i);
|
nuclear@18
|
139
|
nuclear@21
|
140 float z = (float)i / (float)SZ;
|
nuclear@21
|
141
|
nuclear@18
|
142 glBegin(GL_QUADS);
|
nuclear@21
|
143 glTexCoord3f(0, 0, z);
|
nuclear@18
|
144 glVertex2f(-1, -1);
|
nuclear@21
|
145 glTexCoord3f(1, 0, z);
|
nuclear@18
|
146 glVertex2f(1, -1);
|
nuclear@21
|
147 glTexCoord3f(1, 1, z);
|
nuclear@18
|
148 glVertex2f(1, 1);
|
nuclear@21
|
149 glTexCoord3f(0, 1, z);
|
nuclear@18
|
150 glVertex2f(-1, 1);
|
nuclear@18
|
151 glEnd();
|
nuclear@18
|
152 }
|
nuclear@18
|
153
|
nuclear@18
|
154 bind_program(0);
|
nuclear@24
|
155 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
|
nuclear@21
|
156
|
nuclear@21
|
157 glPopAttrib();
|
nuclear@18
|
158 }
|