// Check that the inverse of a perspective view is correct. func TestInverseVp(t *testing.T) { v := newCamera() v.at.Loc.SetS(10, 10, 10) v.at.Rot.SetAa(1, 0, 0, -lin.Rad(90)) vm := VP(v.at, lin.NewQ(), &lin.M4{}) ivm := ivp(v.at, &lin.Q{X: 1, Y: 0, Z: 0, W: 1}, lin.NewQ(), &lin.M4{}) if !vm.Mult(vm, ivm).Aeq(lin.M4I) { t.Errorf("Matrix times inverse should be identity") } }
// newCamera creates a default point of view that is looking down // the positive Z axis. func newCamera() *camera { c := &camera{depth: true} c.vt = VP c.at = lin.NewT() c.vm = &lin.M4{} c.ivm = (&lin.M4{}).Set(lin.M4I) c.pm = &lin.M4{} c.ipm = &lin.M4{} c.q0 = &lin.Q{} c.xrot = lin.NewQ().SetAa(1, 0, 0, 0) c.yrot = lin.NewQ().SetAa(0, 1, 0, 0) c.v0 = &lin.V4{} c.ray = &lin.V3{} return c }
// drawScene renders the 3D models consisting of one VAO func (tag *trtag) drawScene() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) tag.checkError("gl.Clear") gl.UseProgram(tag.shaders) tag.checkError("gl.UseProgram") gl.BindVertexArray(tag.vao) tag.checkError("gl.BindVertexArray") // Use a modelview matrix and quaternion to rotate the 3D object. tag.mvp64.SetQ(lin.NewQ().SetAa(0, 1, 0, lin.Rad(-tag.rotateAngle))) tag.mvp64.TranslateMT(0, 0, -4) tag.mvp.Set(tag.mvp64.Mult(tag.mvp64, tag.persp)) gl.UniformMatrix4fv(tag.mvpRef, 1, false, tag.mvp.Pointer()) if err := gl.GetError(); err != 0 { fmt.Printf("gl.UniformMatrix error %d\n", err) } gl.DrawElements(gl.TRIANGLES, int32(len(tag.faces)), gl.UNSIGNED_BYTE, 0) if err := gl.GetError(); err != 0 { fmt.Printf("gl.DrawElements error %d\n", err) } // cleanup gl.UseProgram(0) tag.checkError("gl.UseProgram-0") gl.BindVertexArray(0) tag.checkError("gl.BindVertexArray-0") // rotate based on time... not on how fast the computer runs. if time.Now().Sub(tag.lastTime).Seconds() > 0.01 { tag.rotateAngle += 1 tag.lastTime = time.Now() } }
// newPov allocates and initialzes a point of view transform. func newPov(eng *engine, eid uint64) *pov { p := &pov{eng: eng, eid: eid, visible: true} p.at = lin.NewT() p.scale = &lin.V3{X: 1, Y: 1, Z: 1} // allocate scratch variables. p.rot = lin.NewQ() p.mm = &lin.M4{} return p }