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,62 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.image.Color;
4
+ import org.sunflow.math.BoundingBox;
5
+ import org.sunflow.math.Vector3;
6
+
7
+ /**
8
+ * Describes an object which can store photons.
9
+ */
10
+ public interface PhotonStore {
11
+
12
+ /**
13
+ * Number of photons to emit from this surface.
14
+ *
15
+ * @return number of photons
16
+ */
17
+ int numEmit();
18
+
19
+ /**
20
+ * Initialize this object for the specified scene size.
21
+ *
22
+ * @param sceneBounds scene bounding box
23
+ */
24
+ void prepare(Options options, BoundingBox sceneBounds);
25
+
26
+ /**
27
+ * Store the specified photon.
28
+ *
29
+ * @param state shading state
30
+ * @param dir photon direction
31
+ * @param power photon power
32
+ * @param diffuse diffuse color at the hit point
33
+ */
34
+ void store(ShadingState state, Vector3 dir, Color power, Color diffuse);
35
+
36
+ /**
37
+ * Initialize the map after all photons have been stored. This can be used
38
+ * to balance a kd-tree based photon map for example.
39
+ */
40
+ void init();
41
+
42
+ /**
43
+ * Allow photons reflected diffusely?
44
+ *
45
+ * @return <code>true</code> if diffuse bounces should be traced
46
+ */
47
+ boolean allowDiffuseBounced();
48
+
49
+ /**
50
+ * Allow specularly reflected photons?
51
+ *
52
+ * @return <code>true</code> if specular reflection bounces should be traced
53
+ */
54
+ boolean allowReflectionBounced();
55
+
56
+ /**
57
+ * Allow refracted photons?
58
+ *
59
+ * @return <code>true</code> if refracted bounces should be traced
60
+ */
61
+ boolean allowRefractionBounced();
62
+ }
@@ -0,0 +1,70 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.math.BoundingBox;
4
+ import org.sunflow.math.Matrix4;
5
+
6
+ /**
7
+ * This class represents an object made up of many primitives.
8
+ */
9
+ public interface PrimitiveList extends RenderObject {
10
+
11
+ /**
12
+ * Compute a bounding box of this object in world space, using the specified
13
+ * object-to-world transformation matrix. The bounds should be as exact as
14
+ * possible, if they are difficult or expensive to compute exactly, you may
15
+ * use {@link Matrix4#transform(BoundingBox)}. If the matrix is
16
+ * <code>null</code> no transformation is needed, and object space is
17
+ * equivalent to world space.
18
+ *
19
+ * @param o2w object to world transformation matrix
20
+ * @return object bounding box in world space
21
+ */
22
+ public BoundingBox getWorldBounds(Matrix4 o2w);
23
+
24
+ /**
25
+ * Returns the number of individual primtives in this aggregate object.
26
+ *
27
+ * @return number of primitives
28
+ */
29
+ public int getNumPrimitives();
30
+
31
+ /**
32
+ * Retrieve the bounding box component of a particular primitive in object
33
+ * space. Even indexes get minimum values, while odd indexes get the maximum
34
+ * values for each axis.
35
+ *
36
+ * @param primID primitive index
37
+ * @param i bounding box side index
38
+ * @return value of the request bound
39
+ */
40
+ public float getPrimitiveBound(int primID, int i);
41
+
42
+ /**
43
+ * Intersect the specified primitive in local space.
44
+ *
45
+ * @param r ray in the object's local space
46
+ * @param primID primitive index to intersect
47
+ * @param state intersection state
48
+ * @see Ray#setMax(float)
49
+ * @see IntersectionState#setIntersection(int, float, float)
50
+ */
51
+ public void intersectPrimitive(Ray r, int primID, IntersectionState state);
52
+
53
+ /**
54
+ * Prepare the specified {@link ShadingState} by setting all of its internal
55
+ * parameters.
56
+ *
57
+ * @param state shading state to fill in
58
+ */
59
+ public void prepareShadingState(ShadingState state);
60
+
61
+ /**
62
+ * Create a new {@link PrimitiveList} object suitable for baking lightmaps.
63
+ * This means a set of primitives laid out in the unit square UV space. This
64
+ * method is optional, objects which do not support it should simply return
65
+ * <code>null</code>.
66
+ *
67
+ * @return a list of baking primitives
68
+ */
69
+ public PrimitiveList getBakingPrimitives();
70
+ }
@@ -0,0 +1,219 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.math.Matrix4;
4
+ import org.sunflow.math.Point3;
5
+ import org.sunflow.math.Vector3;
6
+
7
+ /**
8
+ * This class represents a ray as a oriented half line segment. The ray
9
+ * direction is always normalized. The valid region is delimted by two distances
10
+ * along the ray, tMin and tMax.
11
+ */
12
+ public final class Ray {
13
+
14
+ public float ox, oy, oz;
15
+ public float dx, dy, dz;
16
+ private float tMin;
17
+ private float tMax;
18
+ private static final float EPSILON = 0;// 0.01f;
19
+
20
+ private Ray() {
21
+ }
22
+
23
+ /**
24
+ * Creates a new ray that points from the given origin to the given
25
+ * direction. The ray has infinite length. The direction vector is
26
+ * normalized.
27
+ *
28
+ * @param ox ray origin x
29
+ * @param oy ray origin y
30
+ * @param oz ray origin z
31
+ * @param dx ray direction x
32
+ * @param dy ray direction y
33
+ * @param dz ray direction z
34
+ */
35
+ public Ray(float ox, float oy, float oz, float dx, float dy, float dz) {
36
+ this.ox = ox;
37
+ this.oy = oy;
38
+ this.oz = oz;
39
+ this.dx = dx;
40
+ this.dy = dy;
41
+ this.dz = dz;
42
+ float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
43
+ this.dx *= in;
44
+ this.dy *= in;
45
+ this.dz *= in;
46
+ tMin = EPSILON;
47
+ tMax = Float.POSITIVE_INFINITY;
48
+ }
49
+
50
+ /**
51
+ * Creates a new ray that points from the given origin to the given
52
+ * direction. The ray has infinite length. The direction vector is
53
+ * normalized.
54
+ *
55
+ * @param o ray origin
56
+ * @param d ray direction (need not be normalized)
57
+ */
58
+ public Ray(Point3 o, Vector3 d) {
59
+ ox = o.x;
60
+ oy = o.y;
61
+ oz = o.z;
62
+ dx = d.x;
63
+ dy = d.y;
64
+ dz = d.z;
65
+ float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
66
+ dx *= in;
67
+ dy *= in;
68
+ dz *= in;
69
+ tMin = EPSILON;
70
+ tMax = Float.POSITIVE_INFINITY;
71
+ }
72
+
73
+ /**
74
+ * Creates a new ray that points from point a to point b. The created ray
75
+ * will set tMin and tMax to limit the ray to the segment (a,b)
76
+ * (non-inclusive of a and b). This is often used to create shadow rays.
77
+ *
78
+ * @param a start point
79
+ * @param b end point
80
+ */
81
+ public Ray(Point3 a, Point3 b) {
82
+ ox = a.x;
83
+ oy = a.y;
84
+ oz = a.z;
85
+ dx = b.x - ox;
86
+ dy = b.y - oy;
87
+ dz = b.z - oz;
88
+ tMin = EPSILON;
89
+ float n = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
90
+ float in = 1.0f / n;
91
+ dx *= in;
92
+ dy *= in;
93
+ dz *= in;
94
+ tMax = n - EPSILON;
95
+ }
96
+
97
+ /**
98
+ * Create a new ray by transforming the supplied one by the given matrix. If
99
+ * the matrix is
100
+ * <code>null</code>, the original ray is returned.
101
+ *
102
+ * @param m matrix to transform the ray by
103
+ */
104
+ public Ray transform(Matrix4 m) {
105
+ if (m == null) {
106
+ return this;
107
+ }
108
+ Ray r = new Ray();
109
+ r.ox = m.transformPX(ox, oy, oz);
110
+ r.oy = m.transformPY(ox, oy, oz);
111
+ r.oz = m.transformPZ(ox, oy, oz);
112
+ r.dx = m.transformVX(dx, dy, dz);
113
+ r.dy = m.transformVY(dx, dy, dz);
114
+ r.dz = m.transformVZ(dx, dy, dz);
115
+ r.tMin = tMin;
116
+ r.tMax = tMax;
117
+ return r;
118
+ }
119
+
120
+ /**
121
+ * Normalize the direction component of the ray.
122
+ */
123
+ public void normalize() {
124
+ float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
125
+ dx *= in;
126
+ dy *= in;
127
+ dz *= in;
128
+ }
129
+
130
+ /**
131
+ * Gets the minimum distance along the ray - usually 0.
132
+ *
133
+ * @return value of the smallest distance along the ray
134
+ */
135
+ public final float getMin() {
136
+ return tMin;
137
+ }
138
+
139
+ /**
140
+ * Gets the maximum distance along the ray. May be infinite.
141
+ *
142
+ * @return value of the largest distance along the ray
143
+ */
144
+ public final float getMax() {
145
+ return tMax;
146
+ }
147
+
148
+ /**
149
+ * Creates a vector to represent the direction of the ray.
150
+ *
151
+ * @return a vector equal to the direction of this ray
152
+ */
153
+ public final Vector3 getDirection() {
154
+ return new Vector3(dx, dy, dz);
155
+ }
156
+
157
+ /**
158
+ * Checks to see if the specified distance falls within the valid range on
159
+ * this ray. This should always be used before an intersection with the ray
160
+ * is detected.
161
+ *
162
+ * @param t distance to be tested
163
+ * @return <code>true</code> if t falls between the minimum and maximum
164
+ * distance of this ray, <code>false</code> otherwise
165
+ */
166
+ public final boolean isInside(float t) {
167
+ return (tMin < t) && (t < tMax);
168
+ }
169
+
170
+ /**
171
+ * Gets the end point of the ray. A reference to
172
+ * <code>dest</code> is returned to support chaining.
173
+ *
174
+ * @param dest reference to the point to store
175
+ * @return reference to <code>dest</code>
176
+ */
177
+ public final Point3 getPoint(Point3 dest) {
178
+ dest.x = ox + (tMax * dx);
179
+ dest.y = oy + (tMax * dy);
180
+ dest.z = oz + (tMax * dz);
181
+ return dest;
182
+ }
183
+
184
+ /**
185
+ * Computes the dot product of an arbitrary vector with the direction of the
186
+ * ray. This method avoids having to call getDirection() which would
187
+ * instantiate a new Vector object.
188
+ *
189
+ * @param v vector
190
+ * @return dot product of the ray direction and the specified vector
191
+ */
192
+ public final float dot(Vector3 v) {
193
+ return dx * v.x + dy * v.y + dz * v.z;
194
+ }
195
+
196
+ /**
197
+ * Computes the dot product of an arbitrary vector with the direction of the
198
+ * ray. This method avoids having to call getDirection() which would
199
+ * instantiate a new Vector object.
200
+ *
201
+ * @param vx vector x coordinate
202
+ * @param vy vector y coordinate
203
+ * @param vz vector z coordinate
204
+ * @return dot product of the ray direction and the specified vector
205
+ */
206
+ public final float dot(float vx, float vy, float vz) {
207
+ return dx * vx + dy * vy + dz * vz;
208
+ }
209
+
210
+ /**
211
+ * Updates the maximum to the specified distance if and only if the new
212
+ * distance is smaller than the current one.
213
+ *
214
+ * @param t new maximum distance
215
+ */
216
+ public final void setMax(float t) {
217
+ tMax = t;
218
+ }
219
+ }
@@ -0,0 +1,25 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+
5
+ /**
6
+ * This is the base interface for all public rendering object interfaces. It
7
+ * handles incremental updates via {@link ParameterList} objects.
8
+ */
9
+ public interface RenderObject {
10
+
11
+ /**
12
+ * Update this object given a list of parameters. This method is guarenteed
13
+ * to be called at least once on every object, but it should correctly
14
+ * handle empty parameter lists. This means that the object should be in a
15
+ * valid state from the time it is constructed. This method should also
16
+ * return true or false depending on whether the update was succesfull or
17
+ * not.
18
+ *
19
+ * @param pl list of parameters to read from
20
+ * @param api reference to the current scene
21
+ * @return <code>true</code> if the update is succesfull, <code>false</code>
22
+ * otherwise
23
+ */
24
+ public boolean update(ParameterList pl, SunflowAPI api);
25
+ }
@@ -0,0 +1,377 @@
1
+ package org.sunflow.core;
2
+
3
+ import java.util.ArrayList;
4
+
5
+ import org.sunflow.core.display.FrameDisplay;
6
+ import org.sunflow.image.Color;
7
+ import org.sunflow.math.BoundingBox;
8
+ import org.sunflow.math.MathUtils;
9
+ import org.sunflow.math.Point3;
10
+ import org.sunflow.math.Vector3;
11
+ import org.sunflow.system.UI;
12
+ import org.sunflow.system.UI.Module;
13
+
14
+ /**
15
+ * Represents a entire scene, defined as a collection of instances viewed by a
16
+ * camera.
17
+ */
18
+ public class Scene {
19
+ // scene storage
20
+
21
+ private LightServer lightServer;
22
+ private InstanceList instanceList;
23
+ private InstanceList infiniteInstanceList;
24
+ private Camera camera;
25
+ private AccelerationStructure intAccel;
26
+ private String acceltype;
27
+ private Statistics stats;
28
+ // baking
29
+ private boolean bakingViewDependent;
30
+ private Instance bakingInstance;
31
+ private PrimitiveList bakingPrimitives;
32
+ private AccelerationStructure bakingAccel;
33
+ private boolean rebuildAccel;
34
+ // image size
35
+ private int imageWidth;
36
+ private int imageHeight;
37
+ // global options
38
+ private int threads;
39
+ private boolean lowPriority;
40
+
41
+ /**
42
+ * Creates an empty scene.
43
+ */
44
+ public Scene() {
45
+ lightServer = new LightServer(this);
46
+ instanceList = new InstanceList();
47
+ infiniteInstanceList = new InstanceList();
48
+ acceltype = "auto";
49
+ stats = new Statistics();
50
+
51
+ bakingViewDependent = false;
52
+ bakingInstance = null;
53
+ bakingPrimitives = null;
54
+ bakingAccel = null;
55
+
56
+ camera = null;
57
+ imageWidth = 640;
58
+ imageHeight = 480;
59
+ threads = 0;
60
+ lowPriority = true;
61
+
62
+ rebuildAccel = true;
63
+ }
64
+
65
+ /**
66
+ * Get number of allowed threads for multi-threaded operations.
67
+ *
68
+ * @return number of threads that can be started
69
+ */
70
+ public int getThreads() {
71
+ return threads <= 0 ? Runtime.getRuntime().availableProcessors() : threads;
72
+ }
73
+
74
+ /**
75
+ * Get the priority level to assign to multi-threaded operations.
76
+ *
77
+ * @return thread priority
78
+ */
79
+ public int getThreadPriority() {
80
+ return lowPriority ? Thread.MIN_PRIORITY : Thread.NORM_PRIORITY;
81
+ }
82
+
83
+ /**
84
+ * Sets the current camera (no support for multiple cameras yet).
85
+ *
86
+ * @param camera camera to be used as the viewpoint for the scene
87
+ */
88
+ public void setCamera(Camera camera) {
89
+ this.camera = camera;
90
+ }
91
+
92
+ Camera getCamera() {
93
+ return camera;
94
+ }
95
+
96
+ /**
97
+ * Update the instance lists for this scene.
98
+ *
99
+ * @param instances regular instances
100
+ * @param infinite infinite instances (no bounds)
101
+ */
102
+ public void setInstanceLists(Instance[] instances, Instance[] infinite) {
103
+ infiniteInstanceList = new InstanceList(infinite);
104
+ instanceList = new InstanceList(instances);
105
+ rebuildAccel = true;
106
+ }
107
+
108
+ /**
109
+ * Update the light list for this scene.
110
+ *
111
+ * @param lights array of light source objects
112
+ */
113
+ public void setLightList(LightSource[] lights) {
114
+ lightServer.setLights(lights);
115
+ }
116
+
117
+ /**
118
+ * Enables shader overiding (set null to disable). The specified shader will
119
+ * be used to shade all surfaces
120
+ *
121
+ * @param shader shader to run over all surfaces, or <code>null</code> to
122
+ * disable overriding
123
+ * @param photonOverride <code>true</code> to override photon scattering
124
+ * with this shader or <code>false</code> to run the regular shaders
125
+ */
126
+ public void setShaderOverride(Shader shader, boolean photonOverride) {
127
+ lightServer.setShaderOverride(shader, photonOverride);
128
+ }
129
+
130
+ /**
131
+ * The provided instance will be considered for lightmap baking. If the
132
+ * specified instance is
133
+ * <code>null</code>, lightmap baking will be disabled and normal rendering
134
+ * will occur.
135
+ *
136
+ * @param instance instance to bake
137
+ */
138
+ public void setBakingInstance(Instance instance) {
139
+ bakingInstance = instance;
140
+ }
141
+
142
+ /**
143
+ * Get the radiance seen through a particular pixel
144
+ *
145
+ * @param istate intersection state for ray tracing
146
+ * @param rx pixel x coordinate
147
+ * @param ry pixel y coordinate
148
+ * @param lensU DOF sampling variable
149
+ * @param lensV DOF sampling variable
150
+ * @param time motion blur sampling variable
151
+ * @param instance QMC instance seed
152
+ * @return a shading state for the intersected primitive, or
153
+ * <code>null</code> if nothing is seen through the specifieFd point
154
+ */
155
+ public ShadingState getRadiance(IntersectionState istate, float rx, float ry, double lensU, double lensV, double time, int instance, int dim, ShadingCache cache) {
156
+ istate.numEyeRays++;
157
+ float sceneTime = camera.getTime((float) time);
158
+ if (bakingPrimitives == null) {
159
+ Ray r = camera.getRay(rx, ry, imageWidth, imageHeight, lensU, lensV, sceneTime);
160
+ return r != null ? lightServer.getRadiance(rx, ry, sceneTime, instance, dim, r, istate, cache) : null;
161
+ } else {
162
+ Ray r = new Ray(rx / imageWidth, ry / imageHeight, -1, 0, 0, 1);
163
+ traceBake(r, istate);
164
+ if (!istate.hit()) {
165
+ return null;
166
+ }
167
+ ShadingState state = ShadingState.createState(istate, rx, ry, sceneTime, r, instance, dim, lightServer);
168
+ bakingPrimitives.prepareShadingState(state);
169
+ if (bakingViewDependent) {
170
+ state.setRay(camera.getRay(state.getPoint(), sceneTime));
171
+ } else {
172
+ Point3 p = state.getPoint();
173
+ Vector3 n = state.getNormal();
174
+ // create a ray coming from directly above the point being
175
+ // shaded
176
+ Ray incoming = new Ray(p.x + n.x, p.y + n.y, p.z + n.z, -n.x, -n.y, -n.z);
177
+ incoming.setMax(1);
178
+ state.setRay(incoming);
179
+ }
180
+ lightServer.shadeBakeResult(state);
181
+ return state;
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Get scene world space bounding box.
187
+ *
188
+ * @return scene bounding box
189
+ */
190
+ public BoundingBox getBounds() {
191
+ return instanceList.getWorldBounds(null);
192
+ }
193
+
194
+ public void accumulateStats(IntersectionState state) {
195
+ stats.accumulate(state);
196
+ }
197
+
198
+ public void accumulateStats(ShadingCache cache) {
199
+ stats.accumulate(cache);
200
+ }
201
+
202
+ void trace(Ray r, IntersectionState state) {
203
+ // stats
204
+ state.numRays++;
205
+ // reset object
206
+ state.instance = null;
207
+ state.current = null;
208
+ for (int i = 0; i < infiniteInstanceList.getNumPrimitives(); i++) {
209
+ infiniteInstanceList.intersectPrimitive(r, i, state);
210
+ }
211
+ // reset for next accel structure
212
+ state.current = null;
213
+ intAccel.intersect(r, state);
214
+ }
215
+
216
+ Color traceShadow(Ray r, IntersectionState state) {
217
+ state.numShadowRays++;
218
+ trace(r, state);
219
+ return state.hit() ? Color.WHITE : Color.BLACK;
220
+ }
221
+
222
+ void traceBake(Ray r, IntersectionState state) {
223
+ // set the instance as if tracing a regular instanced object
224
+ state.current = bakingInstance;
225
+ // reset object
226
+ state.instance = null;
227
+ bakingAccel.intersect(r, state);
228
+ }
229
+
230
+ private void createAreaLightInstances() {
231
+ ArrayList<Instance> infiniteAreaLights = null;
232
+ ArrayList<Instance> areaLights = null;
233
+ // create an area light instance from each light source if possible
234
+ for (LightSource l : lightServer.lights) {
235
+ Instance lightInstance = l.createInstance();
236
+ if (lightInstance != null) {
237
+ if (lightInstance.getBounds() == null) {
238
+ if (infiniteAreaLights == null) {
239
+ infiniteAreaLights = new ArrayList<Instance>();
240
+ }
241
+ infiniteAreaLights.add(lightInstance);
242
+ } else {
243
+ if (areaLights == null) {
244
+ areaLights = new ArrayList<Instance>();
245
+ }
246
+ areaLights.add(lightInstance);
247
+ }
248
+ }
249
+ }
250
+ // add area light sources to the list of instances if they exist
251
+ if (infiniteAreaLights != null && infiniteAreaLights.size() > 0) {
252
+ infiniteInstanceList.addLightSourceInstances(infiniteAreaLights.toArray(new Instance[infiniteAreaLights.size()]));
253
+ } else {
254
+ infiniteInstanceList.clearLightSources();
255
+ }
256
+ if (areaLights != null && areaLights.size() > 0) {
257
+ instanceList.addLightSourceInstances(areaLights.toArray(new Instance[areaLights.size()]));
258
+ } else {
259
+ instanceList.clearLightSources();
260
+ }
261
+ // FIXME: this _could_ be done incrementally to avoid top-level rebuilds
262
+ // each frame
263
+ rebuildAccel = true;
264
+ }
265
+
266
+ private void removeAreaLightInstances() {
267
+ infiniteInstanceList.clearLightSources();
268
+ instanceList.clearLightSources();
269
+ }
270
+
271
+ /**
272
+ * Render the scene using the specified options, image sampler and display.
273
+ *
274
+ * @param options rendering options object
275
+ * @param sampler image sampler
276
+ * @param display display to send the final image to, a default display will
277
+ * be created if <code>null</code>
278
+ */
279
+ public void render(Options options, ImageSampler sampler, Display display) {
280
+ stats.reset();
281
+ if (display == null) {
282
+ display = new FrameDisplay();
283
+ }
284
+
285
+ if (bakingInstance != null) {
286
+ UI.printDetailed(Module.SCENE, "Creating primitives for lightmapping ...");
287
+ bakingPrimitives = bakingInstance.getBakingPrimitives();
288
+ if (bakingPrimitives == null) {
289
+ UI.printError(Module.SCENE, "Lightmap baking is not supported for the given instance.");
290
+ return;
291
+ }
292
+ int n = bakingPrimitives.getNumPrimitives();
293
+ UI.printInfo(Module.SCENE, "Building acceleration structure for lightmapping (%d num primitives) ...", n);
294
+ bakingAccel = AccelerationStructureFactory.create("auto", n, true);
295
+ bakingAccel.build(bakingPrimitives);
296
+ } else {
297
+ bakingPrimitives = null;
298
+ bakingAccel = null;
299
+ }
300
+ bakingViewDependent = options.getBoolean("baking.viewdep", bakingViewDependent);
301
+
302
+ if ((bakingInstance != null && bakingViewDependent && camera == null) || (bakingInstance == null && camera == null)) {
303
+ UI.printError(Module.SCENE, "No camera found");
304
+ return;
305
+ }
306
+
307
+ // read from options
308
+ threads = options.getInt("threads", 0);
309
+ lowPriority = options.getBoolean("threads.lowPriority", true);
310
+ imageWidth = options.getInt("resolutionX", 640);
311
+ imageHeight = options.getInt("resolutionY", 480);
312
+ // limit resolution to 16k
313
+ imageWidth = MathUtils.clamp(imageWidth, 1, 1 << 14);
314
+ imageHeight = MathUtils.clamp(imageHeight, 1, 1 << 14);
315
+
316
+ // prepare lights
317
+ createAreaLightInstances();
318
+
319
+ // get acceleration structure info
320
+ // count scene primitives
321
+ long numPrimitives = 0;
322
+ for (int i = 0; i < instanceList.getNumPrimitives(); i++) {
323
+ numPrimitives += instanceList.getNumPrimitives(i);
324
+ }
325
+ UI.printInfo(Module.SCENE, "Scene stats:");
326
+ UI.printInfo(Module.SCENE, " * Infinite instances: %d", infiniteInstanceList.getNumPrimitives());
327
+ UI.printInfo(Module.SCENE, " * Instances: %d", instanceList.getNumPrimitives());
328
+ UI.printInfo(Module.SCENE, " * Primitives: %d", numPrimitives);
329
+ String accelName = options.getString("accel", null);
330
+ if (accelName != null) {
331
+ rebuildAccel = rebuildAccel || !acceltype.equals(accelName);
332
+ acceltype = accelName;
333
+ }
334
+ UI.printInfo(Module.SCENE, " * Instance accel: %s", acceltype);
335
+ if (rebuildAccel) {
336
+ intAccel = AccelerationStructureFactory.create(acceltype, instanceList.getNumPrimitives(), false);
337
+ intAccel.build(instanceList);
338
+ rebuildAccel = false;
339
+ }
340
+ UI.printInfo(Module.SCENE, " * Scene bounds: %s", getBounds());
341
+ UI.printInfo(Module.SCENE, " * Scene center: %s", getBounds().getCenter());
342
+ UI.printInfo(Module.SCENE, " * Scene diameter: %.2f", getBounds().getExtents().length());
343
+ UI.printInfo(Module.SCENE, " * Lightmap bake: %s", bakingInstance != null ? (bakingViewDependent ? "view" : "ortho") : "off");
344
+ if (sampler == null) {
345
+ return;
346
+ }
347
+ if (!lightServer.build(options)) {
348
+ return;
349
+ }
350
+ // render
351
+ UI.printInfo(Module.SCENE, "Rendering ...");
352
+ stats.setResolution(imageWidth, imageHeight);
353
+ sampler.prepare(options, this, imageWidth, imageHeight);
354
+ sampler.render(display);
355
+ // show statistics
356
+ stats.displayStats();
357
+ lightServer.showStats();
358
+ // discard area lights
359
+ removeAreaLightInstances();
360
+ // discard baking tesselation/accel structure
361
+ bakingPrimitives = null;
362
+ bakingAccel = null;
363
+ UI.printInfo(Module.SCENE, "Done.");
364
+ }
365
+
366
+ /**
367
+ * Create a photon map as prescribed by the given {@link PhotonStore}.
368
+ *
369
+ * @param map object that will recieve shot photons
370
+ * @param type type of photons being shot
371
+ * @param seed QMC seed parameter
372
+ * @return <code>true</code> upon success
373
+ */
374
+ public boolean calculatePhotons(PhotonStore map, String type, int seed, Options options) {
375
+ return lightServer.calculatePhotons(map, type, seed, options);
376
+ }
377
+ }