joonsrenderer 1.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +53 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/CHANGELOG.md +2 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +674 -0
  7. data/README.md +2 -0
  8. data/Rakefile +43 -0
  9. data/docs/.gitignore +6 -0
  10. data/docs/_config.yml +20 -0
  11. data/docs/_includes/footer.html +38 -0
  12. data/docs/_includes/head.html +15 -0
  13. data/docs/_includes/header.html +27 -0
  14. data/docs/_includes/icon-github.html +1 -0
  15. data/docs/_includes/icon-github.svg +1 -0
  16. data/docs/_includes/icon-twitter.html +1 -0
  17. data/docs/_includes/icon-twitter.svg +1 -0
  18. data/docs/_layouts/default.html +20 -0
  19. data/docs/_layouts/page.html +14 -0
  20. data/docs/_layouts/post.html +15 -0
  21. data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
  22. data/docs/_posts/2017-01-08-welcome.md +78 -0
  23. data/docs/_sass/_base.scss +206 -0
  24. data/docs/_sass/_layout.scss +242 -0
  25. data/docs/_sass/_syntax-highlighting.scss +71 -0
  26. data/docs/about.md +12 -0
  27. data/docs/assets/Animation.ogv +0 -0
  28. data/docs/assets/Animation.png +0 -0
  29. data/docs/assets/basic.png +0 -0
  30. data/docs/assets/basic_traced.png +0 -0
  31. data/docs/css/main.scss +38 -0
  32. data/docs/favicon.ico +0 -0
  33. data/docs/feed.xml +30 -0
  34. data/docs/index.html +38 -0
  35. data/joonsrenderer.gemspec +23 -0
  36. data/lib/joonsrenderer.rb +12 -0
  37. data/lib/joonsrenderer/version.rb +3 -0
  38. data/pom.rb +75 -0
  39. data/pom.xml +163 -0
  40. data/src/main/java/SunflowGUI.java +1354 -0
  41. data/src/main/java/joons/JRFiller.java +79 -0
  42. data/src/main/java/joons/JRImagePanel.java +141 -0
  43. data/src/main/java/joons/JRRecorder.java +183 -0
  44. data/src/main/java/joons/JRStatics.java +199 -0
  45. data/src/main/java/joons/JoonsRenderer.java +837 -0
  46. data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
  47. data/src/main/java/org/sunflow/Benchmark.java +313 -0
  48. data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
  49. data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
  50. data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
  51. data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
  52. data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
  53. data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
  54. data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
  55. data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
  56. data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
  57. data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
  58. data/src/main/java/org/sunflow/core/Camera.java +125 -0
  59. data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
  60. data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
  61. data/src/main/java/org/sunflow/core/Display.java +78 -0
  62. data/src/main/java/org/sunflow/core/Filter.java +27 -0
  63. data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
  64. data/src/main/java/org/sunflow/core/Geometry.java +157 -0
  65. data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
  66. data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
  67. data/src/main/java/org/sunflow/core/Instance.java +224 -0
  68. data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
  69. data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
  70. data/src/main/java/org/sunflow/core/LightSample.java +104 -0
  71. data/src/main/java/org/sunflow/core/LightServer.java +382 -0
  72. data/src/main/java/org/sunflow/core/LightSource.java +67 -0
  73. data/src/main/java/org/sunflow/core/Modifier.java +16 -0
  74. data/src/main/java/org/sunflow/core/Options.java +20 -0
  75. data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
  76. data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
  77. data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
  78. data/src/main/java/org/sunflow/core/Ray.java +219 -0
  79. data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
  80. data/src/main/java/org/sunflow/core/Scene.java +377 -0
  81. data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
  82. data/src/main/java/org/sunflow/core/Shader.java +30 -0
  83. data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
  84. data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
  85. data/src/main/java/org/sunflow/core/Statistics.java +85 -0
  86. data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
  87. data/src/main/java/org/sunflow/core/Texture.java +128 -0
  88. data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
  89. data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
  90. data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
  91. data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
  92. data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
  93. data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
  94. data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
  95. data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
  96. data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
  97. data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
  98. data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
  99. data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
  100. data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
  101. data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
  102. data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
  103. data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
  104. data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
  105. data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
  106. data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
  107. data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
  108. data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
  109. data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
  110. data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
  111. data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
  112. data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
  113. data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
  114. data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
  115. data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
  116. data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
  117. data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
  118. data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
  119. data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
  120. data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
  121. data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
  122. data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
  123. data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
  124. data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
  125. data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
  126. data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
  127. data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
  128. data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
  129. data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
  130. data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
  131. data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
  132. data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
  133. data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
  134. data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
  135. data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
  136. data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
  137. data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
  138. data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
  139. data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
  140. data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
  141. data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
  142. data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
  143. data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
  144. data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
  145. data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
  146. data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
  147. data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
  148. data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
  149. data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
  150. data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
  151. data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
  152. data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
  153. data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
  154. data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
  155. data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
  156. data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
  157. data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
  158. data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
  159. data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
  160. data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
  161. data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
  162. data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
  163. data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
  164. data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
  165. data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
  166. data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
  167. data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
  168. data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
  169. data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
  170. data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
  171. data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
  172. data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
  173. data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
  174. data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
  175. data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
  176. data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
  177. data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
  178. data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
  179. data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
  180. data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
  181. data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
  182. data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
  183. data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
  184. data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
  185. data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
  186. data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
  187. data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
  188. data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
  189. data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
  190. data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
  191. data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
  192. data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
  193. data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
  194. data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
  195. data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
  196. data/src/main/java/org/sunflow/image/Color.java +374 -0
  197. data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
  198. data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
  199. data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
  200. data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
  201. data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
  202. data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
  203. data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
  204. data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
  205. data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
  206. data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
  207. data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
  208. data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
  209. data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
  210. data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
  211. data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
  212. data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
  213. data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
  214. data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
  215. data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
  216. data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
  217. data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
  218. data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
  219. data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
  220. data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
  221. data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
  222. data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
  223. data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
  224. data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
  225. data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
  226. data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
  227. data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
  228. data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
  229. data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
  230. data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
  231. data/src/main/java/org/sunflow/math/Point2.java +36 -0
  232. data/src/main/java/org/sunflow/math/Point3.java +133 -0
  233. data/src/main/java/org/sunflow/math/QMC.java +209 -0
  234. data/src/main/java/org/sunflow/math/Solvers.java +142 -0
  235. data/src/main/java/org/sunflow/math/Vector3.java +197 -0
  236. data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
  237. data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
  238. data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
  239. data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
  240. data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
  241. data/src/main/java/org/sunflow/system/Memory.java +18 -0
  242. data/src/main/java/org/sunflow/system/Parser.java +162 -0
  243. data/src/main/java/org/sunflow/system/Plugins.java +142 -0
  244. data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
  245. data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
  246. data/src/main/java/org/sunflow/system/Timer.java +53 -0
  247. data/src/main/java/org/sunflow/system/UI.java +112 -0
  248. data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
  249. data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
  250. data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
  251. data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
  252. data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
  253. data/src/main/java/org/sunflow/util/IntArray.java +77 -0
  254. data/src/test/java/a_maintest.java +129 -0
  255. metadata +300 -0
