package main import ( "flag" "fmt" "log" "os" "runtime/pprof" // For performance profiling (unnecessary) ) const ( Width = 512 Height = 512 FOV = 70 NearClip = 0.1 FarClip = 5 // Because the head is so small and close ObjectFile = "head.obj" Repeat = 1 // Because I want to see an animation ) func must(err error) { if err != nil { panic(err) } } // However flag works... idk var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") var xofs = flag.Float64("xofs", 0, "Offset image by x") var zofs = flag.Float64("zofs", -1.5, "Offset image by z (should be negative)") var fov = flag.Float64("fov", 90, "Field of view") func main() { log.Printf("Program start") // Little section for doing cpu profiling. I guess that's all you have to do? flag.Parse() if *cpuprofile != "" { log.Printf("CPU profiling requested, write to %s", *cpuprofile) f, err := os.Create(*cpuprofile) must(err) defer f.Close() err = pprof.StartCPUProfile(f) must(err) defer pprof.StopCPUProfile() } fb := NewFramebuffer(Width, Height) log.Printf("Loading obj %s", ObjectFile) of, err := os.Open(ObjectFile) must(err) defer of.Close() o, err := ParseObj(of) must(err) log.Printf("Running render") halfwidth := float32(fb.Width / 2) halfheight := float32(fb.Height / 2) var projection Mat44f var worldToCamera Mat44f projection.SetProjection(float32(*fov), NearClip, FarClip) worldToCamera.SetIdentity() worldToCamera.Set(0, 3, float32(*xofs)) // Let user decide how to offset x worldToCamera.Set(2, 3, float32(*zofs)) // Get farther away from the face (user) var x [3]int var y [3]int var c [3]uint var hi = int(fb.Height - 1) for range Repeat { for _, f := range o.Faces { // Precompute perspective for vertices to save time. Notice Z // is not considered: is this orthographic projection? Yeah probably... for i := range 3 { // Triangles, bro // The ONLY difference between this and the non-perspective is this multiplication. // Is this really all that's required? fp := worldToCamera.MultiplyPoint3(f[i]) fp = projection.MultiplyPoint3(fp) //log.Print(uint16(fp.Z * 65535)) x[i] = int((fp.X + 1) * halfwidth) y[i] = hi - int((fp.Y+1)*halfheight) c[i] = 0xFFFFFF //c[i] = Col2Uint(byte(0xFF*fp.Z), byte(0xFF*fp.Z), byte(0xFF*fp.Z)) } Bresenham2(&fb, c[0], x[0], y[0], x[1], y[1]) Bresenham2(&fb, c[1], x[1], y[1], x[2], y[2]) Bresenham2(&fb, c[2], x[2], y[2], x[0], y[0]) } } log.Printf("Exporting ppm to stdout") fmt.Print(fb.ExportPPM()) log.Printf("Program end") }