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