PageRenderTime 58ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/goray/main.go

https://bitbucket.org/zombiezen/goray
Go | 229 lines | 174 code | 27 blank | 28 comment | 27 complexity | 9f199f5d9d84ef9243cc2ea78b9e8c10 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (c) 2011 Ross Light.
  3. Copyright (c) 2005 Mathias Wein, Alejandro Conty, and Alfredo de Greef.
  4. This file is part of goray.
  5. goray is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. goray is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with goray. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. package main
  17. import (
  18. "flag"
  19. "fmt"
  20. "os"
  21. "runtime"
  22. "runtime/pprof"
  23. "bitbucket.org/zombiezen/goray/job"
  24. "bitbucket.org/zombiezen/goray/log"
  25. _ "bitbucket.org/zombiezen/goray/cameras"
  26. _ "bitbucket.org/zombiezen/goray/integrators"
  27. _ "bitbucket.org/zombiezen/goray/lights"
  28. _ "bitbucket.org/zombiezen/goray/materials"
  29. _ "bitbucket.org/zombiezen/goray/shaders/texmap"
  30. _ "bitbucket.org/zombiezen/goray/textures"
  31. "bitbucket.org/zombiezen/goray/textures"
  32. "bitbucket.org/zombiezen/goray/yamlscene"
  33. )
  34. var (
  35. showHelp bool
  36. showVersion bool
  37. httpAddress string
  38. dataRoot string
  39. outputPath string
  40. outputFormat string
  41. imagePath string
  42. cpuprofile string
  43. debug int
  44. )
  45. func main() {
  46. flag.BoolVar(&showHelp, "help", false, "display this help")
  47. flag.BoolVar(&showVersion, "version", false, "display the version")
  48. flag.StringVar(&httpAddress, "http", "", "start HTTP server")
  49. flag.StringVar(&dataRoot, "dataroot", "data", "web server resource files")
  50. flag.StringVar(&outputPath, "o", "", "path for the output")
  51. flag.StringVar(&outputFormat, "f", job.DefaultFormat, "output format (default: "+job.DefaultFormat+")")
  52. flag.StringVar(&cpuprofile, "cpuprofile", "", "write CPU profile to file")
  53. flag.IntVar(&debug, "d", 0, "set debug verbosity level")
  54. flag.StringVar(&imagePath, "t", ".", "texture directory (default: current directory)")
  55. maxProcs := flag.Int("procs", 1, "set the number of processors to use")
  56. flag.Usage = printInstructions
  57. flag.Parse()
  58. setupLogging()
  59. runtime.GOMAXPROCS(*maxProcs)
  60. log.Debugf("Using %d processor(s)", runtime.GOMAXPROCS(0))
  61. var exitCode int
  62. switch {
  63. case showHelp:
  64. printInstructions()
  65. case showVersion:
  66. printVersion()
  67. case httpAddress != "":
  68. exitCode = httpServer()
  69. default:
  70. exitCode = singleFile()
  71. }
  72. os.Exit(exitCode)
  73. }
  74. func setupLogging() {
  75. log.Default = filterLogger{log.New(os.Stdout), debug}
  76. }
  77. func printInstructions() {
  78. fmt.Println("USAGE: goray [OPTIONS] FILE")
  79. fmt.Println(" goray -http=:PORT [OPTIONS]")
  80. fmt.Println("OPTIONS:")
  81. flag.PrintDefaults()
  82. }
  83. func printVersion() {
  84. fmt.Println("goray v0.1.0 - The Concurrent Raytracer")
  85. // Copyright notice
  86. fmt.Println("Copyright © 2011 Ross Light")
  87. fmt.Println("Based on YafaRay: Copyright © 2005 Mathias Wein, Alejandro Conty, and Alfredo")
  88. fmt.Println("de Greef")
  89. fmt.Println("jQuery: Copyright © 2011 John Resig")
  90. fmt.Println()
  91. fmt.Println("goray comes with ABSOLUTELY NO WARRANTY. goray is free software, and you are")
  92. fmt.Println("welcome to redistribute it under the conditions of the GNU Lesser General")
  93. fmt.Println("Public License v3, or (at your option) any later version.")
  94. fmt.Println()
  95. // Build information
  96. fmt.Printf("Go runtime: %s\n", runtime.Version())
  97. fmt.Printf("Built for %s (%s)\n", runtime.GOOS, runtime.GOARCH)
  98. }
  99. func singleFile() int {
  100. if flag.NArg() != 1 {
  101. printInstructions()
  102. return 1
  103. }
  104. // Check output format
  105. formatStruct, found := job.FormatMap[outputFormat]
  106. if !found {
  107. log.Criticalf("Unrecognized output format: %s", outputFormat)
  108. return 1
  109. }
  110. // Open input file
  111. inFile, err := os.Open(flag.Arg(0))
  112. if err != nil {
  113. log.Criticalf("Error opening input file: %v", err)
  114. return 1
  115. }
  116. defer inFile.Close()
  117. // Open output file
  118. if outputPath == "" {
  119. outputPath = "goray" + formatStruct.Extension
  120. }
  121. outFile, err := os.Create(outputPath)
  122. if err != nil {
  123. log.Criticalf("Error opening output file: %v", err)
  124. return 1
  125. }
  126. defer outFile.Close()
  127. // Set up profile file
  128. var cpuprofileFile *os.File
  129. if cpuprofile != "" {
  130. cpuprofileFile, err = os.Create(cpuprofile)
  131. if err != nil {
  132. log.Criticalf("Error opening cpuprofile file: %v", err)
  133. return 1
  134. }
  135. defer cpuprofileFile.Close()
  136. }
  137. // Create job
  138. j := job.New("job", inFile, yamlscene.Params{
  139. "ImageLoader": textures.NewImageLoader(imagePath),
  140. "OutputFormat": formatStruct,
  141. })
  142. ch := j.StatusChan()
  143. j.SceneLog = log.Default
  144. j.RenderLog = log.Default
  145. go func() {
  146. if cpuprofileFile != nil {
  147. pprof.StartCPUProfile(cpuprofileFile)
  148. }
  149. j.Render(outFile)
  150. }()
  151. // Log progress
  152. for stat := range ch {
  153. switch stat.Code {
  154. case job.StatusReading:
  155. log.Infof("Reading scene file...")
  156. case job.StatusUpdating:
  157. log.Infof("Preparing scene...")
  158. case job.StatusRendering:
  159. log.Infof("Finalized in %v", stat.UpdateTime)
  160. log.Infof("Rendering...")
  161. case job.StatusWriting:
  162. log.Infof("Render finished in %v", stat.RenderTime)
  163. log.Infof("Writing...")
  164. pprof.StopCPUProfile()
  165. case job.StatusDone:
  166. log.Infof("TOTAL TIME: %v", stat.TotalTime())
  167. case job.StatusError:
  168. log.Criticalf("Error: %v", stat.Error)
  169. return 1
  170. }
  171. }
  172. return 0
  173. }
  174. // A filterLogger can hide messages below a given severity.
  175. type filterLogger struct {
  176. log.Logger
  177. Level int
  178. }
  179. func (l filterLogger) Debugf(format string, args ...interface{}) {
  180. if l.Level >= 1 {
  181. l.Logger.Debugf(format, args...)
  182. }
  183. }
  184. func (l filterLogger) Infof(format string, args ...interface{}) {
  185. if l.Level >= 0 {
  186. l.Logger.Infof(format, args...)
  187. }
  188. }
  189. func (l filterLogger) Warningf(format string, args ...interface{}) {
  190. if l.Level >= -1 {
  191. l.Logger.Warningf(format, args...)
  192. }
  193. }
  194. func (l filterLogger) Errorf(format string, args ...interface{}) {
  195. if l.Level >= -2 {
  196. l.Logger.Errorf(format, args...)
  197. }
  198. }