// gfxLoop is responsible for drawing things to the window. This loop must be // independent of the Chippy main loop. func gfxLoop(w *chippy.Window, r gfx.Renderer) { // Load the Ice file. scene, err := ice.LoadFile(os.Args[1]) if err != nil { log.Fatal(err) } // Setup a camera to use a perspective projection. camera := gfx.NewCamera() camFOV := 75.0 camNear := 0.1 camFar := 100.0 camera.SetPersp(r.Bounds(), camFOV, camNear, camFar) // Move the camera -2 on the Y axis (back two units away from the triangle // object). //camera.SetPos(math.Vec3{0, -50, 10}) //camera.SetPos(math.Vec3{0, -5, 2}) camera.SetPos(math.Vec3{0, -7, 3}) // Create a simple shader. shader := gfx.NewShader("SimpleShader") shader.GLSLVert = glslVert shader.GLSLFrag = glslFrag // Preload the shader (useful for seeing shader errors, if any). onLoad := make(chan *gfx.Shader, 1) r.LoadShader(shader, onLoad) go func() { <-onLoad shader.RLock() if !shader.Loaded { log.Println(string(shader.Error)) } shader.RUnlock() }() // Assign the shader to each object in the scene. for _, o := range scene.Objects { o.Shader = shader o.State.FaceCulling = gfx.NoFaceCulling //var verts = make([]gfx.Vec3, 0, len(o.Meshes[0].Indices)) //for _, v := range o.Meshes[0].Indices { // verts = append(verts, o.Meshes[0].Vertices[v]) //} //o.Meshes[0].Vertices = verts //o.Meshes[0].Indices = nil //if len(o.Meshes[0].Indices) > 5 { // log.Println(name, len(o.Meshes[0].Indices)) // bad := o.Meshes[0].Indices[743] // log.Println(o.Meshes[0].Vertices[bad]) // o.Meshes[0].Indices = o.Meshes[0].Indices[744-3:744] //} } // Start a goroutine to handle window events and move the camera around. go func() { event := w.Events() for { select { case e := <-event: switch ev := e.(type) { case keyboard.TypedEvent: if ev.Rune == 'm' { // Toggle MSAA now. msaa := !r.MSAA() r.SetMSAA(msaa) log.Println("MSAA Enabled?", msaa) } case mouse.Event: if ev.Button == mouse.Left && ev.State == mouse.Down { w.SetCursorGrabbed(!w.CursorGrabbed()) } } } } }() event := w.Events() for { camEvents: for { select { case e := <-event: switch ev := e.(type) { case chippy.ResizedEvent: // Update the camera's projection matrix for the new width and // height. camera.Lock() camera.SetPersp(r.Bounds(), camFOV, camNear, camFar) camera.Unlock() case chippy.CursorPositionEvent: if w.CursorGrabbed() { dt := r.Clock().Dt() camera.Lock() camRot := camera.Rot() camRot.Z -= 4 * ev.X * dt camRot.X -= 4 * ev.Y * dt camera.SetRot(camRot) camera.Unlock() } } default: break camEvents } } // Move the camera now. if w.CursorGrabbed() { dt := r.Clock().Dt() var local, parent math.Vec3 speed := 16.0 if w.Keyboard.Down(keyboard.A) { local.X -= speed * dt } if w.Keyboard.Down(keyboard.D) { local.X += speed * dt } if w.Keyboard.Down(keyboard.W) { local.Y += speed * dt } if w.Keyboard.Down(keyboard.S) { local.Y -= speed * dt } if w.Keyboard.Down(keyboard.LeftCtrl) { parent.Z -= speed * dt } if w.Keyboard.Down(keyboard.LeftShift) { parent.Z += speed * dt } camera.Lock() worldSpace := camera.ConvertPos(local, gfx.LocalToWorld) parentSpace := camera.ConvertPos(worldSpace, gfx.WorldToParent) camera.SetPos(parentSpace.Add(parent)) camera.Unlock() } // Clear the entire area (empty rectangle means "the whole area"). r.Clear(image.Rect(0, 0, 0, 0), gfx.Color{1, 1, 1, 1}) r.ClearDepth(image.Rect(0, 0, 0, 0), 1.0) // Draw each model in the scene. for _, o := range scene.Objects { r.Draw(image.Rect(0, 0, 0, 0), o, camera) } // Render the whole frame. r.Render() } }
// gfxLoop is responsible for drawing things to the window. This loop must be // independent of the Chippy main loop. func gfxLoop(w *chippy.Window, r gfx.Renderer) { w.SetSize(640, 640) w.SetPositionCenter(chippy.DefaultScreen()) glr := r.(*gl2.Renderer) glr.UpdateBounds(image.Rect(0, 0, 640, 640)) // Create a camera. // Wait for the shader to load (not strictly required). onLoad := make(chan *gfx.Shader, 1) r.LoadShader(Wireframe, onLoad) go func() { <-onLoad Wireframe.RLock() if Wireframe.Loaded { fmt.Println("Shader loaded") } else { fmt.Println(string(Wireframe.Error)) } Wireframe.RUnlock() }() // Create a triangle object. triangle := gfx.NewObject() triangle.Shader = Wireframe triangle.Meshes = []*gfx.Mesh{ &gfx.Mesh{}, } triangle.Meshes[0].GenerateBary() triangle.FaceCulling = gfx.NoFaceCulling triangle.AlphaMode = gfx.AlphaToCoverage tree := ntree.New() level := 0 go func() { events := w.Events() for { e := <-events kev, ok := e.(keyboard.TypedEvent) if ok { if kev.Rune == ' ' || kev.Rune == 'b' { for i := 0; i < 1; i++ { s := random(0.1, 0.15) if kev.Rune == 'b' { s = random(0.1, 0.5) } tree.Add(s) } // Create new mesh and ask the renderer to load it. newMesh := NTreeMesh(tree, level) onLoad := make(chan *gfx.Mesh, 1) r.LoadMesh(newMesh, onLoad) <-onLoad // Swap the mesh. triangle.Lock() triangle.Meshes[0] = newMesh triangle.Unlock() } if kev.Rune == '1' || kev.Rune == '2' { if kev.Rune == '1' { level-- } else { level++ } fmt.Println("level", level) // Create new mesh and ask the renderer to load it. newMesh := NTreeMesh(tree, level) onLoad := make(chan *gfx.Mesh, 1) r.LoadMesh(newMesh, onLoad) <-onLoad // Swap the mesh. triangle.Lock() triangle.Meshes[0] = newMesh triangle.Unlock() } if kev.Rune == 's' || kev.Rune == 'S' { fmt.Println("Writing screenshot to file...") // Download the image from the graphics hardware and save // it to disk. complete := make(chan image.Image, 1) r.Download(image.Rect(0, 0, 0, 0), complete) img := <-complete // Wait for download to complete. // Save to png. f, err := os.Create("screenshot.png") if err != nil { log.Fatal(err) } err = png.Encode(f, img) if err != nil { log.Fatal(err) } fmt.Println("Wrote texture to screenshot.png") } } } }() for { // Clear the entire area (empty rectangle means "the whole area"). r.Clear(image.Rect(0, 0, 0, 0), gfx.Color{1, 1, 1, 1}) r.ClearDepth(image.Rect(0, 0, 0, 0), 1.0) // Update the rotation. dt := r.Clock().Dt() triangle.RLock() rot := triangle.Transform.Rot() if w.Keyboard.Down(keyboard.ArrowLeft) { rot.Z += 90 * dt } if w.Keyboard.Down(keyboard.ArrowRight) { rot.Z -= 90 * dt } if w.Keyboard.Down(keyboard.ArrowUp) { rot.X += 20 * dt } if w.Keyboard.Down(keyboard.ArrowDown) { rot.X -= 20 * dt } triangle.Transform.SetRot(rot) triangle.RUnlock() // Draw the triangle to the screen. r.Draw(image.Rect(0, 0, 0, 0), triangle, nil) // Render the whole frame. r.Render() } }