1111#include < brenta/logger.hpp>
1212#include < brenta/gui.hpp>
1313#include < brenta/window.hpp>
14+ #include < brenta/mouse.hpp>
1415
1516#include < bitset>
1617
1718using namespace brenta ;
1819
20+ void setup_gui (FrameBuffer &fb,
21+ ParticleEmitter *emitter);
22+
1923int main ()
2024{
2125 const int SCR_WIDTH = 1280 ;
@@ -65,14 +69,134 @@ int main()
6569 .starting_spread (glm::vec3 (3 .0f , 10 .0f , 3 .0f ))
6670 .starting_time_to_live (0 .5f )
6771 .num_particles (1000 )
68- .spawn_rate (0 .01f )
72+ .spawn_rate (0 .99f )
6973 .scale (1 .0f )
7074 .atlas_path (" examples/assets/textures/particle_atlas.png" )
7175 .atlas_width (8 )
7276 .atlas_height (8 )
7377 .atlas_index (3 )
7478 .build ();
7579
80+
81+ Mouse mouse = {};
82+ mouse.set_sensitivity (0 .05f );
83+
84+ Input::add_mouse_callback (" rotate_camera" ,
85+ [camera, &mouse](double xpos, double ypos)
86+ {
87+ // Rotate the camera
88+ if (Window::is_key_pressed (Key::LeftShift))
89+ {
90+ if (mouse.get_first ())
91+ {
92+ mouse.set_x (xpos);
93+ mouse.set_y (ypos);
94+ mouse.set_first (false );
95+ }
96+
97+ float xoffset = xpos - mouse.get_x ();
98+ float yoffset = mouse.get_y () - ypos;
99+ mouse.set_x (xpos);
100+ mouse.set_y (ypos);
101+
102+ auto sensitivity = mouse.get_sensitivity ();
103+ xoffset *= sensitivity;
104+ yoffset *= sensitivity;
105+
106+ auto new_cam = camera->get_pos ();
107+ try {
108+ Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
109+ scam.theta += yoffset * sensitivity;
110+ scam.phi += xoffset * sensitivity;
111+
112+ if (scam.theta <= 0 .01f ) scam.theta = 0 .01f ;
113+ if (scam.theta >= 3 .13f ) scam.theta = 3 .13f ;
114+
115+ camera->set_pos (scam);
116+
117+ } catch ([[maybe_unused]] const std::bad_variant_access& ex) {
118+ return ;
119+ }
120+ }
121+ // translate the cam center
122+ else if (Window::is_key_pressed (Key::LeftControl))
123+ {
124+ if (mouse.get_first ())
125+ {
126+ mouse.set_x (xpos);
127+ mouse.set_y (ypos);
128+ mouse.set_first (false );
129+ }
130+
131+ float xoffset = xpos - mouse.get_x ();
132+ float yoffset = mouse.get_y () - ypos;
133+ mouse.set_x (xpos);
134+ mouse.set_y (ypos);
135+
136+ auto sensitivity = mouse.get_sensitivity ();
137+ xoffset *= sensitivity * 0 .3f ;
138+ yoffset *= sensitivity * 0 .3f ;
139+
140+ auto new_cam = camera->get_pos ();
141+ try {
142+ Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
143+ glm::vec3 world_pos = camera->get_transform ().get_pos ();
144+ // Local coordinate system
145+ glm::vec3 fixed_center =
146+ glm::vec3 (scam.center .x , world_pos.y , scam.center .z );
147+ // Unit vectors
148+ glm::vec3 front =
149+ glm::normalize (world_pos - fixed_center);
150+ glm::vec3 right =
151+ glm::normalize (glm::cross (front, camera->get_world_up ()));
152+
153+ scam.center += right * glm::vec3 (xoffset);
154+ scam.center -= camera->get_world_up () * glm::vec3 (yoffset);
155+
156+ camera->set_pos (scam);
157+ } catch ([[maybe_unused]] const std::bad_variant_access& ex) {
158+ return ;
159+ }
160+ }
161+ // zoom the camera
162+ else if (Window::is_key_pressed (Key::LeftAlt))
163+ {
164+ if (mouse.get_first ())
165+ {
166+ mouse.set_x (xpos);
167+ mouse.set_y (ypos);
168+ mouse.set_first (false );
169+ }
170+
171+ float xoffset = xpos - mouse.get_x ();
172+ float yoffset = mouse.get_y () - ypos;
173+ mouse.set_x (xpos);
174+ mouse.set_y (ypos);
175+
176+ xoffset *= mouse.get_sensitivity ();
177+ yoffset *= mouse.get_sensitivity ();
178+
179+ auto new_cam = camera->get_pos ();
180+ try {
181+ Camera::Spherical scam = std::get<Camera::Spherical>(new_cam);
182+
183+ scam.radius -= yoffset;
184+ if (scam.radius <= 0 .1f ) scam.radius = 0 .1f ;
185+
186+ camera->set_pos (scam);
187+ } catch ([[maybe_unused]] const std::bad_variant_access& ex) {
188+ return ;
189+ }
190+ }
191+ else
192+ {
193+ mouse.set_first (true );
194+ }
195+ });
196+
197+ Gui::load_font ();
198+ FrameBuffer fb (Window::get_width (), Window::get_height ());
199+
76200 //
77201 // Render loop
78202 //
@@ -81,15 +205,53 @@ int main()
81205 {
82206 if (Window::is_key_pressed (Key::Escape))
83207 Window::close ();
84-
208+ // TODO: movement
209+
210+ setup_gui (fb, &emitter);
211+
85212 Gl::set_color (Color::grey ());
86213 Gl::clear ();
87214
215+ fb.bind ();
88216 emitter.update (Window::get_time ().get_delta ());
89217 emitter.render ();
218+ fb.unbind ();
90219
220+ Gui::render ();
221+
91222 Window::poll_events ();
92223 Window::swap_buffers ();
93224 }
94225 return 0 ;
95226}
227+
228+ void setup_gui (FrameBuffer &fb,
229+ ParticleEmitter *emitter)
230+ {
231+ Gui::new_frame (&fb, " particles" );
232+ Gui::push_font ();
233+ ImGui::Begin (" Particle settings" );
234+
235+ // Position and Movement
236+ ImGui::SliderFloat3 (" Starting position" ,
237+ &emitter->starting_position .x , -50 .0f , 50 .0f );
238+ ImGui::SliderFloat3 (" Starting velocity" ,
239+ &emitter->starting_velocity .x , -15 .0f , 15 .0f );
240+ ImGui::SliderFloat3 (" Starting spread" ,
241+ &emitter->starting_spread .x , 0 .0f , 10 .0f );
242+
243+ // Timing and Life
244+ ImGui::SliderFloat (" Starting time to live" ,
245+ &emitter->starting_time_to_live , 0 .0f , 15 .0f );
246+ ImGui::SliderFloat (" Spawn rate" ,
247+ &emitter->spawn_rate , 0 .0f , 1 .0f );
248+
249+ // Quantity and Appearance
250+ ImGui::SliderInt (" Number of particles" ,
251+ &emitter->num_particles , 1 , BRENTA_MAX_PARTICLES);
252+ ImGui::SliderFloat (" Scale" ,
253+ &emitter->scale , 0 .01f , 5 .0f );
254+
255+ ImGui::End ();
256+ Gui::pop_font ();
257+ }
0 commit comments