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,83 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.math.BoundingBox;
5
+ import org.sunflow.math.Matrix4;
6
+
7
+ final class InstanceList implements PrimitiveList {
8
+
9
+ private Instance[] instances;
10
+ private Instance[] lights;
11
+
12
+ InstanceList() {
13
+ instances = new Instance[0];
14
+ clearLightSources();
15
+ }
16
+
17
+ InstanceList(Instance[] instances) {
18
+ this.instances = instances;
19
+ clearLightSources();
20
+ }
21
+
22
+ void addLightSourceInstances(Instance[] lights) {
23
+ this.lights = lights;
24
+ }
25
+
26
+ void clearLightSources() {
27
+ lights = new Instance[0];
28
+ }
29
+
30
+ @Override
31
+ public final float getPrimitiveBound(int primID, int i) {
32
+ if (primID < instances.length) {
33
+ return instances[primID].getBounds().getBound(i);
34
+ } else {
35
+ return lights[primID - instances.length].getBounds().getBound(i);
36
+ }
37
+ }
38
+
39
+ @Override
40
+ public final BoundingBox getWorldBounds(Matrix4 o2w) {
41
+ BoundingBox bounds = new BoundingBox();
42
+ for (Instance i : instances) {
43
+ bounds.include(i.getBounds());
44
+ }
45
+ for (Instance i : lights) {
46
+ bounds.include(i.getBounds());
47
+ }
48
+ return bounds;
49
+ }
50
+
51
+ @Override
52
+ public final void intersectPrimitive(Ray r, int primID, IntersectionState state) {
53
+ if (primID < instances.length) {
54
+ instances[primID].intersect(r, state);
55
+ } else {
56
+ lights[primID - instances.length].intersect(r, state);
57
+ }
58
+ }
59
+
60
+ @Override
61
+ public final int getNumPrimitives() {
62
+ return instances.length + lights.length;
63
+ }
64
+
65
+ public final int getNumPrimitives(int primID) {
66
+ return primID < instances.length ? instances[primID].getNumPrimitives() : lights[primID - instances.length].getNumPrimitives();
67
+ }
68
+
69
+ @Override
70
+ public final void prepareShadingState(ShadingState state) {
71
+ state.getInstance().prepareShadingState(state);
72
+ }
73
+
74
+ @Override
75
+ public boolean update(ParameterList pl, SunflowAPI api) {
76
+ return true;
77
+ }
78
+
79
+ @Override
80
+ public PrimitiveList getBakingPrimitives() {
81
+ return null;
82
+ }
83
+ }
@@ -0,0 +1,120 @@
1
+ package org.sunflow.core;
2
+
3
+ /**
4
+ * This class is used to store ray/object intersections. It also provides
5
+ * additional data to assist {@link AccelerationStructure} objects with
6
+ * traversal.
7
+ */
8
+ public final class IntersectionState {
9
+
10
+ private static final int MAX_STACK_SIZE = 64;
11
+ float time;
12
+ float u, v, w;
13
+ Instance instance;
14
+ int id;
15
+ private final StackNode[][] stacks = new StackNode[2][MAX_STACK_SIZE];
16
+ Instance current;
17
+ long numEyeRays;
18
+ long numShadowRays;
19
+ long numReflectionRays;
20
+ long numGlossyRays;
21
+ long numRefractionRays;
22
+ long numRays;
23
+
24
+ /**
25
+ * Traversal stack node, helps with tree-based {@link AccelerationStructure}
26
+ * traversal.
27
+ */
28
+ public static final class StackNode {
29
+
30
+ public int node;
31
+ public float near;
32
+ public float far;
33
+ }
34
+
35
+ /**
36
+ * Initializes all traversal stacks.
37
+ */
38
+ public IntersectionState() {
39
+ for (int i = 0; i < stacks.length; i++) {
40
+ for (int j = 0; j < stacks[i].length; j++) {
41
+ stacks[i][j] = new StackNode();
42
+ }
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Returns the time at which the intersection should be calculated. This
48
+ * will be constant for a given ray-tree. This value is guarenteed to be
49
+ * between the camera's shutter open and shutter close time.
50
+ *
51
+ * @return time value
52
+ */
53
+ public float getTime() {
54
+ return time;
55
+ }
56
+
57
+ /**
58
+ * Get stack object for tree based {@link AccelerationStructure}s.
59
+ *
60
+ * @return array of stack nodes
61
+ */
62
+ public final StackNode[] getStack() {
63
+ return current == null ? stacks[0] : stacks[1];
64
+ }
65
+
66
+ /**
67
+ * Checks to see if a hit has been recorded.
68
+ *
69
+ * @return <code>true</code> if a hit has been recorded, <code>false</code>
70
+ * otherwise
71
+ */
72
+ public final boolean hit() {
73
+ return instance != null;
74
+ }
75
+
76
+ /**
77
+ * Record an intersection with the specified primitive id. The parent object
78
+ * is assumed to be the current instance. The u and v parameters are used to
79
+ * pinpoint the location on the surface if needed.
80
+ *
81
+ * @param id primitive id of the intersected object
82
+ */
83
+ public final void setIntersection(int id) {
84
+ instance = current;
85
+ this.id = id;
86
+ }
87
+
88
+ /**
89
+ * Record an intersection with the specified primitive id. The parent object
90
+ * is assumed to be the current instance. The u and v parameters are used to
91
+ * pinpoint the location on the surface if needed.
92
+ *
93
+ * @param id primitive id of the intersected object
94
+ * @param u u surface paramater of the intersection point
95
+ * @param v v surface parameter of the intersection point
96
+ */
97
+ public final void setIntersection(int id, float u, float v) {
98
+ instance = current;
99
+ this.id = id;
100
+ this.u = u;
101
+ this.v = v;
102
+ }
103
+
104
+ /**
105
+ * Record an intersection with the specified primitive id. The parent object
106
+ * is assumed to be the current instance. The u and v parameters are used to
107
+ * pinpoint the location on the surface if needed.
108
+ *
109
+ * @param id primitive id of the intersected object
110
+ * @param u u surface paramater of the intersection point
111
+ * @param v v surface parameter of the intersection point
112
+ */
113
+ public final void setIntersection(int id, float u, float v, float w) {
114
+ instance = current;
115
+ this.id = id;
116
+ this.u = u;
117
+ this.v = v;
118
+ this.w = w;
119
+ }
120
+ }
@@ -0,0 +1,104 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.image.Color;
4
+ import org.sunflow.math.Vector3;
5
+
6
+ /**
7
+ * Represents a sample taken from a light source that faces a point being
8
+ * shaded.
9
+ */
10
+ public class LightSample {
11
+
12
+ private Ray shadowRay; // ray to be used to evaluate if the point is in
13
+ // shadow
14
+ private Color ldiff;
15
+ private Color lspec;
16
+ LightSample next; // pointer to next item in a linked list of samples
17
+
18
+ /**
19
+ * Creates a new light sample object (invalid by default).
20
+ */
21
+ public LightSample() {
22
+ ldiff = lspec = null;
23
+ shadowRay = null;
24
+ next = null;
25
+ }
26
+
27
+ boolean isValid() {
28
+ return ldiff != null && lspec != null && shadowRay != null;
29
+ }
30
+
31
+ /**
32
+ * Set the current shadow ray. The ray's direction is used as the sample's
33
+ * orientation.
34
+ *
35
+ * @param shadowRay shadow ray from the point being shaded towards the light
36
+ */
37
+ public void setShadowRay(Ray shadowRay) {
38
+ this.shadowRay = shadowRay;
39
+ }
40
+
41
+ /**
42
+ * Trace the shadow ray, attenuating the sample's color by the opacity of
43
+ * intersected objects.
44
+ *
45
+ * @param state shading state representing the point to be shaded
46
+ */
47
+ public final void traceShadow(ShadingState state) {
48
+ Color opacity = state.traceShadow(shadowRay);
49
+ Color.blend(ldiff, Color.BLACK, opacity, ldiff);
50
+ Color.blend(lspec, Color.BLACK, opacity, lspec);
51
+ }
52
+
53
+ /**
54
+ * Get the sample's shadow ray.
55
+ *
56
+ * @return shadow ray
57
+ */
58
+ public Ray getShadowRay() {
59
+ return shadowRay;
60
+ }
61
+
62
+ /**
63
+ * Get diffuse radiance.
64
+ *
65
+ * @return diffuse radiance
66
+ */
67
+ public Color getDiffuseRadiance() {
68
+ return ldiff;
69
+ }
70
+
71
+ /**
72
+ * Get specular radiance.
73
+ *
74
+ * @return specular radiance
75
+ */
76
+ public Color getSpecularRadiance() {
77
+ return lspec;
78
+ }
79
+
80
+ /**
81
+ * Set the diffuse and specular radiance emitted by the current light
82
+ * source. These should usually be the same, but are distinguished to allow
83
+ * for non-physical light setups or light source types which compute diffuse
84
+ * and specular responses seperately.
85
+ *
86
+ * @param d diffuse radiance
87
+ * @param s specular radiance
88
+ */
89
+ public void setRadiance(Color d, Color s) {
90
+ ldiff = d.copy();
91
+ lspec = s.copy();
92
+ }
93
+
94
+ /**
95
+ * Compute a dot product between the current shadow ray direction and the
96
+ * specified vector.
97
+ *
98
+ * @param v direction vector
99
+ * @return dot product of the vector with the shadow ray direction
100
+ */
101
+ public float dot(Vector3 v) {
102
+ return shadowRay.dot(v);
103
+ }
104
+ }
@@ -0,0 +1,382 @@
1
+ package org.sunflow.core;
2
+
3
+ import org.sunflow.PluginRegistry;
4
+ import org.sunflow.image.Color;
5
+ import org.sunflow.math.Point3;
6
+ import org.sunflow.math.QMC;
7
+ import org.sunflow.math.Vector3;
8
+ import org.sunflow.system.Timer;
9
+ import org.sunflow.system.UI;
10
+ import org.sunflow.system.UI.Module;
11
+
12
+ class LightServer {
13
+ // parent
14
+
15
+ private Scene scene;
16
+ // lighting
17
+ LightSource[] lights;
18
+ // shading override
19
+ private Shader shaderOverride;
20
+ private boolean shaderOverridePhotons;
21
+ // direct illumination
22
+ private int maxDiffuseDepth;
23
+ private int maxReflectionDepth;
24
+ private int maxRefractionDepth;
25
+ // indirect illumination
26
+ private CausticPhotonMapInterface causticPhotonMap;
27
+ private GIEngine giEngine;
28
+ private int photonCounter;
29
+
30
+ LightServer(Scene scene) {
31
+ this.scene = scene;
32
+ lights = new LightSource[0];
33
+ causticPhotonMap = null;
34
+
35
+ shaderOverride = null;
36
+ shaderOverridePhotons = false;
37
+
38
+ maxDiffuseDepth = 1;
39
+ maxReflectionDepth = 4;
40
+ maxRefractionDepth = 4;
41
+
42
+ causticPhotonMap = null;
43
+ giEngine = null;
44
+ }
45
+
46
+ void setLights(LightSource[] lights) {
47
+ this.lights = lights;
48
+ }
49
+
50
+ Scene getScene() {
51
+ return scene;
52
+ }
53
+
54
+ void setShaderOverride(Shader shader, boolean photonOverride) {
55
+ shaderOverride = shader;
56
+ shaderOverridePhotons = photonOverride;
57
+ }
58
+
59
+ boolean build(Options options) {
60
+ // read options
61
+ maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth);
62
+ maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth);
63
+ maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth);
64
+ String giEngineType = options.getString("gi.engine", null);
65
+ giEngine = PluginRegistry.GI_ENGINE_PLUGINS.createObject(giEngineType);
66
+ String caustics = options.getString("caustics", null);
67
+ causticPhotonMap = PluginRegistry.CAUSTIC_PHOTON_MAP_PLUGINS.createObject(caustics);
68
+
69
+ // validate options
70
+ maxDiffuseDepth = Math.max(0, maxDiffuseDepth);
71
+ maxReflectionDepth = Math.max(0, maxReflectionDepth);
72
+ maxRefractionDepth = Math.max(0, maxRefractionDepth);
73
+
74
+ Timer t = new Timer();
75
+ t.start();
76
+ // count total number of light samples
77
+ int numLightSamples = 0;
78
+ for (int i = 0; i < lights.length; i++) {
79
+ numLightSamples += lights[i].getNumSamples();
80
+ }
81
+ // initialize gi engine
82
+ if (giEngine != null) {
83
+ if (!giEngine.init(options, scene)) {
84
+ return false;
85
+ }
86
+ }
87
+
88
+ if (!calculatePhotons(causticPhotonMap, "caustic", 0, options)) {
89
+ return false;
90
+ }
91
+ t.end();
92
+ UI.printInfo(Module.LIGHT, "Light Server stats:");
93
+ UI.printInfo(Module.LIGHT, " * Light sources found: %d", lights.length);
94
+ UI.printInfo(Module.LIGHT, " * Light samples: %d", numLightSamples);
95
+ UI.printInfo(Module.LIGHT, " * Max raytrace depth:");
96
+ UI.printInfo(Module.LIGHT, " - Diffuse %d", maxDiffuseDepth);
97
+ UI.printInfo(Module.LIGHT, " - Reflection %d", maxReflectionDepth);
98
+ UI.printInfo(Module.LIGHT, " - Refraction %d", maxRefractionDepth);
99
+ UI.printInfo(Module.LIGHT, " * GI engine %s", giEngineType == null ? "none" : giEngineType);
100
+ UI.printInfo(Module.LIGHT, " * Caustics: %s", caustics == null ? "none" : caustics);
101
+ UI.printInfo(Module.LIGHT, " * Shader override: %b", shaderOverride);
102
+ UI.printInfo(Module.LIGHT, " * Photon override: %b", shaderOverridePhotons);
103
+ UI.printInfo(Module.LIGHT, " * Build time: %s", t.toString());
104
+ return true;
105
+ }
106
+
107
+ void showStats() {
108
+ }
109
+
110
+ boolean calculatePhotons(final PhotonStore map, String type, final int seed, Options options) {
111
+ if (map == null) {
112
+ return true;
113
+ }
114
+ if (lights.length == 0) {
115
+ UI.printError(Module.LIGHT, "Unable to trace %s photons, no lights in scene", type);
116
+ return false;
117
+ }
118
+ final float[] histogram = new float[lights.length];
119
+ histogram[0] = lights[0].getPower();
120
+ for (int i = 1; i < lights.length; i++) {
121
+ histogram[i] = histogram[i - 1] + lights[i].getPower();
122
+ }
123
+ UI.printInfo(Module.LIGHT, "Tracing %s photons ...", type);
124
+ map.prepare(options, scene.getBounds());
125
+ int numEmittedPhotons = map.numEmit();
126
+ if (numEmittedPhotons <= 0 || histogram[histogram.length - 1] <= 0) {
127
+ UI.printError(Module.LIGHT, "Photon mapping enabled, but no %s photons to emit", type);
128
+ return false;
129
+ }
130
+ UI.taskStart("Tracing " + type + " photons", 0, numEmittedPhotons);
131
+ Thread[] photonThreads = new Thread[scene.getThreads()];
132
+ final float scale = 1.0f / numEmittedPhotons;
133
+ int delta = numEmittedPhotons / photonThreads.length;
134
+ photonCounter = 0;
135
+ Timer photonTimer = new Timer();
136
+ photonTimer.start();
137
+ for (int i = 0; i < photonThreads.length; i++) {
138
+ final int threadID = i;
139
+ final int start = threadID * delta;
140
+ final int end = (threadID == (photonThreads.length - 1)) ? numEmittedPhotons : (threadID + 1) * delta;
141
+ photonThreads[i] = new Thread(new Runnable() {
142
+ public void run() {
143
+ IntersectionState istate = new IntersectionState();
144
+ for (int i = start; i < end; i++) {
145
+ synchronized (LightServer.this) {
146
+ UI.taskUpdate(photonCounter);
147
+ photonCounter++;
148
+ if (UI.taskCanceled()) {
149
+ return;
150
+ }
151
+ }
152
+
153
+ int qmcI = i + seed;
154
+
155
+ double rand = QMC.halton(0, qmcI) * histogram[histogram.length - 1];
156
+ int j = 0;
157
+ while (rand >= histogram[j] && j < histogram.length) {
158
+ j++;
159
+ }
160
+ // make sure we didn't pick a zero-probability light
161
+ if (j == histogram.length) {
162
+ continue;
163
+ }
164
+
165
+ double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]);
166
+ double randY1 = QMC.halton(1, qmcI);
167
+ double randX2 = QMC.halton(2, qmcI);
168
+ double randY2 = QMC.halton(3, qmcI);
169
+ Point3 pt = new Point3();
170
+ Vector3 dir = new Vector3();
171
+ Color power = new Color();
172
+ lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power);
173
+ power.mul(scale);
174
+ Ray r = new Ray(pt, dir);
175
+ scene.trace(r, istate);
176
+ if (istate.hit()) {
177
+ shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, LightServer.this), power);
178
+ }
179
+ }
180
+ }
181
+ });
182
+ photonThreads[i].setPriority(scene.getThreadPriority());
183
+ photonThreads[i].start();
184
+ }
185
+ for (int i = 0; i < photonThreads.length; i++) {
186
+ try {
187
+ photonThreads[i].join();
188
+ } catch (InterruptedException e) {
189
+ UI.printError(Module.LIGHT, "Photon thread %d of %d was interrupted", i + 1, photonThreads.length);
190
+ return false;
191
+ }
192
+ }
193
+ if (UI.taskCanceled()) {
194
+ UI.taskStop(); // shut down task cleanly
195
+ return false;
196
+ }
197
+ photonTimer.end();
198
+ UI.taskStop();
199
+ UI.printInfo(Module.LIGHT, "Tracing time for %s photons: %s", type, photonTimer.toString());
200
+ map.init();
201
+ return true;
202
+ }
203
+
204
+ void shadePhoton(ShadingState state, Color power) {
205
+ state.getInstance().prepareShadingState(state);
206
+ Shader shader = getPhotonShader(state);
207
+ // scatter photon
208
+ if (shader != null) {
209
+ shader.scatterPhoton(state, power);
210
+ }
211
+ }
212
+
213
+ void traceDiffusePhoton(ShadingState previous, Ray r, Color power) {
214
+ if (previous.getDiffuseDepth() >= maxDiffuseDepth) {
215
+ return;
216
+ }
217
+ IntersectionState istate = previous.getIntersectionState();
218
+ scene.trace(r, istate);
219
+ if (previous.getIntersectionState().hit()) {
220
+ // create a new shading context
221
+ ShadingState state = ShadingState.createDiffuseBounceState(previous, r, 0);
222
+ shadePhoton(state, power);
223
+ }
224
+ }
225
+
226
+ void traceReflectionPhoton(ShadingState previous, Ray r, Color power) {
227
+ if (previous.getReflectionDepth() >= maxReflectionDepth) {
228
+ return;
229
+ }
230
+ IntersectionState istate = previous.getIntersectionState();
231
+ scene.trace(r, istate);
232
+ if (previous.getIntersectionState().hit()) {
233
+ // create a new shading context
234
+ ShadingState state = ShadingState.createReflectionBounceState(previous, r, 0);
235
+ shadePhoton(state, power);
236
+ }
237
+ }
238
+
239
+ void traceRefractionPhoton(ShadingState previous, Ray r, Color power) {
240
+ if (previous.getRefractionDepth() >= maxRefractionDepth) {
241
+ return;
242
+ }
243
+ IntersectionState istate = previous.getIntersectionState();
244
+ scene.trace(r, istate);
245
+ if (previous.getIntersectionState().hit()) {
246
+ // create a new shading context
247
+ ShadingState state = ShadingState.createRefractionBounceState(previous, r, 0);
248
+ shadePhoton(state, power);
249
+ }
250
+ }
251
+
252
+ private Shader getShader(ShadingState state) {
253
+ return shaderOverride != null ? shaderOverride : state.getShader();
254
+ }
255
+
256
+ private Shader getPhotonShader(ShadingState state) {
257
+ return (shaderOverride != null && shaderOverridePhotons) ? shaderOverride : state.getShader();
258
+
259
+ }
260
+
261
+ ShadingState getRadiance(float rx, float ry, float time, int i, int d, Ray r, IntersectionState istate, ShadingCache cache) {
262
+ // set this value once - will stay constant for the entire ray-tree
263
+ istate.time = time;
264
+ scene.trace(r, istate);
265
+ if (istate.hit()) {
266
+ ShadingState state = ShadingState.createState(istate, rx, ry, time, r, i, d, this);
267
+ state.getInstance().prepareShadingState(state);
268
+ Shader shader = getShader(state);
269
+ if (shader == null) {
270
+ state.setResult(Color.BLACK);
271
+ return state;
272
+ }
273
+ if (cache != null) {
274
+ Color c = cache.lookup(state, shader);
275
+ if (c != null) {
276
+ state.setResult(c);
277
+ return state;
278
+ }
279
+ }
280
+ state.setResult(shader.getRadiance(state));
281
+ if (cache != null) {
282
+ cache.add(state, shader, state.getResult());
283
+ }
284
+ checkNanInf(state.getResult());
285
+ return state;
286
+ } else {
287
+ return null;
288
+ }
289
+ }
290
+
291
+ private static final void checkNanInf(Color c) {
292
+ if (c.isNan()) {
293
+ UI.printWarning(Module.LIGHT, "NaN shading sample!");
294
+ } else if (c.isInf()) {
295
+ UI.printWarning(Module.LIGHT, "Inf shading sample!");
296
+ }
297
+ }
298
+
299
+ void shadeBakeResult(ShadingState state) {
300
+ Shader shader = getShader(state);
301
+ if (shader != null) {
302
+ state.setResult(shader.getRadiance(state));
303
+ } else {
304
+ state.setResult(Color.BLACK);
305
+ }
306
+ }
307
+
308
+ Color shadeHit(ShadingState state) {
309
+ state.getInstance().prepareShadingState(state);
310
+ Shader shader = getShader(state);
311
+ return (shader != null) ? shader.getRadiance(state) : Color.BLACK;
312
+ }
313
+
314
+ Color traceGlossy(ShadingState previous, Ray r, int i) {
315
+ // limit path depth and disable caustic paths
316
+ if (previous.getReflectionDepth() >= maxReflectionDepth || previous.getDiffuseDepth() > 0) {
317
+ return Color.BLACK;
318
+ }
319
+ IntersectionState istate = previous.getIntersectionState();
320
+ istate.numGlossyRays++;
321
+ scene.trace(r, istate);
322
+ return istate.hit() ? shadeHit(ShadingState.createGlossyBounceState(previous, r, i)) : Color.BLACK;
323
+ }
324
+
325
+ Color traceReflection(ShadingState previous, Ray r, int i) {
326
+ // limit path depth and disable caustic paths
327
+ if (previous.getReflectionDepth() >= maxReflectionDepth || previous.getDiffuseDepth() > 0) {
328
+ return Color.BLACK;
329
+ }
330
+ IntersectionState istate = previous.getIntersectionState();
331
+ istate.numReflectionRays++;
332
+ scene.trace(r, istate);
333
+ return istate.hit() ? shadeHit(ShadingState.createReflectionBounceState(previous, r, i)) : Color.BLACK;
334
+ }
335
+
336
+ Color traceRefraction(ShadingState previous, Ray r, int i) {
337
+ // limit path depth and disable caustic paths
338
+ if (previous.getRefractionDepth() >= maxRefractionDepth || previous.getDiffuseDepth() > 0) {
339
+ return Color.BLACK;
340
+ }
341
+ IntersectionState istate = previous.getIntersectionState();
342
+ istate.numRefractionRays++;
343
+ scene.trace(r, istate);
344
+ return istate.hit() ? shadeHit(ShadingState.createRefractionBounceState(previous, r, i)) : Color.BLACK;
345
+ }
346
+
347
+ ShadingState traceFinalGather(ShadingState previous, Ray r, int i) {
348
+ if (previous.getDiffuseDepth() >= maxDiffuseDepth) {
349
+ return null;
350
+ }
351
+ IntersectionState istate = previous.getIntersectionState();
352
+ scene.trace(r, istate);
353
+ return istate.hit() ? ShadingState.createFinalGatherState(previous, r, i) : null;
354
+ }
355
+
356
+ Color getGlobalRadiance(ShadingState state) {
357
+ if (giEngine == null) {
358
+ return Color.BLACK;
359
+ }
360
+ return giEngine.getGlobalRadiance(state);
361
+ }
362
+
363
+ Color getIrradiance(ShadingState state, Color diffuseReflectance) {
364
+ // no gi engine, or we have already exceeded number of available bounces
365
+ if (giEngine == null || state.getDiffuseDepth() >= maxDiffuseDepth) {
366
+ return Color.BLACK;
367
+ }
368
+ return giEngine.getIrradiance(state, diffuseReflectance);
369
+ }
370
+
371
+ void initLightSamples(ShadingState state) {
372
+ for (LightSource l : lights) {
373
+ l.getSamples(state);
374
+ }
375
+ }
376
+
377
+ void initCausticSamples(ShadingState state) {
378
+ if (causticPhotonMap != null) {
379
+ causticPhotonMap.getSamples(state);
380
+ }
381
+ }
382
+ }