joonsrenderer 1.1-java

Sign up to get free protection for your applications and to get access to all the features.
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
+ }