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,254 @@
1
+ package org.sunflow.core.tesselatable;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.core.ParameterList;
5
+ import org.sunflow.core.PrimitiveList;
6
+ import org.sunflow.core.Tesselatable;
7
+ import org.sunflow.core.ParameterList.FloatParameter;
8
+ import org.sunflow.core.ParameterList.InterpolationType;
9
+ import org.sunflow.core.primitive.QuadMesh;
10
+ import org.sunflow.core.primitive.TriangleMesh;
11
+ import org.sunflow.math.BoundingBox;
12
+ import org.sunflow.math.Matrix4;
13
+ import org.sunflow.math.Point3;
14
+ import org.sunflow.math.Vector3;
15
+ import org.sunflow.system.UI;
16
+ import org.sunflow.system.UI.Module;
17
+
18
+ public class BezierMesh implements Tesselatable {
19
+
20
+ private int subdivs;
21
+ private boolean smooth;
22
+ private boolean quads;
23
+ private float[][] patches;
24
+
25
+ public BezierMesh() {
26
+ this(null);
27
+ }
28
+
29
+ public BezierMesh(float[][] patches) {
30
+ subdivs = 8;
31
+ smooth = true;
32
+ quads = false;
33
+ // convert to single precision
34
+ this.patches = patches;
35
+ }
36
+
37
+ @Override
38
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
39
+ BoundingBox bounds = new BoundingBox();
40
+ if (o2w == null) {
41
+ for (float[] patch : patches) {
42
+ for (int j = 0; j < patch.length; j += 3) {
43
+ bounds.include(patch[j], patch[j + 1], patch[j + 2]);
44
+ }
45
+ }
46
+ } else {
47
+ // transform vertices first
48
+ for (float[] patch : patches) {
49
+ for (int j = 0; j < patch.length; j += 3) {
50
+ float x = patch[j];
51
+ float y = patch[j + 1];
52
+ float z = patch[j + 2];
53
+ float wx = o2w.transformPX(x, y, z);
54
+ float wy = o2w.transformPY(x, y, z);
55
+ float wz = o2w.transformPZ(x, y, z);
56
+ bounds.include(wx, wy, wz);
57
+ }
58
+ }
59
+ }
60
+ return bounds;
61
+ }
62
+
63
+ private float[] bernstein(float u) {
64
+ float[] b = new float[4];
65
+ float i = 1 - u;
66
+ b[0] = i * i * i;
67
+ b[1] = 3 * u * i * i;
68
+ b[2] = 3 * u * u * i;
69
+ b[3] = u * u * u;
70
+ return b;
71
+ }
72
+
73
+ private float[] bernsteinDeriv(float u) {
74
+ if (!smooth) {
75
+ return null;
76
+ }
77
+ float[] b = new float[4];
78
+ float i = 1 - u;
79
+ b[0] = 3 * (0 - i * i);
80
+ b[1] = 3 * (i * i - 2 * u * i);
81
+ b[2] = 3 * (2 * u * i - u * u);
82
+ b[3] = 3 * (u * u - 0);
83
+ return b;
84
+ }
85
+
86
+ private void getPatchPoint(float u, float v, float[] ctrl, float[] bu, float[] bv, float[] bdu, float[] bdv, Point3 p, Vector3 n) {
87
+ float px = 0;
88
+ float py = 0;
89
+ float pz = 0;
90
+ for (int i = 0, index = 0; i < 4; i++) {
91
+ for (int j = 0; j < 4; j++, index += 3) {
92
+ float scale = bu[j] * bv[i];
93
+ px += ctrl[index + 0] * scale;
94
+ py += ctrl[index + 1] * scale;
95
+ pz += ctrl[index + 2] * scale;
96
+ }
97
+ }
98
+ p.x = px;
99
+ p.y = py;
100
+ p.z = pz;
101
+ if (n != null) {
102
+ float dpdux = 0;
103
+ float dpduy = 0;
104
+ float dpduz = 0;
105
+ float dpdvx = 0;
106
+ float dpdvy = 0;
107
+ float dpdvz = 0;
108
+ for (int i = 0, index = 0; i < 4; i++) {
109
+ for (int j = 0; j < 4; j++, index += 3) {
110
+ float scaleu = bdu[j] * bv[i];
111
+ dpdux += ctrl[index + 0] * scaleu;
112
+ dpduy += ctrl[index + 1] * scaleu;
113
+ dpduz += ctrl[index + 2] * scaleu;
114
+ float scalev = bu[j] * bdv[i];
115
+ dpdvx += ctrl[index + 0] * scalev;
116
+ dpdvy += ctrl[index + 1] * scalev;
117
+ dpdvz += ctrl[index + 2] * scalev;
118
+ }
119
+ }
120
+ // surface normal
121
+ n.x = (dpduy * dpdvz - dpduz * dpdvy);
122
+ n.y = (dpduz * dpdvx - dpdux * dpdvz);
123
+ n.z = (dpdux * dpdvy - dpduy * dpdvx);
124
+ }
125
+ }
126
+
127
+ @Override
128
+ public PrimitiveList tesselate() {
129
+ float[] vertices = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3];
130
+ float[] normals = smooth ? new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3] : null;
131
+ float[] uvs = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 2];
132
+ int[] indices = new int[patches.length * subdivs * subdivs * (quads ? 4 : (2 * 3))];
133
+
134
+ int vidx = 0, pidx = 0;
135
+ float step = 1.0f / subdivs;
136
+ int vstride = subdivs + 1;
137
+ Point3 p = new Point3();
138
+ Vector3 n = smooth ? new Vector3() : null;
139
+ for (float[] patch : patches) {
140
+ // create patch vertices
141
+ for (int i = 0, voff = 0; i <= subdivs; i++) {
142
+ float u = i * step;
143
+ float[] bu = bernstein(u);
144
+ float[] bdu = bernsteinDeriv(u);
145
+ for (int j = 0; j <= subdivs; j++, voff += 3) {
146
+ float v = j * step;
147
+ float[] bv = bernstein(v);
148
+ float[] bdv = bernsteinDeriv(v);
149
+ getPatchPoint(u, v, patch, bu, bv, bdu, bdv, p, n);
150
+ vertices[vidx + voff + 0] = p.x;
151
+ vertices[vidx + voff + 1] = p.y;
152
+ vertices[vidx + voff + 2] = p.z;
153
+ if (smooth) {
154
+ normals[vidx + voff + 0] = n.x;
155
+ normals[vidx + voff + 1] = n.y;
156
+ normals[vidx + voff + 2] = n.z;
157
+ }
158
+ uvs[(vidx + voff) / 3 * 2 + 0] = u;
159
+ uvs[(vidx + voff) / 3 * 2 + 1] = v;
160
+ }
161
+ }
162
+ // generate patch triangles
163
+ for (int i = 0, vbase = vidx / 3; i < subdivs; i++) {
164
+ for (int j = 0; j < subdivs; j++) {
165
+ int v00 = (i + 0) * vstride + (j + 0);
166
+ int v10 = (i + 1) * vstride + (j + 0);
167
+ int v01 = (i + 0) * vstride + (j + 1);
168
+ int v11 = (i + 1) * vstride + (j + 1);
169
+ if (quads) {
170
+ indices[pidx + 0] = vbase + v01;
171
+ indices[pidx + 1] = vbase + v00;
172
+ indices[pidx + 2] = vbase + v10;
173
+ indices[pidx + 3] = vbase + v11;
174
+ pidx += 4;
175
+ } else {
176
+ // add 2 triangles
177
+ indices[pidx + 0] = vbase + v00;
178
+ indices[pidx + 1] = vbase + v10;
179
+ indices[pidx + 2] = vbase + v01;
180
+ indices[pidx + 3] = vbase + v10;
181
+ indices[pidx + 4] = vbase + v11;
182
+ indices[pidx + 5] = vbase + v01;
183
+ pidx += 6;
184
+ }
185
+ }
186
+ }
187
+ vidx += vstride * vstride * 3;
188
+ }
189
+ ParameterList pl = new ParameterList();
190
+ pl.addPoints("points", InterpolationType.VERTEX, vertices);
191
+ if (quads) {
192
+ pl.addIntegerArray("quads", indices);
193
+ } else {
194
+ pl.addIntegerArray("triangles", indices);
195
+ }
196
+ pl.addTexCoords("uvs", InterpolationType.VERTEX, uvs);
197
+ if (smooth) {
198
+ pl.addVectors("normals", InterpolationType.VERTEX, normals);
199
+ }
200
+ PrimitiveList m = quads ? new QuadMesh() : new TriangleMesh();
201
+ m.update(pl, null);
202
+ pl.clear(true);
203
+ return m;
204
+ }
205
+
206
+ @Override
207
+ public boolean update(ParameterList pl, SunflowAPI api) {
208
+ subdivs = pl.getInt("subdivs", subdivs);
209
+ smooth = pl.getBoolean("smooth", smooth);
210
+ quads = pl.getBoolean("quads", quads);
211
+ int nu = pl.getInt("nu", 0);
212
+ int nv = pl.getInt("nv", 0);
213
+ pl.setVertexCount(nu * nv);
214
+ boolean uwrap = pl.getBoolean("uwrap", false);
215
+ boolean vwrap = pl.getBoolean("vwrap", false);
216
+ FloatParameter points = pl.getPointArray("points");
217
+ if (points != null && points.interp == InterpolationType.VERTEX) {
218
+ int numUPatches = uwrap ? nu / 3 : (nu - 4) / 3 + 1;
219
+ int numVPatches = vwrap ? nv / 3 : (nv - 4) / 3 + 1;
220
+ if (numUPatches < 1 || numVPatches < 1) {
221
+ UI.printError(Module.GEOM, "Invalid number of patches for bezier mesh - ignoring");
222
+ return false;
223
+ }
224
+ // generate patches
225
+ patches = new float[numUPatches * numVPatches][];
226
+ for (int v = 0, p = 0; v < numVPatches; v++) {
227
+ for (int u = 0; u < numUPatches; u++, p++) {
228
+ float[] patch = patches[p] = new float[16 * 3];
229
+ int up = u * 3;
230
+ int vp = v * 3;
231
+ for (int pv = 0; pv < 4; pv++) {
232
+ for (int pu = 0; pu < 4; pu++) {
233
+ int meshU = (up + pu) % nu;
234
+ int meshV = (vp + pv) % nv;
235
+ // copy point
236
+ patch[3 * (pv * 4 + pu) + 0] = points.data[3 * (meshU + nu * meshV) + 0];
237
+ patch[3 * (pv * 4 + pu) + 1] = points.data[3 * (meshU + nu * meshV) + 1];
238
+ patch[3 * (pv * 4 + pu) + 2] = points.data[3 * (meshU + nu * meshV) + 2];
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ if (subdivs < 1) {
245
+ UI.printError(Module.GEOM, "Invalid subdivisions for bezier mesh - ignoring");
246
+ return false;
247
+ }
248
+ if (patches == null) {
249
+ UI.printError(Module.GEOM, "No patch data present in bezier mesh - ignoring");
250
+ return false;
251
+ }
252
+ return true;
253
+ }
254
+ }
@@ -0,0 +1,251 @@
1
+ package org.sunflow.core.tesselatable;
2
+
3
+ import java.io.BufferedInputStream;
4
+ import java.io.BufferedReader;
5
+ import java.io.DataInputStream;
6
+ import java.io.File;
7
+ import java.io.FileInputStream;
8
+ import java.io.FileNotFoundException;
9
+ import java.io.FileReader;
10
+ import java.io.IOException;
11
+ import java.nio.ByteOrder;
12
+ import java.nio.FloatBuffer;
13
+ import java.nio.IntBuffer;
14
+ import java.nio.MappedByteBuffer;
15
+ import java.nio.channels.FileChannel;
16
+ import java.util.logging.Level;
17
+ import java.util.logging.Logger;
18
+
19
+ import org.sunflow.SunflowAPI;
20
+ import org.sunflow.core.ParameterList;
21
+ import org.sunflow.core.PrimitiveList;
22
+ import org.sunflow.core.Tesselatable;
23
+ import org.sunflow.core.ParameterList.InterpolationType;
24
+ import org.sunflow.core.primitive.TriangleMesh;
25
+ import org.sunflow.math.BoundingBox;
26
+ import org.sunflow.math.Matrix4;
27
+ import org.sunflow.math.Point3;
28
+ import org.sunflow.math.Vector3;
29
+ import org.sunflow.system.Memory;
30
+ import org.sunflow.system.UI;
31
+ import org.sunflow.system.UI.Module;
32
+ import org.sunflow.util.FloatArray;
33
+ import org.sunflow.util.IntArray;
34
+
35
+ public class FileMesh implements Tesselatable {
36
+
37
+ private String filename = null;
38
+ private boolean smoothNormals = false;
39
+
40
+ @Override
41
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
42
+ // world bounds can't be computed without reading file
43
+ // return null so the mesh will be loaded right away
44
+ return null;
45
+ }
46
+
47
+ @Override
48
+ public PrimitiveList tesselate() {
49
+ if (filename.endsWith(".ra3")) {
50
+ try {
51
+ UI.printInfo(Module.GEOM, "RA3 - Reading geometry: \"%s\" ...", filename);
52
+ File file = new File(filename);
53
+ float[] verts;
54
+ int[] tris;
55
+ try (FileInputStream stream = new FileInputStream(filename)) {
56
+ MappedByteBuffer map = stream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
57
+ map.order(ByteOrder.LITTLE_ENDIAN);
58
+ IntBuffer ints = map.asIntBuffer();
59
+ FloatBuffer buffer = map.asFloatBuffer();
60
+ int numVerts = ints.get(0);
61
+ int numTris = ints.get(1);
62
+ UI.printInfo(Module.GEOM, "RA3 - * Reading %d vertices ...", numVerts);
63
+ verts = new float[3 * numVerts];
64
+ for (int i = 0; i < verts.length; i++) {
65
+ verts[i] = buffer.get(2 + i);
66
+ } UI.printInfo(Module.GEOM, "RA3 - * Reading %d triangles ...", numTris);
67
+ tris = new int[3 * numTris];
68
+ for (int i = 0; i < tris.length; i++) {
69
+ tris[i] = ints.get(2 + verts.length + i);
70
+ }
71
+ }
72
+ UI.printInfo(Module.GEOM, "RA3 - * Creating mesh ...");
73
+ return generate(tris, verts, smoothNormals);
74
+ } catch (FileNotFoundException e) {
75
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
76
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
77
+ } catch (IOException e) {
78
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
79
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
80
+ }
81
+ } else if (filename.endsWith(".obj")) {
82
+ int lineNumber = 1;
83
+ try {
84
+ UI.printInfo(Module.GEOM, "OBJ - Reading geometry: \"%s\" ...", filename);
85
+ FloatArray verts = new FloatArray();
86
+ IntArray tris = new IntArray();
87
+ FileReader file = new FileReader(filename);
88
+ BufferedReader bf = new BufferedReader(file);
89
+ String line;
90
+ while ((line = bf.readLine()) != null) {
91
+ if (line.startsWith("v")) {
92
+ String[] v = line.split("\\s+");
93
+ verts.add(Float.parseFloat(v[1]));
94
+ verts.add(Float.parseFloat(v[2]));
95
+ verts.add(Float.parseFloat(v[3]));
96
+ } else if (line.startsWith("f")) {
97
+ String[] f = line.split("\\s+");
98
+ if (f.length == 5) {
99
+ tris.add(Integer.parseInt(f[1]) - 1);
100
+ tris.add(Integer.parseInt(f[2]) - 1);
101
+ tris.add(Integer.parseInt(f[3]) - 1);
102
+ tris.add(Integer.parseInt(f[1]) - 1);
103
+ tris.add(Integer.parseInt(f[3]) - 1);
104
+ tris.add(Integer.parseInt(f[4]) - 1);
105
+ } else if (f.length == 4) {
106
+ tris.add(Integer.parseInt(f[1]) - 1);
107
+ tris.add(Integer.parseInt(f[2]) - 1);
108
+ tris.add(Integer.parseInt(f[3]) - 1);
109
+ }
110
+ }
111
+ if (lineNumber % 100000 == 0) {
112
+ UI.printInfo(Module.GEOM, "OBJ - * Parsed %7d lines ...", lineNumber);
113
+ }
114
+ lineNumber++;
115
+ }
116
+ file.close();
117
+ UI.printInfo(Module.GEOM, "OBJ - * Creating mesh ...");
118
+ return generate(tris.trim(), verts.trim(), smoothNormals);
119
+ } catch (FileNotFoundException e) {
120
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
121
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
122
+ } catch (NumberFormatException e) {
123
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
124
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - syntax error at line %d", lineNumber);
125
+ } catch (IOException e) {
126
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
127
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
128
+ }
129
+ } else if (filename.endsWith(".stl")) {
130
+ try {
131
+ UI.printInfo(Module.GEOM, "STL - Reading geometry: \"%s\" ...", filename);
132
+ FileInputStream file = new FileInputStream(filename);
133
+ DataInputStream stream = new DataInputStream(new BufferedInputStream(file));
134
+ file.skip(80);
135
+ int numTris = getLittleEndianInt(stream.readInt());
136
+ UI.printInfo(Module.GEOM, "STL - * Reading %d triangles ...", numTris);
137
+ long filesize = new File(filename).length();
138
+ if (filesize != (84 + 50 * numTris)) {
139
+ UI.printWarning(Module.GEOM, "STL - Size of file mismatch (expecting %s, found %s)", Memory.bytesToString(84 + 14 * numTris), Memory.bytesToString(filesize));
140
+ return null;
141
+ }
142
+ int[] tris = new int[3 * numTris];
143
+ float[] verts = new float[9 * numTris];
144
+ for (int i = 0, i3 = 0, index = 0; i < numTris; i++, i3 += 3) {
145
+ // skip normal
146
+ stream.readInt();
147
+ stream.readInt();
148
+ stream.readInt();
149
+ for (int j = 0; j < 3; j++, index += 3) {
150
+ tris[i3 + j] = i3 + j;
151
+ // get xyz
152
+ verts[index + 0] = getLittleEndianFloat(stream.readInt());
153
+ verts[index + 1] = getLittleEndianFloat(stream.readInt());
154
+ verts[index + 2] = getLittleEndianFloat(stream.readInt());
155
+ }
156
+ stream.readShort();
157
+ if ((i + 1) % 100000 == 0) {
158
+ UI.printInfo(Module.GEOM, "STL - * Parsed %7d triangles ...", i + 1);
159
+ }
160
+ }
161
+ file.close();
162
+ // create geometry
163
+ UI.printInfo(Module.GEOM, "STL - * Creating mesh ...");
164
+ if (smoothNormals) {
165
+ UI.printWarning(Module.GEOM, "STL - format does not support shared vertices - normal smoothing disabled");
166
+ }
167
+ return generate(tris, verts, false);
168
+ } catch (FileNotFoundException e) {
169
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
170
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
171
+ } catch (IOException e) {
172
+ Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
173
+ UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
174
+ }
175
+ } else {
176
+ UI.printWarning(Module.GEOM, "Unable to read mesh file \"%s\" - unrecognized format", filename);
177
+ }
178
+ return null;
179
+ }
180
+
181
+ private TriangleMesh generate(int[] tris, float[] verts, boolean smoothNormals) {
182
+ ParameterList pl = new ParameterList();
183
+ pl.addIntegerArray("triangles", tris);
184
+ pl.addPoints("points", InterpolationType.VERTEX, verts);
185
+ if (smoothNormals) {
186
+ float[] normals = new float[verts.length]; // filled with 0's
187
+ Point3 p0 = new Point3();
188
+ Point3 p1 = new Point3();
189
+ Point3 p2 = new Point3();
190
+ Vector3 n = new Vector3();
191
+ for (int i3 = 0; i3 < tris.length; i3 += 3) {
192
+ int v0 = tris[i3 + 0];
193
+ int v1 = tris[i3 + 1];
194
+ int v2 = tris[i3 + 2];
195
+ p0.set(verts[3 * v0 + 0], verts[3 * v0 + 1], verts[3 * v0 + 2]);
196
+ p1.set(verts[3 * v1 + 0], verts[3 * v1 + 1], verts[3 * v1 + 2]);
197
+ p2.set(verts[3 * v2 + 0], verts[3 * v2 + 1], verts[3 * v2 + 2]);
198
+ Point3.normal(p0, p1, p2, n); // compute normal
199
+ // add face normal to each vertex
200
+ // note that these are not normalized so this in fact weights
201
+ // each normal by the area of the triangle
202
+ normals[3 * v0 + 0] += n.x;
203
+ normals[3 * v0 + 1] += n.y;
204
+ normals[3 * v0 + 2] += n.z;
205
+ normals[3 * v1 + 0] += n.x;
206
+ normals[3 * v1 + 1] += n.y;
207
+ normals[3 * v1 + 2] += n.z;
208
+ normals[3 * v2 + 0] += n.x;
209
+ normals[3 * v2 + 1] += n.y;
210
+ normals[3 * v2 + 2] += n.z;
211
+ }
212
+ // normalize all the vectors
213
+ for (int i3 = 0; i3 < normals.length; i3 += 3) {
214
+ n.set(normals[i3 + 0], normals[i3 + 1], normals[i3 + 2]);
215
+ n.normalize();
216
+ normals[i3 + 0] = n.x;
217
+ normals[i3 + 1] = n.y;
218
+ normals[i3 + 2] = n.z;
219
+ }
220
+ pl.addVectors("normals", InterpolationType.VERTEX, normals);
221
+ }
222
+ TriangleMesh m = new TriangleMesh();
223
+ if (m.update(pl, null)) {
224
+ return m;
225
+ }
226
+ // something failed in creating the mesh, the error message will be
227
+ // printed by the mesh itself - no need to repeat it here
228
+ return null;
229
+ }
230
+
231
+ public boolean update(ParameterList pl, SunflowAPI api) {
232
+ String file = pl.getString("filename", null);
233
+ if (file != null) {
234
+ filename = api.resolveIncludeFilename(file);
235
+ }
236
+ smoothNormals = pl.getBoolean("smooth_normals", smoothNormals);
237
+ return filename != null;
238
+ }
239
+
240
+ private int getLittleEndianInt(int i) {
241
+ // input integer has its bytes in big endian byte order
242
+ // swap them around
243
+ return (i >>> 24) | ((i >>> 8) & 0xFF00) | ((i << 8) & 0xFF0000) | (i << 24);
244
+ }
245
+
246
+ private float getLittleEndianFloat(int i) {
247
+ // input integer has its bytes in big endian byte order
248
+ // swap them around and interpret data as floating point
249
+ return Float.intBitsToFloat(getLittleEndianInt(i));
250
+ }
251
+ }