Added linear interpolation between updates to mesh batch.

Cleaned up code.
This commit is contained in:
Harrison Deng 2020-06-25 00:05:44 -05:00
parent e781aea776
commit 8827bfbb78
9 changed files with 93 additions and 18 deletions

View File

@ -164,7 +164,10 @@ namespace SlatedGameToolkit.Framework {
//Updates. //Updates.
manager.update(updateDeltaTime.TotalSeconds <= 0 ? timePassedFromLastUpdate.TotalSeconds : updateDeltaTime.TotalSeconds); manager.update(updateDeltaTime.TotalSeconds <= 0 ? timePassedFromLastUpdate.TotalSeconds : updateDeltaTime.TotalSeconds);
timePassedFromLastUpdate -= updateDeltaTime; timePassedFromLastUpdate -= updateDeltaTime;
if (updateDeltaTime.TotalSeconds <= 0) break; if (updateDeltaTime.TotalSeconds <= 0) {
timePassedFromLastUpdate = TimeSpan.Zero;
break;
}
} }
timePassedFromLastRender += difference; timePassedFromLastRender += difference;

View File

@ -4,15 +4,27 @@ using SlatedGameToolkit.Framework.Utilities;
namespace SlatedGameToolkit.Framework.Graphics.Render namespace SlatedGameToolkit.Framework.Graphics.Render
{ {
public class Camera { public class Camera : IMoveable {
private bool viewUpdated = true, projectionUpdated = true, orthographic; private bool viewUpdated = true, projectionUpdated = true, orthographic = false;
public virtual Vector3 Up { get; set; } = Vector3.UnitY;
private Vector3 position, lookAt; private Vector3 position, lookAt;
private float nearField = 0.01f, farField = 100f; private float nearField = 0.01f, farField = 100f;
private float width, height; private float width, height;
private Matrix4x4 lookAtMatrix = Matrix4x4.Identity; private Matrix4x4 lookAtMatrix = Matrix4x4.Identity;
private Matrix4x4 view = Matrix4x4.Identity, projection; private Matrix4x4 view = Matrix4x4.Identity, projection;
/// <summary>
/// Position updates the camera without changing camera orientation if true.
/// Otherwise, camera will always attempt to look in the direction of the point given by the LookAt vector.
/// </summary>
/// <value>Whether or not to change orientation while moving camera position.</value>
public bool LockedOrientation { get; set; } = false;
/// <summary>
/// The up direction of the camera.
/// </summary>
/// <value>A vector representing the up direction of the camera.</value>
public Vector3 Up { get; set; } = Vector3.UnitY;
public event EventHandler projectionUpdateEvent; public event EventHandler projectionUpdateEvent;
public bool Orthographic { public bool Orthographic {
@ -31,7 +43,9 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
return position; return position;
} }
set { set {
Vector3 orientation = CameraFront;
this.position = value; this.position = value;
if (LockedOrientation) CameraFront = orientation;
viewUpdated = true; viewUpdated = true;
} }
} }
@ -120,6 +134,8 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
} }
} }
public Vector3 MoveTo { get; set; }
public Camera(float width, float height) { public Camera(float width, float height) {
if (width <= 0) throw new ArgumentException("Width can't be less than or equal to 0."); if (width <= 0) throw new ArgumentException("Width can't be less than or equal to 0.");
if (height <= 0) throw new ArgumentException("Height can't be less than or equal to 0."); if (height <= 0) throw new ArgumentException("Height can't be less than or equal to 0.");

View File

@ -10,12 +10,23 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
set { set {
base.Position = new Vector3(value, base.Position.Z); base.Position = new Vector3(value, base.Position.Z);
base.CameraFront = -Vector3.UnitZ; }
}
public new Vector2 MoveTo {
get {
return new Vector2(base.MoveTo.X, base.MoveTo.Y);
}
set {
base.MoveTo = new Vector3(value, base.MoveTo.Z);
} }
} }
public Camera2D(int width, int height) : base(width, height) { public Camera2D(int width, int height) : base(width, height) {
this.Orthographic = true; this.Orthographic = true;
this.LockedOrientation = true;
this.CameraFront = -Vector3.UnitZ;
} }
} }
} }

