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,318 @@
|
|
|
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.ParameterList;
|
|
7
|
+
import org.sunflow.core.PrimitiveList;
|
|
8
|
+
import org.sunflow.core.Ray;
|
|
9
|
+
import org.sunflow.core.ShadingState;
|
|
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 abstract class CubeGrid implements PrimitiveList {
|
|
16
|
+
|
|
17
|
+
private int nx, ny, nz;
|
|
18
|
+
private float voxelwx, voxelwy, voxelwz;
|
|
19
|
+
private float invVoxelwx, invVoxelwy, invVoxelwz;
|
|
20
|
+
private final BoundingBox bounds;
|
|
21
|
+
|
|
22
|
+
public CubeGrid() {
|
|
23
|
+
nx = ny = nz = 1;
|
|
24
|
+
bounds = new BoundingBox(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Override
|
|
28
|
+
public boolean update(ParameterList pl, SunflowAPI api) {
|
|
29
|
+
nx = pl.getInt("resolutionX", nx);
|
|
30
|
+
ny = pl.getInt("resolutionY", ny);
|
|
31
|
+
nz = pl.getInt("resolutionZ", nz);
|
|
32
|
+
voxelwx = 2.0f / nx;
|
|
33
|
+
voxelwy = 2.0f / ny;
|
|
34
|
+
voxelwz = 2.0f / nz;
|
|
35
|
+
invVoxelwx = 1 / voxelwx;
|
|
36
|
+
invVoxelwy = 1 / voxelwy;
|
|
37
|
+
invVoxelwz = 1 / voxelwz;
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected abstract boolean inside(int x, int y, int z);
|
|
42
|
+
|
|
43
|
+
public BoundingBox getBounds() {
|
|
44
|
+
return bounds;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Override
|
|
48
|
+
public void prepareShadingState(ShadingState state) {
|
|
49
|
+
state.init();
|
|
50
|
+
state.getRay().getPoint(state.getPoint());
|
|
51
|
+
Instance parent = state.getInstance();
|
|
52
|
+
Vector3 normal;
|
|
53
|
+
switch (state.getPrimitiveID()) {
|
|
54
|
+
case 0:
|
|
55
|
+
normal = new Vector3(-1, 0, 0);
|
|
56
|
+
break;
|
|
57
|
+
case 1:
|
|
58
|
+
normal = new Vector3(1, 0, 0);
|
|
59
|
+
break;
|
|
60
|
+
case 2:
|
|
61
|
+
normal = new Vector3(0, -1, 0);
|
|
62
|
+
break;
|
|
63
|
+
case 3:
|
|
64
|
+
normal = new Vector3(0, 1, 0);
|
|
65
|
+
break;
|
|
66
|
+
case 4:
|
|
67
|
+
normal = new Vector3(0, 0, -1);
|
|
68
|
+
break;
|
|
69
|
+
case 5:
|
|
70
|
+
normal = new Vector3(0, 0, 1);
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
normal = new Vector3(0, 0, 0);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
state.getNormal().set(state.transformNormalObjectToWorld(normal));
|
|
77
|
+
state.getGeoNormal().set(state.getNormal());
|
|
78
|
+
state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
|
|
79
|
+
state.setShader(parent.getShader(0));
|
|
80
|
+
state.setModifier(parent.getModifier(0));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Override
|
|
84
|
+
public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
|
|
85
|
+
float intervalMin = r.getMin();
|
|
86
|
+
float intervalMax = r.getMax();
|
|
87
|
+
float orgX = r.ox;
|
|
88
|
+
float orgY = r.oy;
|
|
89
|
+
float orgZ = r.oz;
|
|
90
|
+
float dirX = r.dx, invDirX = 1 / dirX;
|
|
91
|
+
float dirY = r.dy, invDirY = 1 / dirY;
|
|
92
|
+
float dirZ = r.dz, invDirZ = 1 / dirZ;
|
|
93
|
+
float t1, t2;
|
|
94
|
+
t1 = (-1 - orgX) * invDirX;
|
|
95
|
+
t2 = (+1 - orgX) * invDirX;
|
|
96
|
+
int curr = -1;
|
|
97
|
+
if (invDirX > 0) {
|
|
98
|
+
if (t1 > intervalMin) {
|
|
99
|
+
intervalMin = t1;
|
|
100
|
+
curr = 0;
|
|
101
|
+
}
|
|
102
|
+
if (t2 < intervalMax) {
|
|
103
|
+
intervalMax = t2;
|
|
104
|
+
}
|
|
105
|
+
if (intervalMin > intervalMax) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
if (t2 > intervalMin) {
|
|
110
|
+
intervalMin = t2;
|
|
111
|
+
curr = 1;
|
|
112
|
+
}
|
|
113
|
+
if (t1 < intervalMax) {
|
|
114
|
+
intervalMax = t1;
|
|
115
|
+
}
|
|
116
|
+
if (intervalMin > intervalMax) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
t1 = (-1 - orgY) * invDirY;
|
|
121
|
+
t2 = (+1 - orgY) * invDirY;
|
|
122
|
+
if (invDirY > 0) {
|
|
123
|
+
if (t1 > intervalMin) {
|
|
124
|
+
intervalMin = t1;
|
|
125
|
+
curr = 2;
|
|
126
|
+
}
|
|
127
|
+
if (t2 < intervalMax) {
|
|
128
|
+
intervalMax = t2;
|
|
129
|
+
}
|
|
130
|
+
if (intervalMin > intervalMax) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
if (t2 > intervalMin) {
|
|
135
|
+
intervalMin = t2;
|
|
136
|
+
curr = 3;
|
|
137
|
+
}
|
|
138
|
+
if (t1 < intervalMax) {
|
|
139
|
+
intervalMax = t1;
|
|
140
|
+
}
|
|
141
|
+
if (intervalMin > intervalMax) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
t1 = (-1 - orgZ) * invDirZ;
|
|
146
|
+
t2 = (+1 - orgZ) * invDirZ;
|
|
147
|
+
if (invDirZ > 0) {
|
|
148
|
+
if (t1 > intervalMin) {
|
|
149
|
+
intervalMin = t1;
|
|
150
|
+
curr = 4;
|
|
151
|
+
}
|
|
152
|
+
if (t2 < intervalMax) {
|
|
153
|
+
intervalMax = t2;
|
|
154
|
+
}
|
|
155
|
+
if (intervalMin > intervalMax) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
if (t2 > intervalMin) {
|
|
160
|
+
intervalMin = t2;
|
|
161
|
+
curr = 5;
|
|
162
|
+
}
|
|
163
|
+
if (t1 < intervalMax) {
|
|
164
|
+
intervalMax = t1;
|
|
165
|
+
}
|
|
166
|
+
if (intervalMin > intervalMax) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// box is hit at [intervalMin, intervalMax]
|
|
171
|
+
orgX += intervalMin * dirX;
|
|
172
|
+
orgY += intervalMin * dirY;
|
|
173
|
+
orgZ += intervalMin * dirZ;
|
|
174
|
+
// locate starting point inside the grid
|
|
175
|
+
// and set up 3D-DDA vars
|
|
176
|
+
int indxX, indxY, indxZ;
|
|
177
|
+
int stepX, stepY, stepZ;
|
|
178
|
+
int stopX, stopY, stopZ;
|
|
179
|
+
float deltaX, deltaY, deltaZ;
|
|
180
|
+
float tnextX, tnextY, tnextZ;
|
|
181
|
+
// stepping factors along X
|
|
182
|
+
indxX = (int) ((orgX + 1) * invVoxelwx);
|
|
183
|
+
if (indxX < 0) {
|
|
184
|
+
indxX = 0;
|
|
185
|
+
} else if (indxX >= nx) {
|
|
186
|
+
indxX = nx - 1;
|
|
187
|
+
}
|
|
188
|
+
if (Math.abs(dirX) < 1e-6f) {
|
|
189
|
+
stepX = 0;
|
|
190
|
+
stopX = indxX;
|
|
191
|
+
deltaX = 0;
|
|
192
|
+
tnextX = Float.POSITIVE_INFINITY;
|
|
193
|
+
} else if (dirX > 0) {
|
|
194
|
+
stepX = 1;
|
|
195
|
+
stopX = nx;
|
|
196
|
+
deltaX = voxelwx * invDirX;
|
|
197
|
+
tnextX = intervalMin + ((indxX + 1) * voxelwx - 1 - orgX) * invDirX;
|
|
198
|
+
} else {
|
|
199
|
+
stepX = -1;
|
|
200
|
+
stopX = -1;
|
|
201
|
+
deltaX = -voxelwx * invDirX;
|
|
202
|
+
tnextX = intervalMin + (indxX * voxelwx - 1 - orgX) * invDirX;
|
|
203
|
+
}
|
|
204
|
+
// stepping factors along Y
|
|
205
|
+
indxY = (int) ((orgY + 1) * invVoxelwy);
|
|
206
|
+
if (indxY < 0) {
|
|
207
|
+
indxY = 0;
|
|
208
|
+
} else if (indxY >= ny) {
|
|
209
|
+
indxY = ny - 1;
|
|
210
|
+
}
|
|
211
|
+
if (Math.abs(dirY) < 1e-6f) {
|
|
212
|
+
stepY = 0;
|
|
213
|
+
stopY = indxY;
|
|
214
|
+
deltaY = 0;
|
|
215
|
+
tnextY = Float.POSITIVE_INFINITY;
|
|
216
|
+
} else if (dirY > 0) {
|
|
217
|
+
stepY = 1;
|
|
218
|
+
stopY = ny;
|
|
219
|
+
deltaY = voxelwy * invDirY;
|
|
220
|
+
tnextY = intervalMin + ((indxY + 1) * voxelwy - 1 - orgY) * invDirY;
|
|
221
|
+
} else {
|
|
222
|
+
stepY = -1;
|
|
223
|
+
stopY = -1;
|
|
224
|
+
deltaY = -voxelwy * invDirY;
|
|
225
|
+
tnextY = intervalMin + (indxY * voxelwy - 1 - orgY) * invDirY;
|
|
226
|
+
}
|
|
227
|
+
// stepping factors along Z
|
|
228
|
+
indxZ = (int) ((orgZ + 1) * invVoxelwz);
|
|
229
|
+
if (indxZ < 0) {
|
|
230
|
+
indxZ = 0;
|
|
231
|
+
} else if (indxZ >= nz) {
|
|
232
|
+
indxZ = nz - 1;
|
|
233
|
+
}
|
|
234
|
+
if (Math.abs(dirZ) < 1e-6f) {
|
|
235
|
+
stepZ = 0;
|
|
236
|
+
stopZ = indxZ;
|
|
237
|
+
deltaZ = 0;
|
|
238
|
+
tnextZ = Float.POSITIVE_INFINITY;
|
|
239
|
+
} else if (dirZ > 0) {
|
|
240
|
+
stepZ = 1;
|
|
241
|
+
stopZ = nz;
|
|
242
|
+
deltaZ = voxelwz * invDirZ;
|
|
243
|
+
tnextZ = intervalMin + ((indxZ + 1) * voxelwz - 1 - orgZ) * invDirZ;
|
|
244
|
+
} else {
|
|
245
|
+
stepZ = -1;
|
|
246
|
+
stopZ = -1;
|
|
247
|
+
deltaZ = -voxelwz * invDirZ;
|
|
248
|
+
tnextZ = intervalMin + (indxZ * voxelwz - 1 - orgZ) * invDirZ;
|
|
249
|
+
}
|
|
250
|
+
// are we starting inside the cube
|
|
251
|
+
boolean isInside = inside(indxX, indxY, indxZ) && bounds.contains(r.ox, r.oy, r.oz);
|
|
252
|
+
// trace through the grid
|
|
253
|
+
for (;;) {
|
|
254
|
+
if (inside(indxX, indxY, indxZ) != isInside) {
|
|
255
|
+
// we hit a boundary
|
|
256
|
+
r.setMax(intervalMin);
|
|
257
|
+
// if we are inside, the last bit needs to be flipped
|
|
258
|
+
if (isInside) {
|
|
259
|
+
curr ^= 1;
|
|
260
|
+
}
|
|
261
|
+
state.setIntersection(curr);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (tnextX < tnextY && tnextX < tnextZ) {
|
|
265
|
+
curr = dirX > 0 ? 0 : 1;
|
|
266
|
+
intervalMin = tnextX;
|
|
267
|
+
if (intervalMin > intervalMax) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
indxX += stepX;
|
|
271
|
+
if (indxX == stopX) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
tnextX += deltaX;
|
|
275
|
+
} else if (tnextY < tnextZ) {
|
|
276
|
+
curr = dirY > 0 ? 2 : 3;
|
|
277
|
+
intervalMin = tnextY;
|
|
278
|
+
if (intervalMin > intervalMax) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
indxY += stepY;
|
|
282
|
+
if (indxY == stopY) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
tnextY += deltaY;
|
|
286
|
+
} else {
|
|
287
|
+
curr = dirZ > 0 ? 4 : 5;
|
|
288
|
+
intervalMin = tnextZ;
|
|
289
|
+
if (intervalMin > intervalMax) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
indxZ += stepZ;
|
|
293
|
+
if (indxZ == stopZ) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
tnextZ += deltaZ;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@Override
|
|
302
|
+
public int getNumPrimitives() {
|
|
303
|
+
return 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@Override
|
|
307
|
+
public float getPrimitiveBound(int primID, int i) {
|
|
308
|
+
return ((i & 1) == 0) ? -1 : 1;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
@Override
|
|
312
|
+
public BoundingBox getWorldBounds(Matrix4 o2w) {
|
|
313
|
+
if (o2w == null) {
|
|
314
|
+
return bounds;
|
|
315
|
+
}
|
|
316
|
+
return o2w.transform(bounds);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
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.ParameterList;
|
|
7
|
+
import org.sunflow.core.PrimitiveList;
|
|
8
|
+
import org.sunflow.core.Ray;
|
|
9
|
+
import org.sunflow.core.ShadingState;
|
|
10
|
+
import org.sunflow.math.BoundingBox;
|
|
11
|
+
import org.sunflow.math.Matrix4;
|
|
12
|
+
import org.sunflow.math.OrthoNormalBasis;
|
|
13
|
+
import org.sunflow.math.Point3;
|
|
14
|
+
import org.sunflow.math.Solvers;
|
|
15
|
+
import org.sunflow.math.Vector3;
|
|
16
|
+
|
|
17
|
+
public class Cylinder implements PrimitiveList {
|
|
18
|
+
|
|
19
|
+
@Override
|
|
20
|
+
public boolean update(ParameterList pl, SunflowAPI api) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Override
|
|
25
|
+
public BoundingBox getWorldBounds(Matrix4 o2w) {
|
|
26
|
+
BoundingBox bounds = new BoundingBox(1);
|
|
27
|
+
if (o2w != null) {
|
|
28
|
+
bounds = o2w.transform(bounds);
|
|
29
|
+
}
|
|
30
|
+
return bounds;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Override
|
|
34
|
+
public float getPrimitiveBound(int primID, int i) {
|
|
35
|
+
return (i & 1) == 0 ? -1 : 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Override
|
|
39
|
+
public int getNumPrimitives() {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Override
|
|
44
|
+
public void prepareShadingState(ShadingState state) {
|
|
45
|
+
state.init();
|
|
46
|
+
state.getRay().getPoint(state.getPoint());
|
|
47
|
+
Instance parent = state.getInstance();
|
|
48
|
+
Point3 localPoint = state.transformWorldToObject(state.getPoint());
|
|
49
|
+
state.getNormal().set(localPoint.x, localPoint.y, 0);
|
|
50
|
+
state.getNormal().normalize();
|
|
51
|
+
|
|
52
|
+
float phi = (float) Math.atan2(state.getNormal().y, state.getNormal().x);
|
|
53
|
+
if (phi < 0) {
|
|
54
|
+
phi += 2 * Math.PI;
|
|
55
|
+
}
|
|
56
|
+
state.getUV().x = phi / (float) (2 * Math.PI);
|
|
57
|
+
state.getUV().y = (localPoint.z + 1) * 0.5f;
|
|
58
|
+
state.setShader(parent.getShader(0));
|
|
59
|
+
state.setModifier(parent.getModifier(0));
|
|
60
|
+
// into world space
|
|
61
|
+
Vector3 worldNormal = state.transformNormalObjectToWorld(state.getNormal());
|
|
62
|
+
Vector3 v = state.transformVectorObjectToWorld(new Vector3(0, 0, 1));
|
|
63
|
+
state.getNormal().set(worldNormal);
|
|
64
|
+
state.getNormal().normalize();
|
|
65
|
+
state.getGeoNormal().set(state.getNormal());
|
|
66
|
+
// compute basis in world space
|
|
67
|
+
state.setBasis(OrthoNormalBasis.makeFromWV(state.getNormal(), v));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Override
|
|
71
|
+
public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
|
|
72
|
+
// intersect in local space
|
|
73
|
+
float qa = r.dx * r.dx + r.dy * r.dy;
|
|
74
|
+
float qb = 2 * ((r.dx * r.ox) + (r.dy * r.oy));
|
|
75
|
+
float qc = ((r.ox * r.ox) + (r.oy * r.oy)) - 1;
|
|
76
|
+
double[] t = Solvers.solveQuadric(qa, qb, qc);
|
|
77
|
+
if (t != null) {
|
|
78
|
+
// early rejection
|
|
79
|
+
if (t[0] >= r.getMax() || t[1] <= r.getMin()) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (t[0] > r.getMin()) {
|
|
83
|
+
float z = r.oz + (float) t[0] * r.dz;
|
|
84
|
+
if (z >= -1 && z <= 1) {
|
|
85
|
+
r.setMax((float) t[0]);
|
|
86
|
+
state.setIntersection(0);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (t[1] < r.getMax()) {
|
|
91
|
+
float z = r.oz + (float) t[1] * r.dz;
|
|
92
|
+
if (z >= -1 && z <= 1) {
|
|
93
|
+
r.setMax((float) t[1]);
|
|
94
|
+
state.setIntersection(0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Override
|
|
101
|
+
public PrimitiveList getBakingPrimitives() {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
package org.sunflow.core.primitive;
|
|
2
|
+
|
|
3
|
+
import java.util.Locale;
|
|
4
|
+
|
|
5
|
+
import org.sunflow.SunflowAPI;
|
|
6
|
+
import org.sunflow.core.Instance;
|
|
7
|
+
import org.sunflow.core.IntersectionState;
|
|
8
|
+
import org.sunflow.core.LightSample;
|
|
9
|
+
import org.sunflow.core.ParameterList;
|
|
10
|
+
import org.sunflow.core.PrimitiveList;
|
|
11
|
+
import org.sunflow.core.Ray;
|
|
12
|
+
import org.sunflow.core.Shader;
|
|
13
|
+
import org.sunflow.core.ShadingState;
|
|
14
|
+
import org.sunflow.core.ParameterList.FloatParameter;
|
|
15
|
+
import org.sunflow.core.ParameterList.InterpolationType;
|
|
16
|
+
import org.sunflow.image.Color;
|
|
17
|
+
import org.sunflow.math.BoundingBox;
|
|
18
|
+
import org.sunflow.math.Matrix4;
|
|
19
|
+
import org.sunflow.math.OrthoNormalBasis;
|
|
20
|
+
import org.sunflow.math.Vector3;
|
|
21
|
+
import org.sunflow.system.UI;
|
|
22
|
+
import org.sunflow.system.UI.Module;
|
|
23
|
+
|
|
24
|
+
public class Hair implements PrimitiveList, Shader {
|
|
25
|
+
|
|
26
|
+
private int numSegments;
|
|
27
|
+
private float[] points;
|
|
28
|
+
private FloatParameter widths;
|
|
29
|
+
|
|
30
|
+
public Hair() {
|
|
31
|
+
numSegments = 1;
|
|
32
|
+
points = null;
|
|
33
|
+
widths = new FloatParameter(1.0f);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Override
|
|
37
|
+
public int getNumPrimitives() {
|
|
38
|
+
return numSegments * (points.length / (3 * (numSegments + 1)));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
public float getPrimitiveBound(int primID, int i) {
|
|
43
|
+
int hair = primID / numSegments;
|
|
44
|
+
int line = primID % numSegments;
|
|
45
|
+
int vn = hair * (numSegments + 1) + line;
|
|
46
|
+
int vRoot = hair * 3 * (numSegments + 1);
|
|
47
|
+
int v0 = vRoot + line * 3;
|
|
48
|
+
int v1 = v0 + 3;
|
|
49
|
+
int axis = i >>> 1;
|
|
50
|
+
if ((i & 1) == 0) {
|
|
51
|
+
return Math.min(points[v0 + axis] - 0.5f * getWidth(vn), points[v1 + axis] - 0.5f * getWidth(vn + 1));
|
|
52
|
+
} else {
|
|
53
|
+
return Math.max(points[v0 + axis] + 0.5f * getWidth(vn), points[v1 + axis] + 0.5f * getWidth(vn + 1));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Override
|
|
58
|
+
public BoundingBox getWorldBounds(Matrix4 o2w) {
|
|
59
|
+
BoundingBox bounds = new BoundingBox();
|
|
60
|
+
for (int i = 0, j = 0; i < points.length; i += 3, j++) {
|
|
61
|
+
float w = 0.5f * getWidth(j);
|
|
62
|
+
bounds.include(points[i] - w, points[i + 1] - w, points[i + 2] - w);
|
|
63
|
+
bounds.include(points[i] + w, points[i + 1] + w, points[i + 2] + w);
|
|
64
|
+
}
|
|
65
|
+
if (o2w != null) {
|
|
66
|
+
bounds = o2w.transform(bounds);
|
|
67
|
+
}
|
|
68
|
+
return bounds;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private float getWidth(int i) {
|
|
72
|
+
switch (widths.interp) {
|
|
73
|
+
case NONE:
|
|
74
|
+
return widths.data[0];
|
|
75
|
+
case VERTEX:
|
|
76
|
+
return widths.data[i];
|
|
77
|
+
default:
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private Vector3 getTangent(int line, int v0, float v) {
|
|
83
|
+
Vector3 vcurr = new Vector3(points[v0 + 3] - points[v0 + 0], points[v0 + 4] - points[v0 + 1], points[v0 + 5] - points[v0 + 2]);
|
|
84
|
+
vcurr.normalize();
|
|
85
|
+
if (line == 0 || line == numSegments - 1) {
|
|
86
|
+
return vcurr;
|
|
87
|
+
}
|
|
88
|
+
if (v <= 0.5f) {
|
|
89
|
+
// get previous segment
|
|
90
|
+
Vector3 vprev = new Vector3(points[v0 + 0] - points[v0 - 3], points[v0 + 1] - points[v0 - 2], points[v0 + 2] - points[v0 - 1]);
|
|
91
|
+
vprev.normalize();
|
|
92
|
+
float t = v + 0.5f;
|
|
93
|
+
float s = 1 - t;
|
|
94
|
+
float vx = vprev.x * s + vcurr.x * t;
|
|
95
|
+
float vy = vprev.y * s + vcurr.y * t;
|
|
96
|
+
float vz = vprev.z * s + vcurr.z * t;
|
|
97
|
+
return new Vector3(vx, vy, vz);
|
|
98
|
+
} else {
|
|
99
|
+
// get next segment
|
|
100
|
+
v0 += 3;
|
|
101
|
+
Vector3 vnext = new Vector3(points[v0 + 3] - points[v0 + 0], points[v0 + 4] - points[v0 + 1], points[v0 + 5] - points[v0 + 2]);
|
|
102
|
+
vnext.normalize();
|
|
103
|
+
float t = 1.5f - v;
|
|
104
|
+
float s = 1 - t;
|
|
105
|
+
float vx = vnext.x * s + vcurr.x * t;
|
|
106
|
+
float vy = vnext.y * s + vcurr.y * t;
|
|
107
|
+
float vz = vnext.z * s + vcurr.z * t;
|
|
108
|
+
return new Vector3(vx, vy, vz);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Override
|
|
113
|
+
public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
|
|
114
|
+
int hair = primID / numSegments;
|
|
115
|
+
int line = primID % numSegments;
|
|
116
|
+
int vRoot = hair * 3 * (numSegments + 1);
|
|
117
|
+
int v0 = vRoot + line * 3;
|
|
118
|
+
int v1 = v0 + 3;
|
|
119
|
+
float vx = points[v1 + 0] - points[v0 + 0];
|
|
120
|
+
float vy = points[v1 + 1] - points[v0 + 1];
|
|
121
|
+
float vz = points[v1 + 2] - points[v0 + 2];
|
|
122
|
+
float ux = r.dy * vz - r.dz * vy;
|
|
123
|
+
float uy = r.dz * vx - r.dx * vz;
|
|
124
|
+
float uz = r.dx * vy - r.dy * vx;
|
|
125
|
+
float nx = uy * vz - uz * vy;
|
|
126
|
+
float ny = uz * vx - ux * vz;
|
|
127
|
+
float nz = ux * vy - uy * vx;
|
|
128
|
+
float tden = 1 / (nx * r.dx + ny * r.dy + nz * r.dz);
|
|
129
|
+
float tnum = nx * (points[v0 + 0] - r.ox) + ny * (points[v0 + 1] - r.oy) + nz * (points[v0 + 2] - r.oz);
|
|
130
|
+
float t = tnum * tden;
|
|
131
|
+
if (r.isInside(t)) {
|
|
132
|
+
int vn = hair * (numSegments + 1) + line;
|
|
133
|
+
float px = r.ox + t * r.dx;
|
|
134
|
+
float py = r.oy + t * r.dy;
|
|
135
|
+
float pz = r.oz + t * r.dz;
|
|
136
|
+
float qx = px - points[v0 + 0];
|
|
137
|
+
float qy = py - points[v0 + 1];
|
|
138
|
+
float qz = pz - points[v0 + 2];
|
|
139
|
+
float q = (vx * qx + vy * qy + vz * qz) / (vx * vx + vy * vy + vz * vz);
|
|
140
|
+
if (q <= 0) {
|
|
141
|
+
// don't included rounded tip at root
|
|
142
|
+
if (line == 0) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
float dx = points[v0 + 0] - px;
|
|
146
|
+
float dy = points[v0 + 1] - py;
|
|
147
|
+
float dz = points[v0 + 2] - pz;
|
|
148
|
+
float d2 = dx * dx + dy * dy + dz * dz;
|
|
149
|
+
float width = getWidth(vn);
|
|
150
|
+
if (d2 < (width * width * 0.25f)) {
|
|
151
|
+
r.setMax(t);
|
|
152
|
+
state.setIntersection(primID, 0, 0);
|
|
153
|
+
}
|
|
154
|
+
} else if (q >= 1) {
|
|
155
|
+
float dx = points[v1 + 0] - px;
|
|
156
|
+
float dy = points[v1 + 1] - py;
|
|
157
|
+
float dz = points[v1 + 2] - pz;
|
|
158
|
+
float d2 = dx * dx + dy * dy + dz * dz;
|
|
159
|
+
float width = getWidth(vn + 1);
|
|
160
|
+
if (d2 < (width * width * 0.25f)) {
|
|
161
|
+
r.setMax(t);
|
|
162
|
+
state.setIntersection(primID, 0, 1);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
float dx = points[v0 + 0] + q * vx - px;
|
|
166
|
+
float dy = points[v0 + 1] + q * vy - py;
|
|
167
|
+
float dz = points[v0 + 2] + q * vz - pz;
|
|
168
|
+
float d2 = dx * dx + dy * dy + dz * dz;
|
|
169
|
+
float width = (1 - q) * getWidth(vn) + q * getWidth(vn + 1);
|
|
170
|
+
if (d2 < (width * width * 0.25f)) {
|
|
171
|
+
r.setMax(t);
|
|
172
|
+
state.setIntersection(primID, 0, q);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Override
|
|
179
|
+
public void prepareShadingState(ShadingState state) {
|
|
180
|
+
state.init();
|
|
181
|
+
Instance i = state.getInstance();
|
|
182
|
+
state.getRay().getPoint(state.getPoint());
|
|
183
|
+
Ray r = state.getRay();
|
|
184
|
+
Shader s = i.getShader(0);
|
|
185
|
+
state.setShader(s != null ? s : this);
|
|
186
|
+
int primID = state.getPrimitiveID();
|
|
187
|
+
int hair = primID / numSegments;
|
|
188
|
+
int line = primID % numSegments;
|
|
189
|
+
int vRoot = hair * 3 * (numSegments + 1);
|
|
190
|
+
int v0 = vRoot + line * 3;
|
|
191
|
+
|
|
192
|
+
// tangent vector
|
|
193
|
+
Vector3 v = getTangent(line, v0, state.getV());
|
|
194
|
+
v = state.transformVectorObjectToWorld(v);
|
|
195
|
+
state.setBasis(OrthoNormalBasis.makeFromWV(v, new Vector3(-r.dx, -r.dy, -r.dz)));
|
|
196
|
+
state.getBasis().swapVW();
|
|
197
|
+
// normal
|
|
198
|
+
state.getNormal().set(0, 0, 1);
|
|
199
|
+
state.getBasis().transform(state.getNormal());
|
|
200
|
+
state.getGeoNormal().set(state.getNormal());
|
|
201
|
+
|
|
202
|
+
state.getUV().set(0, (line + state.getV()) / numSegments);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@Override
|
|
206
|
+
public boolean update(ParameterList pl, SunflowAPI api) {
|
|
207
|
+
numSegments = pl.getInt("segments", numSegments);
|
|
208
|
+
if (numSegments < 1) {
|
|
209
|
+
UI.printError(Module.HAIR, "Invalid number of segments: %d", numSegments);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
FloatParameter pointsP = pl.getPointArray("points");
|
|
213
|
+
if (pointsP != null) {
|
|
214
|
+
if (pointsP.interp != InterpolationType.VERTEX) {
|
|
215
|
+
UI.printError(Module.HAIR, "Point interpolation type must be set to \"vertex\" - was \"%s\"", pointsP.interp.name().toLowerCase(Locale.ENGLISH));
|
|
216
|
+
} else {
|
|
217
|
+
points = pointsP.data;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (points == null) {
|
|
221
|
+
UI.printError(Module.HAIR, "Unabled to update hair - vertices are missing");
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
pl.setVertexCount(points.length / 3);
|
|
226
|
+
FloatParameter widthsP = pl.getFloatArray("widths");
|
|
227
|
+
if (widthsP != null) {
|
|
228
|
+
if (widthsP.interp == InterpolationType.NONE || widthsP.interp == InterpolationType.VERTEX) {
|
|
229
|
+
widths = widthsP;
|
|
230
|
+
} else {
|
|
231
|
+
UI.printWarning(Module.HAIR, "Width interpolation type %s is not supported -- ignoring", widthsP.interp.name().toLowerCase(Locale.ENGLISH));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@Override
|
|
238
|
+
public Color getRadiance(ShadingState state) {
|
|
239
|
+
// don't use these - gather lights for sphere of directions
|
|
240
|
+
// gather lights
|
|
241
|
+
state.initLightSamples();
|
|
242
|
+
state.initCausticSamples();
|
|
243
|
+
Vector3 v = state.getRay().getDirection();
|
|
244
|
+
v.negate();
|
|
245
|
+
Vector3 h = new Vector3();
|
|
246
|
+
Vector3 t = state.getBasis().transform(new Vector3(0, 1, 0));
|
|
247
|
+
Color diff = Color.black();
|
|
248
|
+
Color spec = Color.black();
|
|
249
|
+
for (LightSample ls : state) {
|
|
250
|
+
Vector3 l = ls.getShadowRay().getDirection();
|
|
251
|
+
float dotTL = Vector3.dot(t, l);
|
|
252
|
+
float sinTL = (float) Math.sqrt(1 - dotTL * dotTL);
|
|
253
|
+
// float dotVL = Vector3.dot(v, l);
|
|
254
|
+
diff.madd(sinTL, ls.getDiffuseRadiance());
|
|
255
|
+
Vector3.add(v, l, h);
|
|
256
|
+
h.normalize();
|
|
257
|
+
float dotTH = Vector3.dot(t, h);
|
|
258
|
+
float sinTH = (float) Math.sqrt(1 - dotTH * dotTH);
|
|
259
|
+
float s = (float) Math.pow(sinTH, 10.0f);
|
|
260
|
+
spec.madd(s, ls.getSpecularRadiance());
|
|
261
|
+
}
|
|
262
|
+
Color c = Color.add(diff, spec, new Color());
|
|
263
|
+
// transparency
|
|
264
|
+
return Color.blend(c, state.traceTransparency(), state.getV(), new Color());
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@Override
|
|
268
|
+
public void scatterPhoton(ShadingState state, Color power) {
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Override
|
|
272
|
+
public PrimitiveList getBakingPrimitives() {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|