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 }
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 } }
// 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 }
// 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) } }
func (p *particle) Tick(force mgl.Vec3) { p.velocity = force.Add(p.velocity) p.position = p.position.Add(p.velocity) }
// // 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 }
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} })) } }
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}) }
func (rb *RigidBox) SetPosition(position mgl.Vec3) { rb.body.SetPosition(ToOdeVec3(position.Add(rb.center))) }