Пример #1
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
}
Пример #2
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
	}
}
Пример #3
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
}
Пример #4
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)
	}
}
Пример #5
0
func (p *particle) Tick(force mgl.Vec3) {
	p.velocity = force.Add(p.velocity)
	p.position = p.position.Add(p.velocity)
}
Пример #6
0
//
// objectToObjectData
// Turns the data from .obj format into an internal OpenGL friendly
// format. The following information needs to be created for each mesh.
//
//    mesh.V = append(mesh.V, ...4-float32) - indexed from 0
//    mesh.N = append(mesh.N, ...3-float32) - indexed from 0
//    mesh.T = append(mesh.T, ...2-float32)	- indexed from 0
//    mesh.F = append(mesh.F, ...3-uint16)	- refers to above zero indexed values
//
// objectData holds the global vertex, texture, and normal point information.
// faces are the indexes for this mesh.
//
// Additionally the normals at each vertex are generated as the sum of the
// normals for each face that shares that vertex.
//
// @param name (string) The Name of the Object.
// @param objectData (*objectData) A temporary object data pointer.
// @param objectData (*objectData) The array of Faces / Indices.
//
// @return data (*ObjectData) A pointer to the Object.
// @return error (error) the error (if any)
//
func (loader *Loader) objectToObjectData(name string, objectData *objectData, faces []face) (data *ObjectData, err error) {
	data = &ObjectData{}
	data.Name = name
	vmap := make(map[string]int) // the unique vertex data points for this face.
	vcnt := -1

	// process each vertex of each face.  Each one represents a combination vertex,
	// texture coordinate, and normal.
	for _, face := range faces {
		for pi := 0; pi < 3; pi++ { // Load only triangles
			//		for pi, _ := range face.s {
			v, t, n := -1, -1, -1

			if len(face.s) > pi {
				faceIndex := face.s[pi]

				if v, t, n, err = parseFaceIndices(faceIndex); err != nil {
					return data, fmt.Errorf("Could not parse face data %s", err)
				}

				// cut down the amount of information passed around by reusing points
				// where the vertex and the texture coordinate information is the same.
				vertexIndex := fmt.Sprintf("%d/%d/%d", v, t, n)
				if _, ok := vmap[vertexIndex]; !ok {

					// add a new data point.
					vcnt++
					vmap[vertexIndex] = vcnt
					data.Vertex = append(data.Vertex, objectData.vertices[v].x, objectData.vertices[v].y, objectData.vertices[v].z)

					// Object might not have normals
					if n != -1 {
						data.Normals = append(data.Normals, objectData.normals[n].x, objectData.normals[n].y, objectData.normals[n].z)
					}

					// Object might not have texture information
					if t != -1 {
						data.Coordinates = append(data.Coordinates, objectData.texture[t].u, objectData.texture[t].v)
					}
				} else {
					// update the normal at the vertex to be a combination of
					// all the normals of each face that shares the vertex.
					ni := vmap[vertexIndex] * 3

					// Obj might not have normals
					if n != -1 && len(data.Normals) > (ni+2) {
						var n1 mgl32.Vec3 = mgl32.Vec3{
							float32(data.Normals[ni]),
							float32(data.Normals[ni+1]),
							float32(data.Normals[ni+2]),
						}

						var n2 mgl32.Vec3 = mgl32.Vec3{
							float32(objectData.normals[n].x),
							float32(objectData.normals[n].y),
							float32(objectData.normals[n].z),
						}

						n2 = n2.Add(n1).Normalize()

						data.Normals[ni], data.Normals[ni+1], data.Normals[ni+2] = float32(n2.X()), float32(n2.Y()), float32(n2.Z())
					}
				}

				data.Faces = append(data.Faces, uint16(vmap[vertexIndex]))
			}
		}
	}
	return data, err
}
Пример #7
0
func setupScene(gameEngine engine.Engine, shader *renderer.Shader) {
	camera := gameEngine.Camera()

	transparentNode := renderer.NewNode()
	gameEngine.AddSpatialTransparent(transparentNode)
	transparentNode.RendererParams = &renderer.RendererParams{
		DepthTest:    true,
		Unlit:        true,
		Transparency: renderer.EMISSIVE,
	}

	// Sky cubemap
	skyImg, err := assets.ImportImage("TestAssets/cloudSky.jpg")
	if err == nil {
		skyImg = imaging.AdjustBrightness(skyImg, -30)
		skyImg = imaging.AdjustContrast(skyImg, 30)
		geom := renderer.CreateSkyBox()
		geom.Transform(mgl32.Scale3D(10000, 10000, 10000))
		skyNode := renderer.NewNode()
		skyNode.SetOrientation(mgl32.QuatRotate(1.57, mgl32.Vec3{0, 1, 0}))
		skyNode.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", skyImg, false))
		skyNode.RendererParams = renderer.NewRendererParams()
		skyNode.RendererParams.CullBackface = false
		skyNode.RendererParams.Unlit = true
		skyNode.Add(geom)
		gameEngine.AddSpatial(skyNode)
		// create an environmentMap using the skybox texture
		envCubeMap := renderer.NewCubemap("environmentMap", skyImg, true)
		gameEngine.DefaultCubeMap(envCubeMap)
	}

	// load scene objs
	objs := []string{
		"TestAssets/wellScene/floor.obj",
		"TestAssets/wellScene/frame1.obj",
		"TestAssets/wellScene/frame2.obj",
		"TestAssets/wellScene/well.obj",
		"TestAssets/wellScene/torches.obj",
	}
	for _, objFile := range objs {
		if geom, mat, err := assets.ImportObjCached(objFile); err == nil {
			sceneNode := renderer.NewNode()
			sceneNode.Add(geom)
			sceneNode.Material = mat
			sceneNode.RendererParams = renderer.NewRendererParams()
			sceneNode.RendererParams.CullBackface = false
			gameEngine.AddSpatial(sceneNode)
		}
	}

	for i := 0; i < 2; i++ {
		torchLocation := mgl32.Vec3{0.86, 1.76, 1.05}
		if i == 1 {
			torchLocation = mgl32.Vec3{0.86, 1.76, -1.05}
		}

		fire := fireParticles()
		spark := sparkParticles()
		torchParticles := effects.NewParticleGroup(camera, fire, spark)
		torchParticles.SetTranslation(torchLocation)
		transparentNode.Add(torchParticles)
		gameEngine.AddUpdatable(torchParticles)

		light := renderer.NewLight(renderer.POINT)
		light.SetTranslation(torchLocation.Add(mgl32.Vec3{0, 0.05, 0}))
		gameEngine.AddLight(light)

		var x float64
		gameEngine.AddUpdatable(engine.UpdatableFunc(func(dt float64) {
			x += dt
			mag := float32(math.Abs(0.6*math.Sin(3*x)+0.3*math.Sin(4*x)+0.15*math.Sin(7*x)+0.1*math.Sin(15*x))) + 0.5
			mag *= 0.05
			light.Color = [3]float32{1 * mag, 0.6 * mag, 0.4 * mag}
		}))
	}
}
Пример #8
0
func (c *Camera) Update(dt float32) {
	/* Handle keyboard input */
	move := false
	dir := mgl.Vec3{}
	if KeyDown(KeyW) && !KeyDown(KeyS) {
		dir[2] += 1
		move = true
	}
	if KeyDown(KeyS) && !KeyDown(KeyW) {
		dir[2] -= 1
		move = true
	}
	if KeyDown(KeyA) && !KeyDown(KeyD) {
		dir[0] -= 1
		move = true
	}
	if KeyDown(KeyD) && !KeyDown(KeyA) {
		dir[0] += 1
		move = true
	}
	if KeyDown(KeyE) && !KeyDown(KeyQ) {
		dir[1] += 1
		move = true
	}
	if KeyDown(KeyQ) && !KeyDown(KeyE) {
		dir[1] -= 1
		move = true
	}

	if move {
		/* Calculate normalized movement vector */
		dv := 5.0 * dt /* magic number: movement speed */
		dir = dir.Normalize().Mul(dv)

		right := c.Transform.Right.Mul(dir[0])
		up := mgl.Vec3{0, dir[1], 0}
		forward := c.Transform.Forward.Mul(dir[2])

		/* Translate camera */
		c.Transform.Translate(right.Add(up.Add(forward)))
	}

	/* Mouse look */
	if MouseDown(MouseButton1) {
		rx := c.Transform.Rotation[0] - Mouse.DY*0.08
		ry := c.Transform.Rotation[1] - Mouse.DX*0.09

		/* Camera angle limits */
		/* -90 < rx < 90 */
		rx = float32(math.Max(-90.0, math.Min(90.0, float64(rx))))

		/* -180 < ry < 180 */
		if ry > 180.0 {
			ry -= 360.0
		}
		if ry < -180.0 {
			ry += 360.0
		}
		c.Transform.Rotation[0] = rx
		c.Transform.Rotation[1] = ry
	}

	/* Update transform with new position & rotation */
	c.Transform.Update(dt)

	/* Calculate new view matrix based on forward vector */
	lookAt := c.Transform.Position.Add(c.Transform.Forward)
	c.View = mgl.LookAtV(c.Transform.Position, lookAt, mgl.Vec3{0, 1, 0})
}
Пример #9
0
func (rb *RigidBox) SetPosition(position mgl.Vec3) {
	rb.body.SetPosition(ToOdeVec3(position.Add(rb.center)))
}