leonsal пре 8 година
родитељ
комит
76055516a0
2 измењених фајлова са 94 додато и 1 уклоњено
  1. 17 1
      util/app/app.go
  2. 77 0
      util/app/framerater.go

+ 17 - 1
util/app/app.go

@@ -9,6 +9,7 @@ import (
 	"github.com/g3n/engine/audio/ov"
 	"github.com/g3n/engine/audio/vorbis"
 	"github.com/g3n/engine/camera"
+	"github.com/g3n/engine/core"
 	"github.com/g3n/engine/gls"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/renderer"
@@ -28,7 +29,9 @@ type App struct {
 	audioEFX    bool                 // Audio effect extension support available
 	audioDev    *al.Device           // Audio player device
 	captureDev  *al.Device           // Audio capture device
+	frameRater  *FrameRater
 	oCpuProfile *string
+	scene       *core.Node // Node container for 3D tests
 }
 
 type Options struct {
@@ -38,6 +41,7 @@ type Options struct {
 	VersionMinor int  // Application version minor
 	LogLevel     int  // Initial log level
 	EnableFlags  bool // Enable command line flags
+	TargetFPS    uint // Desired FPS
 }
 
 // appInstance points to the single Application instance
@@ -108,9 +112,15 @@ func Create(name string, ops Options) (*App, error) {
 	app.renderer = renderer.NewRenderer(gl)
 	err = app.renderer.AddDefaultShaders()
 	if err != nil {
-		return nil, fmt.Errorf("Erro from AddDefaulShaders:%v", err)
+		return nil, fmt.Errorf("Error from AddDefaulShaders:%v", err)
 	}
 
+	// Creates scene for 3D objects
+	app.scene = core.NewNode()
+
+	// Create frame rater
+	app.frameRater = NewFrameRater(60)
+
 	// Subscribe to window resize events
 	app.win.Subscribe(window.OnWindowSize, func(evname string, ev interface{}) {
 		app.OnWindowResize()
@@ -135,10 +145,16 @@ func (a *App) Window() window.IWindow {
 func (a *App) Run() {
 
 	for !a.win.ShouldClose() {
+		// Starts measuring this frame
+		a.frameRater.Start()
+
 		// Poll input events and process them
 		a.win.PollEvents()
 
 		a.win.SwapBuffers()
+
+		// Controls the frame rate and updates the FPS for the user
+		a.frameRater.Wait()
 	}
 }
 

+ 77 - 0
util/app/framerater.go

@@ -0,0 +1,77 @@
+package app
+
+import (
+	"time"
+)
+
+// FrameRater implements a frame rate controller
+type FrameRater struct {
+	targetFPS      uint          // desired number of frames per second
+	targetDuration time.Duration // calculated desired duration of frame
+	frameStart     time.Time     // start time of last frame
+	frameTimes     time.Duration // accumulated frame times for potential FPS calculation
+	frameCount     uint          // accumulated number of frames for FPS calculation
+	lastUpdate     time.Time     // time of last FPS calculation update
+	timer          *time.Timer   // timer for sleeping during frame
+}
+
+// NewFrameRater returns a frame rate controller object for the specified
+// number of target frames per second
+func NewFrameRater(targetFPS uint) *FrameRater {
+
+	f := new(FrameRater)
+	f.targetDuration = time.Second / time.Duration(targetFPS)
+	f.frameTimes = 0
+	f.frameCount = 0
+	f.lastUpdate = time.Now()
+	f.timer = time.NewTimer(0)
+	<-f.timer.C
+	return f
+}
+
+// Start should be called at the start of the frame
+func (f *FrameRater) Start() {
+
+	f.frameStart = time.Now()
+}
+
+// Wait should be called at the end of the frame
+// If necessary it will sleep to achieve the desired frame rate
+func (f *FrameRater) Wait() {
+
+	// Calculates the time duration of this frame
+	elapsed := time.Now().Sub(f.frameStart)
+	// Accumulates this frame time for potential FPS calculation
+	f.frameCount++
+	f.frameTimes += elapsed
+	// If this frame duration is less than the target duration, sleeps
+	// during the difference
+	diff := f.targetDuration - elapsed
+	if diff > 0 {
+		f.timer.Reset(diff)
+		<-f.timer.C
+	}
+}
+
+// FPS calculates and returns the current measured FPS and the maximum
+// potential FPS after the specified time interval has elapsed.
+// It returns an indication if the results are valid
+func (f *FrameRater) FPS(t time.Duration) (float64, float64, bool) {
+
+	// If the time from the last update has not passed, nothing to do
+	elapsed := time.Now().Sub(f.lastUpdate)
+	if elapsed < t {
+		return 0, 0, false
+	}
+
+	// Calculates the measured average frame rate
+	fps := float64(f.frameCount) / elapsed.Seconds()
+	// Calculates the average duration of a frame and the potential FPS
+	frameDur := f.frameTimes.Seconds() / float64(f.frameCount)
+	pfps := 1.0 / frameDur
+	// Resets the frame counter and times
+	f.frameCount = 0
+	f.frameTimes = 0
+	f.lastUpdate = time.Now()
+	return fps, pfps, true
+}