// main creates a new scene with a camera and 3 vectors, renders the scene, // draws the result to an image and encodes the image as PNG into a file. // Optionally specify the filename. func main() { var filename = flag.String("file", "triangle.png", "Filename to store image") flag.Parse() cam := render.NewDefCam() v1 := geom.NewVec4(-1, -1, -3) v2 := geom.NewVec4(0, 1, -5) v3 := geom.NewVec4(1, -1, -3) t := cam.PerspTransf(500, 500) w1 := t.Transf(v1) w1.Norm() w2 := t.Transf(v2) w2.Norm() w3 := t.Transf(v3) w3.Norm() x1 := tmath.Round(w1[0]) y1 := tmath.Round(w1[1]) x2 := tmath.Round(w2[0]) y2 := tmath.Round(w2[1]) x3 := tmath.Round(w3[0]) y3 := tmath.Round(w3[1]) img := image.NewImage(500, 500) col := color.RGBA{255, 255, 0, 255} img.DrawDot(x1, y1, col) img.DrawDot(x2, y2, col) img.DrawDot(x3, y3, col) img.DrawLine(x1, y1, x2, y2, col) img.DrawLine(x2, y2, x3, y3, col) img.DrawLine(x3, y3, x1, y1, col) file, err := os.Create(*filename) if err != nil { panic(err) } defer file.Close() img.WritePng(file) }
// Line draws a line between two points. It's 1 pixel thick. func (w *Window) Line(v1, v2 *geom.Vec2, r, g, b byte) { // Always draw from left to right (x1 <= x2) if v1[0] > v2[0] { v1, v2 = v2, v1 } dx := v2[0] - v1[0] dy := v2[1] - v1[1] var steps int if tmath.Absi(dx) > tmath.Absi(dy) { steps = dx } else { steps = tmath.Absi(dy) } xinc := float64(dx) / float64(steps) yinc := float64(dy) / float64(steps) x := float64(v1[0]) y := float64(v1[1]) for s := 0; s <= steps; s++ { w.Setxy(tmath.Round(x), tmath.Round(y), r, g, b) x += xinc y += yinc } }
// DrawLine draws a 1 pixel thick line between the (x1,y1) and (x2,y2) with the // given color. func (img *Image) DrawLine(x1, y1, x2, y2 int, c color.Color) { r := img.Rgba // Always draw from left to right (x1 <= x2) if x1 > x2 { x1, y1, x2, y2 = x2, y2, x1, y1 } dx := x2 - x1 dy := y2 - y1 var steps int if tmath.Absi(dx) > tmath.Absi(dy) { steps = tmath.Absi(dx) } else { steps = tmath.Absi(dy) } xinc := float64(dx) / float64(steps) yinc := float64(dy) / float64(steps) x := float64(x1) y := float64(y1) for s := 0; s <= steps; s++ { r.Set(tmath.Round(x), tmath.Round(y), c) x += xinc y += yinc } }
// Transf transforms a 3D triangle with the given transformation matrix and // returns a 2D triangle. func (t *Tri4) Transf(m *geom.Mat4) *Tri2 { p1 := m.Transf(&t[0]) x1 := tmath.Round(p1[0] / p1[3]) y1 := tmath.Round(p1[1] / p1[3]) p2 := m.Transf(&t[1]) x2 := tmath.Round(p2[0] / p2[3]) y2 := tmath.Round(p2[1] / p2[3]) p3 := m.Transf(&t[2]) x3 := tmath.Round(p3[0] / p3[3]) y3 := tmath.Round(p3[1] / p3[3]) return NewTri2(x1, y1, x2, y2, x3, y3) }