/// <summary> /// Called when it is time to render the next frame. Add your rendering code here. /// </summary> /// <param name="e">Contains timing information.</param> public override void OnRenderFrame(RenderFrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit); // // Draw particles as meta-circles (meta-balls / blobs) // if (m_useBlobs) { m_blobs.Render(this.m_particleSystem.Particles, m_fluidSim.Domain); } // Draw particles as points and a velocity line else { GL.Disable(EnableCap.Texture2D); GL.Color4(m_blobs.Color); foreach (var particle in this.m_particleSystem.Particles) { GL.Begin(BeginMode.Points); GL.Vertex2(particle.Position.X, particle.Position.Y); GL.End(); if (m_drawVel) { Vector2 vel = particle.Position + particle.Velocity * 0.1f; GL.Begin(BeginMode.Lines); GL.Vertex2(particle.Position.X, particle.Position.Y); GL.Vertex2(vel.X, vel.Y); GL.End(); } } } // // Draw Bounding Volumes // m_collisionSolver.BoundingVolumes.Draw(Color.LightGreen); if (m_selectedBoundingVolume != null) { GL.Color3(Color.GreenYellow); m_selectedBoundingVolume.Draw(); } // Draw PointList if (m_pointList != null) { GL.Color4(Color.Red); GL.Begin(BeginMode.LineStrip); foreach (var point in m_pointList) { GL.Vertex2(point.X, point.Y); } GL.End(); } // // Draw OpenTK text // // Text Background if (m_showHelp) { GL.PushAttrib(AttribMask.EnableBit); GL.Enable(EnableCap.Blend); GL.Color4(0.0f, 0.0f, 0.0f, 0.8f); GL.Begin(BeginMode.Quads); GL.Vertex2(m_fluidSim.Domain.Left, m_fluidSim.Domain.Bottom); GL.Vertex2(m_fluidSim.Domain.Right, m_fluidSim.Domain.Bottom); GL.Vertex2(m_fluidSim.Domain.Right, m_fluidSim.Domain.Top); GL.Vertex2(m_fluidSim.Domain.Left, m_fluidSim.Domain.Top); GL.End(); GL.PopAttrib(); } GL.Color4(Color.White); m_textPrinter.Begin(); // FPS & Co. // Show fps (Frames per second) m_textPrinter.Prepare(CreateFPSText(e.Time), m_textFont, out m_textHandleStats); m_textPrinter.Draw(m_textHandleStats); // Help if (m_showHelp) { GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); GL.Translate(0.0f, m_textFont.Height, 0.0f); m_textPrinter.Draw(m_textHandleHelp); GL.MatrixMode(MatrixMode.Modelview); GL.PopMatrix(); } m_textPrinter.End(); // Present SwapBuffers(); // Check OGL errors Utils.TraceGlError(); }
/// <summary>Load resources here.</summary> /// <param name="e">Not used.</param> public override void OnLoad(EventArgs e) { base.OnLoad(e); // // Init. sim // m_pause = false; m_gravity = Constants.GRAVITY * Constants.PARTICLE_MASS; m_fluidSim = new SPHSimulation(Constants.CELL_SPACE, Constants.SIM_DOMAIN); m_collisionSolver = new CollisionResolver { BoundingVolumes = new BoundingVolumes { new OBB { Position = new Vector2(Constants.SIM_DOMAIN.Width / 3, Constants.SIM_DOMAIN.Height / 2), Extents = new Vector2(Constants.SIM_DOMAIN.Width / 6, Constants.SIM_DOMAIN.Height / 30), } }, Bounciness = 0.2f, Friction = 0.01f, }; // Init. particle system double freq = 30; int maxPart = 2000; m_particleSystem = new ParticleSystem { Emitters = new ParticleEmitters { new ParticleEmitter { Position = new Vector2(Constants.SIM_DOMAIN.X, Constants.SIM_DOMAIN.Bottom), VelocityMin = Constants.PARTICLE_MASS * 0.30f, VelocityMax = Constants.PARTICLE_MASS * 0.35f, Direction = new Vector2(0.8f, -0.25f), Distribution = Constants.SIM_DOMAIN.Width * 0.0001f, Frequency = freq, ParticleMass = Constants.PARTICLE_MASS, }, }, MaxParticles = maxPart, MaxLife = (int)((double)maxPart / freq / Constants.DELTA_TIME_SEC), TestMaxLife = false, }; // // Init blobs // m_blobs = new BlobRenderer(1.0f, 0.4f, 0.8f, BLOB_RADIUS, TEX_SIZE, Color.LightSkyBlue); m_useBlobs = true; m_drawVel = false; // // Init OpenGL // GL.ClearColor(System.Drawing.Color.Black); GL.PointSize(5.0f); GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); // Init OpenTK text m_showHelp = false; m_textPrinter = new TextPrinter(); m_textFont = new TextureFont(new Font(FontFamily.GenericMonospace, 12.0f)); m_textPrinter.Prepare( "Press [F1] to hide / show this text\r\n" + "Press [R] to change particle rendering\r\n" + "Press [D] to draw velocity direction\r\n" + "Press [E] to switch emitter on / off\r\n" + "Press [P] to pause\r\n" + "Press [Space] to tilt (add random impulse)\r\n" + "Press [Esc] to close the program\r\n" + "\r\n" + "Use left mouse button <LMB> to select a box\r\n" + "Select a box + <LMB> to move the selected box\r\n" + "Hold [Ctrl] + <RMB> to remove a box\r\n" + "Hold [Ctrl] + <LMB> to draw a new box (AABB)\r\n" + "(Release <LMB> to add the drawn box (AABB))\r\n" + "\r\n" + "Hold [Alt] + <LMB> to exert a negative force field\r\n" + "Hold [Alt] + <RMB> to exert a positive force field\r\n" + "\r\n" + "Use mousewheel <MW> to change some values\r\n" + "(Hold [Shift] to change smaller steps)\r\n" + "Select a box + <MW> to rotate the selected box\r\n" + "Hold [V] + <MW> to change viscosity\r\n" + "Hold [B] + <MW> to change bounciness\r\n" + "Hold [F] + <MW> to change friction\r\n" + "\r\n" + "This program is free software (GPLv3) -> License.txt", m_textFont, out m_textHandleHelp); // Add Keyboard- and Mouse-Handler Keyboard.KeyUp += new KeyUpEvent(Keyboard_KeyUp); Mouse.ButtonDown += new MouseButtonDownEvent(Mouse_ButtonDown); Mouse.ButtonUp += new MouseButtonUpEvent(Mouse_ButtonUp); // Init. misc. m_mouseWheelLastValue = Mouse.Wheel; }