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,530 @@
1
+ package org.sunflow.core.photonmap;
2
+
3
+ import java.util.ArrayList;
4
+
5
+ import org.sunflow.core.GlobalPhotonMapInterface;
6
+ import org.sunflow.core.Options;
7
+ import org.sunflow.core.ShadingState;
8
+ import org.sunflow.image.Color;
9
+ import org.sunflow.math.BoundingBox;
10
+ import org.sunflow.math.Point3;
11
+ import org.sunflow.math.Vector3;
12
+ import org.sunflow.system.Timer;
13
+ import org.sunflow.system.UI;
14
+ import org.sunflow.system.UI.Module;
15
+
16
+ public final class GlobalPhotonMap implements GlobalPhotonMapInterface {
17
+
18
+ private ArrayList<Photon> photonList;
19
+ private Photon[] photons;
20
+ private int storedPhotons;
21
+ private int halfStoredPhotons;
22
+ private int log2n;
23
+ private int numGather;
24
+ private float gatherRadius;
25
+ private BoundingBox bounds;
26
+ private boolean hasRadiance;
27
+ private float maxPower;
28
+ private float maxRadius;
29
+ private int numEmit;
30
+
31
+ public GlobalPhotonMap() {
32
+ bounds = new BoundingBox();
33
+ hasRadiance = false;
34
+ maxPower = 0;
35
+ maxRadius = 0;
36
+ }
37
+
38
+ @Override
39
+ public void prepare(Options options, BoundingBox sceneBounds) {
40
+ // get settings
41
+ numEmit = options.getInt("gi.irr-cache.gmap.emit", 100000);
42
+ numGather = options.getInt("gi.irr-cache.gmap.gather", 50);
43
+ gatherRadius = options.getFloat("gi.irr-cache.gmap.radius", 0.5f);
44
+ // init
45
+ photonList = new ArrayList<Photon>();
46
+ photonList.add(null);
47
+ photons = null;
48
+ storedPhotons = halfStoredPhotons = 0;
49
+ }
50
+
51
+ @Override
52
+ public void store(ShadingState state, Vector3 dir, Color power, Color diffuse) {
53
+ Photon p = new Photon(state.getPoint(), state.getNormal(), dir, power, diffuse);
54
+ synchronized (this) {
55
+ storedPhotons++;
56
+ photonList.add(p);
57
+ bounds.include(new Point3(p.x, p.y, p.z));
58
+ maxPower = Math.max(maxPower, power.getMax());
59
+ }
60
+ }
61
+
62
+ private void locatePhotons(NearestPhotons np) {
63
+ float[] dist1d2 = new float[log2n];
64
+ int[] chosen = new int[log2n];
65
+ int i = 1;
66
+ int level = 0;
67
+ int cameFrom;
68
+ while (true) {
69
+ while (i < halfStoredPhotons) {
70
+ float dist1d = photons[i].getDist1(np.px, np.py, np.pz);
71
+ dist1d2[level] = dist1d * dist1d;
72
+ i += i;
73
+ if (dist1d > 0.0f) {
74
+ i++;
75
+ }
76
+ chosen[level++] = i;
77
+ }
78
+ np.checkAddNearest(photons[i]);
79
+ do {
80
+ cameFrom = i;
81
+ i >>= 1;
82
+ level--;
83
+ if (i == 0) {
84
+ return;
85
+ }
86
+ } while ((dist1d2[level] >= np.dist2[0]) || (cameFrom != chosen[level]));
87
+ np.checkAddNearest(photons[i]);
88
+ i = chosen[level++] ^ 1;
89
+ }
90
+ }
91
+
92
+ private void balance() {
93
+ if (storedPhotons == 0) {
94
+ return;
95
+ }
96
+ photons = photonList.toArray(new Photon[photonList.size()]);
97
+ photonList = null;
98
+ Photon[] temp = new Photon[storedPhotons + 1];
99
+ balanceSegment(temp, 1, 1, storedPhotons);
100
+ photons = temp;
101
+ halfStoredPhotons = storedPhotons / 2;
102
+ log2n = (int) Math.ceil(Math.log(storedPhotons) / Math.log(2.0));
103
+ }
104
+
105
+ private void balanceSegment(Photon[] temp, int index, int start, int end) {
106
+ int median = 1;
107
+ while ((4 * median) <= (end - start + 1)) {
108
+ median += median;
109
+ }
110
+ if ((3 * median) <= (end - start + 1)) {
111
+ median += median;
112
+ median += (start - 1);
113
+ } else {
114
+ median = end - median + 1;
115
+ }
116
+ int axis = Photon.SPLIT_Z;
117
+ Vector3 extents = bounds.getExtents();
118
+ if ((extents.x > extents.y) && (extents.x > extents.z)) {
119
+ axis = Photon.SPLIT_X;
120
+ } else if (extents.y > extents.z) {
121
+ axis = Photon.SPLIT_Y;
122
+ }
123
+ int left = start;
124
+ int right = end;
125
+ while (right > left) {
126
+ double v = photons[right].getCoord(axis);
127
+ int i = left - 1;
128
+ int j = right;
129
+ while (true) {
130
+ while (photons[++i].getCoord(axis) < v) {
131
+ }
132
+ while ((photons[--j].getCoord(axis) > v) && (j > left)) {
133
+ }
134
+ if (i >= j) {
135
+ break;
136
+ }
137
+ swap(i, j);
138
+ }
139
+ swap(i, right);
140
+ if (i >= median) {
141
+ right = i - 1;
142
+ }
143
+ if (i <= median) {
144
+ left = i + 1;
145
+ }
146
+ }
147
+ temp[index] = photons[median];
148
+ temp[index].setSplitAxis(axis);
149
+ if (median > start) {
150
+ if (start < (median - 1)) {
151
+ float tmp;
152
+ switch (axis) {
153
+ case Photon.SPLIT_X:
154
+ tmp = bounds.getMaximum().x;
155
+ bounds.getMaximum().x = temp[index].x;
156
+ balanceSegment(temp, 2 * index, start, median - 1);
157
+ bounds.getMaximum().x = tmp;
158
+ break;
159
+ case Photon.SPLIT_Y:
160
+ tmp = bounds.getMaximum().y;
161
+ bounds.getMaximum().y = temp[index].y;
162
+ balanceSegment(temp, 2 * index, start, median - 1);
163
+ bounds.getMaximum().y = tmp;
164
+ break;
165
+ default:
166
+ tmp = bounds.getMaximum().z;
167
+ bounds.getMaximum().z = temp[index].z;
168
+ balanceSegment(temp, 2 * index, start, median - 1);
169
+ bounds.getMaximum().z = tmp;
170
+ }
171
+ } else {
172
+ temp[2 * index] = photons[start];
173
+ }
174
+ }
175
+ if (median < end) {
176
+ if ((median + 1) < end) {
177
+ float tmp;
178
+ switch (axis) {
179
+ case Photon.SPLIT_X:
180
+ tmp = bounds.getMinimum().x;
181
+ bounds.getMinimum().x = temp[index].x;
182
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
183
+ bounds.getMinimum().x = tmp;
184
+ break;
185
+ case Photon.SPLIT_Y:
186
+ tmp = bounds.getMinimum().y;
187
+ bounds.getMinimum().y = temp[index].y;
188
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
189
+ bounds.getMinimum().y = tmp;
190
+ break;
191
+ default:
192
+ tmp = bounds.getMinimum().z;
193
+ bounds.getMinimum().z = temp[index].z;
194
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
195
+ bounds.getMinimum().z = tmp;
196
+ }
197
+ } else {
198
+ temp[(2 * index) + 1] = photons[end];
199
+ }
200
+ }
201
+ }
202
+
203
+ private void swap(int i, int j) {
204
+ Photon tmp = photons[i];
205
+ photons[i] = photons[j];
206
+ photons[j] = tmp;
207
+ }
208
+
209
+ static class Photon {
210
+
211
+ float x;
212
+ float y;
213
+ float z;
214
+ short dir;
215
+ short normal;
216
+ int data;
217
+ int power;
218
+ int flags;
219
+ static final int SPLIT_X = 0;
220
+ static final int SPLIT_Y = 1;
221
+ static final int SPLIT_Z = 2;
222
+ static final int SPLIT_MASK = 3;
223
+
224
+ Photon(Point3 p, Vector3 n, Vector3 dir, Color power, Color diffuse) {
225
+ x = p.x;
226
+ y = p.y;
227
+ z = p.z;
228
+ this.dir = dir.encode();
229
+ this.power = power.toRGBE();
230
+ flags = 0;
231
+ normal = n.encode();
232
+ data = diffuse.toRGB();
233
+ }
234
+
235
+ void setSplitAxis(int axis) {
236
+ flags &= ~SPLIT_MASK;
237
+ flags |= axis;
238
+ }
239
+
240
+ float getCoord(int axis) {
241
+ switch (axis) {
242
+ case SPLIT_X:
243
+ return x;
244
+ case SPLIT_Y:
245
+ return y;
246
+ default:
247
+ return z;
248
+ }
249
+ }
250
+
251
+ float getDist1(float px, float py, float pz) {
252
+ switch (flags & SPLIT_MASK) {
253
+ case SPLIT_X:
254
+ return px - x;
255
+ case SPLIT_Y:
256
+ return py - y;
257
+ default:
258
+ return pz - z;
259
+ }
260
+ }
261
+
262
+ float getDist2(float px, float py, float pz) {
263
+ float dx = x - px;
264
+ float dy = y - py;
265
+ float dz = z - pz;
266
+ return (dx * dx) + (dy * dy) + (dz * dz);
267
+ }
268
+ }
269
+
270
+ @Override
271
+ public void init() {
272
+ UI.printInfo(Module.LIGHT, "Balancing global photon map ...");
273
+ UI.taskStart("Balancing global photon map", 0, 1);
274
+ Timer t = new Timer();
275
+ t.start();
276
+ balance();
277
+ t.end();
278
+ UI.taskStop();
279
+ UI.printInfo(Module.LIGHT, "Global photon map:");
280
+ UI.printInfo(Module.LIGHT, " * Photons stored: %d", storedPhotons);
281
+ UI.printInfo(Module.LIGHT, " * Photons/estimate: %d", numGather);
282
+ UI.printInfo(Module.LIGHT, " * Estimate radius: %.3f", gatherRadius);
283
+ maxRadius = 1.4f * (float) Math.sqrt(maxPower * numGather);
284
+ UI.printInfo(Module.LIGHT, " * Maximum radius: %.3f", maxRadius);
285
+ UI.printInfo(Module.LIGHT, " * Balancing time: %s", t.toString());
286
+ if (gatherRadius > maxRadius) {
287
+ gatherRadius = maxRadius;
288
+ }
289
+ t.start();
290
+ precomputeRadiance();
291
+ t.end();
292
+ UI.printInfo(Module.LIGHT, " * Precompute time: %s", t.toString());
293
+ UI.printInfo(Module.LIGHT, " * Radiance photons: %d", storedPhotons);
294
+ UI.printInfo(Module.LIGHT, " * Search radius: %.3f", gatherRadius);
295
+ }
296
+
297
+ public void precomputeRadiance() {
298
+ if (storedPhotons == 0) {
299
+ return;
300
+ }
301
+ // precompute the radiance for all photons that are neither
302
+ // leaves nor parents of leaves in the tree.
303
+ int quadStoredPhotons = halfStoredPhotons / 2;
304
+ Point3 p = new Point3();
305
+ Vector3 n = new Vector3();
306
+ Point3 ppos = new Point3();
307
+ Vector3 pdir = new Vector3();
308
+ Vector3 pvec = new Vector3();
309
+ Color irr = new Color();
310
+ Color pow = new Color();
311
+ float maxDist2 = gatherRadius * gatherRadius;
312
+ NearestPhotons np = new NearestPhotons(p, numGather, maxDist2);
313
+ Photon[] temp = new Photon[quadStoredPhotons + 1];
314
+ UI.taskStart("Precomputing radiance", 1, quadStoredPhotons);
315
+ for (int i = 1; i <= quadStoredPhotons; i++) {
316
+ UI.taskUpdate(i);
317
+ Photon curr = photons[i];
318
+ p.set(curr.x, curr.y, curr.z);
319
+ Vector3.decode(curr.normal, n);
320
+ irr.set(Color.BLACK);
321
+ np.reset(p, maxDist2);
322
+ locatePhotons(np);
323
+ if (np.found < 8) {
324
+ curr.data = 0;
325
+ temp[i] = curr;
326
+ continue;
327
+ }
328
+ float invArea = 1.0f / ((float) Math.PI * np.dist2[0]);
329
+ float maxNDist = np.dist2[0] * 0.05f;
330
+ for (int j = 1; j <= np.found; j++) {
331
+ Photon phot = np.index[j];
332
+ Vector3.decode(phot.dir, pdir);
333
+ float cos = -Vector3.dot(pdir, n);
334
+ if (cos > 0.01f) {
335
+ ppos.set(phot.x, phot.y, phot.z);
336
+ Point3.sub(ppos, p, pvec);
337
+ float pcos = Vector3.dot(pvec, n);
338
+ if ((pcos < maxNDist) && (pcos > -maxNDist)) {
339
+ irr.add(pow.setRGBE(phot.power));
340
+ }
341
+ }
342
+ }
343
+ irr.mul(invArea);
344
+ // compute radiance
345
+ irr.mul(new Color(curr.data)).mul(1.0f / (float) Math.PI);
346
+ curr.data = irr.toRGBE();
347
+ temp[i] = curr;
348
+ }
349
+ UI.taskStop();
350
+
351
+ // resize photon map to only include irradiance photons
352
+ numGather /= 4;
353
+ maxRadius = 1.4f * (float) Math.sqrt(maxPower * numGather);
354
+ if (gatherRadius > maxRadius) {
355
+ gatherRadius = maxRadius;
356
+ }
357
+ storedPhotons = quadStoredPhotons;
358
+ halfStoredPhotons = storedPhotons / 2;
359
+ log2n = (int) Math.ceil(Math.log(storedPhotons) / Math.log(2.0));
360
+ photons = temp;
361
+ hasRadiance = true;
362
+ }
363
+
364
+ @Override
365
+ public Color getRadiance(Point3 p, Vector3 n) {
366
+ if (!hasRadiance || (storedPhotons == 0)) {
367
+ return Color.BLACK;
368
+ }
369
+ float px = p.x;
370
+ float py = p.y;
371
+ float pz = p.z;
372
+ int i = 1;
373
+ int level = 0;
374
+ int cameFrom;
375
+ float dist2;
376
+ float maxDist2 = gatherRadius * gatherRadius;
377
+ Photon nearest = null;
378
+ Photon curr;
379
+ Vector3 photN = new Vector3();
380
+ float[] dist1d2 = new float[log2n];
381
+ int[] chosen = new int[log2n];
382
+ while (true) {
383
+ while (i < halfStoredPhotons) {
384
+ float dist1d = photons[i].getDist1(px, py, pz);
385
+ dist1d2[level] = dist1d * dist1d;
386
+ i += i;
387
+ if (dist1d > 0) {
388
+ i++;
389
+ }
390
+ chosen[level++] = i;
391
+ }
392
+ curr = photons[i];
393
+ dist2 = curr.getDist2(px, py, pz);
394
+ if (dist2 < maxDist2) {
395
+ Vector3.decode(curr.normal, photN);
396
+ float currentDotN = Vector3.dot(photN, n);
397
+ if (currentDotN > 0.9f) {
398
+ nearest = curr;
399
+ maxDist2 = dist2;
400
+ }
401
+ }
402
+ do {
403
+ cameFrom = i;
404
+ i >>= 1;
405
+ level--;
406
+ if (i == 0) {
407
+ return (nearest == null) ? Color.BLACK : new Color().setRGBE(nearest.data);
408
+ }
409
+ } while ((dist1d2[level] >= maxDist2) || (cameFrom != chosen[level]));
410
+ curr = photons[i];
411
+ dist2 = curr.getDist2(px, py, pz);
412
+ if (dist2 < maxDist2) {
413
+ Vector3.decode(curr.normal, photN);
414
+ float currentDotN = Vector3.dot(photN, n);
415
+ if (currentDotN > 0.9f) {
416
+ nearest = curr;
417
+ maxDist2 = dist2;
418
+ }
419
+ }
420
+ i = chosen[level++] ^ 1;
421
+ }
422
+ }
423
+
424
+ private static class NearestPhotons {
425
+
426
+ int found;
427
+ float px, py, pz;
428
+ private int max;
429
+ private boolean gotHeap;
430
+ protected float[] dist2;
431
+ protected Photon[] index;
432
+
433
+ NearestPhotons(Point3 p, int n, float maxDist2) {
434
+ max = n;
435
+ found = 0;
436
+ gotHeap = false;
437
+ px = p.x;
438
+ py = p.y;
439
+ pz = p.z;
440
+ dist2 = new float[n + 1];
441
+ index = new Photon[n + 1];
442
+ dist2[0] = maxDist2;
443
+ }
444
+
445
+ void reset(Point3 p, float maxDist2) {
446
+ found = 0;
447
+ gotHeap = false;
448
+ px = p.x;
449
+ py = p.y;
450
+ pz = p.z;
451
+ dist2[0] = maxDist2;
452
+ }
453
+
454
+ void checkAddNearest(Photon p) {
455
+ float fdist2 = p.getDist2(px, py, pz);
456
+ if (fdist2 < dist2[0]) {
457
+ if (found < max) {
458
+ found++;
459
+ dist2[found] = fdist2;
460
+ index[found] = p;
461
+ } else {
462
+ int j;
463
+ int parent;
464
+ if (!gotHeap) {
465
+ float dst2;
466
+ Photon phot;
467
+ int halfFound = found >> 1;
468
+ for (int k = halfFound; k >= 1; k--) {
469
+ parent = k;
470
+ phot = index[k];
471
+ dst2 = dist2[k];
472
+ while (parent <= halfFound) {
473
+ j = parent + parent;
474
+ if ((j < found) && (dist2[j] < dist2[j + 1])) {
475
+ j++;
476
+ }
477
+ if (dst2 >= dist2[j]) {
478
+ break;
479
+ }
480
+ dist2[parent] = dist2[j];
481
+ index[parent] = index[j];
482
+ parent = j;
483
+ }
484
+ dist2[parent] = dst2;
485
+ index[parent] = phot;
486
+ }
487
+ gotHeap = true;
488
+ }
489
+ parent = 1;
490
+ j = 2;
491
+ while (j <= found) {
492
+ if ((j < found) && (dist2[j] < dist2[j + 1])) {
493
+ j++;
494
+ }
495
+ if (fdist2 > dist2[j]) {
496
+ break;
497
+ }
498
+ dist2[parent] = dist2[j];
499
+ index[parent] = index[j];
500
+ parent = j;
501
+ j += j;
502
+ }
503
+ dist2[parent] = fdist2;
504
+ index[parent] = p;
505
+ dist2[0] = dist2[1];
506
+ }
507
+ }
508
+ }
509
+ }
510
+
511
+ @Override
512
+ public boolean allowDiffuseBounced() {
513
+ return true;
514
+ }
515
+
516
+ @Override
517
+ public boolean allowReflectionBounced() {
518
+ return true;
519
+ }
520
+
521
+ @Override
522
+ public boolean allowRefractionBounced() {
523
+ return true;
524
+ }
525
+
526
+ @Override
527
+ public int numEmit() {
528
+ return numEmit;
529
+ }
530
+ }