View File

@ -0,0 +1,22 @@
using System.Numerics;
namespace SlatedGameToolkit.Framework.Graphics.Render
{
public interface IMoveable
{
/// <summary>
/// A vector describing the position this object should move to.
/// This is then used to smooth the movement to the intermediate renders.
///
/// </summary>
/// <value>A vector describing the new position of the object by the end of the update.</value>
Vector3 MoveTo { get; set; }
/// <summary>
/// The current position of the entity.
/// </summary>
/// <value>A vector describing the current objects position.</value>
Vector3 Position { get; set; }
}
}

View File

@ -11,13 +11,14 @@ using SlatedGameToolkit.Framework.Utilities;
namespace SlatedGameToolkit.Framework.Graphics.Render namespace SlatedGameToolkit.Framework.Graphics.Render
{ {
public class MeshBatch : IDisposable { public class MeshBatch : IDisposable {
public GLContext GLContext {get; private set; }
private const int VERTEX_LENGTH = 9; private const int VERTEX_LENGTH = 9;
private bool disposed;
private float batchDelta;
public GLContext GLContext {get; private set; }
private int projALoc, viewALoc, modelALoc, texturedALoc; private int projALoc, viewALoc, modelALoc, texturedALoc;
private Camera camera; private Camera camera;
private RenderProgram renderProgram; private RenderProgram renderProgram;
private ITexture texture; private ITexture texture;
private bool disposed;
private VertexArrayBuffers vertexBuffers; private VertexArrayBuffers vertexBuffers;
public bool Batching { get; private set; } public bool Batching { get; private set; }
@ -59,10 +60,17 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
GLContext.UniformMatrix4fv(projALoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); GLContext.UniformMatrix4fv(projALoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray());
} }
public virtual void Begin(Matrix4x4 modelsMatrix) { /// <summary>
/// Begins a mesh batch for rendering.
/// </summary>
/// <param name="modelsMatrix">The models matrix.</param>
/// <param name="delta">The time elapsed since the last update.</param>
public virtual void Begin(Matrix4x4 modelsMatrix, double delta) {
if (Batching) throw new InvalidOperationException("This batch is already started."); if (Batching) throw new InvalidOperationException("This batch is already started.");
this.Batching = true; this.Batching = true;
this.modelsMatrix = modelsMatrix; this.modelsMatrix = modelsMatrix;
this.batchDelta = (float)delta;
} }
/// <summary> /// <summary>
@ -70,6 +78,14 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
/// </summary> /// </summary>
/// <param name="mesh">Draws the given mesh.</param> /// <param name="mesh">Draws the given mesh.</param>
public virtual void Draw(IMesh mesh) { public virtual void Draw(IMesh mesh) {
IMoveable moveable = mesh as IMoveable;
if (moveable != null) {
if (GameEngine.UpdatesPerSecond <= 0) {
camera.Position = camera.MoveTo;
} else {
camera.Position = camera.Position + (camera.MoveTo - camera.Position) * batchDelta;
}
}
if (mesh.Texture?.Handle != this.texture?.Handle) { if (mesh.Texture?.Handle != this.texture?.Handle) {
Flush(); Flush();
this.texture = mesh.Texture; this.texture = mesh.Texture;
@ -121,6 +137,12 @@ namespace SlatedGameToolkit.Framework.Graphics.Render
protected virtual void Flush() { protected virtual void Flush() {
texture?.Use(); texture?.Use();
renderProgram.Use(); renderProgram.Use();
if (GameEngine.UpdatesPerSecond <= 0) {
camera.Position = camera.MoveTo;
} else {
camera.Position = camera.Position + (camera.MoveTo - camera.Position) * batchDelta;
}
vertexBuffers.BufferVertices(data, true); vertexBuffers.BufferVertices(data, true);
vertexBuffers.BufferIndices(indices, true); vertexBuffers.BufferIndices(indices, true);
GLContext.UniformMatrix4fv(modelALoc, 1, false, modelsMatrix.ToColumnMajorArray()); GLContext.UniformMatrix4fv(modelALoc, 1, false, modelsMatrix.ToColumnMajorArray());

View File

@ -37,14 +37,14 @@ namespace SlatedGameToolkit.Framework.StateSystem
addState(initialState); addState(initialState);
} }
internal void update(double delta) { internal void update(double timeStep) {
if (nextState != null) { if (nextState != null) {
if (currentState.Deactivate() & nextState.Activate()) { if (currentState.Deactivate() & nextState.Activate()) {
currentState = nextState; currentState = nextState;
nextState = null; nextState = null;
} }
} }
currentState.Update(delta); currentState.Update(timeStep);
} }
internal void render(double delta) { internal void render(double delta) {

View File

@ -29,8 +29,8 @@ namespace SlatedGameToolkit.Framework.StateSystem.States
/// Called in intervals dependent on game loop chosen for every update cycle. /// Called in intervals dependent on game loop chosen for every update cycle.
/// Only called on if this state is the active state, indicated on the last status method called on this implementation (acitvate, and deactivate). /// Only called on if this state is the active state, indicated on the last status method called on this implementation (acitvate, and deactivate).
/// </summary> /// </summary>
/// <param name="delta">The time in seconds that has passed since the last update.</param> /// <param name="timeStep">The change in time between the updates in seconds. If fixed, this amounts to the portion of time between the set update rate. If unlocked, represents the actual amount of time passed since the last update.</param>
void Update(double delta); void Update(double timeStep);
/// <summary> /// <summary>
/// Called in intervals dependent on game loop chose for every render cycle. /// Called in intervals dependent on game loop chose for every render cycle.

View File

@ -19,6 +19,7 @@ namespace SlatedGameToolkit.Tools.Commands
interactable.Tell("Engine is already running!"); interactable.Tell("Engine is already running!");
return true; return true;
} }
GameEngine.Ignite(new MainState()); GameEngine.Ignite(new MainState());
return true; return true;
} else if (args[0].Equals("stop")) { } else if (args[0].Equals("stop")) {

View File

@ -77,26 +77,26 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground
public void Render(double delta) public void Render(double delta)
{ {
renderer.Begin(Matrix4x4.Identity); renderer.Begin(Matrix4x4.Identity, delta);
renderer.Draw(logo); renderer.Draw(logo);
renderer.Draw(textureTester); renderer.Draw(textureTester);
renderer.Draw(untextured); renderer.Draw(untextured);
renderer.End(); renderer.End();
} }
public void Update(double delta) public void Update(double timeStep)
{ {
if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_DOWN)) { if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_DOWN)) {
camera.Position += new Vector2(0, (float)(-0.5f * delta)); camera.MoveTo += new Vector2(0, (-0.25f)) * (float) timeStep;
} }
if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_UP)) { if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_UP)) {
camera.Position += new Vector2(0, (float)(0.5f * delta)); camera.MoveTo += new Vector2(0, (0.25f)) * (float) timeStep;
} }
if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_LEFT)) { if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_LEFT)) {
camera.Position += new Vector2((float)(-0.5f * delta), 0); camera.MoveTo += new Vector2((-0.25f) * (float) timeStep, 0);
} }
if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_RIGHT)) { if (Keyboard.IsKeyPressed(SDL.SDL_Keycode.SDLK_RIGHT)) {
camera.Position += new Vector2((float)(0.5f * delta), 0); camera.MoveTo += new Vector2((0.25f) * (float) timeStep, 0);
} }
} }
} }