3 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define GL_GLEXT_PROTOTYPES
32 #include "cwindowgui.h"
34 #include "pluginserver.h"
35 #include "playback3d.h"
38 #include "nbodycuda.h"
39 #include "nbodywindow.h"
42 static struct N_BodyParams demoParams[] = {
43 { 0.016f, 1.54f, 8.0f, 0.1f, 1.0f, 1.0f, 0, -2, -100},
44 { 0.016f, 0.68f, 20.0f, 0.1f, 1.0f, 0.8f, 0, -2, -30},
45 { 0.0006f, 0.16f, 1000.0f, 1.0f, 1.0f, 0.07f, 0, 0, -1.5f},
46 { 0.0006f, 0.16f, 1000.0f, 1.0f, 1.0f, 0.07f, 0, 0, -1.5f},
47 { 0.0019f, 0.32f, 276.0f, 1.0f, 1.0f, 0.07f, 0, 0, -5},
48 { 0.0016f, 0.32f, 272.0f, 0.145f, 1.0f, 0.08f, 0, 0, -5},
49 { 0.0160f, 6.04f, 0.0f, 1.0f, 1.0f, 0.76f, 0, 0, -50},
51 const int N_BodyParams::num_demos = sizeof(demoParams)/sizeof(*demoParams);
54 REGISTER_PLUGIN(N_BodyMain)
56 void N_BodyConfig::reset(int i)
58 *(N_BodyParams*)this = demoParams[i];
59 trans[0] = trans_lag[0] = m_x;
60 trans[1] = trans_lag[1] = m_y;
61 trans[2] = trans_lag[2] = m_z;
62 rot[0] = rot_lag[0] = 0;
63 rot[1] = rot_lag[1] = 0;
64 rot[2] = rot_lag[2] = 0;
65 mode = ParticleRenderer::PARTICLE_SPRITES_COLOR;
70 N_BodyConfig::N_BodyConfig()
75 int N_BodyConfig::equivalent(N_BodyConfig &that)
77 return m_timestep == that.m_timestep &&
78 m_clusterScale == that.m_clusterScale &&
79 m_velocityScale == that.m_velocityScale &&
80 m_softening == that. m_softening &&
81 m_damping == that.m_damping &&
82 m_pointSize == that.m_pointSize &&
86 trans[0] == that.trans[0] &&
87 trans[1] == that.trans[1] &&
88 trans[2] == that.trans[2] &&
89 trans_lag[0] == that.trans_lag[0] &&
90 trans_lag[1] == that.trans_lag[1] &&
91 trans_lag[2] == that.trans_lag[2] &&
92 rot[0] == that.rot[0] &&
93 rot[1] == that.rot[1] &&
94 rot[2] == that.rot[2] &&
95 rot_lag[0] == that.rot_lag[0] &&
96 rot_lag[1] == that.rot_lag[1] &&
97 rot_lag[2] == that.rot_lag[2] &&
98 inertia == that.inertia &&
99 numBodies == that.numBodies;
103 void N_BodyConfig::copy_from(N_BodyConfig &that)
105 m_timestep = that.m_timestep;
106 m_clusterScale = that.m_clusterScale;
107 m_velocityScale = that.m_velocityScale;
108 m_softening = that. m_softening;
109 m_damping = that.m_damping;
110 m_pointSize = that.m_pointSize;
114 trans[0] = that.trans[0];
115 trans[1] = that.trans[1];
116 trans[2] = that.trans[2];
117 trans_lag[0] = that.trans_lag[0];
118 trans_lag[1] = that.trans_lag[1];
119 trans_lag[2] = that.trans_lag[2];
120 rot[0] = that.rot[0];
121 rot[1] = that.rot[1];
122 rot[2] = that.rot[2];
123 rot_lag[0] = that.rot_lag[0];
124 rot_lag[1] = that.rot_lag[1];
125 rot_lag[2] = that.rot_lag[2];
126 inertia = that.inertia;
127 numBodies = that.numBodies;
130 void N_BodyConfig::interpolate( N_BodyConfig &prev, N_BodyConfig &next,
131 long prev_frame, long next_frame, long current_frame)
136 void N_BodyConfig::limits()
138 if( m_damping < 0.001 ) m_damping = 0.001;
139 if( trans[2] < 0.005 ) trans[2] = 0.005;
141 while( n < numBodies ) n <<= 1;
142 bclamp(n, 0x0010, 0x4000);
144 bclamp(inertia, 0.f,1.f);
145 bclamp(mode, 0, (int)ParticleRenderer::PARTICLE_NUM_MODES-1);
149 N_BodyMain::N_BodyMain(PluginServer *server)
150 : PluginVClient(server)
165 N_BodyMain::~N_BodyMain()
170 void N_BodyMain::init(int numBodies)
173 delete m_nbody; m_nbody = new N_BodySystem(numBodies, 1, blockSize);
174 int sz = numBodies*4;
175 delete [] m_hPos; m_hPos = new float[sz];
176 delete [] m_hVel; m_hVel = new float[sz];
177 delete [] m_hColor; m_hColor = new float[sz];
178 delete m_renderer; m_renderer = new ParticleRenderer;
180 m_nbody->setSoftening(config.m_softening);
181 m_nbody->setDamping(config.m_damping);
182 reset(numBodies, NBODY_CONFIG_RANDOM);
186 void N_BodyMain::reset(int numBodies, NBodyConfig cfg)
188 randomizeBodies(cfg, m_hPos, m_hVel, m_hColor,
189 config.m_clusterScale, config.m_velocityScale,
191 setArrays(m_hPos, m_hVel);
194 void N_BodyMain::resetRenderer()
196 float color[4] = { 1.0f, 0.6f, 0.3f, 1.0f};
197 m_renderer->setBaseColor(color);
198 m_renderer->setColors(m_hColor, m_nbody->getNumBodies());
199 m_renderer->setSpriteSize(config.m_pointSize);
202 void N_BodyMain::selectDemo(int index)
207 void N_BodyMain::finalize()
209 delete [] m_hPos; m_hPos = 0;
210 delete [] m_hVel; m_hVel = 0;
211 delete [] m_hColor; m_hColor = 0;
212 delete m_nbody; m_nbody = 0;
213 delete m_renderer; m_renderer = 0;
216 void N_BodyMain::draw()
219 glClearColor(0.,0.,0.,1.);
220 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
221 glColor4f(1.,1.,1.,1.);
222 glMatrixMode(GL_MODELVIEW);
224 float inertia = config.inertia;
225 for( int c=0; c<3; ++c ) {
226 config.trans_lag[c] += (config.trans[c] - config.trans_lag[c]) * inertia;
227 config.rot_lag[c] += (config.rot[c] - config.rot_lag[c]) * inertia;
230 glTranslatef(config.trans_lag[0], config.trans_lag[1], config.trans_lag[2]);
231 glRotatef(config.rot_lag[0], 1.0, 0.0, 0.0);
232 glRotatef(config.rot_lag[1], 0.0, 1.0, 0.0);
233 glDisable(GL_TEXTURE_2D);
238 const char* N_BodyMain::plugin_title() { return N_("N_Body"); }
239 int N_BodyMain::is_realtime() { return 1; }
240 int N_BodyMain::is_synthesis() { return 1; }
242 NEW_WINDOW_MACRO(N_BodyMain, N_BodyWindow);
243 LOAD_CONFIGURATION_MACRO(N_BodyMain, N_BodyConfig)
245 void N_BodyMain::save_data(KeyFrame *keyframe)
249 // cause data to be stored directly in text
250 output.set_shared_output(keyframe->xbuf);
251 output.tag.set_title("NBODYCUDA");
252 output.tag.set_property("TIMESTEP", config.m_timestep);
253 output.tag.set_property("CLUSTER_SCALE", config.m_clusterScale);
254 output.tag.set_property("VELOCITY_SCALE", config.m_velocityScale);
255 output.tag.set_property("SOFTENING", config.m_softening);
256 output.tag.set_property("DAMPING", config.m_damping);
257 output.tag.set_property("POINT_SIZE", config.m_pointSize);
258 output.tag.set_property("X", config.m_x);
259 output.tag.set_property("Y", config.m_y);
260 output.tag.set_property("Z", config.m_z);
261 output.tag.set_property("TRANS_X",config.trans[0]);
262 output.tag.set_property("TRANS_Y",config.trans[1]);
263 output.tag.set_property("TRANS_Z",config.trans[2]);
264 output.tag.set_property("TRANS_LAG_X",config.trans_lag[0]);
265 output.tag.set_property("TRANS_LAG_Y",config.trans_lag[1]);
266 output.tag.set_property("TRANS_LAG_Z",config.trans_lag[2]);
267 output.tag.set_property("ROT_X",config.rot[0]);
268 output.tag.set_property("ROT_Y",config.rot[1]);
269 output.tag.set_property("ROT_Z",config.rot[2]);
270 output.tag.set_property("ROT_LAG_X",config.rot_lag[0]);
271 output.tag.set_property("ROT_LAG_Y",config.rot_lag[1]);
272 output.tag.set_property("ROT_LAG_Z",config.rot_lag[2]);
273 output.tag.set_property("INERTIA", config.inertia);
274 output.tag.set_property("MODE", config.mode);
275 output.tag.set_property("NUM_BODIES", config.numBodies);
277 output.append_newline();
278 output.tag.set_title("/NBODYCUDA");
280 output.append_newline();
281 output.terminate_string();
284 void N_BodyMain::read_data(KeyFrame *keyframe)
287 input.set_shared_input(keyframe->xbuf);
290 while( !(result = input.read_tag()) ) {
291 if( input.tag.title_is("NBODYCUDA") ) {
292 config.m_timestep = input.tag.get_property("TIMESTEP", config.m_timestep);
293 config.m_clusterScale = input.tag.get_property("CLUSTER_SCALE", config.m_clusterScale);
294 config.m_velocityScale = input.tag.get_property("VELOCITY_SCALE", config.m_velocityScale);
295 config.m_softening = input.tag.get_property("SOFTENING", config.m_softening);
296 config.m_damping = input.tag.get_property("DAMPING", config.m_damping);
297 config.m_pointSize = input.tag.get_property("POINT_SIZE", config.m_pointSize);
298 config.m_x = input.tag.get_property("X", config.m_x);
299 config.m_y = input.tag.get_property("Y", config.m_y);
300 config.m_z = input.tag.get_property("Z", config.m_z);
301 config.trans[0] = input.tag.get_property("TRANS_X", config.trans[0]);
302 config.trans[1] = input.tag.get_property("TRANS_Y", config.trans[1]);
303 config.trans[2] = input.tag.get_property("TRANS_Z", config.trans[2]);
304 config.trans_lag[0] = input.tag.get_property("TRANS_LAG_X", config.trans_lag[0]);
305 config.trans_lag[1] = input.tag.get_property("TRANS_LAG_Y", config.trans_lag[1]);
306 config.trans_lag[2] = input.tag.get_property("TRANS_LAG_Z", config.trans_lag[2]);
307 config.rot[0] = input.tag.get_property("ROT_X", config.rot[0]);
308 config.rot[1] = input.tag.get_property("ROT_Y", config.rot[1]);
309 config.rot[2] = input.tag.get_property("ROT_Z", config.rot[2]);
310 config.rot_lag[0] = input.tag.get_property("ROT_LAG_X", config.rot_lag[0]);
311 config.rot_lag[1] = input.tag.get_property("ROT_LAG_Y", config.rot_lag[1]);
312 config.rot_lag[2] = input.tag.get_property("ROT_LAG_Z", config.rot_lag[2]);
313 config.inertia = input.tag.get_property("INERTIA", config.inertia);
314 config.mode = input.tag.get_property("MODE", config.mode);
315 config.numBodies = input.tag.get_property("NUM_BODIES", config.numBodies);
321 void N_BodyMain::update_gui()
323 if( !thread ) return;
324 if( !load_configuration() ) return;
325 thread->window->lock_window("N_BodyMain::update_gui");
326 N_BodyWindow *window = (N_BodyWindow*)thread->window;
327 window->update_gui();
329 window->unlock_window();
332 int N_BodyMain::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
335 //int need_reconfigure =
336 load_configuration();
337 new_position = start_position;
338 output = get_output(0);
339 color_model = output->get_color_model();
340 if( get_use_opengl() )
343 Canvas *canvas = server->mwindow->cwindow->gui->canvas;
344 return server->mwindow->playback_3d->run_plugin(canvas, this);
349 N_BodyCuda::N_BodyCuda()
354 N_BodyCuda::~N_BodyCuda()
358 // opengl from here down
360 void N_BodyMain::init_cuda()
363 cuda = new N_BodyCuda();
368 void N_BodyMain::finish_cuda()
373 int N_BodyMain::handle_opengl()
375 output->enable_opengl();
376 output->init_screen();
377 if( !m_nbody || get_source_position() == 0 ||
378 (int)m_nbody->getNumBodies() != config.numBodies )
379 init(config.numBodies);
381 if( curr_position != new_position ) {
383 curr_position = new_position;
387 output->set_opengl_state(VFrame::SCREEN);
388 if( !get_use_opengl() ) // rendering
389 output->screen_to_ram();