func main() { // Initialize GLFW for window management glfw.SetErrorCallback(glfwErrorCallback) if !glfw.Init() { panic("failed to initialize glfw") } defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 3) glfw.WindowHint(glfw.ContextVersionMinor, 3) glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True) // Necessary for OS X glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile) // Necessary for OS X glfw.WindowHint(glfw.OpenglDebugContext, glfw.True) window, err := glfw.CreateWindow(WindowWidth, WindowHeight, "Cube", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // Initialize Glow if err := gl.Init(); err != nil { panic(err) } // Note that it is possible to use GL functions spanning multiple versions if err := gl4.Init(); err != nil { fmt.Printf("Could not initialize GL 4.4 (non-fatal)") } if gl.ARB_debug_output { gl.Enable(gl.DEBUG_OUTPUT_SYNCHRONOUS_ARB) gl.DebugMessageCallbackARB(gl.DebugProc(glDebugCallback), gl.Ptr(nil)) // Trigger an error to demonstrate debug output gl.Enable(gl.CONTEXT_FLAGS) } version := gl.GoStr(gl.GetString(gl.VERSION)) fmt.Println("OpenGL version", version) // Configure the vertex and fragment shaders program, err := newProgram(vertexShader, fragmentShader) if err != nil { panic(err) } gl.UseProgram(program) projection := mgl32.Perspective(70.0, float32(WindowWidth)/WindowHeight, 0.1, 10.0) projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) camera := mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00")) gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0]) model := mgl32.Ident4() modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00")) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) textureUniform := gl.GetUniformLocation(program, gl.Str("tex\x00")) gl.Uniform1i(textureUniform, 0) gl.BindFragDataLocation(program, 0, gl.Str("outputColor\x00")) // Load the texture texture, err := newTexture("square.png") if err != nil { panic(err) } // Configure the vertex data var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertTexCoord\x00"))) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) // Configure global settings gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(1.0, 1.0, 1.0, 1.0) angle := 0.0 previousTime := glfw.GetTime() for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) // Update time := glfw.GetTime() elapsed := time - previousTime previousTime = time angle += elapsed model = mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0}) // Render gl.UseProgram(program) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) gl.BindVertexArray(vao) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) // Maintenance window.SwapBuffers() glfw.PollEvents() } }
func (self *OpenGLWindow) TimeSinceLast() float32 { if self.timeLastCall == 0 { self.timeLastCall = glfw.GetTime() } now := glfw.GetTime() diff := now - self.timeLastCall self.timeLastCall = now return float32(diff) }
func (ship *Ship) shoot() { if ship.shooting && glfw.GetTime() > ship.lastBulletFired+(1/ship.bulletsPerSecond) && ship.IsAlive() { var rad float64 = ((ship.Angle) * math.Pi) / 180 x, y := RotateVector(&Vector{0, 5}, ship.Angle) bullet := NewBullet( ship.PosX+x, ship.PosY+y, ship.MaxVelocity*math.Sin(rad)*2, ship.MaxVelocity*math.Cos(rad)*2, ) bullets = append(bullets, bullet) ship.lastBulletFired = glfw.GetTime() } }
func main() { glfw.SetErrorCallback(errorCallback) if !glfw.Init() { panic("Can't init glfw!") } defer glfw.Terminate() window, err := glfw.CreateWindow(800, 640, "MyGui", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() glfw.SwapInterval(1) gl.Init() mvp := prepareModelViewProjection(800, 640) prepareScene() dt := float64(0) glfw.SetTime(dt) for !window.ShouldClose() { dt = glfw.GetTime() glfw.SetTime(0) updateScene(dt) drawScene(mvp, dt) window.SwapBuffers() glfw.PollEvents() } }
func (torpedo *Torpedo) Update() { if paused { timediff := (glfw.GetTime() - torpedo.Entity.lastUpdatedTime) torpedo.MaxLifetime = torpedo.MaxLifetime + timediff } torpedo.Entity.Update() }
func (bullet *Bullet) Update() { if paused { timediff := (glfw.GetTime() - bullet.Entity.lastUpdatedTime) bullet.MaxLifetime = bullet.MaxLifetime + timediff } bullet.Entity.Update() }
func (explosion *Explosion) Update() { if paused { timediff := (glfw.GetTime() - explosion.Entity.lastUpdatedTime) explosion.MaxLifetime = explosion.MaxLifetime + timediff } explosion.Entity.Update() for l, _ := range explosion.Lines { explosion.Lines[l].Update() } }
func NewEntity(shape Polygon, x, y, angle, turnrate, vX, vY, accel, maxvel float64) *Entity { return &Entity{ Shape: shape, PosX: x, PosY: y, Angle: angle, TurnRate: turnrate, VelocityX: vX, VelocityY: vY, AccelerationRate: accel, MaxVelocity: maxvel, rotateLeft: false, rotateRight: false, accelerate: false, decelerate: false, isAlive: true, createdTime: glfw.GetTime(), lastUpdatedTime: glfw.GetTime(), } }
func main() { initGlfw() defer terminateGlfw() window := createWindow(int(width), int(height)) game := NewGame(window) profiler := NewProfiler(game.text) defer game.delete() previousFrameTime := glfw.GetTime() profiler.start() for !window.ShouldClose() { now := glfw.GetTime() elapsed := now - previousFrameTime previousFrameTime = now game.update(elapsed) game.render() profiler.update() profiler.render() window.SwapBuffers() glfw.PollEvents() } }
func (explosion *BigExplosion) Update() { timediff := (glfw.GetTime() - explosion.Entity.lastUpdatedTime) if paused { explosion.MaxLifetime = explosion.MaxLifetime + timediff } else { addSize := 50 * timediff for v := range explosion.Entity.Shape.Vectors { explosion.Entity.Shape.Vectors[v].X = explosion.Entity.Shape.Vectors[v].X / explosion.Size * (explosion.Size + addSize) explosion.Entity.Shape.Vectors[v].Y = explosion.Entity.Shape.Vectors[v].Y / explosion.Size * (explosion.Size + addSize) } explosion.Size += addSize } explosion.Entity.Update() }
func (this *Profiler) update() { frameCount := len(this.frameTimes) now := glfw.GetTime() this.frameTimes[this.frame%frameCount] = now - this.lastTime movingAverage := 0.0 for _, f := range this.frameTimes { movingAverage += f } movingAverage /= float64(frameCount) if this.frame%frameCount == 0 { this.frameSpeed = movingAverage } this.lastTime = now this.frame++ }
func (me *context) Time() float64 { return glfw.GetTime() }
func (this *Profiler) start() { this.lastTime = glfw.GetTime() }
func (explosion *BigExplosion) IsAlive() bool { if glfw.GetTime() > explosion.createdTime+explosion.MaxLifetime { return false } return explosion.Entity.IsAlive() }
func (ent *Entity) Update() { if paused { ent.lastUpdatedTime = glfw.GetTime() } else { timediff := (glfw.GetTime() - ent.lastUpdatedTime) * 500 ent.lastUpdatedTime = glfw.GetTime() var rad float64 = ((ent.Angle) * math.Pi) / 180 // rotation if ent.rotateLeft { ent.Angle = ent.Angle - (ent.TurnRate * timediff) if ent.Angle < 0 { ent.Angle += 360 } } else if ent.rotateRight { ent.Angle = ent.Angle + (ent.TurnRate * timediff) if ent.Angle > 360 { ent.Angle -= 360 } } /* 0° Sin(0), Cos(1) 90° Sin(1), Cos(0) 180° Sin(0), Cos(-1) 270° Sin(-1), Cos(0) */ if ent.accelerate { ent.VelocityX = ent.VelocityX + (ent.AccelerationRate * math.Sin(rad)) ent.VelocityY = ent.VelocityY + (ent.AccelerationRate * math.Cos(rad)) } else if ent.decelerate { ent.VelocityX = ent.VelocityX - (ent.AccelerationRate * math.Sin(rad)) ent.VelocityY = ent.VelocityY - (ent.AccelerationRate * math.Cos(rad)) } // max velocity totalVelocity := math.Sqrt(ent.VelocityX*ent.VelocityX + ent.VelocityY*ent.VelocityY) if totalVelocity > ent.MaxVelocity { ent.VelocityX = ent.VelocityX / totalVelocity ent.VelocityY = ent.VelocityY / totalVelocity ent.VelocityX = ent.VelocityX * ent.MaxVelocity ent.VelocityY = ent.VelocityY * ent.MaxVelocity } // move ent.PosX = ent.VelocityX*timediff + ent.PosX ent.PosY = ent.VelocityY*timediff + ent.PosY // crude zone clipping // TODO: for now it works, but needs to be updated for seamless clipping.. if ent.PosX > gameWidth { ent.PosX -= gameWidth } else if ent.PosX < 0 { ent.PosX += gameWidth } if ent.PosY > gameHeight { ent.PosY -= gameHeight } else if ent.PosY < 0 { ent.PosY += gameHeight } } }
func (a *Application) update() { a.Width, a.Height = a.window.GetSize() now := float32(glfw.GetTime()) a.DeltaTime = now - a.Time a.Time = now }
// GetTime returns the number of seconds since the timer was started. // // Please refer to http://www.glfw.org/docs/latest/input.html#time for more // information. func GetTime() float64 { return glfw.GetTime() }
func (torpedo *Torpedo) IsAlive() bool { if glfw.GetTime() > torpedo.createdTime+torpedo.MaxLifetime { torpedo.Destroy() } return torpedo.Entity.IsAlive() }
// update animation parameters func animate() { angle = 100.0 * glfw.GetTime() }
func main() { runtime.LockOSThread() if !glfw.Init() { fmt.Fprintf(os.Stderr, "Can't open GLFW") return } defer glfw.Terminate() glfw.WindowHint(glfw.Samples, 4) glfw.WindowHint(glfw.ContextVersionMajor, 3) glfw.WindowHint(glfw.ContextVersionMinor, 3) glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile) glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True) // needed for macs window, err := glfw.CreateWindow(1024, 768, "Tutorial 8", nil, nil) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) return } window.MakeContextCurrent() gl.Init() gl.GetError() // Ignore error window.SetInputMode(glfw.StickyKeys, 1) window.SetCursorPosition(1024/2, 768/2) window.SetInputMode(glfw.Cursor, glfw.CursorHidden) gl.ClearColor(0., 0., 0.4, 0.) gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.Enable(gl.CULL_FACE) camera := input.NewCamera(window) vertexArray := gl.GenVertexArray() defer vertexArray.Delete() vertexArray.Bind() prog := helper.MakeProgram("StandardShading.vertexshader", "StandardShading.fragmentshader") defer prog.Delete() matrixID := prog.GetUniformLocation("MVP") viewMatrixID := prog.GetUniformLocation("V") modelMatrixID := prog.GetUniformLocation("M") texture, err := helper.TextureFromDDS("uvmap.DDS") if err != nil { fmt.Printf("Could not load texture: %v\n", err) } defer texture.Delete() texSampler := prog.GetUniformLocation("myTextureSampler") meshObj := objloader.LoadObject("suzanne.obj", true) indices, indexedVertices, indexedUVs, indexedNormals := indexer.IndexVBOSlow(meshObj.Vertices, meshObj.UVs, meshObj.Normals) vertexBuffer := gl.GenBuffer() defer vertexBuffer.Delete() vertexBuffer.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, len(indexedVertices)*3*4, indexedVertices, gl.STATIC_DRAW) uvBuffer := gl.GenBuffer() defer uvBuffer.Delete() uvBuffer.Bind(gl.ARRAY_BUFFER) // And yet, the weird length stuff doesn't seem to matter for UV or normal gl.BufferData(gl.ARRAY_BUFFER, len(indexedUVs)*2*4, indexedUVs, gl.STATIC_DRAW) normBuffer := gl.GenBuffer() defer normBuffer.Delete() normBuffer.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, len(indexedNormals)*3*4, indexedNormals, gl.STATIC_DRAW) elementBuffer := gl.GenBuffer() defer elementBuffer.Delete() elementBuffer.Bind(gl.ELEMENT_ARRAY_BUFFER) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*2, indices, gl.STATIC_DRAW) // NOTE: a GL_UNSIGNED_SHORT is 16-bits lightID := prog.GetUniformLocation("LightPosition_worldspace") lastTime := glfw.GetTime() nbFrames := 0 // Equivalent to a do... while for ok := true; ok; ok = (window.GetKey(glfw.KeyEscape) != glfw.Press && !window.ShouldClose()) { currTime := glfw.GetTime() nbFrames++ if currTime-lastTime >= 1.0 { fmt.Printf("%f ms/frame\n", 1000.0/float64(nbFrames)) nbFrames = 0 lastTime += 1.0 } func() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) prog.Use() defer gl.ProgramUnuse() view, proj := camera.ComputeViewPerspective() model := mgl32.Ident4() MVP := proj.Mul4(view).Mul4(model) //mvpArray := mvp.AsCMOArray(mathgl.FLOAT32).([16]float32) //vArray := view.AsCMOArray(mathgl.FLOAT32).([16]float32) //mArray := model.AsCMOArray(mathgl.FLOAT32).([16]float32) matrixID.UniformMatrix4fv(false, MVP) viewMatrixID.UniformMatrix4fv(false, view) modelMatrixID.UniformMatrix4fv(false, model) lightID.Uniform3f(4., 4., 4.) gl.ActiveTexture(gl.TEXTURE0) texture.Bind(gl.TEXTURE_2D) defer texture.Unbind(gl.TEXTURE_2D) texSampler.Uniform1i(0) vertexAttrib := gl.AttribLocation(0) vertexAttrib.EnableArray() defer vertexAttrib.DisableArray() vertexBuffer.Bind(gl.ARRAY_BUFFER) defer vertexBuffer.Unbind(gl.ARRAY_BUFFER) vertexAttrib.AttribPointer(3, gl.FLOAT, false, 0, nil) uvAttrib := gl.AttribLocation(1) uvAttrib.EnableArray() defer uvAttrib.DisableArray() uvBuffer.Bind(gl.ARRAY_BUFFER) defer uvBuffer.Unbind(gl.ARRAY_BUFFER) uvAttrib.AttribPointer(2, gl.FLOAT, false, 0, nil) normAttrib := gl.AttribLocation(2) normAttrib.EnableArray() defer normAttrib.DisableArray() normBuffer.Bind(gl.ARRAY_BUFFER) defer normBuffer.Unbind(gl.ARRAY_BUFFER) normAttrib.AttribPointer(3, gl.FLOAT, false, 0, nil) elementBuffer.Bind(gl.ELEMENT_ARRAY_BUFFER) defer elementBuffer.Unbind(gl.ELEMENT_ARRAY_BUFFER) gl.DrawElements(gl.TRIANGLES, len(indices), gl.UNSIGNED_SHORT, nil) window.SwapBuffers() glfw.PollEvents() }() // Defers unbinds and disables to here, end of the loop } }
// Since go has multiple return values, I just went ahead and made it return the view and perspective matrices (in that order) rather than messing with getter methods func (c *Camera) ComputeViewPerspective() (mgl32.Mat4, mgl32.Mat4) { if mgl64.FloatEqual(-1.0, c.time) { c.time = glfw.GetTime() } currTime := glfw.GetTime() deltaT := currTime - c.time xPos, yPos := c.window.GetCursorPosition() c.window.SetCursorPosition(width/2.0, height/2.0) c.hAngle += mouseSpeed * ((width / 2.0) - float64(xPos)) c.vAngle += mouseSpeed * ((height / 2.0) - float64(yPos)) dir := mgl32.Vec3{ float32(math.Cos(c.vAngle) * math.Sin(c.hAngle)), float32(math.Sin(c.vAngle)), float32(math.Cos(c.vAngle) * math.Cos(c.hAngle))} right := mgl32.Vec3{ float32(math.Sin(c.hAngle - math.Pi/2.0)), 0.0, float32(math.Cos(c.hAngle - math.Pi/2.0))} up := right.Cross(dir) if c.window.GetKey(glfw.KeyUp) == glfw.Press || c.window.GetKey('W') == glfw.Press { c.pos = c.pos.Add(dir.Mul(float32(deltaT * speed))) } if c.window.GetKey(glfw.KeyDown) == glfw.Press || c.window.GetKey('S') == glfw.Press { c.pos = c.pos.Sub(dir.Mul(float32(deltaT * speed))) } if c.window.GetKey(glfw.KeyRight) == glfw.Press || c.window.GetKey('D') == glfw.Press { c.pos = c.pos.Add(right.Mul(float32(deltaT * speed))) } if c.window.GetKey(glfw.KeyLeft) == glfw.Press || c.window.GetKey('A') == glfw.Press { c.pos = c.pos.Sub(right.Mul(float32(deltaT * speed))) } // Adding to the original tutorial, Space goes up if c.window.GetKey(glfw.KeySpace) == glfw.Press { c.pos = c.pos.Add(up.Mul(float32(deltaT * speed))) } // Adding to the original tutorial, left control goes down if c.window.GetKey(glfw.KeyLeftControl) == glfw.Press { c.pos = c.pos.Sub(up.Mul(float32(deltaT * speed))) } fov := initialFOV //- 5.0*float64(glfw.MouseWheel()) proj := mgl32.Perspective(float32(fov), 4.0/3.0, 0.1, 100.0) view := mgl32.LookAtV(c.pos, c.pos.Add(dir), up) c.time = currTime return view, proj }
func (bullet *Bullet) IsAlive() bool { if glfw.GetTime() > bullet.createdTime+bullet.MaxLifetime { return false } return bullet.Entity.IsAlive() }
func (a *Application) HighFreqTime() float64 { // TODO: cgo call overhead probably makes this less useful... return glfw.GetTime() }