package renderer import ( . "github.com/fogleman/fauxgl" "github.com/nfnt/resize" "errors" "image" "log" "os" "path/filepath" "strings" ) const ( scale = 1 // optional supersampling width = 1000 // output width in pixels height = 1000 // output height in pixels fovy = 10 // vertical field of view in degrees near = 1 // near clipping plane far = 40 // far clipping plane ) var ( eye = V(-6, -6, 5) // camera position center = V(0, -0.07, 0) // view center position up = V(0, 0, 1) // up vector light = V(-1, -2, 5).Normalize() // light direction color = ("#42f5b3") // object color background = HexColor("#e0e0e0") //Background color ) type RenderOption struct { Color string BackgroundColor string Width int Height int } type Renderer struct { Option RenderOption } func New3DRenderer(option RenderOption) *Renderer { return &Renderer{ Option: option, } } func (r *Renderer) RenderModel(filename string) (image.Image, error) { // load a mesh var mesh *Mesh if strings.ToLower(filepath.Ext(filename)) == ".stl" { m, err := LoadSTL(filename) if err != nil { return nil, err } mesh = m } else if strings.ToLower(filepath.Ext(filename)) == ".obj" { m, err := LoadOBJ(filename) if err != nil { return nil, err } mesh = m } else { log.Println("Not supported format, given: " + filepath.Ext(filename)) return nil, errors.New("Not supported model format") } // fit mesh in a bi-unit cube centered at the origin mesh.UnitCube() //log.Println(mesh.BoundingBox(), filename) // smooth the normals mesh.SmoothNormalsThreshold(Radians(30)) // create a rendering context context := NewContext(r.Option.Width*scale, r.Option.Height*scale) context.ClearColorBufferWith(HexColor(r.Option.BackgroundColor)) // create transformation matrix and light direction aspect := float64(width) / float64(height) matrix := LookAt(eye, center, up).Perspective(fovy, aspect, near, far) // use builtin phong shader shader := NewPhongShader(matrix, light, eye) shader.ObjectColor = HexColor(r.Option.Color) context.Shader = shader // render context.DrawMesh(mesh) // downsample image for antialiasing image := context.Image() image = resize.Resize(width, height, image, resize.Bilinear) return image, nil } func fileExists(filename string) bool { info, err := os.Stat(filename) if os.IsNotExist(err) { return false } return !info.IsDir() }