func drawScene() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Translatef(0, 0, -3.0) gl.Rotatef(rotationX, 1, 0, 0) gl.Rotatef(rotationY, 0, 1, 0) rotationX += 0.5 rotationY += 0.5 gl.BindTexture(gl.TEXTURE_2D, texture) gl.Color4f(1, 1, 1, 1) gl.Begin(gl.QUADS) gl.Normal3f(0, 0, 1) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, -1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(1, -1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, 1) gl.Normal3f(0, 0, -1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, 1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, 1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, -1) gl.Normal3f(0, 1, 0) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, 1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, -1) gl.Normal3f(0, -1, 0) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, -1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, 1) gl.Normal3f(1, 0, 0) gl.TexCoord2f(1, 0) gl.Vertex3f(1, -1, -1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, 1) gl.Normal3f(-1, 0, 0) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, 1, 1) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, -1) gl.End() }
func (ctx *DrawContext) drawSphere(p vector.V3, r float64, c colorful.Color) { /* TODO: - decrease sphere detail if it's further away - only draw spheres that would be visible inside the frustum: - (no small spheres near the far plane) */ if ctx.cam.SphereInFrustum(p, r) == OUTSIDE { return } gl.Color3f(float32(c.R), float32(c.G), float32(c.B)) gl.MatrixMode(gl.MODELVIEW) gl.PushMatrix() defer gl.PopMatrix() slices := int(math.Max(10, 5*math.Log(r+1))) gl.Translated(p.X, p.Y, p.Z) gl.Scaled(r, r, r) l, ok := uint32(0), false if ctx.wireframe { l, ok = ctx.spheresWireframe[slices] } else { l, ok = ctx.spheresSolid[slices] } if !ok { ctx.listId++ // XXX: atomic? l = ctx.listId gl.NewList(l, gl.COMPILE) for i := 0; i <= slices; i++ { lat0 := math.Pi * (-0.5 + float64(i-1)/float64(slices)) z0 := math.Sin(lat0) zr0 := math.Cos(lat0) lat1 := math.Pi * (-0.5 + float64(i)/float64(slices)) z1 := math.Sin(lat1) zr1 := math.Cos(lat1) if ctx.wireframe { gl.Begin(gl.LINES) } else { gl.Begin(gl.QUAD_STRIP) } for j := 0; j <= slices; j++ { lng := 2 * math.Pi * (float64(j-1) / float64(slices)) x := math.Cos(lng) y := math.Sin(lng) gl.Normal3f(float32(x*zr0), float32(y*zr0), float32(z0)) gl.Vertex3f(float32(x*zr0), float32(y*zr0), float32(z0)) gl.Normal3f(float32(x*zr1), float32(y*zr1), float32(z1)) gl.Vertex3f(float32(x*zr1), float32(y*zr1), float32(z1)) } gl.End() } gl.EndList() if ctx.wireframe { ctx.spheresWireframe[slices] = l } else { ctx.spheresSolid[slices] = l } } gl.CallList(l) }