@@ -0,0 +1,762 @@
1
+ package org.sunflow;
2
+
3
+ import java.io.File;
4
+ import java.io.FileInputStream;
5
+ import java.io.IOException;
6
+ import java.io.StringReader;
7
+ import java.util.Locale;
8
+ import java.util.logging.Level;
9
+ import java.util.logging.Logger;
10
+ import org.codehaus.commons.compiler.CompileException;
11
+ import org.codehaus.janino.ClassBodyEvaluator;
12
+ import org.codehaus.janino.Scanner;
13
+ import org.sunflow.core.Camera;
14
+ import org.sunflow.core.CameraLens;
15
+ import org.sunflow.core.Display;
16
+ import org.sunflow.core.Geometry;
17
+ import org.sunflow.core.ImageSampler;
18
+ import org.sunflow.core.Instance;
19
+ import org.sunflow.core.LightSource;
20
+ import org.sunflow.core.Modifier;
21
+ import org.sunflow.core.Options;
22
+ import org.sunflow.core.ParameterList;
23
+ import org.sunflow.core.PrimitiveList;
24
+ import org.sunflow.core.Scene;
25
+ import org.sunflow.core.SceneParser;
26
+ import org.sunflow.core.Shader;
27
+ import org.sunflow.core.Tesselatable;
28
+ import org.sunflow.core.ParameterList.InterpolationType;
29
+ import org.sunflow.image.ColorFactory;
30
+ import org.sunflow.image.ColorFactory.ColorSpecificationException;
31
+ import org.sunflow.math.BoundingBox;
32
+ import org.sunflow.math.Matrix4;
33
+ import org.sunflow.math.Point2;
34
+ import org.sunflow.math.Point3;
35
+ import org.sunflow.math.Vector3;
36
+ import org.sunflow.system.FileUtils;
37
+ import org.sunflow.system.SearchPath;
38
+ import org.sunflow.system.Timer;
39
+ import org.sunflow.system.UI;
40
+ import org.sunflow.system.UI.Module;
41
+
42
+ /**
43
+ * This API gives a simple interface for creating scenes procedurally. This is
44
+ * the main entry point to Sunflow. To use this class, extend from it and
45
+ * implement the build method which may execute arbitrary code to create a
46
+ * scene.
47
+ */
48
+ public class SunflowAPI implements SunflowAPIInterface {
49
+
50
+ public static final String VERSION = "1.0.0";
51
+ public static final String DEFAULT_OPTIONS = "::options";
52
+ private Scene scene;
53
+ private SearchPath includeSearchPath;
54
+ private SearchPath textureSearchPath;
55
+ private ParameterList parameterList;
56
+ private RenderObjectMap renderObjects;
57
+ private int currentFrame;
58
+ static String COULDNT_MESSAGE_FORMAT = "Could not compile: \"%s\"";
59
+
60
+ /**
61
+ * This is a quick system test which verifies that the user has launched
62
+ * Java properly.
63
+ */
64
+ public static void runSystemCheck() {
65
+ final long RECOMMENDED_MAX_SIZE = 800;
66
+ long maxMb = Runtime.getRuntime().maxMemory() / 1048576;
67
+ if (maxMb < RECOMMENDED_MAX_SIZE) {
68
+ UI.printError(Module.API, "JVM available memory is below %d MB (found %d MB only).\nPlease make sure you launched the program with the -Xmx command line options.", RECOMMENDED_MAX_SIZE, maxMb);
69
+ }
70
+ String compiler = System.getProperty("java.vm.name");
71
+ if (compiler == null || !(compiler.contains("HotSpot") && compiler.contains("Server"))) {
72
+ UI.printError(Module.API, "You do not appear to be running Sun's server JVM\nPerformance may suffer");
73
+ }
74
+ UI.printDetailed(Module.API, "Java environment settings:");
75
+ UI.printDetailed(Module.API, " * Max memory available : %d MB", maxMb);
76
+ UI.printDetailed(Module.API, " * Virtual machine name : %s", compiler == null ? "<unknown" : compiler);
77
+ UI.printDetailed(Module.API, " * Operating system : %s", System.getProperty("os.name"));
78
+ UI.printDetailed(Module.API, " * CPU architecture : %s", System.getProperty("os.arch"));
79
+ }
80
+
81
+ /**
82
+ * Creates an empty scene.
83
+ */
84
+ public SunflowAPI() {
85
+ reset();
86
+ }
87
+
88
+ @Override
89
+ public final void reset() {
90
+ scene = new Scene();
91
+ includeSearchPath = new SearchPath("include");
92
+ textureSearchPath = new SearchPath("texture");
93
+ parameterList = new ParameterList();
94
+ renderObjects = new RenderObjectMap();
95
+ currentFrame = 1;
96
+ }
97
+
98
+ @Override
99
+ public final void plugin(String type, String name, String code) {
100
+ switch (type) {
101
+ case "primitive":
102
+ PluginRegistry.PRIMITIVE_PLUGINS.registerPlugin(name, code);
103
+ break;
104
+ case "tesselatable":
105
+ PluginRegistry.TESSELATABLE_PLUGINS.registerPlugin(name, code);
106
+ break;
107
+ case "shader":
108
+ PluginRegistry.SHADER_PLUGINS.registerPlugin(name, code);
109
+ break;
110
+ case "modifier":
111
+ PluginRegistry.MODIFIER_PLUGINS.registerPlugin(name, code);
112
+ break;
113
+ case "camera_lens":
114
+ PluginRegistry.CAMERA_LENS_PLUGINS.registerPlugin(name, code);
115
+ break;
116
+ case "light":
117
+ PluginRegistry.LIGHT_SOURCE_PLUGINS.registerPlugin(name, code);
118
+ break;
119
+ case "accel":
120
+ PluginRegistry.ACCEL_PLUGINS.registerPlugin(name, code);
121
+ break;
122
+ case "bucket_order":
123
+ PluginRegistry.BUCKET_ORDER_PLUGINS.registerPlugin(name, code);
124
+ break;
125
+ case "filter":
126
+ PluginRegistry.FILTER_PLUGINS.registerPlugin(name, code);
127
+ break;
128
+ case "gi_engine":
129
+ PluginRegistry.GI_ENGINE_PLUGINS.registerPlugin(name, code);
130
+ break;
131
+ case "caustic_photon_map":
132
+ PluginRegistry.CAUSTIC_PHOTON_MAP_PLUGINS.registerPlugin(name, code);
133
+ break;
134
+ case "global_photon_map":
135
+ PluginRegistry.GLOBAL_PHOTON_MAP_PLUGINS.registerPlugin(name, code);
136
+ break;
137
+ case "image_sampler":
138
+ PluginRegistry.IMAGE_SAMPLE_PLUGINS.registerPlugin(name, code);
139
+ break;
140
+ case "parser":
141
+ PluginRegistry.PARSER_PLUGINS.registerPlugin(name, code);
142
+ break;
143
+ case "bitmap_reader":
144
+ PluginRegistry.BITMAP_READER_PLUGINS.registerPlugin(name, code);
145
+ break;
146
+ case "bitmap_writer":
147
+ PluginRegistry.BITMAP_WRITER_PLUGINS.registerPlugin(name, code);
148
+ break;
149
+ default:
150
+ UI.printWarning(Module.API, "Unrecognized plugin type: \"%s\" - ignoring declaration of \"%s\"", type, name);
151
+ break;
152
+ }
153
+ }
154
+
155
+ @Override
156
+ public final void parameter(String name, String value) {
157
+ parameterList.addString(name, value);
158
+ }
159
+
160
+ @Override
161
+ public final void parameter(String name, boolean value) {
162
+ parameterList.addBoolean(name, value);
163
+ }
164
+
165
+ @Override
166
+ public final void parameter(String name, int value) {
167
+ parameterList.addInteger(name, value);
168
+ }
169
+
170
+ @Override
171
+ public final void parameter(String name, float value) {
172
+ parameterList.addFloat(name, value);
173
+ }
174
+
175
+ @Override
176
+ public final void parameter(String name, String colorspace, float... data) {
177
+ try {
178
+ parameterList.addColor(name, ColorFactory.createColor(colorspace, data));
179
+ } catch (ColorSpecificationException e) {
180
+ UI.printError(Module.API, "Unable to specify color: %s - ignoring parameter \"%s\"", e.getMessage(), name);
181
+ }
182
+ }
183
+
184
+ @Override
185
+ public final void parameter(String name, Point3 value) {
186
+ parameterList.addPoints(name, InterpolationType.NONE, new float[]{
187
+ value.x, value.y, value.z});
188
+ }
189
+
190
+ @Override
191
+ public final void parameter(String name, Vector3 value) {
192
+ parameterList.addVectors(name, InterpolationType.NONE, new float[]{
193
+ value.x, value.y, value.z});
194
+ }
195
+
196
+ @Override
197
+ public final void parameter(String name, Point2 value) {
198
+ parameterList.addTexCoords(name, InterpolationType.NONE, new float[]{
199
+ value.x, value.y});
200
+ }
201
+
202
+ @Override
203
+ public final void parameter(String name, Matrix4 value) {
204
+ parameterList.addMatrices(name, InterpolationType.NONE, value.asRowMajor());
205
+ }
206
+
207
+ @Override
208
+ public final void parameter(String name, int[] value) {
209
+ parameterList.addIntegerArray(name, value);
210
+ }
211
+
212
+ @Override
213
+ public final void parameter(String name, String[] value) {
214
+ parameterList.addStringArray(name, value);
215
+ }
216
+
217
+ @Override
218
+ public final void parameter(String name, String type, String interpolation, float[] data) {
219
+ InterpolationType interp;
220
+ try {
221
+ interp = InterpolationType.valueOf(interpolation.toUpperCase(Locale.ENGLISH));
222
+ } catch (IllegalArgumentException e) {
223
+ UI.printError(Module.API, "Unknown interpolation type: %s -- ignoring parameter \"%s\"", interpolation, name);
224
+ return;
225
+ }
226
+ switch (type) {
227
+ case "float":
228
+ parameterList.addFloats(name, interp, data);
229
+ break;
230
+ case "point":
231
+ parameterList.addPoints(name, interp, data);
232
+ break;
233
+ case "vector":
234
+ parameterList.addVectors(name, interp, data);
235
+ break;
236
+ case "texcoord":
237
+ parameterList.addTexCoords(name, interp, data);
238
+ break;
239
+ case "matrix":
240
+ parameterList.addMatrices(name, interp, data);
241
+ break;
242
+ default:
243
+ UI.printError(Module.API, "Unknown parameter type: %s -- ignoring parameter \"%s\"", type, name);
244
+ break;
245
+ }
246
+ }
247
+
248
+ @Override
249
+ public void remove(String name) {
250
+ renderObjects.remove(name);
251
+ }
252
+
253
+ /**
254
+ * Update the specfied object using the currently active parameter list. The
255
+ * object is removed if the update fails to avoid leaving inconsistently set
256
+ * objects in the list.
257
+ *
258
+ * @param name name of the object to update
259
+ * @return <code>true</code> if the update was succesfull, or
260
+ * <code>false</code> if the update failed
261
+ */
262
+ private boolean update(String name) {
263
+ boolean success = renderObjects.update(name, parameterList, this);
264
+ parameterList.clear(success);
265
+ return success;
266
+ }
267
+
268
+ @Override
269
+ public final void searchpath(String type, String path) {
270
+ switch (type) {
271
+ case "include":
272
+ includeSearchPath.addSearchPath(path);
273
+ break;
274
+ case "texture":
275
+ textureSearchPath.addSearchPath(path);
276
+ break;
277
+ default:
278
+ UI.printWarning(Module.API, "Invalid searchpath type: \"%s\"", type);
279
+ break;
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Attempts to resolve the specified filename by checking it against the
285
+ * texture search path.
286
+ *
287
+ * @param filename filename
288
+ * @return a path which matches the filename, or filename if no matches are
289
+ * found
290
+ */
291
+ public final String resolveTextureFilename(String filename) {
292
+ return textureSearchPath.resolvePath(filename);
293
+ }
294
+
295
+ /**
296
+ * Attempts to resolve the specified filename by checking it against the
297
+ * include search path.
298
+ *
299
+ * @param filename filename
300
+ * @return a path which matches the filename, or filename if no matches are
301
+ * found
302
+ */
303
+ public final String resolveIncludeFilename(String filename) {
304
+ return includeSearchPath.resolvePath(filename);
305
+ }
306
+
307
+ @Override
308
+ public final void shader(String name, String shaderType) {
309
+ if (!isIncremental(shaderType)) {
310
+ // we are declaring a shader for the first time
311
+ if (renderObjects.has(name)) {
312
+ UI.printError(Module.API, "Unable to declare shader \"%s\", name is already in use", name);
313
+ parameterList.clear(true);
314
+ return;
315
+ }
316
+ Shader shader = PluginRegistry.SHADER_PLUGINS.createObject(shaderType);
317
+ if (shader == null) {
318
+ UI.printError(Module.API, "Unable to create shader of type \"%s\"", shaderType);
319
+ return;
320
+ }
321
+ renderObjects.put(name, shader);
322
+ }
323
+ // update existing shader (only if it is valid)
324
+ if (lookupShader(name) != null) {
325
+ update(name);
326
+ } else {
327
+ UI.printError(Module.API, "Unable to update shader \"%s\" - shader object was not found", name);
328
+ parameterList.clear(true);
329
+ }
330
+ }
331
+
332
+ @Override
333
+ public final void modifier(String name, String modifierType) {
334
+ if (!isIncremental(modifierType)) {
335
+ // we are declaring a shader for the first time
336
+ if (renderObjects.has(name)) {
337
+ UI.printError(Module.API, "Unable to declare modifier \"%s\", name is already in use", name);
338
+ parameterList.clear(true);
339
+ return;
340
+ }
341
+ Modifier modifier = PluginRegistry.MODIFIER_PLUGINS.createObject(modifierType);
342
+ if (modifier == null) {
343
+ UI.printError(Module.API, "Unable to create modifier of type \"%s\"", modifierType);
344
+ return;
345
+ }
346
+ renderObjects.put(name, modifier);
347
+ }
348
+ // update existing shader (only if it is valid)
349
+ if (lookupModifier(name) != null) {
350
+ update(name);
351
+ } else {
352
+ UI.printError(Module.API, "Unable to update modifier \"%s\" - modifier object was not found", name);
353
+ parameterList.clear(true);
354
+ }
355
+ }
356
+
357
+ @Override
358
+ public final void geometry(String name, String typeName) {
359
+ if (!isIncremental(typeName)) {
360
+ // we are declaring a geometry for the first time
361
+ if (renderObjects.has(name)) {
362
+ UI.printError(Module.API, "Unable to declare geometry \"%s\", name is already in use", name);
363
+ parameterList.clear(true);
364
+ return;
365
+ }
366
+ // check tesselatable first
367
+ if (PluginRegistry.TESSELATABLE_PLUGINS.hasType(typeName)) {
368
+ Tesselatable tesselatable = PluginRegistry.TESSELATABLE_PLUGINS.createObject(typeName);
369
+ if (tesselatable == null) {
370
+ UI.printError(Module.API, "Unable to create tesselatable object of type \"%s\"", typeName);
371
+ return;
372
+ }
373
+ renderObjects.put(name, tesselatable);
374
+ } else {
375
+ PrimitiveList primitives = PluginRegistry.PRIMITIVE_PLUGINS.createObject(typeName);
376
+ if (primitives == null) {
377
+ UI.printError(Module.API, "Unable to create primitive of type \"%s\"", typeName);
378
+ return;
379
+ }
380
+ renderObjects.put(name, primitives);
381
+ }
382
+ }
383
+ if (lookupGeometry(name) != null) {
384
+ update(name);
385
+ } else {
386
+ UI.printError(Module.API, "Unable to update geometry \"%s\" - geometry object was not found", name);
387
+ parameterList.clear(true);
388
+ }
389
+ }
390
+
391
+ @Override
392
+ public final void instance(String name, String geoname) {
393
+ if (!isIncremental(geoname)) {
394
+ // we are declaring this instance for the first time
395
+ if (renderObjects.has(name)) {
396
+ UI.printError(Module.API, "Unable to declare instance \"%s\", name is already in use", name);
397
+ parameterList.clear(true);
398
+ return;
399
+ }
400
+ parameter("geometry", geoname);
401
+ renderObjects.put(name, new Instance());
402
+ }
403
+ if (lookupInstance(name) != null) {
404
+ update(name);
405
+ } else {
406
+ UI.printError(Module.API, "Unable to update instance \"%s\" - instance object was not found", name);
407
+ parameterList.clear(true);
408
+ }
409
+ }
410
+
411
+ @Override
412
+ public final void light(String name, String lightType) {
413
+ if (!isIncremental(lightType)) {
414
+ // we are declaring this light for the first time
415
+ if (renderObjects.has(name)) {
416
+ UI.printError(Module.API, "Unable to declare light \"%s\", name is already in use", name);
417
+ parameterList.clear(true);
418
+ return;
419
+ }
420
+ LightSource light = PluginRegistry.LIGHT_SOURCE_PLUGINS.createObject(lightType);
421
+ if (light == null) {
422
+ UI.printError(Module.API, "Unable to create light source of type \"%s\"", lightType);
423
+ return;
424
+ }
425
+ renderObjects.put(name, light);
426
+ }
427
+ if (lookupLight(name) != null) {
428
+ update(name);
429
+ } else {
430
+ UI.printError(Module.API, "Unable to update instance \"%s\" - instance object was not found", name);
431
+ parameterList.clear(true);
432
+ }
433
+ }
434
+
435
+ @Override
436
+ public final void camera(String name, String lensType) {
437
+ if (!isIncremental(lensType)) {
438
+ // we are declaring this camera for the first time
439
+ if (renderObjects.has(name)) {
440
+ UI.printError(Module.API, "Unable to declare camera \"%s\", name is already in use", name);
441
+ parameterList.clear(true);
442
+ return;
443
+ }
444
+ CameraLens lens = PluginRegistry.CAMERA_LENS_PLUGINS.createObject(lensType);
445
+ if (lens == null) {
446
+ UI.printError(Module.API, "Unable to create a camera lens of type \"%s\"", lensType);
447
+ return;
448
+ }
449
+ renderObjects.put(name, new Camera(lens));
450
+ }
451
+ // update existing shader (only if it is valid)
452
+ if (lookupCamera(name) != null) {
453
+ update(name);
454
+ } else {
455
+ UI.printError(Module.API, "Unable to update camera \"%s\" - camera object was not found", name);
456
+ parameterList.clear(true);
457
+ }
458
+ }
459
+
460
+ @Override
461
+ public final void options(String name) {
462
+ if (lookupOptions(name) == null) {
463
+ if (renderObjects.has(name)) {
464
+ UI.printError(Module.API, "Unable to declare options \"%s\", name is already in use", name);
465
+ parameterList.clear(true);
466
+ return;
467
+ }
468
+ renderObjects.put(name, new Options());
469
+ }
470
+ assert lookupOptions(name) != null;
471
+ update(name);
472
+ }
473
+
474
+ private boolean isIncremental(String typeName) {
475
+ return typeName == null || typeName.equals("incremental");
476
+ }
477
+
478
+ /**
479
+ * Retrieve a geometry object by its name, or
480
+ * <code>null</code> if no geometry was found, or if the specified object is
481
+ * not a geometry.
482
+ *
483
+ * @param name geometry name
484
+ * @return the geometry object associated with that name
485
+ */
486
+ public final Geometry lookupGeometry(String name) {
487
+ return renderObjects.lookupGeometry(name);
488
+ }
489
+
490
+ /**
491
+ * Retrieve an instance object by its name, or
492
+ * <code>null</code> if no instance was found, or if the specified object is
493
+ * not an instance.
494
+ *
495
+ * @param name instance name
496
+ * @return the instance object associated with that name
497
+ */
498
+ private Instance lookupInstance(String name) {
499
+ return renderObjects.lookupInstance(name);
500
+ }
501
+
502
+ /**
503
+ * Retrieve a shader object by its name, or
504
+ * <code>null</code> if no shader was found, or if the specified object is
505
+ * not a shader.
506
+ *
507
+ * @param name camera name
508
+ * @return the camera object associate with that name
509
+ */
510
+ private Camera lookupCamera(String name) {
511
+ return renderObjects.lookupCamera(name);
512
+ }
513
+
514
+ private Options lookupOptions(String name) {
515
+ return renderObjects.lookupOptions(name);
516
+ }
517
+
518
+ /**
519
+ * Retrieve a shader object by its name, or
520
+ * <code>null</code> if no shader was found, or if the specified object is
521
+ * not a shader.
522
+ *
523
+ * @param name shader name
524
+ * @return the shader object associated with that name
525
+ */
526
+ public final Shader lookupShader(String name) {
527
+ return renderObjects.lookupShader(name);
528
+ }
529
+
530
+ /**
531
+ * Retrieve a modifier object by its name, or
532
+ * <code>null</code> if no modifier was found, or if the specified object is
533
+ * not a modifier.
534
+ *
535
+ * @param name modifier name
536
+ * @return the modifier object associated with that name
537
+ */
538
+ public final Modifier lookupModifier(String name) {
539
+ return renderObjects.lookupModifier(name);
540
+ }
541
+
542
+ /**
543
+ * Retrieve a light object by its name, or
544
+ * <code>null</code> if no shader was found, or if the specified object is
545
+ * not a light.
546
+ *
547
+ * @param name light name
548
+ * @return the light object associated with that name
549
+ */
550
+ private LightSource lookupLight(String name) {
551
+ return renderObjects.lookupLight(name);
552
+ }
553
+
554
+ @Override
555
+ public final void render(String optionsName, Display display) {
556
+ renderObjects.updateScene(scene);
557
+ Options opt = lookupOptions(optionsName);
558
+ if (opt == null) {
559
+ opt = new Options();
560
+ }
561
+ scene.setCamera(lookupCamera(opt.getString("camera", null)));
562
+
563
+ // shader override
564
+ String shaderOverrideName = opt.getString("override.shader", "none");
565
+ boolean overridePhotons = opt.getBoolean("override.photons", false);
566
+
567
+ if (shaderOverrideName.equals("none")) {
568
+ scene.setShaderOverride(null, false);
569
+ } else {
570
+ Shader shader = lookupShader(shaderOverrideName);
571
+ if (shader == null) {
572
+ UI.printWarning(Module.API, "Unable to find shader \"%s\" for override, disabling", shaderOverrideName);
573
+ }
574
+ scene.setShaderOverride(shader, overridePhotons);
575
+ }
576
+
577
+ // baking
578
+ String bakingInstanceName = opt.getString("baking.instance", null);
579
+ if (bakingInstanceName != null) {
580
+ Instance bakingInstance = lookupInstance(bakingInstanceName);
581
+ if (bakingInstance == null) {
582
+ UI.printError(Module.API, "Unable to bake instance \"%s\" - not found", bakingInstanceName);
583
+ return;
584
+ }
585
+ scene.setBakingInstance(bakingInstance);
586
+ } else {
587
+ scene.setBakingInstance(null);
588
+ }
589
+
590
+ ImageSampler sampler = PluginRegistry.IMAGE_SAMPLE_PLUGINS.createObject(opt.getString("sampler", "bucket"));
591
+ scene.render(opt, sampler, display);
592
+ }
593
+
594
+ @Override
595
+ public final boolean include(String filename) {
596
+ if (filename == null) {
597
+ return false;
598
+ }
599
+ filename = includeSearchPath.resolvePath(filename);
600
+ String extension = FileUtils.getExtension(filename);
601
+ SceneParser parser = PluginRegistry.PARSER_PLUGINS.createObject(extension);
602
+ if (parser == null) {
603
+ UI.printError(Module.API, "Unable to find a suitable parser for: \"%s\" (extension: %s)", filename, extension);
604
+ return false;
605
+ }
606
+ String currentFolder = new File(filename).getAbsoluteFile().getParentFile().getAbsolutePath();
607
+ includeSearchPath.addSearchPath(currentFolder);
608
+ textureSearchPath.addSearchPath(currentFolder);
609
+ return parser.parse(filename, this);
610
+ }
611
+
612
+ /**
613
+ * Retrieve the bounding box of the scene. This method will be valid only
614
+ * after a first call to {@link #render(String, Display)} has been made.
615
+ * @return
616
+ */
617
+ public final BoundingBox getBounds() {
618
+ return scene.getBounds();
619
+ }
620
+
621
+ /**
622
+ * This method does nothing, but may be overriden to create scenes
623
+ * procedurally.
624
+ */
625
+ public void build() {
626
+ }
627
+
628
+ /**
629
+ * Create an API object from the specified file. Java files are read by
630
+ * Janino and are expected to implement a build method (they implement a
631
+ * derived class of SunflowAPI. The build method is called if the code
632
+ * compiles succesfully. Other files types are handled by the parse method.
633
+ *
634
+ * @param filename filename to load
635
+ * @param frameNumber
636
+ * @return a valid SunflowAPI object or <code>null</code> on failure
637
+ */
638
+ public static SunflowAPI create(String filename, int frameNumber) {
639
+ if (filename == null) {
640
+ return new SunflowAPI();
641
+ }
642
+ SunflowAPI api = null;
643
+ if (filename.endsWith(".java")) {
644
+ Timer t = new Timer();
645
+ UI.printInfo(Module.API, "Compiling \"" + filename + "\" ...");
646
+ t.start();
647
+ try {
648
+ try (FileInputStream stream = new FileInputStream(filename)) {
649
+ api = (SunflowAPI) ClassBodyEvaluator.createFastClassBodyEvaluator(new Scanner(filename, stream), SunflowAPI.class, ClassLoader.getSystemClassLoader());
650
+ }
651
+ } catch (CompileException e) {
652
+ UI.printError(Module.API, COULDNT_MESSAGE_FORMAT, filename);
653
+ UI.printError(Module.API, "%s", e.getMessage());
654
+ return null;
655
+ } catch (IOException e) {
656
+ UI.printError(Module.API, COULDNT_MESSAGE_FORMAT, filename);
657
+ UI.printError(Module.API, "%s", e.getMessage());
658
+ return null;
659
+ }
660
+ t.end();
661
+ UI.printInfo(Module.API, "Compile time: " + t.toString());
662
+ // allow relative paths
663
+ String currentFolder = new File(filename).getAbsoluteFile().getParentFile().getAbsolutePath();
664
+ api.includeSearchPath.addSearchPath(currentFolder);
665
+ api.textureSearchPath.addSearchPath(currentFolder);
666
+ UI.printInfo(Module.API, "Build script running ...");
667
+ t.start();
668
+ api.currentFrame(frameNumber);
669
+ api.build();
670
+ t.end();
671
+ UI.printInfo(Module.API, "Build script time: %s", t.toString());
672
+ } else {
673
+ api = new SunflowAPI();
674
+ api = api.include(filename) ? api : null;
675
+ }
676
+ return api;
677
+ }
678
+
679
+ /**
680
+ * Translate specfied file into the native sunflow scene file format.
681
+ *
682
+ * @param filename input filename
683
+ * @param outputFilename output filename
684
+ * @return <code>true</code> upon success, <code>false</code> otherwise
685
+ */
686
+ public static boolean translate(String filename, String outputFilename) {
687
+ FileSunflowAPI api = null;
688
+ try {
689
+ if (outputFilename.endsWith(".sca")) {
690
+ api = new AsciiFileSunflowAPI(outputFilename);
691
+ } else if (outputFilename.endsWith(".scb")) {
692
+ api = new BinaryFileSunflowAPI(outputFilename);
693
+ } else {
694
+ UI.printError(Module.API, "Unable to determine output filetype: \"%s\"", outputFilename);
695
+ return false;
696
+ }
697
+ } catch (IOException e) {
698
+ UI.printError(Module.API, "Unable to create output file - %s", e.getMessage());
699
+ return false;
700
+ }
701
+ String extension = filename.substring(filename.lastIndexOf('.') + 1);
702
+ SceneParser parser = PluginRegistry.PARSER_PLUGINS.createObject(extension);
703
+ if (parser == null) {
704
+ UI.printError(Module.API, "Unable to find a suitable parser for: \"%s\"", filename);
705
+ return false;
706
+ }
707
+ try {
708
+ return parser.parse(filename, api);
709
+ } catch (RuntimeException e) {
710
+ Logger.getLogger(SunflowAPI.class.getName()).log(Level.SEVERE, null, e);
711
+ UI.printError(Module.API, "Error occured during translation: %s", e.getMessage());
712
+ return false;
713
+ } finally {
714
+ api.close();
715
+ }
716
+ }
717
+
718
+ /**
719
+ * Compile the specified code string via Janino. The code must implement a
720
+ * build method as described above. The build method is not called on the
721
+ * output, it is up the caller to do so.
722
+ *
723
+ * @param code java code string
724
+ * @return a valid SunflowAPI object upon succes, <code>null</code>
725
+ * otherwise.
726
+ */
727
+ public static SunflowAPI compile(String code) {
728
+ SunflowAPI api = null;
729
+ try {
730
+ Timer t = new Timer();
731
+ t.start();
732
+
733
+ try {
734
+ api = (SunflowAPI) ClassBodyEvaluator.createFastClassBodyEvaluator(new Scanner(null, new StringReader(code)), SunflowAPI.class, (ClassLoader) null);
735
+ } catch (IOException ex) {
736
+ Logger.getLogger(SunflowAPI.class.getName()).log(Level.SEVERE, null, ex);
737
+ }
738
+ t.end();
739
+ UI.printInfo(Module.API, "Compile time: %s", t.toString());
740
+ return api;
741
+ } catch (CompileException e) {
742
+ UI.printError(Module.API, "%s", e.getMessage());
743
+ return null;
744
+ }
745
+ }
746
+
747
+ /**
748
+ * Read the value of the current frame. This value is intended only for
749
+ * procedural animation creation. It is not used by the Sunflow core in
750
+ * anyway. The default value is 1.
751
+ *
752
+ * @return current frame number
753
+ */
754
+ public int currentFrame() {
755
+ return currentFrame;
756
+ }
757
+
758
+ @Override
759
+ public void currentFrame(int currentFrame) {
760
+ this.currentFrame = currentFrame;
761
+ }
762
+ }