Example #1
0
func TestStackPushPopPeek(t *testing.T) {
	stack := NewTransformStack()

	if !stack.Peek().ApproxEqual(mgl32.Ident4()) {
		t.Errorf("Peek not working")
	}

	stack.Push(mgl32.HomogRotate3DY(mgl32.DegToRad(90)))

	if !stack.Peek().ApproxEqual(mgl32.HomogRotate3DY(mgl32.DegToRad(90))) {
		t.Errorf("Peek not working")
	}

	if stack.Len() != 2 {
		t.Errorf("Peek alters stack length")
	}

	pop, err := stack.Pop()
	if err != nil || !pop.ApproxEqual(mgl32.HomogRotate3DY(mgl32.DegToRad(90))) {
		t.Errorf("Pop is unsuccessful")
	}

	if stack.Len() != 1 {
		t.Errorf("Pop does not actually shorten stack")
	}

	_, err = stack.Pop()

	if err == nil {
		t.Errorf("Popping stack with 1 element does not return error as expected")
	}
}
Example #2
0
func TestStackMultiPush(t *testing.T) {
	stack := NewTransformStack()

	scale := mgl32.Scale3D(2, 2, 2)
	rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90))
	trans := mgl32.Translate3D(4, 5, 6)

	stack.Push(trans)
	stack.Push(rot)

	if !stack.Peek().ApproxEqualThreshold(trans.Mul4(rot), 1e-4) {
		t.Errorf("Stack does not multiply first two pushes correctly")
	}

	stack.Push(scale)

	if !stack.Peek().ApproxEqualThreshold(trans.Mul4(rot).Mul4(scale), 1e-4) {
		t.Errorf("Stack does not multiple third push correctly")
	}

	stack.Unwind(2)
	stack.Push(scale)

	if !stack.Peek().ApproxEqualThreshold(trans.Mul4(scale), 1e-4) {
		t.Errorf("Unwinding and multiplying does not work correctly")
	}
}
Example #3
0
func ExampleRebase() {
	parent1 := NewTransformStack()

	scale := mgl32.Scale3D(2, 2, 2)
	rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90))
	trans := mgl32.Translate3D(5, 5, 5)

	parent1.Push(trans)
	parent1.Push(rot)
	parent1.Push(scale)

	parent2 := parent1.Copy()

	trans2 := mgl32.Translate3D(1, 1, 1)
	rot2 := mgl32.HomogRotate3DX(mgl32.DegToRad(45))
	parent1.Push(trans2)
	parent1.Push(rot2)

	// Replay the pushes the changes from parent1 after the copy onto parent2, as if
	// they had been done on parent2 instead
	parent2, err := Rebase(parent1, 4, parent2)

	if err != nil {
		panic(err)
	}

	// Now parent2 and parent 1 should be the same!
	fmt.Println(parent2.Peek().ApproxEqualThreshold(parent1.Peek(), 1e-4))
	// Output: true
}
Example #4
0
func TestReseed(t *testing.T) {
	stack := NewTransformStack()

	scale := mgl32.Scale3D(2, 2, 2)
	rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90))
	trans := mgl32.Translate3D(4, 5, 6)

	stack.Push(trans)
	stack.Push(rot)
	stack.Push(scale)

	trans2 := mgl32.Translate3D(1, 2, 3)
	err := stack.Reseed(1, trans2)

	if err != nil {
		t.Fatalf("Rebase returned error when it should not %v", err)
	}

	if !stack.Peek().ApproxEqualThreshold(trans2.Mul4(rot).Mul4(scale), 1e-4) {
		t.Fatalf("Rebase does not remultiply correctly. Got\n %v expected\n %v. (Previous state:\n %v)", stack.Peek(), trans2.Mul4(rot).Mul4(scale), trans.Mul4(rot).Mul4(scale))
	}
}
Example #5
0
func TestRebase(t *testing.T) {
	stack := NewTransformStack()
	stack2 := NewTransformStack()

	scale := mgl32.Scale3D(2, 2, 2)
	rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90))
	trans := mgl32.Translate3D(4, 5, 6)
	trans2 := mgl32.Translate3D(1, 2, 3)

	stack.Push(trans)
	stack.Push(rot)

	stack2.Push(trans2)
	stack2.Push(scale)

	out, _ := Rebase(stack2, 1, stack)

	if !out.Peek().ApproxEqualThreshold(trans.Mul4(rot).Mul4(trans2).Mul4(scale), 1e-4) {
		t.Log("\n", out)
		t.Errorf("Rebase unsuccessful. Got\n %v, expected\n %v", out.Peek(), trans.Mul4(rot).Mul4(trans2).Mul4(scale))
	}
}
Example #6
0
func ExampleReseed() {
	stack := NewTransformStack()

	scale := mgl32.Scale3D(2, 2, 2)
	rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90))
	trans := mgl32.Translate3D(4, 5, 6)

	stack.Push(trans)
	stack.Push(rot)
	stack.Push(scale)

	fmt.Println("Initial state:\n", stack.Peek())

	trans2 := mgl32.Translate3D(1, 2, 3)

	err := stack.Reseed(1, trans2)
	if err == nil {
		panic("Rebase failed")
	}

	fmt.Println("After rebase:\n", stack.Peek())
	fmt.Println("Should be:\n", trans2.Mul4(rot).Mul4(scale))
}
Example #7
0
func main() {
	document := js.Global.Get("document")

	var viewportScale float32 = 2.0

	canvas := document.Call("createElement", "canvas")
	canvas.Set("id", "canvas")
	canvas.Set("width", viewportWidth*viewportScale)
	canvas.Set("height", viewportHeight*viewportScale)
	canvas.Get("style").Set("width", fmt.Sprintf("%dpx", int(viewportWidth)))
	canvas.Get("style").Set("height", fmt.Sprintf("%dpx", int(viewportHeight)))
	document.Get("body").Call("appendChild", canvas)

	textCanvas := document.Call("createElement", "canvas")
	textCanvas.Set("id", "text-canvas")
	textCanvas.Set("width", viewportWidth*viewportScale)
	textCanvas.Set("height", viewportHeight*viewportScale)
	textCanvas.Get("style").Set("width", fmt.Sprintf("%dpx", int(viewportWidth)))
	textCanvas.Get("style").Set("height", fmt.Sprintf("%dpx", int(viewportHeight)))
	document.Get("body").Call("appendChild", textCanvas)

	textContext := textCanvas.Call("getContext", "2d")
	textContext.Call("setTransform", viewportScale, 0, 0, viewportScale, 0, 0)

	attrs := webgl.DefaultAttributes()
	attrs.Alpha = false

	gl, err := webgl.NewContext(canvas, attrs)
	if err != nil {
		goggles.Error(err.Error())
		return
	}

	fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER)
	gl.ShaderSource(fragmentShader, fragmentShaderSource)
	gl.CompileShader(fragmentShader)
	if !gl.GetShaderParameterb(fragmentShader, gl.COMPILE_STATUS) {
		goggles.Error(gl.GetShaderInfoLog(fragmentShader))
		return
	}

	vertexShader := gl.CreateShader(gl.VERTEX_SHADER)
	gl.ShaderSource(vertexShader, vertexShaderSource)
	gl.CompileShader(vertexShader)
	if !gl.GetShaderParameterb(vertexShader, gl.COMPILE_STATUS) {
		goggles.Error(gl.GetShaderInfoLog(vertexShader))
		return
	}

	program := gl.CreateProgram()
	gl.AttachShader(program, vertexShader)
	gl.AttachShader(program, fragmentShader)
	gl.LinkProgram(program)
	if !gl.GetProgramParameterb(program, gl.LINK_STATUS) {
		goggles.Error(gl.GetProgramInfoLog(program))
		return
	}

	gl.UseProgram(program)

	inVertexPositionLocation := gl.GetAttribLocation(program, "inVertexPosition")
	inVertexColorLocation := gl.GetAttribLocation(program, "inVertexColor")
	modelViewMatrixLocation := gl.GetUniformLocation(program, "modelViewMatrix")
	projectionMatrixLocation := gl.GetUniformLocation(program, "projectionMatrix")

	gl.EnableVertexAttribArray(inVertexPositionLocation)
	gl.EnableVertexAttribArray(inVertexColorLocation)

	vertexPositionBuffer := gl.CreateBuffer()
	gl.BindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer)
	gl.BufferData(gl.ARRAY_BUFFER, vertexPositionData, gl.STATIC_DRAW)

	vertexColorBuffer := gl.CreateBuffer()
	gl.BindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer)
	gl.BufferData(gl.ARRAY_BUFFER, vertexColorData, gl.STATIC_DRAW)

	indexBuffer := gl.CreateBuffer()
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW)

	gl.Viewport(0, 0, int(viewportWidth*viewportScale), int(viewportHeight*viewportScale))

	var pitch float32 = 0.0
	var yaw float32 = 0.0
	var tweenTime float32 = 0.0

	var tick func(float32)

	tick = func(timeMs float32) {
		textContext.Call("clearRect", 0, 0, viewportWidth, viewportHeight)
		textContext.Set("font", "12px sans-serif")
		textContext.Set("fillStyle", "rgb(255, 255, 255)")
		textContext.Call("fillText", "Hello, world!", 10, 20)

		time := timeMs / 1000

		if tweenTime == 0.0 {
			tweenTime = time + 1.0
		}

		for tweenTime < time {
			tweenTime += 1.0
			pitch = float32(math.Mod(float64(pitch)+60.0, 360.0))
			yaw = float32(math.Mod(float64(yaw)+40.0, 360.0))
		}

		factor := tweenTime - time
		if factor < 0.0 {
			factor = 0.0
		} else if factor > 1.0 {
			factor = 1.0
		}
		factor = 1.0 - float32(math.Pow(float64(factor), 4.0))

		tweenPitch := pitch + (60.0 * factor)
		tweenYaw := yaw + (40.0 * factor)

		gl.ClearColor(0, 0, 0, 1)
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		gl.Enable(gl.CULL_FACE)
		gl.FrontFace(gl.CW)

		modelViewMatrix := mgl32.Ident4().
			Mul4(mgl32.Translate3D(0, 0, -4)).
			Mul4(mgl32.HomogRotate3DX(goggles.DegToRad(tweenPitch))).
			Mul4(mgl32.HomogRotate3DY(goggles.DegToRad(tweenYaw)))
		gl.UniformMatrix4fv(modelViewMatrixLocation, false, modelViewMatrix[:])

		projectionMatrix := mgl32.Perspective(goggles.DegToRad(60), viewportWidth/viewportHeight, 0.1, 2048)
		gl.UniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix[:])

		gl.BindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer)
		gl.VertexAttribPointer(inVertexPositionLocation, 3, gl.FLOAT, false, 0, 0)
		gl.BindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer)
		gl.VertexAttribPointer(inVertexColorLocation, 3, gl.FLOAT, false, 0, 0)
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
		gl.DrawElements(gl.TRIANGLES, len(indexData), gl.UNSIGNED_SHORT, 0)

		goggles.RequestAnimationFrame(tick)
	}

	goggles.RequestAnimationFrame(tick)
}
Example #8
0
func main() {
	// init glfw
	if err := glfw.Init(); err != nil {
		panic(err)
	}

	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	// make an application window
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "Transform", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// init gl
	if err := gl.Init(); err != nil {
		panic(err)
	}
	fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION)))

	// create vertex & fragment shader
	program, err := newProgram(vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}
	gl.UseProgram(program)

	projection := mgl32.Perspective(mgl32.DegToRad(45.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])

	gl.BindFragDataLocation(program, 0, gl.Str("vert\x00"))

	points := []float32{
		-0.9, -0.9, -0.9,
		0.9, -0.9, -0.9,
		0.9, -0.9, 0.9,
		-0.9, -0.9, 0.9,
		-0.9, 0.9, -0.9,
		0.9, 0.9, -0.9,
		0.9, 0.9, 0.9,
		-0.9, 0.9, 0.9,
	}

	vertices := []uint32{
		0, 1,
		1, 2,
		2, 3,
		3, 0,
		0, 4,
		1, 5,
		2, 6,
		3, 7,
		4, 5,
		5, 6,
		6, 7,
		7, 4,
	}

	// configure the vertex data
	var vao uint32
	gl.GenVertexArrays(1, &vao)
	gl.BindVertexArray(vao)

	defer gl.BindVertexArray(0)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW)

	var ibo uint32
	gl.GenBuffers(1, &ibo)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))

	// global settings
	gl.Enable(gl.DEPTH_TEST)
	gl.DepthFunc(gl.LESS)
	gl.ClearColor(0.0, 0.0, 0.0, 1.0)

	angleX := 0.0
	angleY := 0.0
	angleZ := 0.0
	previousTime := glfw.GetTime()

	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		time := glfw.GetTime()
		elapsed := time - previousTime
		previousTime = time

		angleX += math.Sin((elapsed / period) * math.Pi * 2.0)
		angleY += math.Sin((elapsed / period) / 6.0 * math.Pi * 2.0)
		angleZ += math.Sin((elapsed / period) / 3.0 * math.Pi * 2.0)
		model = mgl32.HomogRotate3DY(float32(angleY)).Mul4(mgl32.HomogRotate3DX(float32(angleX))).Mul4(mgl32.HomogRotate3DZ(float32(angleZ)))
		gl.UseProgram(program)
		gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])

		gl.BindVertexArray(vao)

		gl.DrawElements(gl.LINES, int32(len(vertices)), gl.UNSIGNED_INT, gl.PtrOffset(0))

		window.SwapBuffers()
		glfw.PollEvents()
	}
}