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,174 @@
1
+ package org.sunflow.core.parser;
2
+
3
+ import java.io.FileNotFoundException;
4
+ import java.io.IOException;
5
+ import java.util.logging.Level;
6
+ import java.util.logging.Logger;
7
+
8
+ import org.sunflow.SunflowAPIInterface;
9
+ import org.sunflow.core.SceneParser;
10
+ import org.sunflow.system.Parser;
11
+ import org.sunflow.system.UI;
12
+ import org.sunflow.system.Parser.ParserException;
13
+ import org.sunflow.system.UI.Module;
14
+ import org.sunflow.util.FloatArray;
15
+ import org.sunflow.util.IntArray;
16
+
17
+ public class ShaveRibParser implements SceneParser {
18
+
19
+ @Override
20
+ public boolean parse(String filename, SunflowAPIInterface api) {
21
+ try {
22
+ Parser p = new Parser(filename);
23
+ p.checkNextToken("version");
24
+ p.checkNextToken("3.04");
25
+ p.checkNextToken("TransformBegin");
26
+
27
+ if (p.peekNextToken("Procedural")) {
28
+ // read procedural shave rib
29
+ boolean done = false;
30
+ while (!done) {
31
+ p.checkNextToken("DelayedReadArchive");
32
+ p.checkNextToken("[");
33
+ String f = p.getNextToken();
34
+ UI.printInfo(Module.USER, "RIB - Reading voxel: \"%s\" ...", f);
35
+ api.include(f);
36
+ p.checkNextToken("]");
37
+ while (true) {
38
+ String t = p.getNextToken();
39
+ if (t == null || t.equals("TransformEnd")) {
40
+ done = true;
41
+ break;
42
+ } else if (t.equals("Procedural")) {
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ return true;
48
+ }
49
+
50
+ boolean cubic = false;
51
+ if (p.peekNextToken("Basis")) {
52
+ cubic = true;
53
+ // u basis
54
+ p.checkNextToken("catmull-rom");
55
+ p.checkNextToken("1");
56
+ // v basis
57
+ p.checkNextToken("catmull-rom");
58
+ p.checkNextToken("1");
59
+ }
60
+ while (p.peekNextToken("Declare")) {
61
+ p.getNextToken(); // name
62
+ p.getNextToken(); // interpolation & type
63
+ }
64
+ int index = 0;
65
+ boolean done = false;
66
+ p.checkNextToken("Curves");
67
+ do {
68
+ if (cubic) {
69
+ p.checkNextToken("cubic");
70
+ } else {
71
+ p.checkNextToken("linear");
72
+ }
73
+ int[] nverts = parseIntArray(p);
74
+ for (int i = 1; i < nverts.length; i++) {
75
+ if (nverts[0] != nverts[i]) {
76
+ UI.printError(Module.USER, "RIB - Found variable number of hair segments");
77
+ return false;
78
+ }
79
+ }
80
+ int nhairs = nverts.length;
81
+
82
+ UI.printInfo(Module.USER, "RIB - Parsed %d hair curves", nhairs);
83
+
84
+ api.parameter("segments", nverts[0] - 1);
85
+
86
+ p.checkNextToken("nonperiodic");
87
+ p.checkNextToken("P");
88
+ float[] points = parseFloatArray(p);
89
+ if (points.length != 3 * nhairs * nverts[0]) {
90
+ UI.printError(Module.USER, "RIB - Invalid number of points - expecting %d - found %d", nhairs * nverts[0], points.length / 3);
91
+ return false;
92
+ }
93
+ api.parameter("points", "point", "vertex", points);
94
+
95
+ UI.printInfo(Module.USER, "RIB - Parsed %d hair vertices", points.length / 3);
96
+
97
+ p.checkNextToken("width");
98
+ float[] w = parseFloatArray(p);
99
+ if (w.length != nhairs * nverts[0]) {
100
+ UI.printError(Module.USER, "RIB - Invalid number of hair widths - expecting %d - found %d", nhairs * nverts[0], w.length);
101
+ return false;
102
+ }
103
+ api.parameter("widths", "float", "vertex", w);
104
+
105
+ UI.printInfo(Module.USER, "RIB - Parsed %d hair widths", w.length);
106
+
107
+ String name = String.format("%s[%d]", filename, index);
108
+ UI.printInfo(Module.USER, "RIB - Creating hair object \"%s\"", name);
109
+ api.geometry(name, "hair");
110
+ api.instance(name + ".instance", name);
111
+
112
+ UI.printInfo(Module.USER, "RIB - Searching for next curve group ...");
113
+ while (true) {
114
+ String t = p.getNextToken();
115
+ if (t == null || t.equals("TransformEnd")) {
116
+ done = true;
117
+ break;
118
+ } else if (t.equals("Curves")) {
119
+ break;
120
+ }
121
+ }
122
+ index++;
123
+ } while (!done);
124
+ UI.printInfo(Module.USER, "RIB - Finished reading rib file");
125
+ } catch (FileNotFoundException exp) {
126
+ UI.printError(Module.USER, "RIB - File not found: %s", filename);
127
+ Logger.getLogger(ShaveRibParser.class.getName()).log(Level.SEVERE, null, exp);
128
+ return false;
129
+ } catch (ParserException exp) {
130
+ UI.printError(Module.USER, "RIB - Parser exception: %s", exp);
131
+ Logger.getLogger(ShaveRibParser.class.getName()).log(Level.SEVERE, null, exp);
132
+ return false;
133
+ } catch (IOException exp) {
134
+ UI.printError(Module.USER, "RIB - I/O exception: %s", exp);
135
+ Logger.getLogger(ShaveRibParser.class.getName()).log(Level.SEVERE, null, exp);
136
+ return false;
137
+ }
138
+ return true;
139
+ }
140
+
141
+ private int[] parseIntArray(Parser p) throws IOException {
142
+ IntArray array = new IntArray();
143
+ boolean done = false;
144
+ do {
145
+ String s = p.getNextToken();
146
+ if (s.startsWith("[")) {
147
+ s = s.substring(1);
148
+ }
149
+ if (s.endsWith("]")) {
150
+ s = s.substring(0, s.length() - 1);
151
+ done = true;
152
+ }
153
+ array.add(Integer.parseInt(s));
154
+ } while (!done);
155
+ return array.trim();
156
+ }
157
+
158
+ private float[] parseFloatArray(Parser p) throws IOException {
159
+ FloatArray array = new FloatArray();
160
+ boolean done = false;
161
+ do {
162
+ String s = p.getNextToken();
163
+ if (s.startsWith("[")) {
164
+ s = s.substring(1);
165
+ }
166
+ if (s.endsWith("]")) {
167
+ s = s.substring(0, s.length() - 1);
168
+ done = true;
169
+ }
170
+ array.add(Float.parseFloat(s));
171
+ } while (!done);
172
+ return array.trim();
173
+ }
174
+ }
@@ -0,0 +1,79 @@
1
+ package org.sunflow.core.parser;
2
+
3
+ import java.io.FileNotFoundException;
4
+ import java.io.IOException;
5
+ import java.io.RandomAccessFile;
6
+ import java.nio.ByteOrder;
7
+ import java.nio.FloatBuffer;
8
+ import java.nio.IntBuffer;
9
+ import java.nio.MappedByteBuffer;
10
+ import java.nio.channels.FileChannel.MapMode;
11
+ import java.util.logging.Level;
12
+ import java.util.logging.Logger;
13
+
14
+ import org.sunflow.SunflowAPIInterface;
15
+ import org.sunflow.core.SceneParser;
16
+ import org.sunflow.system.Parser;
17
+ import org.sunflow.system.UI;
18
+ import org.sunflow.system.UI.Module;
19
+
20
+ public class TriParser implements SceneParser {
21
+
22
+ @Override
23
+ public boolean parse(String filename, SunflowAPIInterface api) {
24
+ try {
25
+ UI.printInfo(Module.USER, "TRI - Reading geometry: \"%s\" ...", filename);
26
+ Parser p = new Parser(filename);
27
+ float[] verts = new float[3 * p.getNextInt()];
28
+ for (int v = 0; v < verts.length; v += 3) {
29
+ verts[v + 0] = p.getNextFloat();
30
+ verts[v + 1] = p.getNextFloat();
31
+ verts[v + 2] = p.getNextFloat();
32
+ p.getNextToken();
33
+ p.getNextToken();
34
+ }
35
+ int[] triangles = new int[p.getNextInt() * 3];
36
+ for (int t = 0; t < triangles.length; t += 3) {
37
+ triangles[t + 0] = p.getNextInt();
38
+ triangles[t + 1] = p.getNextInt();
39
+ triangles[t + 2] = p.getNextInt();
40
+ }
41
+
42
+ // create geometry
43
+ api.parameter("triangles", triangles);
44
+ api.parameter("points", "point", "vertex", verts);
45
+ api.geometry(filename, "triangle_mesh");
46
+
47
+ // create shader
48
+ api.shader(filename + ".shader", "simple");
49
+ api.parameter("shaders", filename + ".shader");
50
+
51
+ // create instance
52
+ api.instance(filename + ".instance", filename);
53
+
54
+ p.close();
55
+ // output to ra3 format
56
+ RandomAccessFile stream = new RandomAccessFile(filename.replace(".tri", ".ra3"), "rw");
57
+ MappedByteBuffer map = stream.getChannel().map(MapMode.READ_WRITE, 0, 8 + 4 * (verts.length + triangles.length));
58
+ map.order(ByteOrder.LITTLE_ENDIAN);
59
+ IntBuffer ints = map.asIntBuffer();
60
+ FloatBuffer floats = map.asFloatBuffer();
61
+ ints.put(0, verts.length / 3);
62
+ ints.put(1, triangles.length / 3);
63
+ for (int i = 0; i < verts.length; i++) {
64
+ floats.put(2 + i, verts[i]);
65
+ }
66
+ for (int i = 0; i < triangles.length; i++) {
67
+ ints.put(2 + verts.length + i, triangles[i]);
68
+ }
69
+ stream.close();
70
+ } catch (FileNotFoundException e) {
71
+ Logger.getLogger(TriParser.class.getName()).log(Level.SEVERE, null, e);
72
+ return false;
73
+ } catch (IOException e) {
74
+ Logger.getLogger(TriParser.class.getName()).log(Level.SEVERE, null, e);
75
+ return false;
76
+ }
77
+ return true;
78
+ }
79
+ }
@@ -0,0 +1,429 @@
1
+ package org.sunflow.core.photonmap;
2
+
3
+ import java.util.ArrayList;
4
+
5
+ import org.sunflow.core.CausticPhotonMapInterface;
6
+ import org.sunflow.core.LightSample;
7
+ import org.sunflow.core.Options;
8
+ import org.sunflow.core.Ray;
9
+ import org.sunflow.core.ShadingState;
10
+ import org.sunflow.image.Color;
11
+ import org.sunflow.math.BoundingBox;
12
+ import org.sunflow.math.Point3;
13
+ import org.sunflow.math.Vector3;
14
+ import org.sunflow.system.Timer;
15
+ import org.sunflow.system.UI;
16
+ import org.sunflow.system.UI.Module;
17
+
18
+ public final class CausticPhotonMap implements CausticPhotonMapInterface {
19
+
20
+ private ArrayList<Photon> photonList;
21
+ private Photon[] photons;
22
+ private int storedPhotons;
23
+ private int halfStoredPhotons;
24
+ private int log2n;
25
+ private int gatherNum;
26
+ private float gatherRadius;
27
+ private BoundingBox bounds;
28
+ private float filterValue;
29
+ private float maxPower;
30
+ private float maxRadius;
31
+ private int numEmit;
32
+
33
+ @Override
34
+ public void prepare(Options options, BoundingBox sceneBounds) {
35
+ // get options
36
+ numEmit = options.getInt("caustics.emit", 10000);
37
+ gatherNum = options.getInt("caustics.gather", 50);
38
+ gatherRadius = options.getFloat("caustics.radius", 0.5f);
39
+ filterValue = options.getFloat("caustics.filter", 1.1f);
40
+ // init
41
+ bounds = new BoundingBox();
42
+ maxPower = 0;
43
+ maxRadius = 0;
44
+ photonList = new ArrayList<Photon>();
45
+ photonList.add(null);
46
+ photons = null;
47
+ storedPhotons = halfStoredPhotons = 0;
48
+ }
49
+
50
+ private void locatePhotons(NearestPhotons np) {
51
+ float[] dist1d2 = new float[log2n];
52
+ int[] chosen = new int[log2n];
53
+ int i = 1;
54
+ int level = 0;
55
+ int cameFrom;
56
+ while (true) {
57
+ while (i < halfStoredPhotons) {
58
+ float dist1d = photons[i].getDist1(np.px, np.py, np.pz);
59
+ dist1d2[level] = dist1d * dist1d;
60
+ i += i;
61
+ if (dist1d > 0.0f) {
62
+ i++;
63
+ }
64
+ chosen[level++] = i;
65
+ }
66
+ np.checkAddNearest(photons[i]);
67
+ do {
68
+ cameFrom = i;
69
+ i >>= 1;
70
+ level--;
71
+ if (i == 0) {
72
+ return;
73
+ }
74
+ } while ((dist1d2[level] >= np.dist2[0]) || (cameFrom != chosen[level]));
75
+ np.checkAddNearest(photons[i]);
76
+ i = chosen[level++] ^ 1;
77
+ }
78
+ }
79
+
80
+ private void balance() {
81
+ if (storedPhotons == 0) {
82
+ return;
83
+ }
84
+ photons = photonList.toArray(new Photon[photonList.size()]);
85
+ photonList = null;
86
+ Photon[] temp = new Photon[storedPhotons + 1];
87
+ balanceSegment(temp, 1, 1, storedPhotons);
88
+ photons = temp;
89
+ halfStoredPhotons = storedPhotons / 2;
90
+ log2n = (int) Math.ceil(Math.log(storedPhotons) / Math.log(2.0));
91
+ }
92
+
93
+ private void balanceSegment(Photon[] temp, int index, int start, int end) {
94
+ int median = 1;
95
+ while ((4 * median) <= (end - start + 1)) {
96
+ median += median;
97
+ }
98
+ if ((3 * median) <= (end - start + 1)) {
99
+ median += median;
100
+ median += (start - 1);
101
+ } else {
102
+ median = end - median + 1;
103
+ }
104
+ int axis = Photon.SPLIT_Z;
105
+ Vector3 extents = bounds.getExtents();
106
+ if ((extents.x > extents.y) && (extents.x > extents.z)) {
107
+ axis = Photon.SPLIT_X;
108
+ } else if (extents.y > extents.z) {
109
+ axis = Photon.SPLIT_Y;
110
+ }
111
+ int left = start;
112
+ int right = end;
113
+ while (right > left) {
114
+ double v = photons[right].getCoord(axis);
115
+ int i = left - 1;
116
+ int j = right;
117
+ while (true) {
118
+ while (photons[++i].getCoord(axis) < v) {
119
+ }
120
+ while ((photons[--j].getCoord(axis) > v) && (j > left)) {
121
+ }
122
+ if (i >= j) {
123
+ break;
124
+ }
125
+ swap(i, j);
126
+ }
127
+ swap(i, right);
128
+ if (i >= median) {
129
+ right = i - 1;
130
+ }
131
+ if (i <= median) {
132
+ left = i + 1;
133
+ }
134
+ }
135
+ temp[index] = photons[median];
136
+ temp[index].setSplitAxis(axis);
137
+ if (median > start) {
138
+ if (start < (median - 1)) {
139
+ float tmp;
140
+ switch (axis) {
141
+ case Photon.SPLIT_X:
142
+ tmp = bounds.getMaximum().x;
143
+ bounds.getMaximum().x = temp[index].x;
144
+ balanceSegment(temp, 2 * index, start, median - 1);
145
+ bounds.getMaximum().x = tmp;
146
+ break;
147
+ case Photon.SPLIT_Y:
148
+ tmp = bounds.getMaximum().y;
149
+ bounds.getMaximum().y = temp[index].y;
150
+ balanceSegment(temp, 2 * index, start, median - 1);
151
+ bounds.getMaximum().y = tmp;
152
+ break;
153
+ default:
154
+ tmp = bounds.getMaximum().z;
155
+ bounds.getMaximum().z = temp[index].z;
156
+ balanceSegment(temp, 2 * index, start, median - 1);
157
+ bounds.getMaximum().z = tmp;
158
+ }
159
+ } else {
160
+ temp[2 * index] = photons[start];
161
+ }
162
+ }
163
+ if (median < end) {
164
+ if ((median + 1) < end) {
165
+ float tmp;
166
+ switch (axis) {
167
+ case Photon.SPLIT_X:
168
+ tmp = bounds.getMinimum().x;
169
+ bounds.getMinimum().x = temp[index].x;
170
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
171
+ bounds.getMinimum().x = tmp;
172
+ break;
173
+ case Photon.SPLIT_Y:
174
+ tmp = bounds.getMinimum().y;
175
+ bounds.getMinimum().y = temp[index].y;
176
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
177
+ bounds.getMinimum().y = tmp;
178
+ break;
179
+ default:
180
+ tmp = bounds.getMinimum().z;
181
+ bounds.getMinimum().z = temp[index].z;
182
+ balanceSegment(temp, (2 * index) + 1, median + 1, end);
183
+ bounds.getMinimum().z = tmp;
184
+ }
185
+ } else {
186
+ temp[(2 * index) + 1] = photons[end];
187
+ }
188
+ }
189
+ }
190
+
191
+ private void swap(int i, int j) {
192
+ Photon tmp = photons[i];
193
+ photons[i] = photons[j];
194
+ photons[j] = tmp;
195
+ }
196
+
197
+ @Override
198
+ public void store(ShadingState state, Vector3 dir, Color power, Color diffuse) {
199
+ if (((state.getDiffuseDepth() == 0) && (state.getReflectionDepth() > 0 || state.getRefractionDepth() > 0))) {
200
+ // this is a caustic photon
201
+ Photon p = new Photon(state.getPoint(), dir, power);
202
+ synchronized (this) {
203
+ storedPhotons++;
204
+ photonList.add(p);
205
+ bounds.include(new Point3(p.x, p.y, p.z));
206
+ maxPower = Math.max(maxPower, power.getMax());
207
+ }
208
+ }
209
+ }
210
+
211
+ @Override
212
+ public void init() {
213
+ UI.printInfo(Module.LIGHT, "Balancing caustics photon map ...");
214
+ Timer t = new Timer();
215
+ t.start();
216
+ balance();
217
+ t.end();
218
+ UI.printInfo(Module.LIGHT, "Caustic photon map:");
219
+ UI.printInfo(Module.LIGHT, " * Photons stored: %d", storedPhotons);
220
+ UI.printInfo(Module.LIGHT, " * Photons/estimate: %d", gatherNum);
221
+ maxRadius = 1.4f * (float) Math.sqrt(maxPower * gatherNum);
222
+ UI.printInfo(Module.LIGHT, " * Estimate radius: %.3f", gatherRadius);
223
+ UI.printInfo(Module.LIGHT, " * Maximum radius: %.3f", maxRadius);
224
+ UI.printInfo(Module.LIGHT, " * Balancing time: %s", t.toString());
225
+ if (gatherRadius > maxRadius) {
226
+ gatherRadius = maxRadius;
227
+ }
228
+ }
229
+
230
+ @Override
231
+ public void getSamples(ShadingState state) {
232
+ if (storedPhotons == 0) {
233
+ return;
234
+ }
235
+ NearestPhotons np = new NearestPhotons(state.getPoint(), gatherNum, gatherRadius * gatherRadius);
236
+ locatePhotons(np);
237
+ if (np.found < 8) {
238
+ return;
239
+ }
240
+ Point3 ppos = new Point3();
241
+ Vector3 pdir = new Vector3();
242
+ Vector3 pvec = new Vector3();
243
+ float invArea = 1.0f / ((float) Math.PI * np.dist2[0]);
244
+ float maxNDist = np.dist2[0] * 0.05f;
245
+ float f2r2 = 1.0f / (filterValue * filterValue * np.dist2[0]);
246
+ float fInv = 1.0f / (1.0f - 2.0f / (3.0f * filterValue));
247
+ for (int i = 1; i <= np.found; i++) {
248
+ Photon phot = np.index[i];
249
+ Vector3.decode(phot.dir, pdir);
250
+ float cos = -Vector3.dot(pdir, state.getNormal());
251
+ if (cos > 0.001) {
252
+ ppos.set(phot.x, phot.y, phot.z);
253
+ Point3.sub(ppos, state.getPoint(), pvec);
254
+ float pcos = Vector3.dot(pvec, state.getNormal());
255
+ if ((pcos < maxNDist) && (pcos > -maxNDist)) {
256
+ LightSample sample = new LightSample();
257
+ sample.setShadowRay(new Ray(state.getPoint(), pdir.negate()));
258
+ sample.setRadiance(new Color().setRGBE(np.index[i].power).mul(invArea / cos), Color.BLACK);
259
+ sample.getDiffuseRadiance().mul((1.0f - (float) Math.sqrt(np.dist2[i] * f2r2)) * fInv);
260
+ state.addSample(sample);
261
+ }
262
+ }
263
+ }
264
+ }
265
+
266
+ private static class NearestPhotons {
267
+
268
+ int found;
269
+ float px, py, pz;
270
+ private int max;
271
+ private boolean gotHeap;
272
+ protected float[] dist2;
273
+ protected Photon[] index;
274
+
275
+ NearestPhotons(Point3 p, int n, float maxDist2) {
276
+ max = n;
277
+ found = 0;
278
+ gotHeap = false;
279
+ px = p.x;
280
+ py = p.y;
281
+ pz = p.z;
282
+ dist2 = new float[n + 1];
283
+ index = new Photon[n + 1];
284
+ dist2[0] = maxDist2;
285
+ }
286
+
287
+ void reset(Point3 p, float maxDist2) {
288
+ found = 0;
289
+ gotHeap = false;
290
+ px = p.x;
291
+ py = p.y;
292
+ pz = p.z;
293
+ dist2[0] = maxDist2;
294
+ }
295
+
296
+ void checkAddNearest(Photon p) {
297
+ float fdist2 = p.getDist2(px, py, pz);
298
+ if (fdist2 < dist2[0]) {
299
+ if (found < max) {
300
+ found++;
301
+ dist2[found] = fdist2;
302
+ index[found] = p;
303
+ } else {
304
+ int j;
305
+ int parent;
306
+ if (!gotHeap) {
307
+ float dst2;
308
+ Photon phot;
309
+ int halfFound = found >> 1;
310
+ for (int k = halfFound; k >= 1; k--) {
311
+ parent = k;
312
+ phot = index[k];
313
+ dst2 = dist2[k];
314
+ while (parent <= halfFound) {
315
+ j = parent + parent;
316
+ if ((j < found) && (dist2[j] < dist2[j + 1])) {
317
+ j++;
318
+ }
319
+ if (dst2 >= dist2[j]) {
320
+ break;
321
+ }
322
+ dist2[parent] = dist2[j];
323
+ index[parent] = index[j];
324
+ parent = j;
325
+ }
326
+ dist2[parent] = dst2;
327
+ index[parent] = phot;
328
+ }
329
+ gotHeap = true;
330
+ }
331
+ parent = 1;
332
+ j = 2;
333
+ while (j <= found) {
334
+ if ((j < found) && (dist2[j] < dist2[j + 1])) {
335
+ j++;
336
+ }
337
+ if (fdist2 > dist2[j]) {
338
+ break;
339
+ }
340
+ dist2[parent] = dist2[j];
341
+ index[parent] = index[j];
342
+ parent = j;
343
+ j += j;
344
+ }
345
+ dist2[parent] = fdist2;
346
+ index[parent] = p;
347
+ dist2[0] = dist2[1];
348
+ }
349
+ }
350
+ }
351
+ }
352
+
353
+ private static class Photon {
354
+
355
+ float x;
356
+ float y;
357
+ float z;
358
+ short dir;
359
+ int power;
360
+ int flags;
361
+ static final int SPLIT_X = 0;
362
+ static final int SPLIT_Y = 1;
363
+ static final int SPLIT_Z = 2;
364
+ static final int SPLIT_MASK = 3;
365
+
366
+ Photon(Point3 p, Vector3 dir, Color power) {
367
+ x = p.x;
368
+ y = p.y;
369
+ z = p.z;
370
+ this.dir = dir.encode();
371
+ this.power = power.toRGBE();
372
+ flags = SPLIT_X;
373
+ }
374
+
375
+ void setSplitAxis(int axis) {
376
+ flags &= ~SPLIT_MASK;
377
+ flags |= axis;
378
+ }
379
+
380
+ float getCoord(int axis) {
381
+ switch (axis) {
382
+ case SPLIT_X:
383
+ return x;
384
+ case SPLIT_Y:
385
+ return y;
386
+ default:
387
+ return z;
388
+ }
389
+ }
390
+
391
+ float getDist1(float px, float py, float pz) {
392
+ switch (flags & SPLIT_MASK) {
393
+ case SPLIT_X:
394
+ return px - x;
395
+ case SPLIT_Y:
396
+ return py - y;
397
+ default:
398
+ return pz - z;
399
+ }
400
+ }
401
+
402
+ float getDist2(float px, float py, float pz) {
403
+ float dx = x - px;
404
+ float dy = y - py;
405
+ float dz = z - pz;
406
+ return (dx * dx) + (dy * dy) + (dz * dz);
407
+ }
408
+ }
409
+
410
+ @Override
411
+ public boolean allowDiffuseBounced() {
412
+ return false;
413
+ }
414
+
415
+ @Override
416
+ public boolean allowReflectionBounced() {
417
+ return true;
418
+ }
419
+
420
+ @Override
421
+ public boolean allowRefractionBounced() {
422
+ return true;
423
+ }
424
+
425
+ @Override
426
+ public int numEmit() {
427
+ return numEmit;
428
+ }
429
+ }