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.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/.mvn/extensions.xml +8 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/Rakefile +43 -0
- data/docs/.gitignore +6 -0
- data/docs/_config.yml +20 -0
- data/docs/_includes/footer.html +38 -0
- data/docs/_includes/head.html +15 -0
- data/docs/_includes/header.html +27 -0
- data/docs/_includes/icon-github.html +1 -0
- data/docs/_includes/icon-github.svg +1 -0
- data/docs/_includes/icon-twitter.html +1 -0
- data/docs/_includes/icon-twitter.svg +1 -0
- data/docs/_layouts/default.html +20 -0
- data/docs/_layouts/page.html +14 -0
- data/docs/_layouts/post.html +15 -0
- data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
- data/docs/_posts/2017-01-08-welcome.md +78 -0
- data/docs/_sass/_base.scss +206 -0
- data/docs/_sass/_layout.scss +242 -0
- data/docs/_sass/_syntax-highlighting.scss +71 -0
- data/docs/about.md +12 -0
- data/docs/assets/Animation.ogv +0 -0
- data/docs/assets/Animation.png +0 -0
- data/docs/assets/basic.png +0 -0
- data/docs/assets/basic_traced.png +0 -0
- data/docs/css/main.scss +38 -0
- data/docs/favicon.ico +0 -0
- data/docs/feed.xml +30 -0
- data/docs/index.html +38 -0
- data/joonsrenderer.gemspec +23 -0
- data/lib/joonsrenderer.rb +12 -0
- data/lib/joonsrenderer/version.rb +3 -0
- data/pom.rb +75 -0
- data/pom.xml +163 -0
- data/src/main/java/SunflowGUI.java +1354 -0
- data/src/main/java/joons/JRFiller.java +79 -0
- data/src/main/java/joons/JRImagePanel.java +141 -0
- data/src/main/java/joons/JRRecorder.java +183 -0
- data/src/main/java/joons/JRStatics.java +199 -0
- data/src/main/java/joons/JoonsRenderer.java +837 -0
- data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
- data/src/main/java/org/sunflow/Benchmark.java +313 -0
- data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
- data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
- data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
- data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
- data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
- data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
- data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
- data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
- data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
- data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/Camera.java +125 -0
- data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
- data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
- data/src/main/java/org/sunflow/core/Display.java +78 -0
- data/src/main/java/org/sunflow/core/Filter.java +27 -0
- data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
- data/src/main/java/org/sunflow/core/Geometry.java +157 -0
- data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
- data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
- data/src/main/java/org/sunflow/core/Instance.java +224 -0
- data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
- data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
- data/src/main/java/org/sunflow/core/LightSample.java +104 -0
- data/src/main/java/org/sunflow/core/LightServer.java +382 -0
- data/src/main/java/org/sunflow/core/LightSource.java +67 -0
- data/src/main/java/org/sunflow/core/Modifier.java +16 -0
- data/src/main/java/org/sunflow/core/Options.java +20 -0
- data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
- data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
- data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
- data/src/main/java/org/sunflow/core/Ray.java +219 -0
- data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
- data/src/main/java/org/sunflow/core/Scene.java +377 -0
- data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
- data/src/main/java/org/sunflow/core/Shader.java +30 -0
- data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
- data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
- data/src/main/java/org/sunflow/core/Statistics.java +85 -0
- data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
- data/src/main/java/org/sunflow/core/Texture.java +128 -0
- data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
- data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
- data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
- data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
- data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
- data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
- data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
- data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
- data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
- data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
- data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
- data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
- data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
- data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
- data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
- data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
- data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
- data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
- data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
- data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
- data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
- data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
- data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
- data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
- data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
- data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
- data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
- data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
- data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
- data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
- data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
- data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
- data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
- data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
- data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
- data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
- data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
- data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
- data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
- data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
- data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
- data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
- data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
- data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
- data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
- data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
- data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
- data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
- data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
- data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
- data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
- data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
- data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
- data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
- data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
- data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
- data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
- data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
- data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
- data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
- data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
- data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
- data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
- data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
- data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
- data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
- data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
- data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
- data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
- data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
- data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
- data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
- data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
- data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
- data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
- data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
- data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
- data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
- data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
- data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
- data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
- data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
- data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
- data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
- data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
- data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
- data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
- data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
- data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
- data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
- data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
- data/src/main/java/org/sunflow/image/Color.java +374 -0
- data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
- data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
- data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
- data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
- data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
- data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
- data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
- data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
- data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
- data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
- data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
- data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
- data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
- data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
- data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
- data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
- data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
- data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
- data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
- data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
- data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
- data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
- data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
- data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
- data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
- data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
- data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
- data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
- data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
- data/src/main/java/org/sunflow/math/Point2.java +36 -0
- data/src/main/java/org/sunflow/math/Point3.java +133 -0
- data/src/main/java/org/sunflow/math/QMC.java +209 -0
- data/src/main/java/org/sunflow/math/Solvers.java +142 -0
- data/src/main/java/org/sunflow/math/Vector3.java +197 -0
- data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
- data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
- data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
- data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
- data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
- data/src/main/java/org/sunflow/system/Memory.java +18 -0
- data/src/main/java/org/sunflow/system/Parser.java +162 -0
- data/src/main/java/org/sunflow/system/Plugins.java +142 -0
- data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
- data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
- data/src/main/java/org/sunflow/system/Timer.java +53 -0
- data/src/main/java/org/sunflow/system/UI.java +112 -0
- data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
- data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
- data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
- data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
- data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
- data/src/main/java/org/sunflow/util/IntArray.java +77 -0
- data/src/test/java/a_maintest.java +129 -0
- metadata +300 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
package org.sunflow.core;
|
2
|
+
|
3
|
+
import org.sunflow.image.Color;
|
4
|
+
import org.sunflow.math.BoundingBox;
|
5
|
+
import org.sunflow.math.Vector3;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Describes an object which can store photons.
|
9
|
+
*/
|
10
|
+
public interface PhotonStore {
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Number of photons to emit from this surface.
|
14
|
+
*
|
15
|
+
* @return number of photons
|
16
|
+
*/
|
17
|
+
int numEmit();
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Initialize this object for the specified scene size.
|
21
|
+
*
|
22
|
+
* @param sceneBounds scene bounding box
|
23
|
+
*/
|
24
|
+
void prepare(Options options, BoundingBox sceneBounds);
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Store the specified photon.
|
28
|
+
*
|
29
|
+
* @param state shading state
|
30
|
+
* @param dir photon direction
|
31
|
+
* @param power photon power
|
32
|
+
* @param diffuse diffuse color at the hit point
|
33
|
+
*/
|
34
|
+
void store(ShadingState state, Vector3 dir, Color power, Color diffuse);
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Initialize the map after all photons have been stored. This can be used
|
38
|
+
* to balance a kd-tree based photon map for example.
|
39
|
+
*/
|
40
|
+
void init();
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Allow photons reflected diffusely?
|
44
|
+
*
|
45
|
+
* @return <code>true</code> if diffuse bounces should be traced
|
46
|
+
*/
|
47
|
+
boolean allowDiffuseBounced();
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Allow specularly reflected photons?
|
51
|
+
*
|
52
|
+
* @return <code>true</code> if specular reflection bounces should be traced
|
53
|
+
*/
|
54
|
+
boolean allowReflectionBounced();
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Allow refracted photons?
|
58
|
+
*
|
59
|
+
* @return <code>true</code> if refracted bounces should be traced
|
60
|
+
*/
|
61
|
+
boolean allowRefractionBounced();
|
62
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
package org.sunflow.core;
|
2
|
+
|
3
|
+
import org.sunflow.math.BoundingBox;
|
4
|
+
import org.sunflow.math.Matrix4;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* This class represents an object made up of many primitives.
|
8
|
+
*/
|
9
|
+
public interface PrimitiveList extends RenderObject {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Compute a bounding box of this object in world space, using the specified
|
13
|
+
* object-to-world transformation matrix. The bounds should be as exact as
|
14
|
+
* possible, if they are difficult or expensive to compute exactly, you may
|
15
|
+
* use {@link Matrix4#transform(BoundingBox)}. If the matrix is
|
16
|
+
* <code>null</code> no transformation is needed, and object space is
|
17
|
+
* equivalent to world space.
|
18
|
+
*
|
19
|
+
* @param o2w object to world transformation matrix
|
20
|
+
* @return object bounding box in world space
|
21
|
+
*/
|
22
|
+
public BoundingBox getWorldBounds(Matrix4 o2w);
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Returns the number of individual primtives in this aggregate object.
|
26
|
+
*
|
27
|
+
* @return number of primitives
|
28
|
+
*/
|
29
|
+
public int getNumPrimitives();
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Retrieve the bounding box component of a particular primitive in object
|
33
|
+
* space. Even indexes get minimum values, while odd indexes get the maximum
|
34
|
+
* values for each axis.
|
35
|
+
*
|
36
|
+
* @param primID primitive index
|
37
|
+
* @param i bounding box side index
|
38
|
+
* @return value of the request bound
|
39
|
+
*/
|
40
|
+
public float getPrimitiveBound(int primID, int i);
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Intersect the specified primitive in local space.
|
44
|
+
*
|
45
|
+
* @param r ray in the object's local space
|
46
|
+
* @param primID primitive index to intersect
|
47
|
+
* @param state intersection state
|
48
|
+
* @see Ray#setMax(float)
|
49
|
+
* @see IntersectionState#setIntersection(int, float, float)
|
50
|
+
*/
|
51
|
+
public void intersectPrimitive(Ray r, int primID, IntersectionState state);
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Prepare the specified {@link ShadingState} by setting all of its internal
|
55
|
+
* parameters.
|
56
|
+
*
|
57
|
+
* @param state shading state to fill in
|
58
|
+
*/
|
59
|
+
public void prepareShadingState(ShadingState state);
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Create a new {@link PrimitiveList} object suitable for baking lightmaps.
|
63
|
+
* This means a set of primitives laid out in the unit square UV space. This
|
64
|
+
* method is optional, objects which do not support it should simply return
|
65
|
+
* <code>null</code>.
|
66
|
+
*
|
67
|
+
* @return a list of baking primitives
|
68
|
+
*/
|
69
|
+
public PrimitiveList getBakingPrimitives();
|
70
|
+
}
|
@@ -0,0 +1,219 @@
|
|
1
|
+
package org.sunflow.core;
|
2
|
+
|
3
|
+
import org.sunflow.math.Matrix4;
|
4
|
+
import org.sunflow.math.Point3;
|
5
|
+
import org.sunflow.math.Vector3;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* This class represents a ray as a oriented half line segment. The ray
|
9
|
+
* direction is always normalized. The valid region is delimted by two distances
|
10
|
+
* along the ray, tMin and tMax.
|
11
|
+
*/
|
12
|
+
public final class Ray {
|
13
|
+
|
14
|
+
public float ox, oy, oz;
|
15
|
+
public float dx, dy, dz;
|
16
|
+
private float tMin;
|
17
|
+
private float tMax;
|
18
|
+
private static final float EPSILON = 0;// 0.01f;
|
19
|
+
|
20
|
+
private Ray() {
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Creates a new ray that points from the given origin to the given
|
25
|
+
* direction. The ray has infinite length. The direction vector is
|
26
|
+
* normalized.
|
27
|
+
*
|
28
|
+
* @param ox ray origin x
|
29
|
+
* @param oy ray origin y
|
30
|
+
* @param oz ray origin z
|
31
|
+
* @param dx ray direction x
|
32
|
+
* @param dy ray direction y
|
33
|
+
* @param dz ray direction z
|
34
|
+
*/
|
35
|
+
public Ray(float ox, float oy, float oz, float dx, float dy, float dz) {
|
36
|
+
this.ox = ox;
|
37
|
+
this.oy = oy;
|
38
|
+
this.oz = oz;
|
39
|
+
this.dx = dx;
|
40
|
+
this.dy = dy;
|
41
|
+
this.dz = dz;
|
42
|
+
float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
|
43
|
+
this.dx *= in;
|
44
|
+
this.dy *= in;
|
45
|
+
this.dz *= in;
|
46
|
+
tMin = EPSILON;
|
47
|
+
tMax = Float.POSITIVE_INFINITY;
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Creates a new ray that points from the given origin to the given
|
52
|
+
* direction. The ray has infinite length. The direction vector is
|
53
|
+
* normalized.
|
54
|
+
*
|
55
|
+
* @param o ray origin
|
56
|
+
* @param d ray direction (need not be normalized)
|
57
|
+
*/
|
58
|
+
public Ray(Point3 o, Vector3 d) {
|
59
|
+
ox = o.x;
|
60
|
+
oy = o.y;
|
61
|
+
oz = o.z;
|
62
|
+
dx = d.x;
|
63
|
+
dy = d.y;
|
64
|
+
dz = d.z;
|
65
|
+
float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
|
66
|
+
dx *= in;
|
67
|
+
dy *= in;
|
68
|
+
dz *= in;
|
69
|
+
tMin = EPSILON;
|
70
|
+
tMax = Float.POSITIVE_INFINITY;
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Creates a new ray that points from point a to point b. The created ray
|
75
|
+
* will set tMin and tMax to limit the ray to the segment (a,b)
|
76
|
+
* (non-inclusive of a and b). This is often used to create shadow rays.
|
77
|
+
*
|
78
|
+
* @param a start point
|
79
|
+
* @param b end point
|
80
|
+
*/
|
81
|
+
public Ray(Point3 a, Point3 b) {
|
82
|
+
ox = a.x;
|
83
|
+
oy = a.y;
|
84
|
+
oz = a.z;
|
85
|
+
dx = b.x - ox;
|
86
|
+
dy = b.y - oy;
|
87
|
+
dz = b.z - oz;
|
88
|
+
tMin = EPSILON;
|
89
|
+
float n = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
|
90
|
+
float in = 1.0f / n;
|
91
|
+
dx *= in;
|
92
|
+
dy *= in;
|
93
|
+
dz *= in;
|
94
|
+
tMax = n - EPSILON;
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Create a new ray by transforming the supplied one by the given matrix. If
|
99
|
+
* the matrix is
|
100
|
+
* <code>null</code>, the original ray is returned.
|
101
|
+
*
|
102
|
+
* @param m matrix to transform the ray by
|
103
|
+
*/
|
104
|
+
public Ray transform(Matrix4 m) {
|
105
|
+
if (m == null) {
|
106
|
+
return this;
|
107
|
+
}
|
108
|
+
Ray r = new Ray();
|
109
|
+
r.ox = m.transformPX(ox, oy, oz);
|
110
|
+
r.oy = m.transformPY(ox, oy, oz);
|
111
|
+
r.oz = m.transformPZ(ox, oy, oz);
|
112
|
+
r.dx = m.transformVX(dx, dy, dz);
|
113
|
+
r.dy = m.transformVY(dx, dy, dz);
|
114
|
+
r.dz = m.transformVZ(dx, dy, dz);
|
115
|
+
r.tMin = tMin;
|
116
|
+
r.tMax = tMax;
|
117
|
+
return r;
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Normalize the direction component of the ray.
|
122
|
+
*/
|
123
|
+
public void normalize() {
|
124
|
+
float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
|
125
|
+
dx *= in;
|
126
|
+
dy *= in;
|
127
|
+
dz *= in;
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Gets the minimum distance along the ray - usually 0.
|
132
|
+
*
|
133
|
+
* @return value of the smallest distance along the ray
|
134
|
+
*/
|
135
|
+
public final float getMin() {
|
136
|
+
return tMin;
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Gets the maximum distance along the ray. May be infinite.
|
141
|
+
*
|
142
|
+
* @return value of the largest distance along the ray
|
143
|
+
*/
|
144
|
+
public final float getMax() {
|
145
|
+
return tMax;
|
146
|
+
}
|
147
|
+
|
148
|
+
/**
|
149
|
+
* Creates a vector to represent the direction of the ray.
|
150
|
+
*
|
151
|
+
* @return a vector equal to the direction of this ray
|
152
|
+
*/
|
153
|
+
public final Vector3 getDirection() {
|
154
|
+
return new Vector3(dx, dy, dz);
|
155
|
+
}
|
156
|
+
|
157
|
+
/**
|
158
|
+
* Checks to see if the specified distance falls within the valid range on
|
159
|
+
* this ray. This should always be used before an intersection with the ray
|
160
|
+
* is detected.
|
161
|
+
*
|
162
|
+
* @param t distance to be tested
|
163
|
+
* @return <code>true</code> if t falls between the minimum and maximum
|
164
|
+
* distance of this ray, <code>false</code> otherwise
|
165
|
+
*/
|
166
|
+
public final boolean isInside(float t) {
|
167
|
+
return (tMin < t) && (t < tMax);
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Gets the end point of the ray. A reference to
|
172
|
+
* <code>dest</code> is returned to support chaining.
|
173
|
+
*
|
174
|
+
* @param dest reference to the point to store
|
175
|
+
* @return reference to <code>dest</code>
|
176
|
+
*/
|
177
|
+
public final Point3 getPoint(Point3 dest) {
|
178
|
+
dest.x = ox + (tMax * dx);
|
179
|
+
dest.y = oy + (tMax * dy);
|
180
|
+
dest.z = oz + (tMax * dz);
|
181
|
+
return dest;
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* Computes the dot product of an arbitrary vector with the direction of the
|
186
|
+
* ray. This method avoids having to call getDirection() which would
|
187
|
+
* instantiate a new Vector object.
|
188
|
+
*
|
189
|
+
* @param v vector
|
190
|
+
* @return dot product of the ray direction and the specified vector
|
191
|
+
*/
|
192
|
+
public final float dot(Vector3 v) {
|
193
|
+
return dx * v.x + dy * v.y + dz * v.z;
|
194
|
+
}
|
195
|
+
|
196
|
+
/**
|
197
|
+
* Computes the dot product of an arbitrary vector with the direction of the
|
198
|
+
* ray. This method avoids having to call getDirection() which would
|
199
|
+
* instantiate a new Vector object.
|
200
|
+
*
|
201
|
+
* @param vx vector x coordinate
|
202
|
+
* @param vy vector y coordinate
|
203
|
+
* @param vz vector z coordinate
|
204
|
+
* @return dot product of the ray direction and the specified vector
|
205
|
+
*/
|
206
|
+
public final float dot(float vx, float vy, float vz) {
|
207
|
+
return dx * vx + dy * vy + dz * vz;
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Updates the maximum to the specified distance if and only if the new
|
212
|
+
* distance is smaller than the current one.
|
213
|
+
*
|
214
|
+
* @param t new maximum distance
|
215
|
+
*/
|
216
|
+
public final void setMax(float t) {
|
217
|
+
tMax = t;
|
218
|
+
}
|
219
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
package org.sunflow.core;
|
2
|
+
|
3
|
+
import org.sunflow.SunflowAPI;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* This is the base interface for all public rendering object interfaces. It
|
7
|
+
* handles incremental updates via {@link ParameterList} objects.
|
8
|
+
*/
|
9
|
+
public interface RenderObject {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Update this object given a list of parameters. This method is guarenteed
|
13
|
+
* to be called at least once on every object, but it should correctly
|
14
|
+
* handle empty parameter lists. This means that the object should be in a
|
15
|
+
* valid state from the time it is constructed. This method should also
|
16
|
+
* return true or false depending on whether the update was succesfull or
|
17
|
+
* not.
|
18
|
+
*
|
19
|
+
* @param pl list of parameters to read from
|
20
|
+
* @param api reference to the current scene
|
21
|
+
* @return <code>true</code> if the update is succesfull, <code>false</code>
|
22
|
+
* otherwise
|
23
|
+
*/
|
24
|
+
public boolean update(ParameterList pl, SunflowAPI api);
|
25
|
+
}
|
@@ -0,0 +1,377 @@
|
|
1
|
+
package org.sunflow.core;
|
2
|
+
|
3
|
+
import java.util.ArrayList;
|
4
|
+
|
5
|
+
import org.sunflow.core.display.FrameDisplay;
|
6
|
+
import org.sunflow.image.Color;
|
7
|
+
import org.sunflow.math.BoundingBox;
|
8
|
+
import org.sunflow.math.MathUtils;
|
9
|
+
import org.sunflow.math.Point3;
|
10
|
+
import org.sunflow.math.Vector3;
|
11
|
+
import org.sunflow.system.UI;
|
12
|
+
import org.sunflow.system.UI.Module;
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Represents a entire scene, defined as a collection of instances viewed by a
|
16
|
+
* camera.
|
17
|
+
*/
|
18
|
+
public class Scene {
|
19
|
+
// scene storage
|
20
|
+
|
21
|
+
private LightServer lightServer;
|
22
|
+
private InstanceList instanceList;
|
23
|
+
private InstanceList infiniteInstanceList;
|
24
|
+
private Camera camera;
|
25
|
+
private AccelerationStructure intAccel;
|
26
|
+
private String acceltype;
|
27
|
+
private Statistics stats;
|
28
|
+
// baking
|
29
|
+
private boolean bakingViewDependent;
|
30
|
+
private Instance bakingInstance;
|
31
|
+
private PrimitiveList bakingPrimitives;
|
32
|
+
private AccelerationStructure bakingAccel;
|
33
|
+
private boolean rebuildAccel;
|
34
|
+
// image size
|
35
|
+
private int imageWidth;
|
36
|
+
private int imageHeight;
|
37
|
+
// global options
|
38
|
+
private int threads;
|
39
|
+
private boolean lowPriority;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Creates an empty scene.
|
43
|
+
*/
|
44
|
+
public Scene() {
|
45
|
+
lightServer = new LightServer(this);
|
46
|
+
instanceList = new InstanceList();
|
47
|
+
infiniteInstanceList = new InstanceList();
|
48
|
+
acceltype = "auto";
|
49
|
+
stats = new Statistics();
|
50
|
+
|
51
|
+
bakingViewDependent = false;
|
52
|
+
bakingInstance = null;
|
53
|
+
bakingPrimitives = null;
|
54
|
+
bakingAccel = null;
|
55
|
+
|
56
|
+
camera = null;
|
57
|
+
imageWidth = 640;
|
58
|
+
imageHeight = 480;
|
59
|
+
threads = 0;
|
60
|
+
lowPriority = true;
|
61
|
+
|
62
|
+
rebuildAccel = true;
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Get number of allowed threads for multi-threaded operations.
|
67
|
+
*
|
68
|
+
* @return number of threads that can be started
|
69
|
+
*/
|
70
|
+
public int getThreads() {
|
71
|
+
return threads <= 0 ? Runtime.getRuntime().availableProcessors() : threads;
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Get the priority level to assign to multi-threaded operations.
|
76
|
+
*
|
77
|
+
* @return thread priority
|
78
|
+
*/
|
79
|
+
public int getThreadPriority() {
|
80
|
+
return lowPriority ? Thread.MIN_PRIORITY : Thread.NORM_PRIORITY;
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Sets the current camera (no support for multiple cameras yet).
|
85
|
+
*
|
86
|
+
* @param camera camera to be used as the viewpoint for the scene
|
87
|
+
*/
|
88
|
+
public void setCamera(Camera camera) {
|
89
|
+
this.camera = camera;
|
90
|
+
}
|
91
|
+
|
92
|
+
Camera getCamera() {
|
93
|
+
return camera;
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Update the instance lists for this scene.
|
98
|
+
*
|
99
|
+
* @param instances regular instances
|
100
|
+
* @param infinite infinite instances (no bounds)
|
101
|
+
*/
|
102
|
+
public void setInstanceLists(Instance[] instances, Instance[] infinite) {
|
103
|
+
infiniteInstanceList = new InstanceList(infinite);
|
104
|
+
instanceList = new InstanceList(instances);
|
105
|
+
rebuildAccel = true;
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Update the light list for this scene.
|
110
|
+
*
|
111
|
+
* @param lights array of light source objects
|
112
|
+
*/
|
113
|
+
public void setLightList(LightSource[] lights) {
|
114
|
+
lightServer.setLights(lights);
|
115
|
+
}
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Enables shader overiding (set null to disable). The specified shader will
|
119
|
+
* be used to shade all surfaces
|
120
|
+
*
|
121
|
+
* @param shader shader to run over all surfaces, or <code>null</code> to
|
122
|
+
* disable overriding
|
123
|
+
* @param photonOverride <code>true</code> to override photon scattering
|
124
|
+
* with this shader or <code>false</code> to run the regular shaders
|
125
|
+
*/
|
126
|
+
public void setShaderOverride(Shader shader, boolean photonOverride) {
|
127
|
+
lightServer.setShaderOverride(shader, photonOverride);
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* The provided instance will be considered for lightmap baking. If the
|
132
|
+
* specified instance is
|
133
|
+
* <code>null</code>, lightmap baking will be disabled and normal rendering
|
134
|
+
* will occur.
|
135
|
+
*
|
136
|
+
* @param instance instance to bake
|
137
|
+
*/
|
138
|
+
public void setBakingInstance(Instance instance) {
|
139
|
+
bakingInstance = instance;
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Get the radiance seen through a particular pixel
|
144
|
+
*
|
145
|
+
* @param istate intersection state for ray tracing
|
146
|
+
* @param rx pixel x coordinate
|
147
|
+
* @param ry pixel y coordinate
|
148
|
+
* @param lensU DOF sampling variable
|
149
|
+
* @param lensV DOF sampling variable
|
150
|
+
* @param time motion blur sampling variable
|
151
|
+
* @param instance QMC instance seed
|
152
|
+
* @return a shading state for the intersected primitive, or
|
153
|
+
* <code>null</code> if nothing is seen through the specifieFd point
|
154
|
+
*/
|
155
|
+
public ShadingState getRadiance(IntersectionState istate, float rx, float ry, double lensU, double lensV, double time, int instance, int dim, ShadingCache cache) {
|
156
|
+
istate.numEyeRays++;
|
157
|
+
float sceneTime = camera.getTime((float) time);
|
158
|
+
if (bakingPrimitives == null) {
|
159
|
+
Ray r = camera.getRay(rx, ry, imageWidth, imageHeight, lensU, lensV, sceneTime);
|
160
|
+
return r != null ? lightServer.getRadiance(rx, ry, sceneTime, instance, dim, r, istate, cache) : null;
|
161
|
+
} else {
|
162
|
+
Ray r = new Ray(rx / imageWidth, ry / imageHeight, -1, 0, 0, 1);
|
163
|
+
traceBake(r, istate);
|
164
|
+
if (!istate.hit()) {
|
165
|
+
return null;
|
166
|
+
}
|
167
|
+
ShadingState state = ShadingState.createState(istate, rx, ry, sceneTime, r, instance, dim, lightServer);
|
168
|
+
bakingPrimitives.prepareShadingState(state);
|
169
|
+
if (bakingViewDependent) {
|
170
|
+
state.setRay(camera.getRay(state.getPoint(), sceneTime));
|
171
|
+
} else {
|
172
|
+
Point3 p = state.getPoint();
|
173
|
+
Vector3 n = state.getNormal();
|
174
|
+
// create a ray coming from directly above the point being
|
175
|
+
// shaded
|
176
|
+
Ray incoming = new Ray(p.x + n.x, p.y + n.y, p.z + n.z, -n.x, -n.y, -n.z);
|
177
|
+
incoming.setMax(1);
|
178
|
+
state.setRay(incoming);
|
179
|
+
}
|
180
|
+
lightServer.shadeBakeResult(state);
|
181
|
+
return state;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Get scene world space bounding box.
|
187
|
+
*
|
188
|
+
* @return scene bounding box
|
189
|
+
*/
|
190
|
+
public BoundingBox getBounds() {
|
191
|
+
return instanceList.getWorldBounds(null);
|
192
|
+
}
|
193
|
+
|
194
|
+
public void accumulateStats(IntersectionState state) {
|
195
|
+
stats.accumulate(state);
|
196
|
+
}
|
197
|
+
|
198
|
+
public void accumulateStats(ShadingCache cache) {
|
199
|
+
stats.accumulate(cache);
|
200
|
+
}
|
201
|
+
|
202
|
+
void trace(Ray r, IntersectionState state) {
|
203
|
+
// stats
|
204
|
+
state.numRays++;
|
205
|
+
// reset object
|
206
|
+
state.instance = null;
|
207
|
+
state.current = null;
|
208
|
+
for (int i = 0; i < infiniteInstanceList.getNumPrimitives(); i++) {
|
209
|
+
infiniteInstanceList.intersectPrimitive(r, i, state);
|
210
|
+
}
|
211
|
+
// reset for next accel structure
|
212
|
+
state.current = null;
|
213
|
+
intAccel.intersect(r, state);
|
214
|
+
}
|
215
|
+
|
216
|
+
Color traceShadow(Ray r, IntersectionState state) {
|
217
|
+
state.numShadowRays++;
|
218
|
+
trace(r, state);
|
219
|
+
return state.hit() ? Color.WHITE : Color.BLACK;
|
220
|
+
}
|
221
|
+
|
222
|
+
void traceBake(Ray r, IntersectionState state) {
|
223
|
+
// set the instance as if tracing a regular instanced object
|
224
|
+
state.current = bakingInstance;
|
225
|
+
// reset object
|
226
|
+
state.instance = null;
|
227
|
+
bakingAccel.intersect(r, state);
|
228
|
+
}
|
229
|
+
|
230
|
+
private void createAreaLightInstances() {
|
231
|
+
ArrayList<Instance> infiniteAreaLights = null;
|
232
|
+
ArrayList<Instance> areaLights = null;
|
233
|
+
// create an area light instance from each light source if possible
|
234
|
+
for (LightSource l : lightServer.lights) {
|
235
|
+
Instance lightInstance = l.createInstance();
|
236
|
+
if (lightInstance != null) {
|
237
|
+
if (lightInstance.getBounds() == null) {
|
238
|
+
if (infiniteAreaLights == null) {
|
239
|
+
infiniteAreaLights = new ArrayList<Instance>();
|
240
|
+
}
|
241
|
+
infiniteAreaLights.add(lightInstance);
|
242
|
+
} else {
|
243
|
+
if (areaLights == null) {
|
244
|
+
areaLights = new ArrayList<Instance>();
|
245
|
+
}
|
246
|
+
areaLights.add(lightInstance);
|
247
|
+
}
|
248
|
+
}
|
249
|
+
}
|
250
|
+
// add area light sources to the list of instances if they exist
|
251
|
+
if (infiniteAreaLights != null && infiniteAreaLights.size() > 0) {
|
252
|
+
infiniteInstanceList.addLightSourceInstances(infiniteAreaLights.toArray(new Instance[infiniteAreaLights.size()]));
|
253
|
+
} else {
|
254
|
+
infiniteInstanceList.clearLightSources();
|
255
|
+
}
|
256
|
+
if (areaLights != null && areaLights.size() > 0) {
|
257
|
+
instanceList.addLightSourceInstances(areaLights.toArray(new Instance[areaLights.size()]));
|
258
|
+
} else {
|
259
|
+
instanceList.clearLightSources();
|
260
|
+
}
|
261
|
+
// FIXME: this _could_ be done incrementally to avoid top-level rebuilds
|
262
|
+
// each frame
|
263
|
+
rebuildAccel = true;
|
264
|
+
}
|
265
|
+
|
266
|
+
private void removeAreaLightInstances() {
|
267
|
+
infiniteInstanceList.clearLightSources();
|
268
|
+
instanceList.clearLightSources();
|
269
|
+
}
|
270
|
+
|
271
|
+
/**
|
272
|
+
* Render the scene using the specified options, image sampler and display.
|
273
|
+
*
|
274
|
+
* @param options rendering options object
|
275
|
+
* @param sampler image sampler
|
276
|
+
* @param display display to send the final image to, a default display will
|
277
|
+
* be created if <code>null</code>
|
278
|
+
*/
|
279
|
+
public void render(Options options, ImageSampler sampler, Display display) {
|
280
|
+
stats.reset();
|
281
|
+
if (display == null) {
|
282
|
+
display = new FrameDisplay();
|
283
|
+
}
|
284
|
+
|
285
|
+
if (bakingInstance != null) {
|
286
|
+
UI.printDetailed(Module.SCENE, "Creating primitives for lightmapping ...");
|
287
|
+
bakingPrimitives = bakingInstance.getBakingPrimitives();
|
288
|
+
if (bakingPrimitives == null) {
|
289
|
+
UI.printError(Module.SCENE, "Lightmap baking is not supported for the given instance.");
|
290
|
+
return;
|
291
|
+
}
|
292
|
+
int n = bakingPrimitives.getNumPrimitives();
|
293
|
+
UI.printInfo(Module.SCENE, "Building acceleration structure for lightmapping (%d num primitives) ...", n);
|
294
|
+
bakingAccel = AccelerationStructureFactory.create("auto", n, true);
|
295
|
+
bakingAccel.build(bakingPrimitives);
|
296
|
+
} else {
|
297
|
+
bakingPrimitives = null;
|
298
|
+
bakingAccel = null;
|
299
|
+
}
|
300
|
+
bakingViewDependent = options.getBoolean("baking.viewdep", bakingViewDependent);
|
301
|
+
|
302
|
+
if ((bakingInstance != null && bakingViewDependent && camera == null) || (bakingInstance == null && camera == null)) {
|
303
|
+
UI.printError(Module.SCENE, "No camera found");
|
304
|
+
return;
|
305
|
+
}
|
306
|
+
|
307
|
+
// read from options
|
308
|
+
threads = options.getInt("threads", 0);
|
309
|
+
lowPriority = options.getBoolean("threads.lowPriority", true);
|
310
|
+
imageWidth = options.getInt("resolutionX", 640);
|
311
|
+
imageHeight = options.getInt("resolutionY", 480);
|
312
|
+
// limit resolution to 16k
|
313
|
+
imageWidth = MathUtils.clamp(imageWidth, 1, 1 << 14);
|
314
|
+
imageHeight = MathUtils.clamp(imageHeight, 1, 1 << 14);
|
315
|
+
|
316
|
+
// prepare lights
|
317
|
+
createAreaLightInstances();
|
318
|
+
|
319
|
+
// get acceleration structure info
|
320
|
+
// count scene primitives
|
321
|
+
long numPrimitives = 0;
|
322
|
+
for (int i = 0; i < instanceList.getNumPrimitives(); i++) {
|
323
|
+
numPrimitives += instanceList.getNumPrimitives(i);
|
324
|
+
}
|
325
|
+
UI.printInfo(Module.SCENE, "Scene stats:");
|
326
|
+
UI.printInfo(Module.SCENE, " * Infinite instances: %d", infiniteInstanceList.getNumPrimitives());
|
327
|
+
UI.printInfo(Module.SCENE, " * Instances: %d", instanceList.getNumPrimitives());
|
328
|
+
UI.printInfo(Module.SCENE, " * Primitives: %d", numPrimitives);
|
329
|
+
String accelName = options.getString("accel", null);
|
330
|
+
if (accelName != null) {
|
331
|
+
rebuildAccel = rebuildAccel || !acceltype.equals(accelName);
|
332
|
+
acceltype = accelName;
|
333
|
+
}
|
334
|
+
UI.printInfo(Module.SCENE, " * Instance accel: %s", acceltype);
|
335
|
+
if (rebuildAccel) {
|
336
|
+
intAccel = AccelerationStructureFactory.create(acceltype, instanceList.getNumPrimitives(), false);
|
337
|
+
intAccel.build(instanceList);
|
338
|
+
rebuildAccel = false;
|
339
|
+
}
|
340
|
+
UI.printInfo(Module.SCENE, " * Scene bounds: %s", getBounds());
|
341
|
+
UI.printInfo(Module.SCENE, " * Scene center: %s", getBounds().getCenter());
|
342
|
+
UI.printInfo(Module.SCENE, " * Scene diameter: %.2f", getBounds().getExtents().length());
|
343
|
+
UI.printInfo(Module.SCENE, " * Lightmap bake: %s", bakingInstance != null ? (bakingViewDependent ? "view" : "ortho") : "off");
|
344
|
+
if (sampler == null) {
|
345
|
+
return;
|
346
|
+
}
|
347
|
+
if (!lightServer.build(options)) {
|
348
|
+
return;
|
349
|
+
}
|
350
|
+
// render
|
351
|
+
UI.printInfo(Module.SCENE, "Rendering ...");
|
352
|
+
stats.setResolution(imageWidth, imageHeight);
|
353
|
+
sampler.prepare(options, this, imageWidth, imageHeight);
|
354
|
+
sampler.render(display);
|
355
|
+
// show statistics
|
356
|
+
stats.displayStats();
|
357
|
+
lightServer.showStats();
|
358
|
+
// discard area lights
|
359
|
+
removeAreaLightInstances();
|
360
|
+
// discard baking tesselation/accel structure
|
361
|
+
bakingPrimitives = null;
|
362
|
+
bakingAccel = null;
|
363
|
+
UI.printInfo(Module.SCENE, "Done.");
|
364
|
+
}
|
365
|
+
|
366
|
+
/**
|
367
|
+
* Create a photon map as prescribed by the given {@link PhotonStore}.
|
368
|
+
*
|
369
|
+
* @param map object that will recieve shot photons
|
370
|
+
* @param type type of photons being shot
|
371
|
+
* @param seed QMC seed parameter
|
372
|
+
* @return <code>true</code> upon success
|
373
|
+
*/
|
374
|
+
public boolean calculatePhotons(PhotonStore map, String type, int seed, Options options) {
|
375
|
+
return lightServer.calculatePhotons(map, type, seed, options);
|
376
|
+
}
|
377
|
+
}
|