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,54 @@
|
|
|
1
|
+
package org.sunflow.image.writers;
|
|
2
|
+
|
|
3
|
+
import java.io.BufferedOutputStream;
|
|
4
|
+
import java.io.FileOutputStream;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.io.OutputStream;
|
|
7
|
+
|
|
8
|
+
import org.sunflow.image.BitmapWriter;
|
|
9
|
+
import org.sunflow.image.Color;
|
|
10
|
+
import org.sunflow.image.ColorEncoder;
|
|
11
|
+
|
|
12
|
+
public class HDRBitmapWriter implements BitmapWriter {
|
|
13
|
+
|
|
14
|
+
private String filename;
|
|
15
|
+
private int width, height;
|
|
16
|
+
private int[] data;
|
|
17
|
+
|
|
18
|
+
public void configure(String option, String value) {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public void openFile(String filename) throws IOException {
|
|
22
|
+
this.filename = filename;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void writeHeader(int width, int height, int tileSize) throws IOException, UnsupportedOperationException {
|
|
26
|
+
this.width = width;
|
|
27
|
+
this.height = height;
|
|
28
|
+
data = new int[width * height];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public void writeTile(int x, int y, int w, int h, Color[] color, float[] alpha) throws IOException {
|
|
32
|
+
int[] tileData = ColorEncoder.encodeRGBE(color);
|
|
33
|
+
for (int j = 0, index = 0, pixel = x + y * width; j < h; j++, pixel += width - w) {
|
|
34
|
+
for (int i = 0; i < w; i++, index++, pixel++) {
|
|
35
|
+
data[pixel] = tileData[index];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public void closeFile() throws IOException {
|
|
41
|
+
OutputStream f = new BufferedOutputStream(new FileOutputStream(filename));
|
|
42
|
+
f.write("#?RGBE\n".getBytes());
|
|
43
|
+
f.write("FORMAT=32-bit_rle_rgbe\n\n".getBytes());
|
|
44
|
+
f.write(("-Y " + height + " +X " + width + "\n").getBytes());
|
|
45
|
+
for (int i = 0; i < data.length; i++) {
|
|
46
|
+
int rgbe = data[i];
|
|
47
|
+
f.write(rgbe >> 24);
|
|
48
|
+
f.write(rgbe >> 16);
|
|
49
|
+
f.write(rgbe >> 8);
|
|
50
|
+
f.write(rgbe);
|
|
51
|
+
}
|
|
52
|
+
f.close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package org.sunflow.image.writers;
|
|
2
|
+
|
|
3
|
+
import java.io.BufferedOutputStream;
|
|
4
|
+
import java.io.FileOutputStream;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.io.OutputStream;
|
|
7
|
+
|
|
8
|
+
import org.sunflow.image.BitmapWriter;
|
|
9
|
+
import org.sunflow.image.Color;
|
|
10
|
+
import org.sunflow.image.XYZColor;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Writes images in Indigo's native XYZ format.
|
|
14
|
+
* http://www2.indigorenderer.com/joomla/forum/viewtopic.php?p=11430
|
|
15
|
+
*/
|
|
16
|
+
public class IGIBitmapWriter implements BitmapWriter {
|
|
17
|
+
|
|
18
|
+
private String filename;
|
|
19
|
+
private int width, height;
|
|
20
|
+
private float[] xyz;
|
|
21
|
+
|
|
22
|
+
public void configure(String option, String value) {
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void openFile(String filename) throws IOException {
|
|
26
|
+
this.filename = filename;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public void writeHeader(int width, int height, int tileSize) throws IOException, UnsupportedOperationException {
|
|
30
|
+
this.width = width;
|
|
31
|
+
this.height = height;
|
|
32
|
+
xyz = new float[width * height * 3];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void writeTile(int x, int y, int w, int h, Color[] color, float[] alpha) throws IOException {
|
|
36
|
+
for (int j = 0, index = 0, pixel = 3 * (x + y * width); j < h; j++, pixel += 3 * (width - w)) {
|
|
37
|
+
for (int i = 0; i < w; i++, index++, pixel += 3) {
|
|
38
|
+
XYZColor c = Color.NATIVE_SPACE.convertRGBtoXYZ(color[index]);
|
|
39
|
+
xyz[pixel + 0] = c.getX();
|
|
40
|
+
xyz[pixel + 1] = c.getY();
|
|
41
|
+
xyz[pixel + 2] = c.getZ();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public void closeFile() throws IOException {
|
|
47
|
+
OutputStream stream = new BufferedOutputStream(new FileOutputStream(filename));
|
|
48
|
+
write32(stream, 66613373); // magic number
|
|
49
|
+
write32(stream, 1); // version
|
|
50
|
+
write32(stream, 0); // this should be a double - assume it won't be used
|
|
51
|
+
write32(stream, 0);
|
|
52
|
+
write32(stream, width);
|
|
53
|
+
write32(stream, height);
|
|
54
|
+
write32(stream, 1); // super sampling factor
|
|
55
|
+
write32(stream, 0); // compression
|
|
56
|
+
write32(stream, width * height * 12); // data size
|
|
57
|
+
write32(stream, 0); // colorspace
|
|
58
|
+
stream.write(new byte[5000]);
|
|
59
|
+
for (float f : xyz) {
|
|
60
|
+
write32(stream, f);
|
|
61
|
+
}
|
|
62
|
+
stream.close();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private static final void write32(OutputStream stream, int i) throws IOException {
|
|
66
|
+
stream.write(i & 0xFF);
|
|
67
|
+
stream.write((i >> 8) & 0xFF);
|
|
68
|
+
stream.write((i >> 16) & 0xFF);
|
|
69
|
+
stream.write((i >> 24) & 0xFF);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private static final void write32(OutputStream stream, float f) throws IOException {
|
|
73
|
+
write32(stream, Float.floatToIntBits(f));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package org.sunflow.image.writers;
|
|
2
|
+
|
|
3
|
+
import java.awt.image.BufferedImage;
|
|
4
|
+
import java.io.File;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
|
|
7
|
+
import javax.imageio.ImageIO;
|
|
8
|
+
|
|
9
|
+
import org.sunflow.image.BitmapWriter;
|
|
10
|
+
import org.sunflow.image.Color;
|
|
11
|
+
|
|
12
|
+
public class PNGBitmapWriter implements BitmapWriter {
|
|
13
|
+
|
|
14
|
+
private String filename;
|
|
15
|
+
private BufferedImage image;
|
|
16
|
+
|
|
17
|
+
public void configure(String option, String value) {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public void openFile(String filename) throws IOException {
|
|
21
|
+
this.filename = filename;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public void writeHeader(int width, int height, int tileSize) throws IOException, UnsupportedOperationException {
|
|
25
|
+
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public void writeTile(int x, int y, int w, int h, Color[] color, float[] alpha) throws IOException {
|
|
29
|
+
for (int j = 0, index = 0; j < h; j++) {
|
|
30
|
+
for (int i = 0; i < w; i++, index++) {
|
|
31
|
+
image.setRGB(x + i, y + j, color[index].copy().mul(1.0f / alpha[index]).toNonLinear().toRGBA(alpha[index]));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public void closeFile() throws IOException {
|
|
37
|
+
ImageIO.write(image, "png", new File(filename));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package org.sunflow.image.writers;
|
|
2
|
+
|
|
3
|
+
import java.io.BufferedOutputStream;
|
|
4
|
+
import java.io.FileOutputStream;
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.io.OutputStream;
|
|
7
|
+
|
|
8
|
+
import org.sunflow.image.BitmapWriter;
|
|
9
|
+
import org.sunflow.image.Color;
|
|
10
|
+
import org.sunflow.image.ColorEncoder;
|
|
11
|
+
|
|
12
|
+
public class TGABitmapWriter implements BitmapWriter {
|
|
13
|
+
|
|
14
|
+
private String filename;
|
|
15
|
+
private int width, height;
|
|
16
|
+
private byte[] data;
|
|
17
|
+
|
|
18
|
+
public void configure(String option, String value) {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public void openFile(String filename) throws IOException {
|
|
22
|
+
this.filename = filename;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void writeHeader(int width, int height, int tileSize) throws IOException, UnsupportedOperationException {
|
|
26
|
+
this.width = width;
|
|
27
|
+
this.height = height;
|
|
28
|
+
data = new byte[width * height * 4]; // RGBA8
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public void writeTile(int x, int y, int w, int h, Color[] color, float[] alpha) throws IOException {
|
|
32
|
+
color = ColorEncoder.unlinearize(color); // gamma correction
|
|
33
|
+
byte[] tileData = ColorEncoder.quantizeRGBA8(color, alpha);
|
|
34
|
+
for (int j = 0, index = 0; j < h; j++) {
|
|
35
|
+
int imageIndex = 4 * (x + (height - 1 - (y + j)) * width);
|
|
36
|
+
for (int i = 0; i < w; i++, index += 4, imageIndex += 4) {
|
|
37
|
+
// swap bytes around so buffer is in native BGRA order
|
|
38
|
+
data[imageIndex + 0] = tileData[index + 2];
|
|
39
|
+
data[imageIndex + 1] = tileData[index + 1];
|
|
40
|
+
data[imageIndex + 2] = tileData[index + 0];
|
|
41
|
+
data[imageIndex + 3] = tileData[index + 3];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public void closeFile() throws IOException {
|
|
47
|
+
// actually write the file from here
|
|
48
|
+
OutputStream f = new BufferedOutputStream(new FileOutputStream(filename));
|
|
49
|
+
// no id, no colormap, uncompressed 32bpp RGBA
|
|
50
|
+
byte[] tgaHeader = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
51
|
+
f.write(tgaHeader);
|
|
52
|
+
// then the size info
|
|
53
|
+
f.write(width & 0xFF);
|
|
54
|
+
f.write((width >> 8) & 0xFF);
|
|
55
|
+
f.write(height & 0xFF);
|
|
56
|
+
f.write((height >> 8) & 0xFF);
|
|
57
|
+
// bitsperpixel and filler
|
|
58
|
+
f.write(32);
|
|
59
|
+
f.write(0);
|
|
60
|
+
f.write(data); // write image data bytes (already in BGRA order)
|
|
61
|
+
f.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
package org.sunflow.math;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 3D axis-aligned bounding box. Stores only the minimum and maximum corner
|
|
5
|
+
* points.
|
|
6
|
+
*/
|
|
7
|
+
public class BoundingBox {
|
|
8
|
+
|
|
9
|
+
private Point3 minimum;
|
|
10
|
+
private Point3 maximum;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates an empty box. The minimum point will have all components set to
|
|
14
|
+
* positive infinity, and the maximum will have all components set to
|
|
15
|
+
* negative infinity.
|
|
16
|
+
*/
|
|
17
|
+
public BoundingBox() {
|
|
18
|
+
minimum = new Point3(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
|
|
19
|
+
maximum = new Point3(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Creates a copy of the given box.
|
|
24
|
+
*
|
|
25
|
+
* @param b bounding box to copy
|
|
26
|
+
*/
|
|
27
|
+
public BoundingBox(BoundingBox b) {
|
|
28
|
+
minimum = new Point3(b.minimum);
|
|
29
|
+
maximum = new Point3(b.maximum);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Creates a bounding box containing only the specified point.
|
|
34
|
+
*
|
|
35
|
+
* @param p point to include
|
|
36
|
+
*/
|
|
37
|
+
public BoundingBox(Point3 p) {
|
|
38
|
+
this(p.x, p.y, p.z);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates a bounding box containing only the specified point.
|
|
43
|
+
*
|
|
44
|
+
* @param x x coordinate of the point to include
|
|
45
|
+
* @param y y coordinate of the point to include
|
|
46
|
+
* @param z z coordinate of the point to include
|
|
47
|
+
*/
|
|
48
|
+
public BoundingBox(float x, float y, float z) {
|
|
49
|
+
minimum = new Point3(x, y, z);
|
|
50
|
+
maximum = new Point3(x, y, z);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a bounding box centered around the origin.
|
|
55
|
+
*
|
|
56
|
+
* @param size half edge length of the bounding box
|
|
57
|
+
*/
|
|
58
|
+
public BoundingBox(float size) {
|
|
59
|
+
minimum = new Point3(-size, -size, -size);
|
|
60
|
+
maximum = new Point3(size, size, size);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the minimum corner of the box. That is the corner of smallest
|
|
65
|
+
* coordinates on each axis. Note that the returned reference is not cloned
|
|
66
|
+
* for efficiency purposes so care must be taken not to change the
|
|
67
|
+
* coordinates of the point.
|
|
68
|
+
*
|
|
69
|
+
* @return a reference to the minimum corner
|
|
70
|
+
*/
|
|
71
|
+
public final Point3 getMinimum() {
|
|
72
|
+
return minimum;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets the maximum corner of the box. That is the corner of largest
|
|
77
|
+
* coordinates on each axis. Note that the returned reference is not cloned
|
|
78
|
+
* for efficiency purposes so care must be taken not to change the
|
|
79
|
+
* coordinates of the point.
|
|
80
|
+
*
|
|
81
|
+
* @return a reference to the maximum corner
|
|
82
|
+
*/
|
|
83
|
+
public final Point3 getMaximum() {
|
|
84
|
+
return maximum;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the center of the box, computed as (min + max) / 2.
|
|
89
|
+
*
|
|
90
|
+
* @return a reference to the center of the box
|
|
91
|
+
*/
|
|
92
|
+
public final Point3 getCenter() {
|
|
93
|
+
return Point3.mid(minimum, maximum, new Point3());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Gets a corner of the bounding box. The index scheme uses the binary
|
|
98
|
+
* representation of the index to decide which corner to return. Corner 0 is
|
|
99
|
+
* equivalent to the minimum and corner 7 is equivalent to the maximum.
|
|
100
|
+
*
|
|
101
|
+
* @param i a corner index, from 0 to 7
|
|
102
|
+
* @return the corresponding corner
|
|
103
|
+
*/
|
|
104
|
+
public final Point3 getCorner(int i) {
|
|
105
|
+
float x = (i & 1) == 0 ? minimum.x : maximum.x;
|
|
106
|
+
float y = (i & 2) == 0 ? minimum.y : maximum.y;
|
|
107
|
+
float z = (i & 4) == 0 ? minimum.z : maximum.z;
|
|
108
|
+
return new Point3(x, y, z);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Gets a specific coordinate of the surface's bounding box.
|
|
113
|
+
*
|
|
114
|
+
* @param i index of a side from 0 to 5
|
|
115
|
+
* @return value of the request bounding box side
|
|
116
|
+
*/
|
|
117
|
+
public final float getBound(int i) {
|
|
118
|
+
switch (i) {
|
|
119
|
+
case 0:
|
|
120
|
+
return minimum.x;
|
|
121
|
+
case 1:
|
|
122
|
+
return maximum.x;
|
|
123
|
+
case 2:
|
|
124
|
+
return minimum.y;
|
|
125
|
+
case 3:
|
|
126
|
+
return maximum.y;
|
|
127
|
+
case 4:
|
|
128
|
+
return minimum.z;
|
|
129
|
+
case 5:
|
|
130
|
+
return maximum.z;
|
|
131
|
+
default:
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Gets the extents vector for the box. This vector is computed as (max -
|
|
138
|
+
* min). Its coordinates are always positive and represent the dimensions of
|
|
139
|
+
* the box along the three axes.
|
|
140
|
+
*
|
|
141
|
+
* @return a refreence to the extent vector
|
|
142
|
+
* @see org.sunflow.math.Vector3#length()
|
|
143
|
+
*/
|
|
144
|
+
public final Vector3 getExtents() {
|
|
145
|
+
return Point3.sub(maximum, minimum, new Vector3());
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Gets the surface area of the box.
|
|
150
|
+
*
|
|
151
|
+
* @return surface area
|
|
152
|
+
*/
|
|
153
|
+
public final float getArea() {
|
|
154
|
+
Vector3 w = getExtents();
|
|
155
|
+
float ax = Math.max(w.x, 0);
|
|
156
|
+
float ay = Math.max(w.y, 0);
|
|
157
|
+
float az = Math.max(w.z, 0);
|
|
158
|
+
return 2 * (ax * ay + ay * az + az * ax);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Gets the box's volume
|
|
163
|
+
*
|
|
164
|
+
* @return volume
|
|
165
|
+
*/
|
|
166
|
+
public final float getVolume() {
|
|
167
|
+
Vector3 w = getExtents();
|
|
168
|
+
float ax = Math.max(w.x, 0);
|
|
169
|
+
float ay = Math.max(w.y, 0);
|
|
170
|
+
float az = Math.max(w.z, 0);
|
|
171
|
+
return ax * ay * az;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Enlarge the bounding box by the minimum possible amount to avoid numeric
|
|
176
|
+
* precision related problems.
|
|
177
|
+
*/
|
|
178
|
+
public final void enlargeUlps() {
|
|
179
|
+
final float eps = 0.0001f;
|
|
180
|
+
minimum.x -= Math.max(eps, Math.ulp(minimum.x));
|
|
181
|
+
minimum.y -= Math.max(eps, Math.ulp(minimum.y));
|
|
182
|
+
minimum.z -= Math.max(eps, Math.ulp(minimum.z));
|
|
183
|
+
maximum.x += Math.max(eps, Math.ulp(maximum.x));
|
|
184
|
+
maximum.y += Math.max(eps, Math.ulp(maximum.y));
|
|
185
|
+
maximum.z += Math.max(eps, Math.ulp(maximum.z));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Returns
|
|
190
|
+
* <code>true</code> when the box has just been initialized, and is still
|
|
191
|
+
* empty. This method might also return true if the state of the box becomes
|
|
192
|
+
* inconsistent and some component of the minimum corner is larger than the
|
|
193
|
+
* corresponding coordinate of the maximum corner.
|
|
194
|
+
*
|
|
195
|
+
* @return <code>true</code> if the box is empty, <code>false</code>
|
|
196
|
+
* otherwise
|
|
197
|
+
*/
|
|
198
|
+
public final boolean isEmpty() {
|
|
199
|
+
return (maximum.x < minimum.x) || (maximum.y < minimum.y) || (maximum.z < minimum.z);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Returns
|
|
204
|
+
* <code>true</code> if the specified bounding box intersects this one. The
|
|
205
|
+
* boxes are treated as volumes, so a box inside another will return true.
|
|
206
|
+
* Returns
|
|
207
|
+
* <code>false</code> if the parameter is
|
|
208
|
+
* <code>null</code>.
|
|
209
|
+
*
|
|
210
|
+
* @param b box to be tested for intersection
|
|
211
|
+
* @return <code>true</code> if the boxes overlap, <code>false</code>
|
|
212
|
+
* otherwise
|
|
213
|
+
*/
|
|
214
|
+
public final boolean intersects(BoundingBox b) {
|
|
215
|
+
return ((b != null) && (minimum.x <= b.maximum.x) && (maximum.x >= b.minimum.x) && (minimum.y <= b.maximum.y) && (maximum.y >= b.minimum.y) && (minimum.z <= b.maximum.z) && (maximum.z >= b.minimum.z));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Checks to see if the specified {@link org.sunflow.math.Point3 point}is
|
|
220
|
+
* inside the volume defined by this box. Returns
|
|
221
|
+
* <code>false</code> if the parameter is
|
|
222
|
+
* <code>null</code>.
|
|
223
|
+
*
|
|
224
|
+
* @param p point to be tested for containment
|
|
225
|
+
* @return <code>true</code> if the point is inside the box,
|
|
226
|
+
* <code>false</code> otherwise
|
|
227
|
+
*/
|
|
228
|
+
public final boolean contains(Point3 p) {
|
|
229
|
+
return ((p != null) && (p.x >= minimum.x) && (p.x <= maximum.x) && (p.y >= minimum.y) && (p.y <= maximum.y) && (p.z >= minimum.z) && (p.z <= maximum.z));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Check to see if the specified point is inside the volume defined by this
|
|
234
|
+
* box.
|
|
235
|
+
*
|
|
236
|
+
* @param x x coordinate of the point to be tested
|
|
237
|
+
* @param y y coordinate of the point to be tested
|
|
238
|
+
* @param z z coordinate of the point to be tested
|
|
239
|
+
* @return <code>true</code> if the point is inside the box,
|
|
240
|
+
* <code>false</code> otherwise
|
|
241
|
+
*/
|
|
242
|
+
public final boolean contains(float x, float y, float z) {
|
|
243
|
+
return ((x >= minimum.x) && (x <= maximum.x) && (y >= minimum.y) && (y <= maximum.y) && (z >= minimum.z) && (z <= maximum.z));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Changes the extents of the box as needed to include the given
|
|
248
|
+
* {@link org.sunflow.math.Point3 point}into this box. Does nothing if the
|
|
249
|
+
* parameter is
|
|
250
|
+
* <code>null</code>.
|
|
251
|
+
*
|
|
252
|
+
* @param p point to be included
|
|
253
|
+
*/
|
|
254
|
+
public final void include(Point3 p) {
|
|
255
|
+
if (p != null) {
|
|
256
|
+
if (p.x < minimum.x) {
|
|
257
|
+
minimum.x = p.x;
|
|
258
|
+
}
|
|
259
|
+
if (p.x > maximum.x) {
|
|
260
|
+
maximum.x = p.x;
|
|
261
|
+
}
|
|
262
|
+
if (p.y < minimum.y) {
|
|
263
|
+
minimum.y = p.y;
|
|
264
|
+
}
|
|
265
|
+
if (p.y > maximum.y) {
|
|
266
|
+
maximum.y = p.y;
|
|
267
|
+
}
|
|
268
|
+
if (p.z < minimum.z) {
|
|
269
|
+
minimum.z = p.z;
|
|
270
|
+
}
|
|
271
|
+
if (p.z > maximum.z) {
|
|
272
|
+
maximum.z = p.z;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Changes the extents of the box as needed to include the given point into
|
|
279
|
+
* this box.
|
|
280
|
+
*
|
|
281
|
+
* @param x x coordinate of the point
|
|
282
|
+
* @param y y coordinate of the point
|
|
283
|
+
* @param z z coordinate of the point
|
|
284
|
+
*/
|
|
285
|
+
public final void include(float x, float y, float z) {
|
|
286
|
+
if (x < minimum.x) {
|
|
287
|
+
minimum.x = x;
|
|
288
|
+
}
|
|
289
|
+
if (x > maximum.x) {
|
|
290
|
+
maximum.x = x;
|
|
291
|
+
}
|
|
292
|
+
if (y < minimum.y) {
|
|
293
|
+
minimum.y = y;
|
|
294
|
+
}
|
|
295
|
+
if (y > maximum.y) {
|
|
296
|
+
maximum.y = y;
|
|
297
|
+
}
|
|
298
|
+
if (z < minimum.z) {
|
|
299
|
+
minimum.z = z;
|
|
300
|
+
}
|
|
301
|
+
if (z > maximum.z) {
|
|
302
|
+
maximum.z = z;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Changes the extents of the box as needed to include the given box into
|
|
308
|
+
* this box. Does nothing if the parameter is
|
|
309
|
+
* <code>null</code>.
|
|
310
|
+
*
|
|
311
|
+
* @param b box to be included
|
|
312
|
+
*/
|
|
313
|
+
public final void include(BoundingBox b) {
|
|
314
|
+
if (b != null) {
|
|
315
|
+
if (b.minimum.x < minimum.x) {
|
|
316
|
+
minimum.x = b.minimum.x;
|
|
317
|
+
}
|
|
318
|
+
if (b.maximum.x > maximum.x) {
|
|
319
|
+
maximum.x = b.maximum.x;
|
|
320
|
+
}
|
|
321
|
+
if (b.minimum.y < minimum.y) {
|
|
322
|
+
minimum.y = b.minimum.y;
|
|
323
|
+
}
|
|
324
|
+
if (b.maximum.y > maximum.y) {
|
|
325
|
+
maximum.y = b.maximum.y;
|
|
326
|
+
}
|
|
327
|
+
if (b.minimum.z < minimum.z) {
|
|
328
|
+
minimum.z = b.minimum.z;
|
|
329
|
+
}
|
|
330
|
+
if (b.maximum.z > maximum.z) {
|
|
331
|
+
maximum.z = b.maximum.z;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@Override
|
|
337
|
+
public final String toString() {
|
|
338
|
+
return String.format("(%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f)", minimum.x, minimum.y, minimum.z, maximum.x, maximum.y, maximum.z);
|
|
339
|
+
}
|
|
340
|
+
}
|