Example #1
0
// RotateTo adjusts the yaw and pitch to face a point.
func (c *QuatCamera) RotateTo(center mgl.Vec3) {
	direction := center.Sub(c.position).Normalize()
	right := direction.Cross(AxisUp)
	up := right.Cross(direction)

	c.rotation = mgl.QuatLookAtV(c.position, center, up)
}
Example #2
0
func safeNormalize(v mgl32.Vec3) mgl32.Vec3 {
	v = v.Normalize()
	if math.IsInf(float64(v[0]), 0) || math.IsNaN(float64(v[0])) {
		return mgl32.Vec3{}
	}
	return v
}
Example #3
0
func (e *Editor) MoveSelectedNodeModel(x, y float32, axisLock mgl32.Vec3) {
	selectedModel, _ := e.overviewMenu.getSelectedNode(e.currentMap.Root)
	if selectedModel != nil {
		selectedModel.Translation = selectedModel.Translation.Add(axisLock.Mul(x * mouseSpeed))
	}
	updateMap(e.currentMap.Root)
}
Example #4
0
//PointToLineDist distance from line (a,b) to point
func PointToLineDist(a, b, point mgl32.Vec3) float32 {
	ab := b.Sub(a)
	ap := point.Sub(a)
	prj := ap.Dot(ab)
	lenSq := ab.Dot(ab)
	t := prj / lenSq
	return ab.Mul(t).Add(a).Sub(point).Len()
}
Example #5
0
func (f *fPlane) setPoints(v1, v2, v3 mgl32.Vec3) {
	aux1 := v1.Sub(v2)
	aux2 := v3.Sub(v2)

	f.N = aux2.Cross(aux1)
	f.N = safeNormalize(f.N)
	f.P = v2
	f.D = -(f.N.Dot(f.P))
}
Example #6
0
// Lerp will interpolate between the desired position/center by amount.
func (c *QuatCamera) Lerp(position mgl.Vec3, center mgl.Vec3, amount float32) {
	direction := center.Sub(position).Normalize()
	right := direction.Cross(AxisUp)
	up := right.Cross(direction)

	targetRot := mgl.QuatLookAtV(position, center, up)
	c.rotation = mgl.QuatNlerp(c.rotation, targetRot, amount)
	c.position = c.position.Add(position.Sub(c.position).Mul(amount))
}
Example #7
0
func (self *pane) pix2Vec(evnt *js.Object) mgl32.Vec2 {
	v := mgl32.Vec3{ // generate vector from current pixel coords
		float32(evnt.Get("clientX").Float()),
		float32(evnt.Get("clientY").Float()),
		1.0, // apply translations from transform matrix
	}
	v = self.untransform.Mul3x1(v) // apply pan & zoom untransform matrix

	return v.Vec2() // return vec2
}
Example #8
0
func getIntersection(fDst1, fDst2 float32, P1, P2 mgl32.Vec3, Hit *mgl32.Vec3) bool {
	if (fDst1 * fDst2) >= 0.0 {
		return false
	}
	if fDst1 == fDst2 {
		return false
	}
	*Hit = P1.Add((P2.Sub(P1)).Mul(-fDst1 / (fDst2 - fDst1)))
	return true
}
Example #9
0
// Rotate adjusts the direction vectors by a delta vector of {pitch, yaw, roll}.
// Roll is ignored for now.
func (c *EulerCamera) Rotate(delta mgl.Vec3) {
	c.yaw += float64(delta.Y())
	c.pitch += float64(delta.X())

	// Limit vertical rotation to avoid gimbal lock
	if c.pitch > halfPi {
		c.pitch = halfPi
	} else if c.pitch < -halfPi {
		c.pitch = -halfPi
	}

	c.updateVectors()
}
Example #10
0
// CreateBeam - creates a square prism oriented along the vector
func CreateBeam(width float32, vector mgl32.Vec3) *Geometry {
	direction := vector.Normalize()
	geo := CreateBoxWithOffset(width, width, -width*0.5, -width*0.5)
	geo2 := CreateBoxWithOffset(width, width, -width*0.5, -width*0.5)
	facingTx := util.Mat4From(mgl32.Vec3{1, 1, 1}, mgl32.Vec3{}, util.FacingOrientation(0, direction, mgl32.Vec3{0, 0, 1}, mgl32.Vec3{1, 0, 0}))
	geo.Transform(facingTx)
	facingTx = util.Mat4From(mgl32.Vec3{1, 1, 1}, vector, util.FacingOrientation(0, direction, mgl32.Vec3{0, 0, -1}, mgl32.Vec3{1, 0, 0}))
	geo2.Optimize(geo, facingTx)
	geo.Indicies = append(geo.Indicies, 0, 1, 4, 4, 5, 0) //top
	geo.Indicies = append(geo.Indicies, 1, 2, 7, 7, 4, 1) //side
	geo.Indicies = append(geo.Indicies, 2, 3, 6, 6, 7, 2) //bottom
	geo.Indicies = append(geo.Indicies, 3, 0, 5, 5, 6, 3) //side
	return geo
}
Example #11
0
func Upvote(tip mgl.Vec3, size float32) []float32 {
	a := tip.Add(mgl.Vec3{-size / 2, -size * 2, 0})
	b := tip.Add(mgl.Vec3{size / 2, -size, 0})
	return []float32{
		tip[0], tip[1], tip[2], // Top
		tip[0] - size, tip[1] - size, tip[2], // Bottom left
		tip[0] + size, tip[1] - size, tip[2], // Bottom right

		// Arrow handle
		b[0], b[1], b[2], // Top Right
		a[0], b[1], a[2], // Top Left
		a[0], a[1], a[2], // Bottom Left
		a[0], a[1], a[2], // Bottom Left
		b[0], b[1], b[2], // Top Right
		b[0], a[1], b[2], // Bottom Right
	}
}
Example #12
0
func (p *fullPiano) GetKeyFromRay(rayStart, rayEnd mgl32.Vec3) *PianoKey {
	minDist := float32(10000)
	minDistIdx := -1

	for i, k := range p.Keys {
		hit, pos := k.Hit(rayStart, rayEnd)
		if hit {
			dist := rayStart.Sub(pos).Len()
			if dist < minDist {
				minDistIdx = i
				minDist = dist
			}
		}
	}

	if minDistIdx != -1 {
		return &p.Keys[minDistIdx]
	}

	return nil
}
Example #13
0
//PointToPlaneDist distance from plane (a,b,c) to point
func PointToPlaneDist(a, b, c, point mgl32.Vec3) float32 {
	ab := b.Sub(a)
	ac := c.Sub(a)
	ap := point.Sub(a)
	normal := ac.Cross(ab).Normalize()
	return float32(math.Abs(float64(ap.Dot(normal))))
}
Example #14
0
// NewPianoKey returns a key for our piano.
func NewPianoKey(pos mgl32.Vec3, lightColor mgl32.Vec3, white bool, freq float32) PianoKey {
	var color mgl32.Vec4
	var keySize float32
	if white {
		color = mgl32.Vec4{0.98, 0.97, 0.94}
		keySize = 2
	} else {
		color = mgl32.Vec4{0.1, 0.1, 0.1, 1.0}
		keySize = 1

	}
	pk := PianoKey{Pos: pos, Angle: 0, Color: color, Frequency: freq, Finger: -1, white: white, LightColor: lightColor}
	pk.BBox[0] = pos.Sub(mgl32.Vec3{0.5, 0.6, keySize})
	pk.BBox[1] = pos.Add(mgl32.Vec3{0.5, 0.6, keySize})
	pk.source = al.GenSources(1)[0]
	pk.source.SetGain(1.0)
	pk.source.SetPosition(al.Vector{pos.X(), pos.Y(), pos.Z()})
	pk.source.SetVelocity(al.Vector{})
	pk.buffers = al.GenBuffers(3)

	var samples [1024 * 16]int16

	sampleRate := 44100
	amplitude := float32(0.8 * 0x7FFF)

	for i := 0; i < len(samples); i++ {
		val := f32.Sin((2.0 * math.Pi * freq) / float32(sampleRate) * float32(i))
		samples[i] = int16(amplitude * val)
	}

	buf := &bytes.Buffer{}
	binary.Write(buf, binary.LittleEndian, &samples)
	pk.buffers[0].BufferData(al.FormatMono16, buf.Bytes(), 44100)

	f, _ := os.Create("audio.raw")
	binary.Write(f, binary.LittleEndian, &samples)
	f.Close()

	return pk
}
Example #15
0
// updates the Colors of the model to fake lighting
func esLightModel(p PositionComponent, s SizeComponent, m interface {
	Model() *render.StaticModel
}) {
	if m.Model() == nil {
		return
	}
	xx, yy, zz := p.Position()
	bounds := s.Bounds()
	bounds = bounds.Shift(float32(xx), float32(yy), float32(zz))

	c := mgl32.Vec3{float32(xx), float32(yy), float32(zz)}
	c[1] += bounds.Max.Sub(bounds.Min).Mul(0.5).Y()

	var light, skyLight float32
	var count float32
	for y := bounds.Min.Y(); y <= bounds.Max.Y(); y++ {
		for z := bounds.Min.Z() - 1; z <= bounds.Max.Z()+1; z++ {
			for x := bounds.Min.X() - 1; x <= bounds.Max.X()+1; x++ {
				bx, by, bz := int(math.Floor(float64(x))), int(math.Floor(float64(y))), int(math.Floor(float64(z)))
				bl := float32(chunkMap.BlockLight(bx, by, bz))
				sl := float32(chunkMap.SkyLight(bx, by, bz))

				dist := 1.0 - c.Sub(mgl32.Vec3{float32(bx) + 0.5, float32(by) + 0.5, float32(bz) + 0.5}).Len()
				if dist < 0 {
					continue
				}

				light += bl * dist
				skyLight += sl * dist
				count += dist
			}
		}
	}
	light /= count
	skyLight /= count
	model := m.Model()
	model.BlockLight, model.SkyLight = light, skyLight
}
//	Calculate normals by using cross products along the triangle strips
//	and averaging the normals for each vertex
func (terrain *Terrain) CalculateNormals() {
	var element_pos uint32 = 0
	var AB, AC, cross_product mgl32.Vec3

	// Loop through each triangle strip
	for x := uint32(0); x < terrain.XSize-1; x++ {
		// Loop along the strip
		for tri := uint32(0); tri < terrain.ZSize*2-2; tri++ {
			// Extract the vertex indices from the element array
			v1 := terrain.Indices[element_pos]
			v2 := terrain.Indices[element_pos+1]
			v3 := terrain.Indices[element_pos+2]

			// Define the two vectors for the triangle
			AB = terrain.Vertices[v2].Sub(terrain.Vertices[v1])
			AC = terrain.Vertices[v3].Sub(terrain.Vertices[v1])

			// Calculate the cross product
			cross_product = AB.Cross(AC)

			// Add this normal to the vertex normal for all three vertices in the triangle
			terrain.Normals[v1] = terrain.Normals[v1].Add(cross_product)
			terrain.Normals[v2] = terrain.Normals[v2].Add(cross_product)
			terrain.Normals[v3] = terrain.Normals[v3].Add(cross_product)

			// Move on to the next vertex along the strip
			element_pos++
		}

		// Jump past the lat two element positions to reach the start of the strip
		element_pos += 2
	}

	// Normalise the normals
	for v := uint32(0); v < terrain.XSize*terrain.ZSize; v++ {
		terrain.Normals[v] = terrain.Normals[v].Normalize()
	}
}
Example #17
0
File: model.go Project: num5/steven
// Draw draws this to the target region.
func (m *Model) Draw(r Region, delta float64) {
	if m.isNew || m.isDirty() || forceDirty {
		m.isNew = false
		data := m.data[:0]

		for _, v := range m.verts {
			vec := mgl32.Vec3{v.X - 0.5, v.Y - 0.5, v.Z - 0.5}
			vec = m.mat.Mul4x1(vec.Vec4(1)).Vec3().
				Add(mgl32.Vec3{0.5, 0.5, 0.5})
			vX, vY, vZ := vec[0], 1.0-vec[1], vec[2]

			dx := r.X + r.W*float64(vX)
			dy := r.Y + r.H*float64(vY)
			dx /= scaledWidth
			dy /= scaledHeight
			data = appendShort(data, int16(math.Floor((dx*float64(lastWidth))+0.5)))
			data = appendShort(data, int16(math.Floor((dy*float64(lastHeight))+0.5)))
			data = appendShort(data, 256*int16(m.Layer())+int16(256*vZ))
			data = appendShort(data, 0)
			data = appendUnsignedShort(data, v.TX)
			data = appendUnsignedShort(data, v.TY)
			data = appendUnsignedShort(data, v.TW)
			data = appendUnsignedShort(data, v.TH)
			data = appendShort(data, v.TOffsetX)
			data = appendShort(data, v.TOffsetY)
			data = appendShort(data, v.TAtlas)
			data = appendShort(data, 0)
			data = appendUnsignedByte(data, v.R)
			data = appendUnsignedByte(data, v.G)
			data = appendUnsignedByte(data, v.B)
			data = appendUnsignedByte(data, v.A)
		}
		m.data = data
	}
	render.UIAddBytes(m.data)
}
Example #18
0
func TestTransformTranslate(t *testing.T) {
	transform := NewTransform()
	transform.SetPosition(10, 10, 10)

	vector := mgl32.Vec3{-5, 6, 3}
	expected := mgl32.Vec3{5, 16, 13}
	transform.Translate(vector)

	if transform.position != expected {
		t.Errorf("Expected position to be %v got %v", expected, transform.position)
	}

	if transform.matrix[12] != expected.X() ||
		transform.matrix[13] != expected.Y() ||
		transform.matrix[14] != expected.Z() {
		t.Error("Matrix was not updated correctly after translation.")
	}
}
Example #19
0
func (f *Frustum) SetCamera(p, l, u mgl32.Vec3) {
	Z := p.Sub(l)
	Z = safeNormalize(Z)

	X := u.Cross(Z)
	X = safeNormalize(X)

	Y := Z.Cross(X)

	nc := p.Sub(Z.Mul(f.near))
	fc := p.Sub(Z.Mul(f.far))

	ntl := nc.Add(Y.Mul(f.nh)).Sub(X.Mul(f.nw))
	ntr := nc.Add(Y.Mul(f.nh)).Add(X.Mul(f.nw))
	nbl := nc.Sub(Y.Mul(f.nh)).Sub(X.Mul(f.nw))
	nbr := nc.Sub(Y.Mul(f.nh)).Add(X.Mul(f.nw))

	ftl := fc.Add(Y.Mul(f.fh)).Sub(X.Mul(f.fw))
	ftr := fc.Add(Y.Mul(f.fh)).Add(X.Mul(f.fw))
	fbl := fc.Sub(Y.Mul(f.fh)).Sub(X.Mul(f.fw))
	fbr := fc.Sub(Y.Mul(f.fh)).Add(X.Mul(f.fw))

	const (
		top = iota
		bottom
		left
		right
		nearP
		farP
	)
	f.planes[top].setPoints(ntr, ntl, ftl)
	f.planes[bottom].setPoints(nbl, nbr, fbr)
	f.planes[left].setPoints(ntl, nbl, fbl)
	f.planes[right].setPoints(nbr, ntr, fbr)
	f.planes[nearP].setPoints(ntl, ntr, nbr)
	f.planes[farP].setPoints(ftr, ftl, fbl)
}
Example #20
0
func (w *Window) SetTranslation(translation mgl32.Vec3) {
	w.node.SetTranslation(translation)
	w.position = translation.Vec2()
}
Example #21
0
func (b bbox) Contains(pos mgl32.Vec3) bool {
	return pos.X() > b[0].X() &&
		pos.Y() > b[0].Y() &&
		pos.Z() > b[0].Z() &&
		pos.X() < b[1].X() &&
		pos.Y() < b[1].Y() &&
		pos.Z() < b[1].Z()

}
Example #22
0
// returns true if line (L1, L2) intersects with the box (B1, B2)
// returns intersection point in Hit
func checkLineBox(B1, B2, L1, L2 mgl32.Vec3) (bool, mgl32.Vec3) {
	var Hit mgl32.Vec3

	if L2.X() < B1.X() && L1.X() < B1.X() {
		return false, mgl32.Vec3{}
	}
	if L2.X() > B2.X() && L1.X() > B2.X() {
		return false, mgl32.Vec3{}
	}
	if L2.Y() < B1.Y() && L1.Y() < B1.Y() {
		return false, mgl32.Vec3{}
	}
	if L2.Y() > B2.Y() && L1.Y() > B2.Y() {
		return false, mgl32.Vec3{}
	}
	if L2.Z() < B1.Z() && L1.Z() < B1.Z() {
		return false, mgl32.Vec3{}
	}
	if L2.Z() > B2.Z() && L1.Z() > B2.Z() {
		return false, mgl32.Vec3{}
	}
	if L1.X() > B1.X() && L1.X() < B2.X() &&
		L1.Y() > B1.Y() && L1.Y() < B2.Y() &&
		L1.Z() > B1.Z() && L1.Z() < B2.Z() {
		Hit = L1
		return true, Hit
	}
	if (getIntersection(L1.X()-B1.X(), L2.X()-B1.X(), L1, L2, &Hit) && inBox(Hit, B1, B2, 1)) ||
		(getIntersection(L1.Y()-B1.Y(), L2.Y()-B1.Y(), L1, L2, &Hit) && inBox(Hit, B1, B2, 2)) ||
		(getIntersection(L1.Z()-B1.Z(), L2.Z()-B1.Z(), L1, L2, &Hit) && inBox(Hit, B1, B2, 3)) ||
		(getIntersection(L1.X()-B2.X(), L2.X()-B2.X(), L1, L2, &Hit) && inBox(Hit, B1, B2, 1)) ||
		(getIntersection(L1.Y()-B2.Y(), L2.Y()-B2.Y(), L1, L2, &Hit) && inBox(Hit, B1, B2, 2)) ||
		(getIntersection(L1.Z()-B2.Z(), L2.Z()-B2.Z(), L1, L2, &Hit) && inBox(Hit, B1, B2, 3)) {
		return true, Hit
	}

	return false, mgl32.Vec3{}
}
Example #23
0
func inBox(Hit, B1, B2 mgl32.Vec3, Axis int) bool {
	if Axis == 1 && Hit.Z() > B1.Z() && Hit.Z() < B2.Z() && Hit.Y() > B1.Y() && Hit.Y() < B2.Y() {
		return true
	}
	if Axis == 2 && Hit.Z() > B1.Z() && Hit.Z() < B2.Z() && Hit.X() > B1.X() && Hit.X() < B2.X() {
		return true
	}
	if Axis == 3 && Hit.X() > B1.X() && Hit.X() < B2.X() && Hit.Y() > B1.Y() && Hit.Y() < B2.Y() {
		return true
	}
	return false
}
Example #24
0
// Draw draws a single frame
func Draw(width, height int, delta float64) {
	tickAnimatedTextures(delta)
	frameID++
sync:
	for {
		select {
		case f := <-syncChan:
			f()
		default:
			break sync
		}
	}

	// Only update the viewport if the window was resized
	if lastHeight != height || lastWidth != width || lastFOV != FOV.Value() {
		lastWidth = width
		lastHeight = height
		lastFOV = FOV.Value()

		perspectiveMatrix = mgl32.Perspective(
			(math.Pi/180)*float32(lastFOV),
			float32(width)/float32(height),
			0.1,
			500.0,
		)
		gl.Viewport(0, 0, width, height)
		frustum.SetPerspective(
			(math.Pi/180)*float32(lastFOV),
			float32(width)/float32(height),
			0.1,
			500.0,
		)
		initTrans()
	}

	mainFramebuffer.Bind()
	gl.Enable(gl.Multisample)

	gl.ActiveTexture(0)
	glTexture.Bind(gl.Texture2DArray)

	gl.ClearColor(ClearColour.R, ClearColour.G, ClearColour.B, 1.0)
	gl.Clear(gl.ColorBufferBit | gl.DepthBufferBit)

	chunkProgram.Use()

	viewVector = mgl32.Vec3{
		float32(math.Cos(Camera.Yaw-math.Pi/2) * -math.Cos(Camera.Pitch)),
		float32(-math.Sin(Camera.Pitch)),
		float32(-math.Sin(Camera.Yaw-math.Pi/2) * -math.Cos(Camera.Pitch)),
	}
	cam := mgl32.Vec3{-float32(Camera.X), -float32(Camera.Y), float32(Camera.Z)}
	cameraMatrix = mgl32.LookAtV(
		cam,
		cam.Add(mgl32.Vec3{-viewVector.X(), -viewVector.Y(), viewVector.Z()}),
		mgl32.Vec3{0, -1, 0},
	)
	cameraMatrix = cameraMatrix.Mul4(mgl32.Scale3D(-1.0, 1.0, 1.0))

	frustum.SetCamera(
		cam,
		cam.Add(mgl32.Vec3{-viewVector.X(), -viewVector.Y(), viewVector.Z()}),
		mgl32.Vec3{0, -1, 0},
	)

	shaderChunk.PerspectiveMatrix.Matrix4(&perspectiveMatrix)
	shaderChunk.CameraMatrix.Matrix4(&cameraMatrix)
	shaderChunk.Texture.Int(0)
	shaderChunk.LightLevel.Float(LightLevel)
	shaderChunk.SkyOffset.Float(SkyOffset)

	chunkPos := position{
		X: int(Camera.X) >> 4,
		Y: int(Camera.Y) >> 4,
		Z: int(Camera.Z) >> 4,
	}
	nearestBuffer = buffers[chunkPos]

	for _, dir := range direction.Values {
		validDirs[dir] = viewVector.Dot(dir.AsVec()) > -0.8
	}

	renderOrder = renderOrder[:0]
	renderBuffer(nearestBuffer, chunkPos, direction.Invalid, delta)

	drawLines()
	drawModels()
	clouds.tick(delta)

	chunkProgramT.Use()
	shaderChunkT.PerspectiveMatrix.Matrix4(&perspectiveMatrix)
	shaderChunkT.CameraMatrix.Matrix4(&cameraMatrix)
	shaderChunkT.Texture.Int(0)
	shaderChunkT.LightLevel.Float(LightLevel)
	shaderChunkT.SkyOffset.Float(SkyOffset)

	// Copy the depth buffer
	mainFramebuffer.BindRead()
	transFramebuffer.BindDraw()
	gl.BlitFramebuffer(
		0, 0, lastWidth, lastHeight,
		0, 0, lastWidth, lastHeight,
		gl.DepthBufferBit, gl.Nearest,
	)

	gl.Enable(gl.Blend)
	gl.DepthMask(false)
	transFramebuffer.Bind()
	gl.ClearColor(0, 0, 0, 1)
	gl.Clear(gl.ColorBufferBit)
	gl.ClearBuffer(gl.Color, 0, []float32{0, 0, 0, 1})
	gl.ClearBuffer(gl.Color, 1, []float32{0, 0, 0, 0})
	gl.BlendFuncSeparate(gl.OneFactor, gl.OneFactor, gl.ZeroFactor, gl.OneMinusSrcAlpha)
	for _, chunk := range renderOrder {
		if chunk.countT > 0 && chunk.bufferT.IsValid() {
			shaderChunkT.Offset.Int3(chunk.X, chunk.Y*4096-chunk.Y*int(4096*(1-chunk.progress)), chunk.Z)

			chunk.arrayT.Bind()
			gl.DrawElements(gl.Triangles, chunk.countT, elementBufferType, 0)
		}
	}

	gl.UnbindFramebuffer()
	gl.Disable(gl.DepthTest)
	gl.Clear(gl.ColorBufferBit)
	gl.Disable(gl.Blend)

	transDraw()

	gl.Enable(gl.DepthTest)
	gl.DepthMask(true)
	gl.BlendFunc(gl.SrcAlpha, gl.OneMinusSrcAlpha)
	gl.Disable(gl.Multisample)

	drawUI()

	if debugFramebuffers.Value() {
		gl.Enable(gl.Multisample)
		blitBuffers()
		gl.Disable(gl.Multisample)
	}
}
Example #25
0
func programLoop(window *win.Window) error {

	// the linked shader program determines how the data will be rendered
	vertShader, err := gfx.NewShaderFromFile("shaders/phong.vert", gl.VERTEX_SHADER)
	if err != nil {
		return err
	}

	fragShader, err := gfx.NewShaderFromFile("shaders/phong.frag", gl.FRAGMENT_SHADER)
	if err != nil {
		return err
	}

	program, err := gfx.NewProgram(vertShader, fragShader)
	if err != nil {
		return err
	}
	defer program.Delete()

	lightFragShader, err := gfx.NewShaderFromFile("shaders/light.frag", gl.FRAGMENT_SHADER)
	if err != nil {
		return err
	}

	// special shader program so that lights themselves are not affected by lighting
	lightProgram, err := gfx.NewProgram(vertShader, lightFragShader)
	if err != nil {
		return err
	}

	VAO := createVAO(cubeVertices, nil)
	lightVAO := createVAO(cubeVertices, nil)

	// ensure that triangles that are "behind" others do not draw over top of them
	gl.Enable(gl.DEPTH_TEST)

	camera := cam.NewFpsCamera(mgl32.Vec3{0, 0, 3}, mgl32.Vec3{0, 1, 0}, -90, 0, window.InputManager())

	for !window.ShouldClose() {

		// swaps in last buffer, polls for window events, and generally sets up for a new render frame
		window.StartFrame()

		// update camera position and direction from input evevnts
		camera.Update(window.SinceLastFrame())

		// background color
		gl.ClearColor(0, 0, 0, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) // depth buffer needed for DEPTH_TEST

		// cube rotation matrices
		rotateX := (mgl32.Rotate3DX(mgl32.DegToRad(-45 * float32(glfw.GetTime()))))
		rotateY := (mgl32.Rotate3DY(mgl32.DegToRad(-45 * float32(glfw.GetTime()))))
		rotateZ := (mgl32.Rotate3DZ(mgl32.DegToRad(-45 * float32(glfw.GetTime()))))

		// creates perspective
		fov := float32(60.0)
		projectTransform := mgl32.Perspective(mgl32.DegToRad(fov),
			float32(window.Width())/float32(window.Height()),
			0.1,
			100.0)

		camTransform := camera.GetTransform()
		lightPos := mgl32.Vec3{0.6, 1, 0.1}
		lightTransform := mgl32.Translate3D(lightPos.X(), lightPos.Y(), lightPos.Z()).Mul4(
			mgl32.Scale3D(0.2, 0.2, 0.2))

		program.Use()
		gl.UniformMatrix4fv(program.GetUniformLocation("view"), 1, false, &camTransform[0])
		gl.UniformMatrix4fv(program.GetUniformLocation("project"), 1, false,
			&projectTransform[0])

		gl.BindVertexArray(VAO)

		// draw each cube after all coordinate system transforms are bound

		// obj is colored, light is white
		gl.Uniform3f(program.GetUniformLocation("material.ambient"), 1.0, 0.5, 0.31)
		gl.Uniform3f(program.GetUniformLocation("material.diffuse"), 1.0, 0.5, 0.31)
		gl.Uniform3f(program.GetUniformLocation("material.specular"), 0.5, 0.5, 0.5)
		gl.Uniform1f(program.GetUniformLocation("material.shininess"), 32.0)

		lightColor := mgl32.Vec3{
			float32(math.Sin(glfw.GetTime() * 1)),
			float32(math.Sin(glfw.GetTime() * 0.35)),
			float32(math.Sin(glfw.GetTime() * 0.65)),
		}

		diffuseColor := mgl32.Vec3{
			0.5 * lightColor[0],
			0.5 * lightColor[1],
			0.5 * lightColor[2],
		}
		ambientColor := mgl32.Vec3{
			0.2 * lightColor[0],
			0.2 * lightColor[1],
			0.2 * lightColor[2],
		}

		gl.Uniform3f(program.GetUniformLocation("light.ambient"),
			ambientColor[0], ambientColor[1], ambientColor[2])
		gl.Uniform3f(program.GetUniformLocation("light.diffuse"),
			diffuseColor[0], diffuseColor[1], diffuseColor[2])
		gl.Uniform3f(program.GetUniformLocation("light.specular"), 1.0, 1.0, 1.0)
		gl.Uniform3f(program.GetUniformLocation("light.position"), lightPos.X(), lightPos.Y(), lightPos.Z())

		for _, pos := range cubePositions {

			// turn the cubes into rectangular prisms for more fun
			worldTranslate := mgl32.Translate3D(pos[0], pos[1], pos[2])
			worldTransform := worldTranslate.Mul4(
				rotateX.Mul3(rotateY).Mul3(rotateZ).Mat4(),
			)

			gl.UniformMatrix4fv(program.GetUniformLocation("model"), 1, false,
				&worldTransform[0])

			gl.DrawArrays(gl.TRIANGLES, 0, 36)
		}
		gl.BindVertexArray(0)

		// Draw the light obj after the other boxes using its separate shader program
		// this means that we must re-bind any uniforms
		lightProgram.Use()
		gl.BindVertexArray(lightVAO)
		gl.UniformMatrix4fv(lightProgram.GetUniformLocation("model"), 1, false, &lightTransform[0])
		gl.UniformMatrix4fv(lightProgram.GetUniformLocation("view"), 1, false, &camTransform[0])
		gl.UniformMatrix4fv(lightProgram.GetUniformLocation("project"), 1, false, &projectTransform[0])
		gl.DrawArrays(gl.TRIANGLES, 0, 36)

		gl.BindVertexArray(0)

		// end of draw loop
	}

	return nil
}
Example #26
0
// 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
}
Example #27
0
File: aabb.go Project: num5/steven
func (a AABB) MoveOutOf(o AABB, dir mgl32.Vec3) AABB {
	if dir.X() != 0 {
		if dir.X() > 0 {
			ox := a.Max.X()
			a.Max[0] = o.Min.X() - 0.0001
			a.Min[0] += a.Max.X() - ox
		} else {
			ox := a.Min.X()
			a.Min[0] = o.Max.X() + 0.0001
			a.Max[0] += a.Min.X() - ox
		}
	}
	if dir.Y() != 0 {
		if dir.Y() > 0 {
			oy := a.Max.Y()
			a.Max[1] = o.Min.Y() - 0.0001
			a.Min[1] += a.Max.Y() - oy
		} else {
			oy := a.Min.Y()
			a.Min[1] = o.Max.Y() + 0.0001
			a.Max[1] += a.Min.Y() - oy
		}
	}

	if dir.Z() != 0 {
		if dir.Z() > 0 {
			oz := a.Max.Z()
			a.Max[2] = o.Min.Z() - 0.0001
			a.Min[2] += a.Max.Z() - oz
		} else {
			oz := a.Min.Z()
			a.Min[2] = o.Max.Z() + 0.0001
			a.Max[2] += a.Min.Z() - oz
		}
	}
	return a
}
Example #28
0
func randomVector(min, max mgl32.Vec3) mgl32.Vec3 {
	r1, r2, r3 := rand.Float32(), rand.Float32(), rand.Float32()
	return mgl32.Vec3{min.X()*(1.0-r1) + max.X()*r1, min.Y()*(1.0-r2) + max.Y()*r2, min.Z()*(1.0-r3) + max.Z()*r3}
}
Example #29
0
//given 3 vertices, returns the normal of the plane formed by this triangle
//TODO: move to a math package
func NormalToPlane(v1, v2, v3 glm.Vec3) glm.Vec3 {
	u := v2.Sub(v1)
	v := v3.Sub(v1)
	return glm.Vec3{u.Y()*v.Z() - u.Z()*v.Y(), u.Z()*v.X() - u.X()*v.Z(), u.X()*v.Y() - u.Y()*v.X()}
}
Example #30
0
func (w *Window) SetScale(scale mgl32.Vec3) {
	w.background.SetScale(scale)
	w.size = scale.Vec2()
	w.Render()
}