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