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,106 @@
|
|
|
1
|
+
package toxi.newmesh;
|
|
2
|
+
|
|
3
|
+
import java.util.ArrayList;
|
|
4
|
+
import java.util.List;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @author tux
|
|
9
|
+
*/
|
|
10
|
+
public class AttributedEdge {
|
|
11
|
+
|
|
12
|
+
public final int a,
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
b;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
public List<AttributedFace> faces;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param a
|
|
31
|
+
* @param b
|
|
32
|
+
*/
|
|
33
|
+
public AttributedEdge(int a, int b) {
|
|
34
|
+
this.a = a;
|
|
35
|
+
this.b = b;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param f
|
|
41
|
+
*/
|
|
42
|
+
public void addFace(AttributedFace f) {
|
|
43
|
+
if (faces == null) {
|
|
44
|
+
faces = new ArrayList<>(2);
|
|
45
|
+
}
|
|
46
|
+
faces.add(f);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* (non-Javadoc)
|
|
51
|
+
*
|
|
52
|
+
* @see java.lang.Object#equals(java.lang.Object)
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @param obj
|
|
58
|
+
* @return
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
@Override
|
|
62
|
+
public boolean equals(Object obj) {
|
|
63
|
+
if (this == obj) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (obj == null) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (getClass() != obj.getClass()) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
AttributedEdge other = (AttributedEdge) obj;
|
|
73
|
+
if (a != other.a) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return (b != other.b) ;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* (non-Javadoc)
|
|
81
|
+
*
|
|
82
|
+
* @see java.lang.Object#hashCode()
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* @return
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
@Override
|
|
91
|
+
public int hashCode() {
|
|
92
|
+
final int prime = 31;
|
|
93
|
+
int result = prime + a;
|
|
94
|
+
result = prime * result + b;
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @return
|
|
101
|
+
*/
|
|
102
|
+
@Override
|
|
103
|
+
public String toString() {
|
|
104
|
+
return String.format("a=%d, b=%d", a, b);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package toxi.newmesh;
|
|
2
|
+
|
|
3
|
+
import java.util.HashMap;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @author tux
|
|
8
|
+
*/
|
|
9
|
+
public class AttributedFace {
|
|
10
|
+
|
|
11
|
+
public int a,
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
b,
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
c;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
public int normal = -1;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
public HashMap<String, int[]> attribs;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @param a
|
|
44
|
+
* @param b
|
|
45
|
+
* @param c
|
|
46
|
+
* @param attribs
|
|
47
|
+
*/
|
|
48
|
+
public AttributedFace(int a, int b, int c, HashMap<String, int[]> attribs) {
|
|
49
|
+
this.a = a;
|
|
50
|
+
this.b = b;
|
|
51
|
+
this.c = c;
|
|
52
|
+
this.attribs = attribs;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @return
|
|
58
|
+
*/
|
|
59
|
+
@Override
|
|
60
|
+
public String toString() {
|
|
61
|
+
return String.format("a=%d,b=%d,c=%d,n=%d", a, b, c, normal);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
package toxi.newmesh;
|
|
2
|
+
|
|
3
|
+
import java.util.ArrayList;
|
|
4
|
+
import java.util.HashMap;
|
|
5
|
+
import java.util.HashSet;
|
|
6
|
+
import java.util.Iterator;
|
|
7
|
+
import java.util.List;
|
|
8
|
+
|
|
9
|
+
import toxi.geom.AABB;
|
|
10
|
+
import toxi.geom.IsectData3D;
|
|
11
|
+
import toxi.geom.Ray3D;
|
|
12
|
+
import toxi.geom.ReadonlyVec3D;
|
|
13
|
+
import toxi.geom.Sphere;
|
|
14
|
+
import toxi.geom.Triangle3D;
|
|
15
|
+
import toxi.geom.TriangleIntersector;
|
|
16
|
+
import toxi.geom.Vec2D;
|
|
17
|
+
import toxi.geom.Vec3D;
|
|
18
|
+
import toxi.geom.mesh.subdiv.NewSubdivStrategy;
|
|
19
|
+
import toxi.util.datatypes.ItemIndex;
|
|
20
|
+
import toxi.util.datatypes.UniqueItemIndex;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @author tux
|
|
25
|
+
*/
|
|
26
|
+
public class IndexedTriangleMesh {
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
public static final String ATTR_EDGES = "edges";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
public static final String ATTR_FNORMALS = "fnormals";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
*/
|
|
41
|
+
public static final String ATTR_UVCOORDS = "uv";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
public static final String ATTR_VCOLORS = "col";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
public static final String ATTR_VERTICES = "vertices";
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
public static final String ATTR_VNORMALS = "vnormals";
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
public SpatialIndex vertices = new SpatialIndex(0.001f);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
public ItemIndex<Vec3D> fnormals = new UniqueItemIndex<>();
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
71
|
+
public final ArrayList<AttributedFace> faces = new ArrayList<>();
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
*/
|
|
76
|
+
public final HashMap<String, UniqueItemIndex<Object>> attributes = new HashMap<>();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
public IndexedTriangleMesh() {
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
* @param a
|
|
87
|
+
* @param b
|
|
88
|
+
* @param c
|
|
89
|
+
* @param attribs
|
|
90
|
+
* @return
|
|
91
|
+
*/
|
|
92
|
+
public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c,
|
|
93
|
+
HashMap<String, Object[]> attribs) {
|
|
94
|
+
int idA = vertices.index(a);
|
|
95
|
+
int idB = vertices.index(b);
|
|
96
|
+
int idC = vertices.index(c);
|
|
97
|
+
if (idA != idB && idA != idC && idB != idC) {
|
|
98
|
+
AttributedFace f = new AttributedFace(idA, idB, idC,
|
|
99
|
+
addFaceAttributes(null, attribs));
|
|
100
|
+
faces.add(f);
|
|
101
|
+
}
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @param a
|
|
108
|
+
* @param b
|
|
109
|
+
* @param c
|
|
110
|
+
* @param uva
|
|
111
|
+
* @param uvb
|
|
112
|
+
* @param uvc
|
|
113
|
+
* @return
|
|
114
|
+
*/
|
|
115
|
+
public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec2D uva,
|
|
116
|
+
Vec2D uvb, Vec2D uvc) {
|
|
117
|
+
HashMap<String, Object[]> attribs = null;
|
|
118
|
+
if (uva != null && uvb != null && uvc != null) {
|
|
119
|
+
attribs = new HashMap<>();
|
|
120
|
+
attribs.put(ATTR_UVCOORDS, new Object[] {
|
|
121
|
+
uva, uvb, uvc
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return addFace(a, b, c, attribs);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
* @param f
|
|
130
|
+
* @param attrib
|
|
131
|
+
* @param attA
|
|
132
|
+
* @param attB
|
|
133
|
+
* @param attC
|
|
134
|
+
* @return
|
|
135
|
+
*/
|
|
136
|
+
public HashMap<String, int[]> addFaceAttribute(AttributedFace f,
|
|
137
|
+
String attrib, Object attA, Object attB, Object attC) {
|
|
138
|
+
if (f != null && attrib != null && attA != null && attB != null
|
|
139
|
+
&& attC != null) {
|
|
140
|
+
ItemIndex<Object> idx = getAttributeIndex(attrib);
|
|
141
|
+
f.attribs.put(attrib, new int[] {
|
|
142
|
+
idx.index(attA), idx.index(attB), idx.index(attC)
|
|
143
|
+
});
|
|
144
|
+
return f.attribs;
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
* @param f
|
|
152
|
+
* @param attribs
|
|
153
|
+
* @return
|
|
154
|
+
*/
|
|
155
|
+
public HashMap<String, int[]> addFaceAttributes(AttributedFace f,
|
|
156
|
+
HashMap<String, Object[]> attribs) {
|
|
157
|
+
HashMap<String, int[]> fattribs = null;
|
|
158
|
+
if (attribs != null) {
|
|
159
|
+
fattribs = (f != null) ? f.attribs : new HashMap<String, int[]>(
|
|
160
|
+
attribs.size(), 1);
|
|
161
|
+
for (String attID : attribs.keySet()) {
|
|
162
|
+
Object[] items = attribs.get(attID);
|
|
163
|
+
if (items.length >= 3) {
|
|
164
|
+
ItemIndex<Object> idx = getAttributeIndex(attID);
|
|
165
|
+
int[] ids = new int[] {
|
|
166
|
+
idx.index(items[0]), idx.index(items[1]),
|
|
167
|
+
idx.index(items[2])
|
|
168
|
+
};
|
|
169
|
+
fattribs.put(attID, ids);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return fattribs;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
* @param mesh
|
|
179
|
+
* @return
|
|
180
|
+
*/
|
|
181
|
+
public IndexedTriangleMesh addMesh(IndexedTriangleMesh mesh) {
|
|
182
|
+
Vec3D[] v = null;
|
|
183
|
+
for (AttributedFace f : mesh.faces) {
|
|
184
|
+
v = mesh.getFaceVertices(f, v);
|
|
185
|
+
addFace(v[0], v[1], v[2], null);
|
|
186
|
+
}
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
*
|
|
192
|
+
* @param mesh
|
|
193
|
+
* @return
|
|
194
|
+
*/
|
|
195
|
+
public IndexedTriangleMesh addMeshWithAttribs(IndexedTriangleMesh mesh) {
|
|
196
|
+
HashMap<String, Object[]> attribs = new HashMap<>();
|
|
197
|
+
Vec3D[] v = null;
|
|
198
|
+
for (AttributedFace f : mesh.faces) {
|
|
199
|
+
attribs.clear();
|
|
200
|
+
for (String a : f.attribs.keySet()) {
|
|
201
|
+
attribs.put(a, mesh.getFaceAttribValues(f, a));
|
|
202
|
+
}
|
|
203
|
+
v = mesh.getFaceVertices(f, v);
|
|
204
|
+
addFace(v[0], v[1], v[2], attribs);
|
|
205
|
+
}
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
*
|
|
211
|
+
* @return
|
|
212
|
+
*/
|
|
213
|
+
public IndexedTriangleMesh clear() {
|
|
214
|
+
vertices.clear();
|
|
215
|
+
fnormals.clear();
|
|
216
|
+
attributes.clear();
|
|
217
|
+
faces.clear();
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
*
|
|
223
|
+
* @return
|
|
224
|
+
*/
|
|
225
|
+
public HashMap<String, float[]> compile() {
|
|
226
|
+
HashSet<String> attribs = new HashSet<>();
|
|
227
|
+
attribs.add(ATTR_VERTICES);
|
|
228
|
+
attribs.add(ATTR_FNORMALS);
|
|
229
|
+
return compile(attribs, null);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
*
|
|
234
|
+
* @param attribs
|
|
235
|
+
* @param compilers
|
|
236
|
+
* @return
|
|
237
|
+
*/
|
|
238
|
+
public HashMap<String, float[]> compile(HashSet<String> attribs,
|
|
239
|
+
HashMap<String, MeshAttributeCompiler> compilers) {
|
|
240
|
+
HashMap<String, MeshAttributeCompiler> mergedComps = new HashMap<>(
|
|
241
|
+
getDefaultCompilers());
|
|
242
|
+
if (compilers != null) {
|
|
243
|
+
mergedComps.putAll(compilers);
|
|
244
|
+
}
|
|
245
|
+
HashMap<String, float[]> buffers = new HashMap<>();
|
|
246
|
+
int numF = faces.size();
|
|
247
|
+
for (String attrib : attribs) {
|
|
248
|
+
MeshAttributeCompiler comp = mergedComps.get(attrib);
|
|
249
|
+
if (comp != null) {
|
|
250
|
+
comp.setMesh(this);
|
|
251
|
+
ItemIndex<?> index = comp.getIndex();
|
|
252
|
+
int faceStride = 3 * comp.getStride();
|
|
253
|
+
float[] buf = new float[numF * faceStride];
|
|
254
|
+
int offset = 0;
|
|
255
|
+
for (AttributedFace f : faces) {
|
|
256
|
+
comp.compileFace(f, index, buf, offset);
|
|
257
|
+
offset += faceStride;
|
|
258
|
+
}
|
|
259
|
+
buffers.put(attrib, buf);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return buffers;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
*
|
|
267
|
+
* @return
|
|
268
|
+
*/
|
|
269
|
+
public List<Object> computeEdges() {
|
|
270
|
+
ItemIndex<Object> edges = getAttributeIndex(ATTR_EDGES);
|
|
271
|
+
edges.clear();
|
|
272
|
+
for (AttributedFace f : faces) {
|
|
273
|
+
if (f.attribs == null) {
|
|
274
|
+
f.attribs = new HashMap<>();
|
|
275
|
+
}
|
|
276
|
+
f.attribs.put(ATTR_EDGES, new int[] {
|
|
277
|
+
indexFaceEdge(f, f.a, f.b), indexFaceEdge(f, f.b, f.c),
|
|
278
|
+
indexFaceEdge(f, f.c, f.a)
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
return edges.getItems();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
*
|
|
286
|
+
* @return
|
|
287
|
+
*/
|
|
288
|
+
public List<Vec3D> computeFaceNormals() {
|
|
289
|
+
fnormals.clear();
|
|
290
|
+
Vec3D[] v = null;
|
|
291
|
+
for (AttributedFace f : faces) {
|
|
292
|
+
v = getFaceVertices(f, v);
|
|
293
|
+
f.normal = fnormals.index(v[0].sub(v[1]).crossSelf(v[0].sub(v[2]))
|
|
294
|
+
.normalize());
|
|
295
|
+
}
|
|
296
|
+
return fnormals.getItems();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
*
|
|
301
|
+
* @return
|
|
302
|
+
*/
|
|
303
|
+
public List<Object> computeVertexNormals() {
|
|
304
|
+
Vec3D[] vnorms = new Vec3D[vertices.size()];
|
|
305
|
+
for (int i = 0; i < vnorms.length; i++) {
|
|
306
|
+
vnorms[i] = new Vec3D();
|
|
307
|
+
}
|
|
308
|
+
for (AttributedFace f : faces) {
|
|
309
|
+
final Vec3D n = fnormals.forID(f.normal);
|
|
310
|
+
vnorms[f.a].addSelf(n);
|
|
311
|
+
vnorms[f.b].addSelf(n);
|
|
312
|
+
vnorms[f.c].addSelf(n);
|
|
313
|
+
}
|
|
314
|
+
for (Vec3D vnorm : vnorms) {
|
|
315
|
+
vnorm.normalize();
|
|
316
|
+
}
|
|
317
|
+
ItemIndex<Object> idx = getAttributeIndex(ATTR_VNORMALS);
|
|
318
|
+
idx.clear();
|
|
319
|
+
for (AttributedFace f : faces) {
|
|
320
|
+
if (f.attribs == null) {
|
|
321
|
+
f.attribs = new HashMap<>();
|
|
322
|
+
}
|
|
323
|
+
f.attribs.put(
|
|
324
|
+
ATTR_VNORMALS,
|
|
325
|
+
new int[] {
|
|
326
|
+
idx.index(vnorms[f.a]), idx.index(vnorms[f.b]),
|
|
327
|
+
idx.index(vnorms[f.c])
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return idx.getItems();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
*
|
|
335
|
+
* @param f
|
|
336
|
+
* @param offset
|
|
337
|
+
* @param scale
|
|
338
|
+
* @return
|
|
339
|
+
*/
|
|
340
|
+
public IndexedTriangleMesh extrudeFace(AttributedFace f, Vec3D offset,
|
|
341
|
+
float scale) {
|
|
342
|
+
Vec3D[] v = getFaceVertices(f, null);
|
|
343
|
+
Vec3D[] v2 = new Vec3D[3];
|
|
344
|
+
Vec3D c = v[0].add(v[1]).addSelf(v[2]).scaleSelf(1 / 3f);
|
|
345
|
+
Vec3D n = c.add(offset);
|
|
346
|
+
v2[0] = v[0].sub(c).scaleSelf(scale).addSelf(n);
|
|
347
|
+
v2[1] = v[1].sub(c).scaleSelf(scale).addSelf(n);
|
|
348
|
+
v2[2] = v[2].sub(c).scaleSelf(scale).addSelf(n);
|
|
349
|
+
removeFace(f);
|
|
350
|
+
// extruded copy
|
|
351
|
+
addFace(v2[0], v2[1], v2[2], null);
|
|
352
|
+
// sides
|
|
353
|
+
addFace(v[0], v[1], v2[0], null);
|
|
354
|
+
addFace(v[1], v2[1], v2[0], null);
|
|
355
|
+
addFace(v[1], v[2], v2[1], null);
|
|
356
|
+
addFace(v[2], v2[2], v2[1], null);
|
|
357
|
+
addFace(v[2], v[0], v2[2], null);
|
|
358
|
+
addFace(v[0], v2[0], v2[2], null);
|
|
359
|
+
return this;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Flips the current order of all face vertices and attributes. If face or
|
|
364
|
+
* vertex normals are present their direction will be inverted as well.
|
|
365
|
+
*
|
|
366
|
+
* @return itself
|
|
367
|
+
*/
|
|
368
|
+
public IndexedTriangleMesh flipVertexOrder() {
|
|
369
|
+
for (AttributedFace f : faces) {
|
|
370
|
+
int t = f.b;
|
|
371
|
+
f.b = f.c;
|
|
372
|
+
f.c = t;
|
|
373
|
+
if (f.attribs != null) {
|
|
374
|
+
for (int[] att : f.attribs.values()) {
|
|
375
|
+
t = att[1];
|
|
376
|
+
att[1] = att[2];
|
|
377
|
+
att[2] = t;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
for (Vec3D n : fnormals.getItems()) {
|
|
382
|
+
fnormals.reindex(n, n.getInverted());
|
|
383
|
+
}
|
|
384
|
+
ItemIndex<Object> vnormals = attributes.get(ATTR_VNORMALS);
|
|
385
|
+
if (vnormals != null) {
|
|
386
|
+
for (Object n : vnormals.getItems()) {
|
|
387
|
+
vnormals.reindex(n, ((Vec3D) n).getInverted());
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
*
|
|
395
|
+
* @param attID
|
|
396
|
+
* @return
|
|
397
|
+
*/
|
|
398
|
+
public ItemIndex<Object> getAttributeIndex(String attID) {
|
|
399
|
+
UniqueItemIndex<Object> idx = attributes.get(attID);
|
|
400
|
+
if (idx == null) {
|
|
401
|
+
idx = new UniqueItemIndex<>();
|
|
402
|
+
attributes.put(attID, idx);
|
|
403
|
+
}
|
|
404
|
+
return idx;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
*
|
|
409
|
+
* @return
|
|
410
|
+
*/
|
|
411
|
+
public Sphere getBoundingSphere() {
|
|
412
|
+
return getBounds().getBoundingSphere();
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
*
|
|
417
|
+
* @return
|
|
418
|
+
*/
|
|
419
|
+
public AABB getBounds() {
|
|
420
|
+
return AABB.getBoundingBox(vertices.getItems());
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
*
|
|
425
|
+
* @return
|
|
426
|
+
*/
|
|
427
|
+
public Vec3D getCentroid() {
|
|
428
|
+
return new Vec3D(getBounds());
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
*
|
|
433
|
+
* @param p
|
|
434
|
+
* @return
|
|
435
|
+
*/
|
|
436
|
+
public Vec3D getClosestVertexToPoint(ReadonlyVec3D p) {
|
|
437
|
+
Vec3D closest = null;
|
|
438
|
+
float minDist = Float.MAX_VALUE;
|
|
439
|
+
for (Vec3D v : vertices.getItems()) {
|
|
440
|
+
float d = v.distanceToSquared(p);
|
|
441
|
+
if (d < minDist) {
|
|
442
|
+
closest = v;
|
|
443
|
+
minDist = d;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return closest;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
*
|
|
451
|
+
* @return
|
|
452
|
+
*/
|
|
453
|
+
public HashMap<String, MeshAttributeCompiler> getDefaultCompilers() {
|
|
454
|
+
HashMap<String, MeshAttributeCompiler> compilers = new HashMap<>();
|
|
455
|
+
compilers.put(ATTR_VERTICES, new MeshVertexCompiler());
|
|
456
|
+
compilers.put(ATTR_FNORMALS, new MeshFaceNormalCompiler());
|
|
457
|
+
compilers.put(ATTR_VNORMALS, new MeshVertexNormalCompiler());
|
|
458
|
+
compilers.put(ATTR_UVCOORDS, new MeshUVCompiler());
|
|
459
|
+
compilers.put(ATTR_VCOLORS, new MeshVertexColorCompiler());
|
|
460
|
+
return compilers;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* @return the edges
|
|
465
|
+
*/
|
|
466
|
+
public List<Object> getEdges() {
|
|
467
|
+
return getAttributeIndex(ATTR_EDGES).getItems();
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
*
|
|
472
|
+
* @param v
|
|
473
|
+
* @return
|
|
474
|
+
*/
|
|
475
|
+
public List<AttributedEdge> getEdgesForVertex(Vec3D v) {
|
|
476
|
+
List<AttributedEdge> vedges = null;
|
|
477
|
+
int id = vertices.getID(v);
|
|
478
|
+
if (id != -1) {
|
|
479
|
+
vedges = getEdgesForVertexID(id);
|
|
480
|
+
}
|
|
481
|
+
return vedges;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
*
|
|
486
|
+
* @param id
|
|
487
|
+
* @return
|
|
488
|
+
*/
|
|
489
|
+
public List<AttributedEdge> getEdgesForVertexID(int id) {
|
|
490
|
+
List<AttributedEdge> vedges = new ArrayList<>(2);
|
|
491
|
+
for (Object o : getEdges()) {
|
|
492
|
+
AttributedEdge e = (AttributedEdge) o;
|
|
493
|
+
if (e.a == id || e.b == id) {
|
|
494
|
+
vedges.add(e);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return vedges;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
*
|
|
502
|
+
* @param f
|
|
503
|
+
* @return
|
|
504
|
+
*/
|
|
505
|
+
public Triangle3D getFaceAsTriangle(AttributedFace f) {
|
|
506
|
+
Vec3D[] verts = getFaceVertices(f, null);
|
|
507
|
+
return new Triangle3D(verts[0], verts[1], verts[2]);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
*
|
|
512
|
+
* @param f
|
|
513
|
+
* @param attribs
|
|
514
|
+
* @return
|
|
515
|
+
*/
|
|
516
|
+
public HashMap<String, Object[]> getFaceAttribValues(AttributedFace f,
|
|
517
|
+
String... attribs) {
|
|
518
|
+
HashMap<String, Object[]> values = new HashMap<>(
|
|
519
|
+
attribs.length, 1);
|
|
520
|
+
for (String a : attribs) {
|
|
521
|
+
values.put(a, getFaceAttribValues(f, a));
|
|
522
|
+
}
|
|
523
|
+
return values;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
*
|
|
528
|
+
* @param f
|
|
529
|
+
* @param att
|
|
530
|
+
* @return
|
|
531
|
+
*/
|
|
532
|
+
public Object[] getFaceAttribValues(AttributedFace f, String att) {
|
|
533
|
+
ItemIndex<Object> idx = attributes.get(att);
|
|
534
|
+
int[] fattribs = f.attribs.get(att);
|
|
535
|
+
if (idx == null || fattribs == null) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
return new Object[] {
|
|
539
|
+
idx.forID(fattribs[0]), idx.forID(fattribs[1]),
|
|
540
|
+
idx.forID(fattribs[2])
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* @return the fnormals
|
|
546
|
+
*/
|
|
547
|
+
public List<Vec3D> getFaceNormals() {
|
|
548
|
+
return fnormals.getItems();
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* @return the faces
|
|
553
|
+
*/
|
|
554
|
+
public List<AttributedFace> getFaces() {
|
|
555
|
+
return faces;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
*
|
|
560
|
+
* @param v
|
|
561
|
+
* @return
|
|
562
|
+
*/
|
|
563
|
+
public List<AttributedFace> getFacesForVertex(Vec3D v) {
|
|
564
|
+
List<AttributedFace> vfaces = null;
|
|
565
|
+
int id = vertices.getID(v);
|
|
566
|
+
if (id != -1) {
|
|
567
|
+
vfaces = new ArrayList<>(2);
|
|
568
|
+
for (AttributedFace f : faces) {
|
|
569
|
+
if (f.a == id || f.b == id || f.c == id) {
|
|
570
|
+
vfaces.add(f);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return vfaces;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
*
|
|
579
|
+
* @param f
|
|
580
|
+
* @param verts
|
|
581
|
+
* @return
|
|
582
|
+
*/
|
|
583
|
+
public final Vec3D[] getFaceVertices(AttributedFace f, Vec3D[] verts) {
|
|
584
|
+
if (verts != null) {
|
|
585
|
+
verts[0] = vertices.forID(f.a);
|
|
586
|
+
verts[1] = vertices.forID(f.b);
|
|
587
|
+
verts[2] = vertices.forID(f.c);
|
|
588
|
+
return verts;
|
|
589
|
+
} else {
|
|
590
|
+
return new Vec3D[] {
|
|
591
|
+
vertices.forID(f.a), vertices.forID(f.b),
|
|
592
|
+
vertices.forID(f.c)
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
*
|
|
599
|
+
* @param id
|
|
600
|
+
* @param neighbors
|
|
601
|
+
* @return
|
|
602
|
+
*/
|
|
603
|
+
public List<Vec3D> getNeighborsForVertexID(int id, List<Vec3D> neighbors) {
|
|
604
|
+
List<AttributedEdge> vedges = getEdgesForVertexID(id);
|
|
605
|
+
if (vedges.size() > 0) {
|
|
606
|
+
if (neighbors == null) {
|
|
607
|
+
neighbors = new ArrayList<>();
|
|
608
|
+
} else {
|
|
609
|
+
neighbors.clear();
|
|
610
|
+
}
|
|
611
|
+
for (AttributedEdge e : vedges) {
|
|
612
|
+
neighbors.add(vertices.forID((e.a == id) ? e.b : e.a));
|
|
613
|
+
}
|
|
614
|
+
} else if (neighbors != null) {
|
|
615
|
+
neighbors.clear();
|
|
616
|
+
}
|
|
617
|
+
return neighbors;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
*
|
|
622
|
+
* @return
|
|
623
|
+
*/
|
|
624
|
+
public final int getNumFaces() {
|
|
625
|
+
return faces.size();
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
*
|
|
630
|
+
* @return
|
|
631
|
+
*/
|
|
632
|
+
public final int getNumVertices() {
|
|
633
|
+
return vertices.size();
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
*
|
|
638
|
+
* @return
|
|
639
|
+
*/
|
|
640
|
+
public float getVertexDelta() {
|
|
641
|
+
return vertices.getDelta();
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* @return the vertices
|
|
646
|
+
*/
|
|
647
|
+
public List<Vec3D> getVertices() {
|
|
648
|
+
return vertices.getItems();
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
*
|
|
653
|
+
* @param verts
|
|
654
|
+
* @param ids
|
|
655
|
+
* @return
|
|
656
|
+
*/
|
|
657
|
+
public List<Vec3D> getVerticesForIDs(List<Vec3D> verts, int... ids) {
|
|
658
|
+
if (verts == null) {
|
|
659
|
+
verts = new ArrayList<>(ids.length);
|
|
660
|
+
}
|
|
661
|
+
for (int id : ids) {
|
|
662
|
+
verts.add(vertices.forID(id));
|
|
663
|
+
}
|
|
664
|
+
return verts;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
*
|
|
669
|
+
* @param f
|
|
670
|
+
* @param a
|
|
671
|
+
* @param b
|
|
672
|
+
* @return
|
|
673
|
+
*/
|
|
674
|
+
protected final int indexFaceEdge(AttributedFace f, int a, int b) {
|
|
675
|
+
final AttributedEdge e1 = new AttributedEdge(a, b);
|
|
676
|
+
final AttributedEdge e2 = new AttributedEdge(b, a);
|
|
677
|
+
ItemIndex<Object> edges = getAttributeIndex(ATTR_EDGES);
|
|
678
|
+
final int id1 = edges.getID(e1);
|
|
679
|
+
final int id2 = edges.getID(e2);
|
|
680
|
+
if (id1 != -1) {
|
|
681
|
+
((AttributedEdge) edges.forID(id1)).addFace(f);
|
|
682
|
+
return id1;
|
|
683
|
+
} else if (id2 != -1) {
|
|
684
|
+
((AttributedEdge) edges.forID(id2)).addFace(f);
|
|
685
|
+
return id2;
|
|
686
|
+
} else {
|
|
687
|
+
e1.addFace(f);
|
|
688
|
+
return edges.index(e1);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
*
|
|
694
|
+
* @param ray
|
|
695
|
+
* @return
|
|
696
|
+
*/
|
|
697
|
+
public IsectData3D intersectsRay(Ray3D ray) {
|
|
698
|
+
TriangleIntersector intersector = new TriangleIntersector();
|
|
699
|
+
Triangle3D tri = intersector.getTriangle();
|
|
700
|
+
Vec3D[] v = null;
|
|
701
|
+
for (AttributedFace f : faces) {
|
|
702
|
+
v = getFaceVertices(f, v);
|
|
703
|
+
tri.set(v[0], v[1], v[2]);
|
|
704
|
+
if (intersector.intersectsRay(ray)) {
|
|
705
|
+
return intersector.getIntersectionData();
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
*
|
|
713
|
+
*/
|
|
714
|
+
public void rebuildVertexIndex() {
|
|
715
|
+
SpatialIndex newVerts = new SpatialIndex(vertices.getDelta());
|
|
716
|
+
Vec3D[] v = null;
|
|
717
|
+
for (AttributedFace f : faces) {
|
|
718
|
+
v = getFaceVertices(f, v);
|
|
719
|
+
f.a = newVerts.index(v[0]);
|
|
720
|
+
f.b = newVerts.index(v[1]);
|
|
721
|
+
f.c = newVerts.index(v[2]);
|
|
722
|
+
}
|
|
723
|
+
vertices = newVerts;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
*
|
|
728
|
+
* @param f
|
|
729
|
+
* @return
|
|
730
|
+
*/
|
|
731
|
+
public IndexedTriangleMesh removeFace(AttributedFace f) {
|
|
732
|
+
faces.remove(f);
|
|
733
|
+
return this;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
*
|
|
738
|
+
* @param delta
|
|
739
|
+
* @return
|
|
740
|
+
*/
|
|
741
|
+
public IndexedTriangleMesh setVertexDelta(float delta) {
|
|
742
|
+
vertices.setDelta(delta);
|
|
743
|
+
return this;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
*
|
|
748
|
+
* @return
|
|
749
|
+
*/
|
|
750
|
+
public IndexedTriangleMesh smooth() {
|
|
751
|
+
HashMap<Integer, Vec3D> lapIndex = new HashMap<>();
|
|
752
|
+
List<Vec3D> neighbors = null;
|
|
753
|
+
for (int i = 0, numV = getNumVertices(); i < numV; i++) {
|
|
754
|
+
neighbors = getNeighborsForVertexID(i, neighbors);
|
|
755
|
+
if (neighbors != null && neighbors.size() > 0) {
|
|
756
|
+
Vec3D l = new Vec3D();
|
|
757
|
+
for (Vec3D n : neighbors) {
|
|
758
|
+
l.addSelf(n);
|
|
759
|
+
}
|
|
760
|
+
l.scaleSelf(1f / neighbors.size());
|
|
761
|
+
lapIndex.put(i, l);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
SpatialIndex newVerts = new SpatialIndex(vertices.getDelta());
|
|
765
|
+
for (Iterator<AttributedFace> i = faces.iterator(); i.hasNext();) {
|
|
766
|
+
AttributedFace f = i.next();
|
|
767
|
+
f.a = newVerts.index(lapIndex.get(f.a));
|
|
768
|
+
f.b = newVerts.index(lapIndex.get(f.b));
|
|
769
|
+
f.c = newVerts.index(lapIndex.get(f.c));
|
|
770
|
+
if (f.a == f.b || f.a == f.c || f.b == f.c) {
|
|
771
|
+
i.remove();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
vertices = newVerts;
|
|
775
|
+
computeEdges();
|
|
776
|
+
return this;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
*
|
|
781
|
+
* @param strategy
|
|
782
|
+
* @return
|
|
783
|
+
*/
|
|
784
|
+
public IndexedTriangleMesh subdivide(NewSubdivStrategy strategy) {
|
|
785
|
+
Vec3D[] v = null;
|
|
786
|
+
List<Vec3D[]> splitFaces = new ArrayList<>();
|
|
787
|
+
for (AttributedFace f : new ArrayList<>(faces)) {
|
|
788
|
+
removeFace(f);
|
|
789
|
+
v = getFaceVertices(f, v);
|
|
790
|
+
for (Vec3D[] fverts : strategy.subdivideTriangle(v[0], v[1], v[2],
|
|
791
|
+
splitFaces)) {
|
|
792
|
+
addFace(fverts[0], fverts[1], fverts[2], null);
|
|
793
|
+
}
|
|
794
|
+
splitFaces.clear();
|
|
795
|
+
}
|
|
796
|
+
rebuildVertexIndex();
|
|
797
|
+
return this;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
*
|
|
802
|
+
* @return
|
|
803
|
+
*/
|
|
804
|
+
@Override
|
|
805
|
+
public String toString() {
|
|
806
|
+
return String.format("vertices: %d, faces: %d", getNumVertices(),
|
|
807
|
+
getNumFaces());
|
|
808
|
+
}
|
|
809
|
+
}
|