Example #1
0
func TestRoundTrip(t *testing.T) {
	cam, _, _ := initScene()
	cx, cy, cz := 0.0, 0.0, 14.0 // camera location to
	cam.SetLocation(cx, cy, cz)  // ...point directly at 0, 0, 0

	// Create the matricies to go between clip and world space.
	toClip := lin.NewM4().Mult(cam.vm, cam.pm)
	toWorld := lin.NewM4().Mult(cam.ipm, cam.ivm)
	if !lin.NewM4().Mult(toClip, toWorld).Aeq(lin.M4I) {
		t.Errorf("Invalid world<->clip matricies")
	}

	// start with world coordinates carefully chosen to give x=1, y=1 clip values
	px, py := 6.002062, 3.751289
	pnt := lin.NewV4().SetS(px, py, 0, 1)
	pnt.MultMv(toClip, pnt)
	if !lin.Aeq(pnt.X/pnt.W, 1) || !lin.Aeq(pnt.Y/pnt.W, 1) {
		t.Errorf("%f %f gave clip %f %f %f, expected (1 1 -0.071429)", px, py, pnt.X, pnt.Y, pnt.Z)
	}

	// now reverse back to world coordinates.
	pnt.MultMv(toWorld, pnt)
	if !lin.Aeq(pnt.X, px) || !lin.Aeq(pnt.Y, py) {
		t.Errorf("got point %f %f %f, expected x=%f y=%f", pnt.X, pnt.Y, pnt.Z, px, py)
	}
}
Example #2
0
// Test perspective and view inverses.
func TestInverses(t *testing.T) {
	cam, _, _ := initScene()
	cam.AdjustPitch(45)
	cam.Move(0, -15, 15, cam.Lookat())

	// the inverses multiplied with non-inverses should be the identity matrix.
	if !lin.NewM4().Mult(cam.pm, cam.ipm).Aeq(lin.M4I) {
		t.Error("Invalid inverse projection matrix")
	}
	if !lin.NewM4().Mult(cam.vm, cam.ivm).Aeq(lin.M4I) {
		t.Error("Invalid inverse view matrix")
	}
}
Example #3
0
File: tr.go Project: skyview059/vu
// initScene is one time initialization that creates a single VAO
func (tag *trtag) initScene() {
	tag.mvp64 = lin.NewM4()
	tag.persp = lin.NewM4().Persp(60, float64(600)/float64(600), 0.1, 50)
	tag.mvp = render.NewMvp()
	tag.initData()

	// Bind the OpenGL calls and dump some version info.
	gl.Init()
	fmt.Printf("%s %s", gl.GetString(gl.RENDERER), gl.GetString(gl.VERSION))
	fmt.Printf(" GLSL %s\n", gl.GetString(gl.SHADING_LANGUAGE_VERSION))

	// Gather the one scene into this one vertex array object.
	gl.GenVertexArrays(1, &tag.vao)
	gl.BindVertexArray(tag.vao)

	// create shaders
	tag.initShader()
	gl.UseProgram(tag.shaders)

	// vertex data.
	var vbuff uint32
	gl.GenBuffers(1, &vbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(tag.verticies)*4), gl.Pointer(&(tag.verticies[0])), gl.STATIC_DRAW)
	vattr := uint32(gl.GetAttribLocation(tag.shaders, "in_v"))
	gl.EnableVertexAttribArray(vattr)
	gl.VertexAttribPointer(vattr, 3, gl.FLOAT, false, 0, 0)

	// colour data.
	var cbuff uint32
	gl.GenBuffers(1, &cbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, cbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(tag.colour)*4), gl.Pointer(&(tag.colour[0])), gl.STATIC_DRAW)
	cattr := uint32(gl.GetAttribLocation(tag.shaders, "in_c"))
	gl.EnableVertexAttribArray(cattr)
	gl.VertexAttribPointer(cattr, 4, gl.FLOAT, false, 0, 0)

	// faces data.
	var ebuff uint32
	gl.GenBuffers(1, &ebuff)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuff)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(tag.faces)), gl.Pointer(&(tag.faces[0])), gl.STATIC_DRAW)

	// set some state that doesn't need to change during drawing.
	gl.ClearColor(0.0, 0.0, 0.0, 1.0)
	gl.Enable(gl.CULL_FACE)
	gl.CullFace(gl.BACK)
}
Example #4
0
File: ld.go Project: toophy/vu
// initScene is called once on startup to load the 3D data.
func (ld *ldtag) initScene() {
	ld.persp = lin.NewM4()
	ld.mvp64 = lin.NewM4()
	ld.mvp = render.NewMvp()
	gl.Init()
	ldr := load.NewLoader()
	meshes, _ := ldr.Obj("monkey")
	mesh := meshes[0]
	ld.faceCount = int32(len(mesh.F))

	// Gather the one scene into this one vertex array object.
	gl.GenVertexArrays(1, &ld.vao)
	gl.BindVertexArray(ld.vao)

	// vertex data.
	var vbuff uint32
	gl.GenBuffers(1, &vbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.V)*4), gl.Pointer(&(mesh.V[0])), gl.STATIC_DRAW)
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(0)

	// normal data.
	var nbuff uint32
	gl.GenBuffers(1, &nbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, nbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.N)*4), gl.Pointer(&(mesh.N[0])), gl.STATIC_DRAW)
	gl.VertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(1)

	// faces data, uint32 in this case, so 4 bytes per element.
	var fbuff uint32
	gl.GenBuffers(1, &fbuff)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, fbuff)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(mesh.F)*2), gl.Pointer(&(mesh.F[0])), gl.STATIC_DRAW)

	ld.initShader()
	gl.ClearColor(0.2, 0.2, 0.2, 1.0)
	gl.Enable(gl.DEPTH_TEST)
	gl.Enable(gl.CULL_FACE)

	// set the initial perspetive matrix.
	ld.resize(0, 0, 800, 600)
}
Example #5
0
File: iqm.go Project: skyview059/vu
// Concatenate each pose with the inverse base pose to avoid doing this at animation time.
// If the joint has a parent, then it needs to be pre-concatenated with its parent's base pose.
// Thus it all negates at animation time like so:
//    (parentPose * parentInverseBasePose) * (parentBasePose * childPose * childInverseBasePose) =>
//    parentPose * (parentInverseBasePose * parentBasePose) * childPose * childInverseBasePose =>
//    parentPose * childPose * childInverseBasePose
func (l *loader) genFrame(scr *scratch, pt *transform, pcnt, numPoses, parent int) *lin.M4 {
	pt.q.Unit()
	m4 := lin.NewM4().SetQ(pt.q)
	m4.Transpose(m4).ScaleSM(pt.s.X, pt.s.Y, pt.s.Z)       // apply scale before rotation.
	m4.Wx, m4.Wy, m4.Wz, m4.Ww = pt.t.X, pt.t.Y, pt.t.Z, 1 // translation added in, not multiplied.
	if parent >= 0 {
		// parentBasePose * childPose * childInverseBasePose
		return m4.Mult(scr.inversebaseframe[pcnt], m4).Mult(m4, scr.baseframe[parent])
	} else {
		// childPose * childInverseBasePose
		return m4.Mult(scr.inversebaseframe[pcnt], m4)
	}
}
Example #6
0
File: iqm.go Project: skyview059/vu
// createBaseFrames constructs the joint transform base-pose matricies.
// These are temporary structures used later in genFrame to prepare the
// per-frame animation data.
func (l *loader) createBaseFrames(iqd *IqData, poses []*transform, scr *scratch) {
	i3 := lin.NewM3()                                   // scratch
	vx, vy, vz := lin.NewV3(), lin.NewV3(), lin.NewV3() // scratch
	numJoints := len(poses)
	scr.baseframe = make([]*lin.M4, numJoints)        // joint transforms.
	scr.inversebaseframe = make([]*lin.M4, numJoints) // inverse transforms.
	for cnt := 0; cnt < numJoints; cnt++ {
		j := poses[cnt]

		// Get the joint transform.
		j.q.Unit() // ensure unit quaternion.
		m4 := lin.NewM4().SetQ(j.q)
		m4.Transpose(m4).ScaleSM(j.s.X, j.s.Y, j.s.Z)       // apply scale before rotation.
		m4.Wx, m4.Wy, m4.Wz, m4.Ww = j.t.X, j.t.Y, j.t.Z, 1 // translation added in, not multiplied.
		scr.baseframe[cnt] = m4

		// invert the joint transform for frame generation later on.
		i3.Inv(i3.SetM4(m4))
		itx := -vx.SetS(i3.Xx, i3.Yx, i3.Zx).Dot(j.t)
		ity := -vy.SetS(i3.Xy, i3.Yy, i3.Zy).Dot(j.t)
		itz := -vz.SetS(i3.Xz, i3.Yz, i3.Zz).Dot(j.t)
		i4 := lin.NewM4()
		i4.Xx, i4.Xy, i4.Xz, i4.Xw = i3.Xx, i3.Xy, i3.Xz, 0
		i4.Yx, i4.Yy, i4.Yz, i4.Yw = i3.Yx, i3.Yy, i3.Yz, 0
		i4.Zx, i4.Zy, i4.Zz, i4.Zw = i3.Zx, i3.Zy, i3.Zz, 0
		i4.Wx, i4.Wy, i4.Wz, i4.Ww = itx, ity, itz, 1
		scr.inversebaseframe[cnt] = i4

		// Combine the joint transforms and inverse transform with the parent transform.
		parent := iqd.Joints[cnt]
		if parent >= 0 {
			// childBasePose * parentBasePose
			scr.baseframe[cnt].Mult(scr.baseframe[cnt], scr.baseframe[parent])

			// childInverseBasePose * parentInverseBasePose
			scr.inversebaseframe[cnt].Mult(scr.inversebaseframe[parent], scr.inversebaseframe[cnt])
		}
	}
}
Example #7
0
File: sf.go Project: toophy/vu
// initScene is one time initialization that creates a single VAO
func (sf *sftag) initScene() {
	sf.sTime = time.Now()
	sf.initData()

	// Bind the OpenGL calls and dump some version info.
	gl.Init()
	fmt.Printf("%s %s", gl.GetString(gl.RENDERER), gl.GetString(gl.VERSION))
	fmt.Printf(" GLSL %s\n", gl.GetString(gl.SHADING_LANGUAGE_VERSION))
	gl.GenVertexArrays(1, &sf.vao)
	gl.BindVertexArray(sf.vao)

	// vertex data.
	var vbuff uint32
	gl.GenBuffers(1, &vbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(sf.verticies)*4), gl.Pointer(&(sf.verticies[0])), gl.STATIC_DRAW)
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(0)

	// faces data.
	var ebuff uint32
	gl.GenBuffers(1, &ebuff)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuff)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(sf.faces)), gl.Pointer(&(sf.faces[0])), gl.STATIC_DRAW)

	// create texture and shaders after all the data has been set up.
	// renderer := render.New()
	shader := "fire"
	loader := load.NewLoader()
	vsrc, verr := loader.Vsh(shader)
	fsrc, ferr := loader.Fsh(shader)
	if verr == nil && ferr == nil {
		sf.shaders = gl.CreateProgram()
		if err := gl.BindProgram(sf.shaders, vsrc, fsrc); err != nil {
			fmt.Printf("Failed to create program: %s\n", err)
		}
		sf.mvpref = gl.GetUniformLocation(sf.shaders, "mvpm")
		sf.gTime = gl.GetUniformLocation(sf.shaders, "time")
		sf.sizes = gl.GetUniformLocation(sf.shaders, "screen")
		sf.mvp = render.NewMvp().Set(lin.NewM4().Ortho(0, 4, 0, 4, 0, 10))

		// set some state that doesn't need to change during drawing.
		gl.ClearColor(0.0, 0.0, 0.0, 1.0)
	}
}
Example #8
0
File: rt.go Project: skyview059/vu
// initRender is one time initialization that creates a single VAO
// to display a single ray trace generated texture.
func (rt *rtrace) initRender() {
	rt.verts = []float32{ // four verticies for a quad.
		0, 0, 0,
		4, 0, 0,
		0, 4, 0,
		4, 4, 0,
	}
	rt.faces = []uint8{ // create quad from 2 triangles.
		0, 2, 1,
		1, 2, 3,
	}
	rt.uvs = []float32{ // texture coordinates to sample the image.
		0, 0,
		1, 0,
		0, 1,
		1, 1,
	}

	// Start up OpenGL and create a single vertex array object.
	gl.Init()
	gl.GenVertexArrays(1, &rt.vao)
	gl.BindVertexArray(rt.vao)

	// vertex data.
	var vbuff uint32
	gl.GenBuffers(1, &vbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(rt.verts)*4), gl.Pointer(&(rt.verts[0])), gl.STATIC_DRAW)
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(0)

	// faces data.
	var ebuff uint32
	gl.GenBuffers(1, &ebuff)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuff)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(rt.faces)), gl.Pointer(&(rt.faces[0])), gl.STATIC_DRAW)

	// texture coordatinates
	var tbuff uint32
	gl.GenBuffers(1, &tbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, tbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(rt.uvs)*4), gl.Pointer(&(rt.uvs[0])), gl.STATIC_DRAW)
	var tattr uint32 = 2
	gl.VertexAttribPointer(tattr, 2, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(tattr)

	// use ray trace generated texture image.
	bounds := rt.img.Bounds()
	width, height := int32(bounds.Dx()), int32(bounds.Dy())
	ptr := gl.Pointer(&(rt.img.Pix[0]))
	gl.GenTextures(1, &rt.texId)
	gl.BindTexture(gl.TEXTURE_2D, rt.texId)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, ptr)

	// texture sampling shader.
	loader := load.NewLoader()
	shader := "tuv"
	vsrc, verr := loader.Vsh(shader)
	fsrc, ferr := loader.Fsh(shader)
	if verr != nil || ferr != nil {
		log.Fatalf("Failed to load shaders %s %s\n", verr, ferr)
	}
	rt.shaders = gl.CreateProgram()
	if err := gl.BindProgram(rt.shaders, vsrc, fsrc); err != nil {
		log.Fatalf("Failed to create program: %s\n", err)
	}
	rt.mvpId = gl.GetUniformLocation(rt.shaders, "mvpm")
	rt.tex2D = gl.GetUniformLocation(rt.shaders, "sampler2D")
	rt.mvp = render.NewMvp().Set(lin.NewM4().Ortho(0, 4, 0, 4, 0, 10))

	// set some state that doesn't need to change during drawing.
	gl.ClearColor(0.0, 0.0, 0.0, 1.0)
}