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