toxiclibs 0.2-java → 0.5.0-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 +4 -4
- data/.gitignore +16 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE +675 -0
- data/README.md +12 -5
- data/Rakefile +25 -82
- data/examples/attract_repel/attract_repel.rb +30 -0
- data/examples/attract_repel/attractor.rb +23 -0
- data/examples/attract_repel/particle.rb +27 -0
- data/examples/data/ti_yong.png +0 -0
- data/examples/force_directed/cluster.rb +76 -0
- data/examples/force_directed/force_directed_graph.rb +92 -0
- data/examples/force_directed/node.rb +26 -0
- data/examples/gray_scott_image.rb +75 -0
- data/examples/gray_scott_tone_map.rb +77 -0
- data/examples/implicit.rb +139 -0
- data/examples/inflate_mesh.rb +89 -0
- data/examples/model_align.rb +44 -0
- data/examples/povmesh/ftest.rb +46 -0
- data/examples/povmesh/tentacle.rb +73 -0
- data/examples/simple_cluster/cluster.rb +47 -0
- data/examples/simple_cluster/node.rb +27 -0
- data/examples/simple_cluster/simple_cluster.rb +60 -0
- data/examples/soft_body/blanket.rb +45 -0
- data/examples/soft_body/connection.rb +16 -0
- data/examples/soft_body/particle.rb +22 -0
- data/examples/soft_body/soft_body_square_adapted.rb +55 -0
- data/lib/toxiclibs.jar +0 -0
- data/lib/toxiclibs.rb +91 -32
- data/lib/toxiclibs/version.rb +1 -1
- data/pom.xml +122 -0
- data/src/com/toxi/net/ClientListener.java +41 -0
- data/src/com/toxi/net/ServerListener.java +70 -0
- data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
- data/src/com/toxi/net/ServerState.java +18 -0
- data/src/com/toxi/net/UDPConnection.java +66 -0
- data/src/com/toxi/net/UDPSyncClient.java +81 -0
- data/src/com/toxi/net/UDPSyncServer.java +450 -0
- data/src/com/toxi/nio/UDPClient.java +121 -0
- data/src/com/toxi/nio/UDPClientState.java +32 -0
- data/src/com/toxi/nio/UDPServer.java +129 -0
- data/src/toxi/color/AccessCriteria.java +114 -0
- data/src/toxi/color/AlphaAccessor.java +67 -0
- data/src/toxi/color/CMYKAccessor.java +122 -0
- data/src/toxi/color/CMYKDistanceProxy.java +40 -0
- data/src/toxi/color/ColorGradient.java +260 -0
- data/src/toxi/color/ColorList.java +699 -0
- data/src/toxi/color/ColorRange.java +671 -0
- data/src/toxi/color/ColorTheme.java +163 -0
- data/src/toxi/color/DistanceProxy.java +44 -0
- data/src/toxi/color/HSVAccessor.java +113 -0
- data/src/toxi/color/HSVDistanceProxy.java +40 -0
- data/src/toxi/color/HistEntry.java +85 -0
- data/src/toxi/color/Histogram.java +185 -0
- data/src/toxi/color/Hue.java +249 -0
- data/src/toxi/color/LuminanceAccessor.java +78 -0
- data/src/toxi/color/NamedColor.java +935 -0
- data/src/toxi/color/ProximityComparator.java +70 -0
- data/src/toxi/color/RGBAccessor.java +113 -0
- data/src/toxi/color/RGBDistanceProxy.java +41 -0
- data/src/toxi/color/ReadonlyTColor.java +296 -0
- data/src/toxi/color/TColor.java +1677 -0
- data/src/toxi/color/TColorAdapter.java +68 -0
- data/src/toxi/color/ToneMap.java +218 -0
- data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
- data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
- data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
- data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
- data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
- data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
- data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
- data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
- data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
- data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
- data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
- data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
- data/src/toxi/data/csv/CSVAdapter.java +74 -0
- data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
- data/src/toxi/data/csv/CSVListener.java +61 -0
- data/src/toxi/data/csv/CSVParser.java +202 -0
- data/src/toxi/data/feeds/AtomAuthor.java +49 -0
- data/src/toxi/data/feeds/AtomContent.java +50 -0
- data/src/toxi/data/feeds/AtomEntry.java +111 -0
- data/src/toxi/data/feeds/AtomFeed.java +129 -0
- data/src/toxi/data/feeds/AtomLink.java +62 -0
- data/src/toxi/data/feeds/RSSChannel.java +88 -0
- data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
- data/src/toxi/data/feeds/RSSFeed.java +99 -0
- data/src/toxi/data/feeds/RSSItem.java +104 -0
- data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
- data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
- data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
- data/src/toxi/geom/AABB.java +658 -0
- data/src/toxi/geom/Axis3D.java +116 -0
- data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
- data/src/toxi/geom/BernsteinPolynomial.java +94 -0
- data/src/toxi/geom/BezierCurve2D.java +159 -0
- data/src/toxi/geom/BezierCurve3D.java +148 -0
- data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
- data/src/toxi/geom/BoxIntersector.java +52 -0
- data/src/toxi/geom/Circle.java +230 -0
- data/src/toxi/geom/CircleIntersector.java +85 -0
- data/src/toxi/geom/Cone.java +150 -0
- data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
- data/src/toxi/geom/CoordinateExtractor.java +16 -0
- data/src/toxi/geom/Ellipse.java +250 -0
- data/src/toxi/geom/GMatrix.java +2599 -0
- data/src/toxi/geom/GVector.java +833 -0
- data/src/toxi/geom/GlobalGridTesselator.java +54 -0
- data/src/toxi/geom/GridTesselator.java +108 -0
- data/src/toxi/geom/Intersector2D.java +49 -0
- data/src/toxi/geom/Intersector3D.java +51 -0
- data/src/toxi/geom/IsectData2D.java +103 -0
- data/src/toxi/geom/IsectData3D.java +103 -0
- data/src/toxi/geom/Line2D.java +534 -0
- data/src/toxi/geom/Line3D.java +471 -0
- data/src/toxi/geom/LineStrip2D.java +430 -0
- data/src/toxi/geom/LineStrip3D.java +230 -0
- data/src/toxi/geom/LocalGridTesselator.java +57 -0
- data/src/toxi/geom/Matrix3d.java +3048 -0
- data/src/toxi/geom/Matrix4f.java +3446 -0
- data/src/toxi/geom/Matrix4x4.java +1076 -0
- data/src/toxi/geom/MatrixSizeException.java +58 -0
- data/src/toxi/geom/OctreeVisitor.java +44 -0
- data/src/toxi/geom/Origin3D.java +148 -0
- data/src/toxi/geom/Plane.java +293 -0
- data/src/toxi/geom/PlaneIntersector.java +57 -0
- data/src/toxi/geom/PointCloud3D.java +253 -0
- data/src/toxi/geom/PointOctree.java +502 -0
- data/src/toxi/geom/PointQuadtree.java +375 -0
- data/src/toxi/geom/Polygon2D.java +1038 -0
- data/src/toxi/geom/PolygonClipper2D.java +45 -0
- data/src/toxi/geom/PolygonTesselator.java +20 -0
- data/src/toxi/geom/QuadtreeVisitor.java +44 -0
- data/src/toxi/geom/Quaternion.java +641 -0
- data/src/toxi/geom/Ray2D.java +146 -0
- data/src/toxi/geom/Ray3D.java +150 -0
- data/src/toxi/geom/Ray3DIntersector.java +75 -0
- data/src/toxi/geom/ReadonlyVec2D.java +575 -0
- data/src/toxi/geom/ReadonlyVec3D.java +628 -0
- data/src/toxi/geom/ReadonlyVec4D.java +431 -0
- data/src/toxi/geom/Rect.java +720 -0
- data/src/toxi/geom/Reflector3D.java +58 -0
- data/src/toxi/geom/Shape2D.java +94 -0
- data/src/toxi/geom/Shape3D.java +42 -0
- data/src/toxi/geom/SingularMatrixException.java +57 -0
- data/src/toxi/geom/SpatialBins.java +182 -0
- data/src/toxi/geom/SpatialIndex.java +61 -0
- data/src/toxi/geom/Sphere.java +224 -0
- data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
- data/src/toxi/geom/Spline2D.java +349 -0
- data/src/toxi/geom/Spline3D.java +351 -0
- data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
- data/src/toxi/geom/Triangle2D.java +422 -0
- data/src/toxi/geom/Triangle3D.java +456 -0
- data/src/toxi/geom/TriangleIntersector.java +105 -0
- data/src/toxi/geom/Vec2D.java +1328 -0
- data/src/toxi/geom/Vec3D.java +1832 -0
- data/src/toxi/geom/Vec4D.java +985 -0
- data/src/toxi/geom/VecMathUtil.java +100 -0
- data/src/toxi/geom/XAxisCylinder.java +64 -0
- data/src/toxi/geom/YAxisCylinder.java +65 -0
- data/src/toxi/geom/ZAxisCylinder.java +64 -0
- data/src/toxi/geom/mesh/BezierPatch.java +200 -0
- data/src/toxi/geom/mesh/BoxSelector.java +62 -0
- data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
- data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
- data/src/toxi/geom/mesh/Face.java +176 -0
- data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
- data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
- data/src/toxi/geom/mesh/Mesh3D.java +224 -0
- data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
- data/src/toxi/geom/mesh/OBJWriter.java +194 -0
- data/src/toxi/geom/mesh/PLYWriter.java +167 -0
- data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
- data/src/toxi/geom/mesh/STLColorModel.java +54 -0
- data/src/toxi/geom/mesh/STLReader.java +185 -0
- data/src/toxi/geom/mesh/STLWriter.java +323 -0
- data/src/toxi/geom/mesh/SphereFunction.java +156 -0
- data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
- data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
- data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
- data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
- data/src/toxi/geom/mesh/Terrain.java +451 -0
- data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
- data/src/toxi/geom/mesh/Vertex.java +78 -0
- data/src/toxi/geom/mesh/VertexSelector.java +193 -0
- data/src/toxi/geom/mesh/WEFace.java +100 -0
- data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
- data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
- data/src/toxi/geom/mesh/WEVertex.java +134 -0
- data/src/toxi/geom/mesh/WingedEdge.java +115 -0
- data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
- data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
- data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
- data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
- data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
- data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
- data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
- data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
- data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
- data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
- data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
- data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
- data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
- data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
- data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
- data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
- data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
- data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
- data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
- data/src/toxi/geom/nurbs/ControlNet.java +148 -0
- data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
- data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
- data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
- data/src/toxi/geom/nurbs/KnotVector.java +333 -0
- data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
- data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
- data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
- data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
- data/src/toxi/image/util/Filter8bit.java +331 -0
- data/src/toxi/image/util/TiledFrameExporter.java +162 -0
- data/src/toxi/math/BezierInterpolation.java +102 -0
- data/src/toxi/math/CircularInterpolation.java +88 -0
- data/src/toxi/math/CosineInterpolation.java +51 -0
- data/src/toxi/math/DecimatedInterpolation.java +77 -0
- data/src/toxi/math/ExponentialInterpolation.java +68 -0
- data/src/toxi/math/InterpolateStrategy.java +60 -0
- data/src/toxi/math/Interpolation2D.java +93 -0
- data/src/toxi/math/LinearInterpolation.java +46 -0
- data/src/toxi/math/MathUtils.java +990 -0
- data/src/toxi/math/NonLinearScaleMap.java +101 -0
- data/src/toxi/math/ScaleMap.java +183 -0
- data/src/toxi/math/SigmoidInterpolation.java +78 -0
- data/src/toxi/math/SinCosLUT.java +141 -0
- data/src/toxi/math/ThresholdInterpolation.java +58 -0
- data/src/toxi/math/ZoomLensInterpolation.java +126 -0
- data/src/toxi/math/conversion/UnitTranslator.java +161 -0
- data/src/toxi/math/noise/PerlinNoise.java +281 -0
- data/src/toxi/math/noise/SimplexNoise.java +542 -0
- data/src/toxi/math/waves/AMFMSineWave.java +143 -0
- data/src/toxi/math/waves/AbstractWave.java +248 -0
- data/src/toxi/math/waves/ConstantWave.java +48 -0
- data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
- data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
- data/src/toxi/math/waves/FMSineWave.java +142 -0
- data/src/toxi/math/waves/FMSquareWave.java +143 -0
- data/src/toxi/math/waves/FMTriangleWave.java +126 -0
- data/src/toxi/math/waves/SineWave.java +81 -0
- data/src/toxi/math/waves/Wave2D.java +68 -0
- data/src/toxi/math/waves/WaveState.java +69 -0
- data/src/toxi/music/scale/AbstractScale.java +117 -0
- data/src/toxi/music/scale/GenericScale.java +66 -0
- data/src/toxi/music/scale/MajorScale.java +41 -0
- data/src/toxi/newmesh/AttributedEdge.java +106 -0
- data/src/toxi/newmesh/AttributedFace.java +63 -0
- data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
- data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
- data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
- data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
- data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
- data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
- data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
- data/src/toxi/newmesh/SpatialIndex.java +78 -0
- data/src/toxi/physics2d/ParticlePath2D.java +100 -0
- data/src/toxi/physics2d/ParticleString2D.java +184 -0
- data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
- data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
- data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
- data/src/toxi/physics2d/VerletParticle2D.java +457 -0
- data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
- data/src/toxi/physics2d/VerletSpring2D.java +181 -0
- data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
- data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
- data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
- data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
- data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
- data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
- data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
- data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
- data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
- data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
- data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
- data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
- data/src/toxi/physics3d/ParticlePath3D.java +100 -0
- data/src/toxi/physics3d/ParticleString3D.java +184 -0
- data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
- data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
- data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
- data/src/toxi/physics3d/VerletParticle3D.java +385 -0
- data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
- data/src/toxi/physics3d/VerletSpring3D.java +180 -0
- data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
- data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
- data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
- data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
- data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
- data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
- data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
- data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
- data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
- data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
- data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
- data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
- data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
- data/src/toxi/processing/ArrowModifier.java +116 -0
- data/src/toxi/processing/DashedLineModifier.java +48 -0
- data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
- data/src/toxi/processing/Line2DRenderModifier.java +18 -0
- data/src/toxi/processing/MeshToVBO.java +94 -0
- data/src/toxi/processing/NormalMapper.java +18 -0
- data/src/toxi/processing/POVInterface.java +121 -0
- data/src/toxi/processing/POVMesh.java +219 -0
- data/src/toxi/processing/POVWriter.java +460 -0
- data/src/toxi/processing/RCOpaque.java +77 -0
- data/src/toxi/processing/RCTransp.java +78 -0
- data/src/toxi/processing/TextureBuilder.java +232 -0
- data/src/toxi/processing/Textures.java +110 -0
- data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
- data/src/toxi/processing/Tracing.java +25 -0
- data/src/toxi/processing/XYZNormalMapper.java +30 -0
- data/src/toxi/sim/automata/CAMatrix.java +297 -0
- data/src/toxi/sim/automata/CARule.java +76 -0
- data/src/toxi/sim/automata/CARule2D.java +354 -0
- data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
- data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
- data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
- data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
- data/src/toxi/sim/dla/DLA.java +497 -0
- data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
- data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
- data/src/toxi/sim/dla/DLAEventListener.java +57 -0
- data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
- data/src/toxi/sim/dla/DLAParticle.java +102 -0
- data/src/toxi/sim/dla/DLASegment.java +88 -0
- data/src/toxi/sim/dla/PipelineOrder.java +50 -0
- data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
- data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
- data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
- data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
- data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
- data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
- data/src/toxi/sim/grayscott/GrayScott.java +469 -0
- data/src/toxi/util/DateUtils.java +141 -0
- data/src/toxi/util/FileSequenceDescriptor.java +181 -0
- data/src/toxi/util/FileUtils.java +467 -0
- data/src/toxi/util/datatypes/ArraySet.java +128 -0
- data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
- data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
- data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
- data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
- data/src/toxi/util/datatypes/DoubleRange.java +251 -0
- data/src/toxi/util/datatypes/FloatRange.java +251 -0
- data/src/toxi/util/datatypes/GenericSet.java +215 -0
- data/src/toxi/util/datatypes/IntegerRange.java +247 -0
- data/src/toxi/util/datatypes/IntegerSet.java +149 -0
- data/src/toxi/util/datatypes/ItemIndex.java +72 -0
- data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
- data/src/toxi/util/datatypes/TypedProperties.java +291 -0
- data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
- data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
- data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
- data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
- data/src/toxi/util/events/EventDispatcher.java +86 -0
- data/src/toxi/volume/AdditiveBrush.java +19 -0
- data/src/toxi/volume/ArrayIsoSurface.java +297 -0
- data/src/toxi/volume/BoxBrush.java +100 -0
- data/src/toxi/volume/BrushMode.java +16 -0
- data/src/toxi/volume/HashIsoSurface.java +354 -0
- data/src/toxi/volume/IsoSurface.java +59 -0
- data/src/toxi/volume/MarchingCubesIndex.java +312 -0
- data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
- data/src/toxi/volume/MeshVoxelizer.java +216 -0
- data/src/toxi/volume/MultiplyBrush.java +20 -0
- data/src/toxi/volume/PeakBrush.java +21 -0
- data/src/toxi/volume/ReplaceBrush.java +19 -0
- data/src/toxi/volume/RoundBrush.java +113 -0
- data/src/toxi/volume/VolumetricBrush.java +160 -0
- data/src/toxi/volume/VolumetricHashMap.java +179 -0
- data/src/toxi/volume/VolumetricSpace.java +195 -0
- data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
- data/toxiclibs.gemspec +34 -0
- metadata +424 -27
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package toxi.volume;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @author tux
|
|
6
|
+
*/
|
|
7
|
+
public class AdditiveBrush implements BrushMode {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param orig
|
|
12
|
+
* @param brush
|
|
13
|
+
* @return
|
|
14
|
+
*/
|
|
15
|
+
@Override
|
|
16
|
+
public final float apply(float orig, float brush) {
|
|
17
|
+
return orig + brush;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* __ .__ .__ ._____.
|
|
3
|
+
* _/ |_ _______ __|__| ____ | | |__\_ |__ ______
|
|
4
|
+
* \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
|
|
5
|
+
* | | ( <_> > <| \ \___| |_| || \_\ \\___ \
|
|
6
|
+
* |__| \____/__/\_ \__|\___ >____/__||___ /____ >
|
|
7
|
+
* \/ \/ \/ \/
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2006-2011 Karsten Schmidt
|
|
10
|
+
*
|
|
11
|
+
* This library is free software; you can redistribute it and/or
|
|
12
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
* License as published by the Free Software Foundation; either
|
|
14
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
*
|
|
16
|
+
* http://creativecommons.org/licenses/LGPL/2.1/
|
|
17
|
+
*
|
|
18
|
+
* This library is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
21
|
+
* Lesser General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
24
|
+
* License along with this library; if not, write to the Free Software
|
|
25
|
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
package toxi.volume;
|
|
29
|
+
|
|
30
|
+
import java.util.logging.Logger;
|
|
31
|
+
|
|
32
|
+
import toxi.geom.Vec3D;
|
|
33
|
+
import toxi.geom.mesh.Mesh3D;
|
|
34
|
+
import toxi.geom.mesh.TriangleMesh;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* IsoSurface class based on C version by Paul Bourke and Lingo version by
|
|
38
|
+
* myself.
|
|
39
|
+
*/
|
|
40
|
+
public class ArrayIsoSurface implements IsoSurface {
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
protected static final Logger logger = Logger
|
|
46
|
+
.getLogger(ArrayIsoSurface.class.getName());
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
protected Vec3D cellSize;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
protected Vec3D centreOffset;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
protected VolumetricSpace volume;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
public float isoValue;
|
|
67
|
+
|
|
68
|
+
protected int resX,
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
*/
|
|
77
|
+
resY,
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
*/
|
|
86
|
+
resZ;
|
|
87
|
+
protected int resX1,
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
*
|
|
91
|
+
*/
|
|
92
|
+
resY1,
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
*/
|
|
101
|
+
resZ1;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
protected int sliceRes;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
*/
|
|
111
|
+
protected int nextXY;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
*/
|
|
116
|
+
protected Vec3D[] edgeVertices;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
* @param volume
|
|
121
|
+
*/
|
|
122
|
+
public ArrayIsoSurface(VolumetricSpace volume) {
|
|
123
|
+
this.volume = volume;
|
|
124
|
+
cellSize = new Vec3D(volume.scale.x / volume.resX1, volume.scale.y
|
|
125
|
+
/ volume.resY1, volume.scale.z / volume.resZ1);
|
|
126
|
+
|
|
127
|
+
resX = volume.resX;
|
|
128
|
+
resY = volume.resY;
|
|
129
|
+
resZ = volume.resZ;
|
|
130
|
+
resX1 = volume.resX1;
|
|
131
|
+
resY1 = volume.resY1;
|
|
132
|
+
resZ1 = volume.resZ1;
|
|
133
|
+
|
|
134
|
+
sliceRes = volume.sliceRes;
|
|
135
|
+
nextXY = resX + sliceRes;
|
|
136
|
+
|
|
137
|
+
centreOffset = volume.halfScale.getInverted();
|
|
138
|
+
|
|
139
|
+
edgeVertices = new Vec3D[3 * volume.numCells];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Computes the surface mesh for the given volumetric data and iso value.
|
|
144
|
+
*/
|
|
145
|
+
@Override
|
|
146
|
+
public Mesh3D computeSurfaceMesh(Mesh3D mesh, final float iso) {
|
|
147
|
+
if (mesh == null) {
|
|
148
|
+
mesh = new TriangleMesh("isosurface-" + iso);
|
|
149
|
+
} else {
|
|
150
|
+
mesh.clear();
|
|
151
|
+
}
|
|
152
|
+
isoValue = iso;
|
|
153
|
+
float offsetZ = centreOffset.z;
|
|
154
|
+
for (int z = 0; z < resZ1; z++) {
|
|
155
|
+
int sliceOffset = sliceRes * z;
|
|
156
|
+
float offsetY = centreOffset.y;
|
|
157
|
+
for (int y = 0; y < resY1; y++) {
|
|
158
|
+
float offsetX = centreOffset.x;
|
|
159
|
+
int offset = resX * y + sliceOffset;
|
|
160
|
+
for (int x = 0; x < resX1; x++) {
|
|
161
|
+
final int cellIndex = getCellIndex(x, y, z);
|
|
162
|
+
if (cellIndex > 0 && cellIndex < 255) {
|
|
163
|
+
final int edgeFlags = MarchingCubesIndex.edgesToCompute[cellIndex];
|
|
164
|
+
if (edgeFlags > 0 && edgeFlags < 255) {
|
|
165
|
+
int edgeOffsetIndex = offset * 3;
|
|
166
|
+
float offsetData = volume.getVoxelAt(offset);
|
|
167
|
+
float isoDiff = isoValue - offsetData;
|
|
168
|
+
if ((edgeFlags & 1) > 0) {
|
|
169
|
+
if (edgeVertices[edgeOffsetIndex] == null) {
|
|
170
|
+
float t = isoDiff
|
|
171
|
+
/ (volume.getVoxelAt(offset + 1) - offsetData);
|
|
172
|
+
edgeVertices[edgeOffsetIndex] = new Vec3D(
|
|
173
|
+
offsetX + t * cellSize.x, y
|
|
174
|
+
* cellSize.y
|
|
175
|
+
+ centreOffset.y, z
|
|
176
|
+
* cellSize.z
|
|
177
|
+
+ centreOffset.z);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if ((edgeFlags & 2) > 0) {
|
|
181
|
+
if (edgeVertices[edgeOffsetIndex + 1] == null) {
|
|
182
|
+
float t = isoDiff
|
|
183
|
+
/ (volume.getVoxelAt(offset + resX) - offsetData);
|
|
184
|
+
edgeVertices[edgeOffsetIndex + 1] = new Vec3D(
|
|
185
|
+
x * cellSize.x + centreOffset.x,
|
|
186
|
+
offsetY + t * cellSize.y, z
|
|
187
|
+
* cellSize.z
|
|
188
|
+
+ centreOffset.z);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if ((edgeFlags & 4) > 0) {
|
|
192
|
+
if (edgeVertices[edgeOffsetIndex + 2] == null) {
|
|
193
|
+
float t = isoDiff
|
|
194
|
+
/ (volume.getVoxelAt(offset
|
|
195
|
+
+ sliceRes) - offsetData);
|
|
196
|
+
edgeVertices[edgeOffsetIndex + 2] = new Vec3D(
|
|
197
|
+
x * cellSize.x + centreOffset.x, y
|
|
198
|
+
* cellSize.y
|
|
199
|
+
+ centreOffset.y, offsetZ
|
|
200
|
+
+ t * cellSize.z);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
offsetX += cellSize.x;
|
|
206
|
+
offset++;
|
|
207
|
+
}
|
|
208
|
+
offsetY += cellSize.y;
|
|
209
|
+
}
|
|
210
|
+
offsetZ += cellSize.z;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
final int[] face = new int[16];
|
|
214
|
+
for (int z = 0; z < resZ1; z++) {
|
|
215
|
+
int sliceOffset = sliceRes * z;
|
|
216
|
+
for (int y = 0; y < resY1; y++) {
|
|
217
|
+
int offset = resX * y + sliceOffset;
|
|
218
|
+
for (int x = 0; x < resX1; x++) {
|
|
219
|
+
final int cellIndex = getCellIndex(x, y, z);
|
|
220
|
+
if (cellIndex > 0 && cellIndex < 255) {
|
|
221
|
+
int n = 0;
|
|
222
|
+
int edgeIndex;
|
|
223
|
+
final int[] cellTriangles = MarchingCubesIndex.cellTriangles[cellIndex];
|
|
224
|
+
while ((edgeIndex = cellTriangles[n]) != -1) {
|
|
225
|
+
int[] edgeOffsetInfo = MarchingCubesIndex.edgeOffsets[edgeIndex];
|
|
226
|
+
face[n] = ((x + edgeOffsetInfo[0]) + resX
|
|
227
|
+
* (y + edgeOffsetInfo[1]) + sliceRes
|
|
228
|
+
* (z + edgeOffsetInfo[2]))
|
|
229
|
+
* 3 + edgeOffsetInfo[3];
|
|
230
|
+
n++;
|
|
231
|
+
}
|
|
232
|
+
for (int i = 0; i < n; i += 3) {
|
|
233
|
+
final Vec3D va = edgeVertices[face[i + 1]];
|
|
234
|
+
final Vec3D vb = edgeVertices[face[i + 2]];
|
|
235
|
+
final Vec3D vc = edgeVertices[face[i]];
|
|
236
|
+
if (va != null && vb != null && vc != null) {
|
|
237
|
+
mesh.addFace(va, vb, vc);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
offset++;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return mesh;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
*
|
|
250
|
+
* @param x
|
|
251
|
+
* @param y
|
|
252
|
+
* @param z
|
|
253
|
+
* @return
|
|
254
|
+
*/
|
|
255
|
+
protected final int getCellIndex(int x, int y, int z) {
|
|
256
|
+
int cellIndex = 0;
|
|
257
|
+
int idx = x + y * resX + z * sliceRes;
|
|
258
|
+
if (volume.getVoxelAt(idx) < isoValue) {
|
|
259
|
+
cellIndex |= 0x01;
|
|
260
|
+
}
|
|
261
|
+
if (volume.getVoxelAt(idx + sliceRes) < isoValue) {
|
|
262
|
+
cellIndex |= 0x08;
|
|
263
|
+
}
|
|
264
|
+
if (volume.getVoxelAt(idx + resX) < isoValue) {
|
|
265
|
+
cellIndex |= 0x10;
|
|
266
|
+
}
|
|
267
|
+
if (volume.getVoxelAt(idx + resX + sliceRes) < isoValue) {
|
|
268
|
+
cellIndex |= 0x80;
|
|
269
|
+
}
|
|
270
|
+
idx++;
|
|
271
|
+
if (volume.getVoxelAt(idx) < isoValue) {
|
|
272
|
+
cellIndex |= 0x02;
|
|
273
|
+
}
|
|
274
|
+
if (volume.getVoxelAt(idx + sliceRes) < isoValue) {
|
|
275
|
+
cellIndex |= 0x04;
|
|
276
|
+
}
|
|
277
|
+
if (volume.getVoxelAt(idx + resX) < isoValue) {
|
|
278
|
+
cellIndex |= 0x20;
|
|
279
|
+
}
|
|
280
|
+
if (volume.getVoxelAt(idx + resX + sliceRes) < isoValue) {
|
|
281
|
+
cellIndex |= 0x40;
|
|
282
|
+
}
|
|
283
|
+
return cellIndex;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Resets mesh vertices to default positions and clears face index. Needs to
|
|
288
|
+
* be called inbetween successive calls to
|
|
289
|
+
* {@link #computeSurfaceMesh(Mesh3D, float)}
|
|
290
|
+
*/
|
|
291
|
+
@Override
|
|
292
|
+
public void reset() {
|
|
293
|
+
for (int i = 0; i < edgeVertices.length; i++) {
|
|
294
|
+
edgeVertices[i] = null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* __ .__ .__ ._____.
|
|
3
|
+
* _/ |_ _______ __|__| ____ | | |__\_ |__ ______
|
|
4
|
+
* \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
|
|
5
|
+
* | | ( <_> > <| \ \___| |_| || \_\ \\___ \
|
|
6
|
+
* |__| \____/__/\_ \__|\___ >____/__||___ /____ >
|
|
7
|
+
* \/ \/ \/ \/
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2006-2011 Karsten Schmidt
|
|
10
|
+
*
|
|
11
|
+
* This library is free software; you can redistribute it and/or
|
|
12
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
* License as published by the Free Software Foundation; either
|
|
14
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
*
|
|
16
|
+
* http://creativecommons.org/licenses/LGPL/2.1/
|
|
17
|
+
*
|
|
18
|
+
* This library is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
21
|
+
* Lesser General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
24
|
+
* License along with this library; if not, write to the Free Software
|
|
25
|
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
package toxi.volume;
|
|
29
|
+
|
|
30
|
+
import java.util.logging.Level;
|
|
31
|
+
|
|
32
|
+
import toxi.math.MathUtils;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @author tux
|
|
37
|
+
*/
|
|
38
|
+
public class BoxBrush extends VolumetricBrush {
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param volume
|
|
43
|
+
* @param size
|
|
44
|
+
*/
|
|
45
|
+
public BoxBrush(VolumetricSpace volume, float size) {
|
|
46
|
+
super(volume);
|
|
47
|
+
setSize(size);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param cx
|
|
53
|
+
* @param cy
|
|
54
|
+
* @param cz
|
|
55
|
+
* @param density
|
|
56
|
+
*/
|
|
57
|
+
@Override
|
|
58
|
+
public void drawAtGridPos(float cx, float cy, float cz, float density) {
|
|
59
|
+
int minX = MathUtils.max(Math.round(cx - cellRadiusX), 0);
|
|
60
|
+
int minY = MathUtils.max(Math.round(cy - cellRadiusY), 0);
|
|
61
|
+
int minZ = MathUtils.max(Math.round(cz - cellRadiusZ), 0);
|
|
62
|
+
int maxX = MathUtils.min(Math.round(cx + cellRadiusX), volume.resX);
|
|
63
|
+
int maxY = MathUtils.min(Math.round(cy + cellRadiusY), volume.resY);
|
|
64
|
+
int maxZ = MathUtils.min(Math.round(cz + cellRadiusZ), volume.resZ);
|
|
65
|
+
for (int z = minZ; z < maxZ; z++) {
|
|
66
|
+
for (int y = minY; y < maxY; y++) {
|
|
67
|
+
for (int x = minX; x < maxX; x++) {
|
|
68
|
+
updateVoxel(x, y, z, density);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @param size
|
|
77
|
+
*/
|
|
78
|
+
@Override
|
|
79
|
+
public final void setSize(float size) {
|
|
80
|
+
setSize(size, size, size);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
* @param sizeX
|
|
86
|
+
* @param sizeY
|
|
87
|
+
* @param sizeZ
|
|
88
|
+
*/
|
|
89
|
+
public void setSize(float sizeX, float sizeY, float sizeZ) {
|
|
90
|
+
this.cellRadiusX = (int) (sizeX * 0.5f / volume.scale.x * volume.resX + 1);
|
|
91
|
+
this.cellRadiusY = (int) (sizeY * 0.5f / volume.scale.y * volume.resY + 1);
|
|
92
|
+
this.cellRadiusZ = (int) (sizeZ * 0.5f / volume.scale.z * volume.resZ + 1);
|
|
93
|
+
stretchY = (float) cellRadiusX / cellRadiusY;
|
|
94
|
+
stretchZ = (float) cellRadiusX / cellRadiusZ;
|
|
95
|
+
if (logger.isLoggable(Level.FINE)) {
|
|
96
|
+
logger.log(Level.FINE, "new brush size: {0}x{1}x{2}", new Object[]{cellRadiusX, cellRadiusY, cellRadiusZ});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* __ .__ .__ ._____.
|
|
3
|
+
* _/ |_ _______ __|__| ____ | | |__\_ |__ ______
|
|
4
|
+
* \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
|
|
5
|
+
* | | ( <_> > <| \ \___| |_| || \_\ \\___ \
|
|
6
|
+
* |__| \____/__/\_ \__|\___ >____/__||___ /____ >
|
|
7
|
+
* \/ \/ \/ \/
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2006-2011 Karsten Schmidt
|
|
10
|
+
*
|
|
11
|
+
* This library is free software; you can redistribute it and/or
|
|
12
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
* License as published by the Free Software Foundation; either
|
|
14
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
*
|
|
16
|
+
* http://creativecommons.org/licenses/LGPL/2.1/
|
|
17
|
+
*
|
|
18
|
+
* This library is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
21
|
+
* Lesser General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
24
|
+
* License along with this library; if not, write to the Free Software
|
|
25
|
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
package toxi.volume;
|
|
29
|
+
|
|
30
|
+
import java.util.HashMap;
|
|
31
|
+
import java.util.Iterator;
|
|
32
|
+
import java.util.Map.Entry;
|
|
33
|
+
import java.util.logging.Level;
|
|
34
|
+
import java.util.logging.Logger;
|
|
35
|
+
|
|
36
|
+
import toxi.geom.Vec3D;
|
|
37
|
+
import toxi.geom.mesh.Mesh3D;
|
|
38
|
+
import toxi.geom.mesh.TriangleMesh;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* HashMap based implementation of the IsoSurface interface. More memory
|
|
42
|
+
* efficient than {@link ArrayIsoSurface} and so better suited for very
|
|
43
|
+
* high-resolution volumes.
|
|
44
|
+
*/
|
|
45
|
+
public class HashIsoSurface implements IsoSurface {
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
protected static final Logger logger = Logger
|
|
51
|
+
.getLogger(HashIsoSurface.class.getName());
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
protected Vec3D cellSize;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
protected Vec3D centreOffset;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
protected VolumetricSpace volume;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
71
|
+
public float isoValue;
|
|
72
|
+
|
|
73
|
+
protected int resX,
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
*/
|
|
82
|
+
resY,
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
*/
|
|
91
|
+
resZ;
|
|
92
|
+
protected int resX1,
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
resY1,
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
resZ1;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
*/
|
|
111
|
+
protected int sliceRes;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
*/
|
|
116
|
+
protected int nextXY;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
*/
|
|
121
|
+
protected HashMap<Integer, Vec3D> edgeVertices;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
*/
|
|
126
|
+
protected float density;
|
|
127
|
+
|
|
128
|
+
protected short[] cellIndexCache,
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
prevCellIndexCache;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Creates a new instance using the expected default vertex density of 50%.
|
|
141
|
+
*
|
|
142
|
+
* @see #setExpectedDensity(float)
|
|
143
|
+
*
|
|
144
|
+
* @param volume
|
|
145
|
+
*/
|
|
146
|
+
public HashIsoSurface(VolumetricSpace volume) {
|
|
147
|
+
this(volume, 0.5f);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates a new instance using the given expected vertex density.
|
|
152
|
+
*
|
|
153
|
+
* @param density
|
|
154
|
+
* @see #setExpectedDensity(float)
|
|
155
|
+
*
|
|
156
|
+
* @param volume
|
|
157
|
+
*/
|
|
158
|
+
public HashIsoSurface(VolumetricSpace volume, float density) {
|
|
159
|
+
this.volume = volume;
|
|
160
|
+
this.density = density;
|
|
161
|
+
cellSize = new Vec3D(volume.scale.x / volume.resX1, volume.scale.y
|
|
162
|
+
/ volume.resY1, volume.scale.z / volume.resZ1);
|
|
163
|
+
|
|
164
|
+
resX = volume.resX;
|
|
165
|
+
resY = volume.resY;
|
|
166
|
+
resZ = volume.resZ;
|
|
167
|
+
resX1 = volume.resX1;
|
|
168
|
+
resY1 = volume.resY1;
|
|
169
|
+
resZ1 = volume.resZ1;
|
|
170
|
+
|
|
171
|
+
sliceRes = volume.sliceRes;
|
|
172
|
+
nextXY = resX + sliceRes;
|
|
173
|
+
|
|
174
|
+
cellIndexCache = new short[sliceRes];
|
|
175
|
+
prevCellIndexCache = new short[sliceRes];
|
|
176
|
+
|
|
177
|
+
centreOffset = volume.halfScale.getInverted();
|
|
178
|
+
reset();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@Override
|
|
182
|
+
public Mesh3D computeSurfaceMesh(Mesh3D mesh, final float iso) {
|
|
183
|
+
if (mesh == null) {
|
|
184
|
+
mesh = new TriangleMesh("isosurface-" + iso);
|
|
185
|
+
} else {
|
|
186
|
+
mesh.clear();
|
|
187
|
+
}
|
|
188
|
+
isoValue = iso;
|
|
189
|
+
float offsetZ = centreOffset.z;
|
|
190
|
+
for (int z = 0; z < resZ1; z++) {
|
|
191
|
+
int sliceOffset = sliceRes * z;
|
|
192
|
+
float offsetY = centreOffset.y;
|
|
193
|
+
for (int y = 0; y < resY1; y++) {
|
|
194
|
+
float offsetX = centreOffset.x;
|
|
195
|
+
int sliceIndex = resX * y;
|
|
196
|
+
int offset = sliceIndex + sliceOffset;
|
|
197
|
+
for (int x = 0; x < resX1; x++) {
|
|
198
|
+
final int cellIndex = getCellIndex(x, y, z);
|
|
199
|
+
cellIndexCache[sliceIndex + x] = (short) cellIndex;
|
|
200
|
+
if (cellIndex > 0 && cellIndex < 255) {
|
|
201
|
+
final int edgeFlags = MarchingCubesIndex.edgesToCompute[cellIndex];
|
|
202
|
+
if (edgeFlags > 0 && edgeFlags < 255) {
|
|
203
|
+
int edgeOffsetIndex = offset * 3;
|
|
204
|
+
float offsetData = volume.getVoxelAt(offset);
|
|
205
|
+
float isoDiff = isoValue - offsetData;
|
|
206
|
+
if ((edgeFlags & 1) > 0) {
|
|
207
|
+
float t = isoDiff
|
|
208
|
+
/ (volume.getVoxelAt(offset + 1) - offsetData);
|
|
209
|
+
edgeVertices.put(edgeOffsetIndex, new Vec3D(
|
|
210
|
+
offsetX + t * cellSize.x, y
|
|
211
|
+
* cellSize.y + centreOffset.y,
|
|
212
|
+
z * cellSize.z + centreOffset.z));
|
|
213
|
+
}
|
|
214
|
+
if ((edgeFlags & 2) > 0) {
|
|
215
|
+
float t = isoDiff
|
|
216
|
+
/ (volume.getVoxelAt(offset + resX) - offsetData);
|
|
217
|
+
edgeVertices.put(edgeOffsetIndex + 1,
|
|
218
|
+
new Vec3D(x * cellSize.x
|
|
219
|
+
+ centreOffset.x, offsetY + t
|
|
220
|
+
* cellSize.y, z * cellSize.z
|
|
221
|
+
+ centreOffset.z));
|
|
222
|
+
}
|
|
223
|
+
if ((edgeFlags & 4) > 0) {
|
|
224
|
+
float t = isoDiff
|
|
225
|
+
/ (volume.getVoxelAt(offset + sliceRes) - offsetData);
|
|
226
|
+
edgeVertices.put(edgeOffsetIndex + 2,
|
|
227
|
+
new Vec3D(x * cellSize.x
|
|
228
|
+
+ centreOffset.x, y
|
|
229
|
+
* cellSize.y + centreOffset.y,
|
|
230
|
+
offsetZ + t * cellSize.z));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
offsetX += cellSize.x;
|
|
235
|
+
offset++;
|
|
236
|
+
}
|
|
237
|
+
offsetY += cellSize.y;
|
|
238
|
+
}
|
|
239
|
+
if (z > 0) {
|
|
240
|
+
createFacesForSlice(mesh, z - 1);
|
|
241
|
+
}
|
|
242
|
+
short[] tmp = prevCellIndexCache;
|
|
243
|
+
prevCellIndexCache = cellIndexCache;
|
|
244
|
+
cellIndexCache = tmp;
|
|
245
|
+
offsetZ += cellSize.z;
|
|
246
|
+
}
|
|
247
|
+
createFacesForSlice(mesh, resZ1 - 1);
|
|
248
|
+
return mesh;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private void createFacesForSlice(Mesh3D mesh, int z) {
|
|
252
|
+
if (logger.isLoggable(Level.FINE)) {
|
|
253
|
+
logger.log(Level.FINE, "creating polygons for slice: {0}", z);
|
|
254
|
+
}
|
|
255
|
+
int[] face = new int[16];
|
|
256
|
+
int sliceOffset = sliceRes * z;
|
|
257
|
+
for (int y = 0; y < resY1; y++) {
|
|
258
|
+
int offset = resX * y;
|
|
259
|
+
for (int x = 0; x < resX1; x++) {
|
|
260
|
+
final int cellIndex = prevCellIndexCache[offset];
|
|
261
|
+
if (cellIndex > 0 && cellIndex < 255) {
|
|
262
|
+
int n = 0;
|
|
263
|
+
int edgeIndex;
|
|
264
|
+
int[] cellTriangles = MarchingCubesIndex.cellTriangles[cellIndex];
|
|
265
|
+
while ((edgeIndex = cellTriangles[n]) != -1) {
|
|
266
|
+
int[] edgeOffsetInfo = MarchingCubesIndex.edgeOffsets[edgeIndex];
|
|
267
|
+
face[n] = ((x + edgeOffsetInfo[0]) + resX
|
|
268
|
+
* (y + edgeOffsetInfo[1]) + sliceRes
|
|
269
|
+
* (z + edgeOffsetInfo[2]))
|
|
270
|
+
* 3 + edgeOffsetInfo[3];
|
|
271
|
+
n++;
|
|
272
|
+
}
|
|
273
|
+
for (int i = 0; i < n; i += 3) {
|
|
274
|
+
final Vec3D va = edgeVertices.get(face[i + 1]);
|
|
275
|
+
if (va != null) {
|
|
276
|
+
final Vec3D vb = edgeVertices.get(face[i + 2]);
|
|
277
|
+
if (vb != null) {
|
|
278
|
+
final Vec3D vc = edgeVertices.get(face[i]);
|
|
279
|
+
if (vc != null) {
|
|
280
|
+
mesh.addFace(va, vb, vc);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
offset++;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
int minIndex = sliceOffset * 3;
|
|
290
|
+
for (Iterator<Entry<Integer, Vec3D>> i = edgeVertices.entrySet()
|
|
291
|
+
.iterator(); i.hasNext();) {
|
|
292
|
+
if (i.next().getKey() < minIndex) {
|
|
293
|
+
i.remove();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
*
|
|
300
|
+
* @param x
|
|
301
|
+
* @param y
|
|
302
|
+
* @param z
|
|
303
|
+
* @return
|
|
304
|
+
*/
|
|
305
|
+
protected final int getCellIndex(int x, int y, int z) {
|
|
306
|
+
int cellIndex = 0;
|
|
307
|
+
int idx = x + y * resX + z * sliceRes;
|
|
308
|
+
if (volume.getVoxelAt(idx) < isoValue) {
|
|
309
|
+
cellIndex |= 0x01;
|
|
310
|
+
}
|
|
311
|
+
if (volume.getVoxelAt(idx + sliceRes) < isoValue) {
|
|
312
|
+
cellIndex |= 0x08;
|
|
313
|
+
}
|
|
314
|
+
if (volume.getVoxelAt(idx + resX) < isoValue) {
|
|
315
|
+
cellIndex |= 0x10;
|
|
316
|
+
}
|
|
317
|
+
if (volume.getVoxelAt(idx + resX + sliceRes) < isoValue) {
|
|
318
|
+
cellIndex |= 0x80;
|
|
319
|
+
}
|
|
320
|
+
idx++;
|
|
321
|
+
if (volume.getVoxelAt(idx) < isoValue) {
|
|
322
|
+
cellIndex |= 0x02;
|
|
323
|
+
}
|
|
324
|
+
if (volume.getVoxelAt(idx + sliceRes) < isoValue) {
|
|
325
|
+
cellIndex |= 0x04;
|
|
326
|
+
}
|
|
327
|
+
if (volume.getVoxelAt(idx + resX) < isoValue) {
|
|
328
|
+
cellIndex |= 0x20;
|
|
329
|
+
}
|
|
330
|
+
if (volume.getVoxelAt(idx + resX + sliceRes) < isoValue) {
|
|
331
|
+
cellIndex |= 0x40;
|
|
332
|
+
}
|
|
333
|
+
return cellIndex;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Resets mesh vertices to default positions and clears face index. Needs to
|
|
338
|
+
* be called inbetween successive calls to
|
|
339
|
+
* {@link #computeSurfaceMesh(Mesh3D, float)}.
|
|
340
|
+
*/
|
|
341
|
+
@Override
|
|
342
|
+
public final void reset() {
|
|
343
|
+
edgeVertices = new HashMap<>(
|
|
344
|
+
(int) (density * volume.numCells));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
*
|
|
349
|
+
* @param density
|
|
350
|
+
*/
|
|
351
|
+
public void setExpectedDensity(float density) {
|
|
352
|
+
this.density = density;
|
|
353
|
+
}
|
|
354
|
+
}
|