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,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
+ }