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,210 @@
1
+ package org.sunflow.core.primitive;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.core.IntersectionState;
5
+ import org.sunflow.core.ParameterList;
6
+ import org.sunflow.core.PrimitiveList;
7
+ import org.sunflow.core.Ray;
8
+ import org.sunflow.core.ShadingState;
9
+ import org.sunflow.core.ParameterList.FloatParameter;
10
+ import org.sunflow.math.BoundingBox;
11
+ import org.sunflow.math.Matrix4;
12
+ import org.sunflow.math.OrthoNormalBasis;
13
+ import org.sunflow.math.Vector3;
14
+
15
+ public class Box implements PrimitiveList {
16
+
17
+ private float minX, minY, minZ;
18
+ private float maxX, maxY, maxZ;
19
+
20
+ public Box() {
21
+ minX = minY = minZ = -1;
22
+ maxX = maxY = maxZ = +1;
23
+ }
24
+
25
+ @Override
26
+ public boolean update(ParameterList pl, SunflowAPI api) {
27
+ FloatParameter pts = pl.getPointArray("points");
28
+ if (pts != null) {
29
+ BoundingBox bounds = new BoundingBox();
30
+ for (int i = 0; i < pts.data.length; i += 3) {
31
+ bounds.include(pts.data[i], pts.data[i + 1], pts.data[i + 2]);
32
+ }
33
+ // cube extents
34
+ minX = bounds.getMinimum().x;
35
+ minY = bounds.getMinimum().y;
36
+ minZ = bounds.getMinimum().z;
37
+ maxX = bounds.getMaximum().x;
38
+ maxY = bounds.getMaximum().y;
39
+ maxZ = bounds.getMaximum().z;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ @Override
45
+ public void prepareShadingState(ShadingState state) {
46
+ state.init();
47
+ state.getRay().getPoint(state.getPoint());
48
+ int n = state.getPrimitiveID();
49
+ switch (n) {
50
+ case 0:
51
+ state.getNormal().set(new Vector3(1, 0, 0));
52
+ break;
53
+ case 1:
54
+ state.getNormal().set(new Vector3(-1, 0, 0));
55
+ break;
56
+ case 2:
57
+ state.getNormal().set(new Vector3(0, 1, 0));
58
+ break;
59
+ case 3:
60
+ state.getNormal().set(new Vector3(0, -1, 0));
61
+ break;
62
+ case 4:
63
+ state.getNormal().set(new Vector3(0, 0, 1));
64
+ break;
65
+ case 5:
66
+ state.getNormal().set(new Vector3(0, 0, -1));
67
+ break;
68
+ default:
69
+ state.getNormal().set(new Vector3(0, 0, 0));
70
+ break;
71
+ }
72
+ state.getGeoNormal().set(state.getNormal());
73
+ state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
74
+ state.setShader(state.getInstance().getShader(0));
75
+ state.setModifier(state.getInstance().getModifier(0));
76
+ }
77
+
78
+ @Override
79
+ public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
80
+ float intervalMin = Float.NEGATIVE_INFINITY;
81
+ float intervalMax = Float.POSITIVE_INFINITY;
82
+ float orgX = r.ox;
83
+ float invDirX = 1 / r.dx;
84
+ float t1, t2;
85
+ t1 = (minX - orgX) * invDirX;
86
+ t2 = (maxX - orgX) * invDirX;
87
+ int sideIn = -1, sideOut = -1;
88
+ if (invDirX > 0) {
89
+ if (t1 > intervalMin) {
90
+ intervalMin = t1;
91
+ sideIn = 0;
92
+ }
93
+ if (t2 < intervalMax) {
94
+ intervalMax = t2;
95
+ sideOut = 1;
96
+ }
97
+ } else {
98
+ if (t2 > intervalMin) {
99
+ intervalMin = t2;
100
+ sideIn = 1;
101
+ }
102
+ if (t1 < intervalMax) {
103
+ intervalMax = t1;
104
+ sideOut = 0;
105
+ }
106
+ }
107
+ if (intervalMin > intervalMax) {
108
+ return;
109
+ }
110
+ float orgY = r.oy;
111
+ float invDirY = 1 / r.dy;
112
+ t1 = (minY - orgY) * invDirY;
113
+ t2 = (maxY - orgY) * invDirY;
114
+ if (invDirY > 0) {
115
+ if (t1 > intervalMin) {
116
+ intervalMin = t1;
117
+ sideIn = 2;
118
+ }
119
+ if (t2 < intervalMax) {
120
+ intervalMax = t2;
121
+ sideOut = 3;
122
+ }
123
+ } else {
124
+ if (t2 > intervalMin) {
125
+ intervalMin = t2;
126
+ sideIn = 3;
127
+ }
128
+ if (t1 < intervalMax) {
129
+ intervalMax = t1;
130
+ sideOut = 2;
131
+ }
132
+ }
133
+ if (intervalMin > intervalMax) {
134
+ return;
135
+ }
136
+ float orgZ = r.oz;
137
+ float invDirZ = 1 / r.dz;
138
+ t1 = (minZ - orgZ) * invDirZ; // no front wall
139
+ t2 = (maxZ - orgZ) * invDirZ;
140
+ if (invDirZ > 0) {
141
+ if (t1 > intervalMin) {
142
+ intervalMin = t1;
143
+ sideIn = 4;
144
+ }
145
+ if (t2 < intervalMax) {
146
+ intervalMax = t2;
147
+ sideOut = 5;
148
+ }
149
+ } else {
150
+ if (t2 > intervalMin) {
151
+ intervalMin = t2;
152
+ sideIn = 5;
153
+ }
154
+ if (t1 < intervalMax) {
155
+ intervalMax = t1;
156
+ sideOut = 4;
157
+ }
158
+ }
159
+ if (intervalMin > intervalMax) {
160
+ return;
161
+ }
162
+ if (r.isInside(intervalMin)) {
163
+ r.setMax(intervalMin);
164
+ state.setIntersection(sideIn);
165
+ } else if (r.isInside(intervalMax)) {
166
+ r.setMax(intervalMax);
167
+ state.setIntersection(sideOut);
168
+ }
169
+ }
170
+
171
+ @Override
172
+ public int getNumPrimitives() {
173
+ return 1;
174
+ }
175
+
176
+ @Override
177
+ public float getPrimitiveBound(int primID, int i) {
178
+ switch (i) {
179
+ case 0:
180
+ return minX;
181
+ case 1:
182
+ return maxX;
183
+ case 2:
184
+ return minY;
185
+ case 3:
186
+ return maxY;
187
+ case 4:
188
+ return minZ;
189
+ case 5:
190
+ return maxZ;
191
+ default:
192
+ return 0;
193
+ }
194
+ }
195
+
196
+ @Override
197
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
198
+ BoundingBox bounds = new BoundingBox(minX, minY, minZ);
199
+ bounds.include(maxX, maxY, maxZ);
200
+ if (o2w == null) {
201
+ return bounds;
202
+ }
203
+ return o2w.transform(bounds);
204
+ }
205
+
206
+ @Override
207
+ public PrimitiveList getBakingPrimitives() {
208
+ return null;
209
+ }
210
+ }
@@ -0,0 +1,476 @@
1
+ package org.sunflow.core.primitive;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.core.Instance;
5
+ import org.sunflow.core.IntersectionState;
6
+ import org.sunflow.core.LightSample;
7
+ import org.sunflow.core.LightSource;
8
+ import org.sunflow.core.ParameterList;
9
+ import org.sunflow.core.PrimitiveList;
10
+ import org.sunflow.core.Ray;
11
+ import org.sunflow.core.Shader;
12
+ import org.sunflow.core.ShadingState;
13
+ import org.sunflow.image.Color;
14
+ import org.sunflow.math.BoundingBox;
15
+ import org.sunflow.math.Matrix4;
16
+ import org.sunflow.math.OrthoNormalBasis;
17
+ import org.sunflow.math.Point3;
18
+ import org.sunflow.math.Vector3;
19
+
20
+ public class CornellBox implements PrimitiveList, Shader, LightSource {
21
+
22
+ private float minX, minY, minZ;
23
+ private float maxX, maxY, maxZ;
24
+ private Color left, right, top, bottom, back;
25
+ private Color radiance;
26
+ private int samples;
27
+ private float lxmin, lymin, lxmax, lymax;
28
+ private float area;
29
+ private BoundingBox lightBounds;
30
+
31
+ public CornellBox() {
32
+ updateGeometry(new Point3(-1, -1, -1), new Point3(1, 1, 1));
33
+
34
+ // cube colors
35
+ left = new Color(0.80f, 0.25f, 0.25f);
36
+ right = new Color(0.25f, 0.25f, 0.80f);
37
+ Color gray = new Color(0.70f, 0.70f, 0.70f);
38
+ top = bottom = back = gray;
39
+
40
+ // light source
41
+ radiance = Color.WHITE;
42
+ samples = 16;
43
+ }
44
+
45
+ private void updateGeometry(Point3 c0, Point3 c1) {
46
+ // figure out cube extents
47
+ lightBounds = new BoundingBox(c0);
48
+ lightBounds.include(c1);
49
+
50
+ // cube extents
51
+ minX = lightBounds.getMinimum().x;
52
+ minY = lightBounds.getMinimum().y;
53
+ minZ = lightBounds.getMinimum().z;
54
+ maxX = lightBounds.getMaximum().x;
55
+ maxY = lightBounds.getMaximum().y;
56
+ maxZ = lightBounds.getMaximum().z;
57
+
58
+ // work around epsilon problems for light test
59
+ lightBounds.enlargeUlps();
60
+
61
+ // light source geometry
62
+ lxmin = maxX / 3 + 2 * minX / 3;
63
+ lxmax = minX / 3 + 2 * maxX / 3;
64
+ lymin = maxY / 3 + 2 * minY / 3;
65
+ lymax = minY / 3 + 2 * maxY / 3;
66
+ area = (lxmax - lxmin) * (lymax - lymin);
67
+ }
68
+
69
+ @Override
70
+ public boolean update(ParameterList pl, SunflowAPI api) {
71
+ Point3 corner0 = pl.getPoint("corner0", null);
72
+ Point3 corner1 = pl.getPoint("corner1", null);
73
+ if (corner0 != null && corner1 != null) {
74
+ updateGeometry(corner0, corner1);
75
+ }
76
+
77
+ // shader colors
78
+ left = pl.getColor("leftColor", left);
79
+ right = pl.getColor("rightColor", right);
80
+ top = pl.getColor("topColor", top);
81
+ bottom = pl.getColor("bottomColor", bottom);
82
+ back = pl.getColor("backColor", back);
83
+
84
+ // light
85
+ radiance = pl.getColor("radiance", radiance);
86
+ samples = pl.getInt("samples", samples);
87
+ return true;
88
+ }
89
+
90
+ public BoundingBox getBounds() {
91
+ return lightBounds;
92
+ }
93
+
94
+ public float getBound(int i) {
95
+ switch (i) {
96
+ case 0:
97
+ return minX;
98
+ case 1:
99
+ return maxX;
100
+ case 2:
101
+ return minY;
102
+ case 3:
103
+ return maxY;
104
+ case 4:
105
+ return minZ;
106
+ case 5:
107
+ return maxZ;
108
+ default:
109
+ return 0;
110
+ }
111
+ }
112
+
113
+ public boolean intersects(BoundingBox box) {
114
+ // this could be optimized
115
+ BoundingBox b = new BoundingBox();
116
+ b.include(new Point3(minX, minY, minZ));
117
+ b.include(new Point3(maxX, maxY, maxZ));
118
+ if (b.intersects(box)) {
119
+ // the box is overlapping or enclosed
120
+ if (!b.contains(new Point3(box.getMinimum().x, box.getMinimum().y, box.getMinimum().z))) {
121
+ return true;
122
+ }
123
+ if (!b.contains(new Point3(box.getMinimum().x, box.getMinimum().y, box.getMaximum().z))) {
124
+ return true;
125
+ }
126
+ if (!b.contains(new Point3(box.getMinimum().x, box.getMaximum().y, box.getMinimum().z))) {
127
+ return true;
128
+ }
129
+ if (!b.contains(new Point3(box.getMinimum().x, box.getMaximum().y, box.getMaximum().z))) {
130
+ return true;
131
+ }
132
+ if (!b.contains(new Point3(box.getMaximum().x, box.getMinimum().y, box.getMinimum().z))) {
133
+ return true;
134
+ }
135
+ if (!b.contains(new Point3(box.getMaximum().x, box.getMinimum().y, box.getMaximum().z))) {
136
+ return true;
137
+ }
138
+ if (!b.contains(new Point3(box.getMaximum().x, box.getMaximum().y, box.getMinimum().z))) {
139
+ return true;
140
+ }
141
+ if (!b.contains(new Point3(box.getMaximum().x, box.getMaximum().y, box.getMaximum().z))) {
142
+ return true;
143
+ }
144
+ // all vertices of the box are inside - the surface of the box is
145
+ // not intersected
146
+ }
147
+ return false;
148
+ }
149
+
150
+ @Override
151
+ public void prepareShadingState(ShadingState state) {
152
+ state.init();
153
+ state.getRay().getPoint(state.getPoint());
154
+ int n = state.getPrimitiveID();
155
+ switch (n) {
156
+ case 0:
157
+ state.getNormal().set(new Vector3(1, 0, 0));
158
+ break;
159
+ case 1:
160
+ state.getNormal().set(new Vector3(-1, 0, 0));
161
+ break;
162
+ case 2:
163
+ state.getNormal().set(new Vector3(0, 1, 0));
164
+ break;
165
+ case 3:
166
+ state.getNormal().set(new Vector3(0, -1, 0));
167
+ break;
168
+ case 4:
169
+ state.getNormal().set(new Vector3(0, 0, 1));
170
+ break;
171
+ case 5:
172
+ state.getNormal().set(new Vector3(0, 0, -1));
173
+ break;
174
+ default:
175
+ state.getNormal().set(new Vector3(0, 0, 0));
176
+ break;
177
+ }
178
+ state.getGeoNormal().set(state.getNormal());
179
+ state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
180
+ state.setShader(this);
181
+ }
182
+
183
+ @Override
184
+ public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
185
+ float intervalMin = Float.NEGATIVE_INFINITY;
186
+ float intervalMax = Float.POSITIVE_INFINITY;
187
+ float orgX = r.ox;
188
+ float invDirX = 1 / r.dx;
189
+ float t1, t2;
190
+ t1 = (minX - orgX) * invDirX;
191
+ t2 = (maxX - orgX) * invDirX;
192
+ int sideIn = -1, sideOut = -1;
193
+ if (invDirX > 0) {
194
+ if (t1 > intervalMin) {
195
+ intervalMin = t1;
196
+ sideIn = 0;
197
+ }
198
+ if (t2 < intervalMax) {
199
+ intervalMax = t2;
200
+ sideOut = 1;
201
+ }
202
+ } else {
203
+ if (t2 > intervalMin) {
204
+ intervalMin = t2;
205
+ sideIn = 1;
206
+ }
207
+ if (t1 < intervalMax) {
208
+ intervalMax = t1;
209
+ sideOut = 0;
210
+ }
211
+ }
212
+ if (intervalMin > intervalMax) {
213
+ return;
214
+ }
215
+ float orgY = r.oy;
216
+ float invDirY = 1 / r.dy;
217
+ t1 = (minY - orgY) * invDirY;
218
+ t2 = (maxY - orgY) * invDirY;
219
+ if (invDirY > 0) {
220
+ if (t1 > intervalMin) {
221
+ intervalMin = t1;
222
+ sideIn = 2;
223
+ }
224
+ if (t2 < intervalMax) {
225
+ intervalMax = t2;
226
+ sideOut = 3;
227
+ }
228
+ } else {
229
+ if (t2 > intervalMin) {
230
+ intervalMin = t2;
231
+ sideIn = 3;
232
+ }
233
+ if (t1 < intervalMax) {
234
+ intervalMax = t1;
235
+ sideOut = 2;
236
+ }
237
+ }
238
+ if (intervalMin > intervalMax) {
239
+ return;
240
+ }
241
+ float orgZ = r.oz;
242
+ float invDirZ = 1 / r.dz;
243
+ t1 = (minZ - orgZ) * invDirZ; // no front wall
244
+ t2 = (maxZ - orgZ) * invDirZ;
245
+ if (invDirZ > 0) {
246
+ if (t1 > intervalMin) {
247
+ intervalMin = t1;
248
+ sideIn = 4;
249
+ }
250
+ if (t2 < intervalMax) {
251
+ intervalMax = t2;
252
+ sideOut = 5;
253
+ }
254
+ } else {
255
+ if (t2 > intervalMin) {
256
+ intervalMin = t2;
257
+ sideIn = 5;
258
+ }
259
+ if (t1 < intervalMax) {
260
+ intervalMax = t1;
261
+ sideOut = 4;
262
+ }
263
+ }
264
+ if (intervalMin > intervalMax) {
265
+ return;
266
+ }
267
+ assert sideIn != -1;
268
+ assert sideOut != -1;
269
+ // can't hit minY wall, there is none
270
+ if (sideIn != 2 && r.isInside(intervalMin)) {
271
+ r.setMax(intervalMin);
272
+ state.setIntersection(sideIn);
273
+ } else if (sideOut != 2 && r.isInside(intervalMax)) {
274
+ r.setMax(intervalMax);
275
+ state.setIntersection(sideOut);
276
+ }
277
+ }
278
+
279
+ @Override
280
+ public Color getRadiance(ShadingState state) {
281
+ int side = state.getPrimitiveID();
282
+ Color kd = null;
283
+ switch (side) {
284
+ case 0:
285
+ kd = left;
286
+ break;
287
+ case 1:
288
+ kd = right;
289
+ break;
290
+ case 3:
291
+ kd = back;
292
+ break;
293
+ case 4:
294
+ kd = bottom;
295
+ break;
296
+ case 5:
297
+ float lx = state.getPoint().x;
298
+ float ly = state.getPoint().y;
299
+ if (lx >= lxmin && lx < lxmax && ly >= lymin && ly < lymax && state.getRay().dz > 0) {
300
+ return state.includeLights() ? radiance : Color.BLACK;
301
+ }
302
+ kd = top;
303
+ break;
304
+ default:
305
+ assert false;
306
+ }
307
+ // make sure we are on the right side of the material
308
+ state.faceforward();
309
+ // setup lighting
310
+ state.initLightSamples();
311
+ state.initCausticSamples();
312
+ return state.diffuse(kd);
313
+ }
314
+
315
+ @Override
316
+ public void scatterPhoton(ShadingState state, Color power) {
317
+ int side = state.getPrimitiveID();
318
+ Color kd = null;
319
+ switch (side) {
320
+ case 0:
321
+ kd = left;
322
+ break;
323
+ case 1:
324
+ kd = right;
325
+ break;
326
+ case 3:
327
+ kd = back;
328
+ break;
329
+ case 4:
330
+ kd = bottom;
331
+ break;
332
+ case 5:
333
+ float lx = state.getPoint().x;
334
+ float ly = state.getPoint().y;
335
+ if (lx >= lxmin && lx < lxmax && ly >= lymin && ly < lymax && state.getRay().dz > 0) {
336
+ return;
337
+ }
338
+ kd = top;
339
+ break;
340
+ default:
341
+ assert false;
342
+ }
343
+ // make sure we are on the right side of the material
344
+ if (Vector3.dot(state.getNormal(), state.getRay().getDirection()) > 0) {
345
+ state.getNormal().negate();
346
+ state.getGeoNormal().negate();
347
+ }
348
+ state.storePhoton(state.getRay().getDirection(), power, kd);
349
+ double avg = kd.getAverage();
350
+ double rnd = state.getRandom(0, 0, 1);
351
+ if (rnd < avg) {
352
+ // photon is scattered
353
+ power.mul(kd).mul(1 / (float) avg);
354
+ OrthoNormalBasis onb = OrthoNormalBasis.makeFromW(state.getNormal());
355
+ double u = 2 * Math.PI * rnd / avg;
356
+ double v = state.getRandom(0, 1, 1);
357
+ float s = (float) Math.sqrt(v);
358
+ float s1 = (float) Math.sqrt(1.0 - v);
359
+ Vector3 w = new Vector3((float) Math.cos(u) * s, (float) Math.sin(u) * s, s1);
360
+ w = onb.transform(w, new Vector3());
361
+ state.traceDiffusePhoton(new Ray(state.getPoint(), w), power);
362
+ }
363
+ }
364
+
365
+ @Override
366
+ public int getNumSamples() {
367
+ return samples;
368
+ }
369
+
370
+ @Override
371
+ public void getSamples(ShadingState state) {
372
+ if (lightBounds.contains(state.getPoint()) && state.getPoint().z < maxZ) {
373
+ int n = state.getDiffuseDepth() > 0 ? 1 : samples;
374
+ float a = area / n;
375
+ for (int i = 0; i < n; i++) {
376
+ // random offset on unit square
377
+ double randX = state.getRandom(i, 0, n);
378
+ double randY = state.getRandom(i, 1, n);
379
+ Point3 p = new Point3();
380
+ p.x = (float) (lxmin * (1 - randX) + lxmax * randX);
381
+ p.y = (float) (lymin * (1 - randY) + lymax * randY);
382
+ p.z = maxZ - 0.001f;
383
+
384
+ LightSample dest = new LightSample();
385
+ // prepare shadow ray to sampled point
386
+ dest.setShadowRay(new Ray(state.getPoint(), p));
387
+
388
+ // check that the direction of the sample is the same as the
389
+ // normal
390
+ float cosNx = dest.dot(state.getNormal());
391
+ if (cosNx <= 0) {
392
+ return;
393
+ }
394
+
395
+ // light source facing point ?
396
+ // (need to check with light source's normal)
397
+ float cosNy = dest.getShadowRay().dz;
398
+ if (cosNy > 0) {
399
+ // compute geometric attenuation and probability scale
400
+ // factor
401
+ float r = dest.getShadowRay().getMax();
402
+ float g = cosNy / (r * r);
403
+ float scale = g * a;
404
+ // set final sample radiance
405
+ dest.setRadiance(radiance, radiance);
406
+ dest.getDiffuseRadiance().mul(scale);
407
+ dest.getSpecularRadiance().mul(scale);
408
+ dest.traceShadow(state);
409
+ state.addSample(dest);
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ @Override
416
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
417
+ p.x = (float) (lxmin * (1 - randX2) + lxmax * randX2);
418
+ p.y = (float) (lymin * (1 - randY2) + lymax * randY2);
419
+ p.z = maxZ - 0.001f;
420
+
421
+ double u = 2 * Math.PI * randX1;
422
+ double s = Math.sqrt(randY1);
423
+ dir.set((float) (Math.cos(u) * s), (float) (Math.sin(u) * s), (float) -Math.sqrt(1.0f - randY1));
424
+ Color.mul((float) Math.PI * area, radiance, power);
425
+ }
426
+
427
+ @Override
428
+ public float getPower() {
429
+ return radiance.copy().mul((float) Math.PI * area).getLuminance();
430
+ }
431
+
432
+ @Override
433
+ public int getNumPrimitives() {
434
+ return 1;
435
+ }
436
+
437
+ @Override
438
+ public float getPrimitiveBound(int primID, int i) {
439
+ switch (i) {
440
+ case 0:
441
+ return minX;
442
+ case 1:
443
+ return maxX;
444
+ case 2:
445
+ return minY;
446
+ case 3:
447
+ return maxY;
448
+ case 4:
449
+ return minZ;
450
+ case 5:
451
+ return maxZ;
452
+ default:
453
+ return 0;
454
+ }
455
+ }
456
+
457
+ @Override
458
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
459
+ BoundingBox bounds = new BoundingBox(minX, minY, minZ);
460
+ bounds.include(maxX, maxY, maxZ);
461
+ if (o2w == null) {
462
+ return bounds;
463
+ }
464
+ return o2w.transform(bounds);
465
+ }
466
+
467
+ @Override
468
+ public PrimitiveList getBakingPrimitives() {
469
+ return null;
470
+ }
471
+
472
+ @Override
473
+ public Instance createInstance() {
474
+ return Instance.createTemporary(this, null, this);
475
+ }
476
+ }