toxiclibs 0.9.2 → 2.1.0
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 +5 -5
- data/.mvn/extensions.xml +1 -1
- data/.travis.yml +3 -4
- data/CHANGELOG.md +10 -1
- data/README.md +3 -3
- data/Rakefile +1 -2
- data/examples/attract_repel/attractor.rb +1 -1
- data/examples/attract_repel/particle.rb +1 -1
- data/examples/boolean_shapes.rb +9 -5
- data/examples/force_directed/node.rb +1 -1
- data/examples/inflate_mesh.rb +1 -1
- data/examples/model_align.rb +1 -1
- data/examples/physics_type.rb +1 -1
- data/examples/povmesh/ftest.rb +3 -3
- data/examples/toxiclibs_color_theme.rb +91 -0
- data/lib/toxiclibs/version.rb +2 -1
- data/lib/toxiclibs.jar +0 -0
- data/lib/toxiclibs.rb +54 -37
- data/pom.rb +20 -28
- data/pom.xml +39 -65
- data/src/main/java/module-info.java +22 -0
- data/src/{toxi → main/java/toxi}/color/AccessCriteria.java +0 -0
- data/src/{toxi → main/java/toxi}/color/AlphaAccessor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/CMYKAccessor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/CMYKDistanceProxy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/ColorGradient.java +0 -0
- data/src/{toxi → main/java/toxi}/color/ColorList.java +2 -4
- data/src/{toxi → main/java/toxi}/color/ColorRange.java +0 -0
- data/src/{toxi → main/java/toxi}/color/ColorTheme.java +0 -0
- data/src/{toxi → main/java/toxi}/color/DistanceProxy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/HSVAccessor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/HSVDistanceProxy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/HistEntry.java +0 -0
- data/src/{toxi → main/java/toxi}/color/Histogram.java +0 -0
- data/src/{toxi → main/java/toxi}/color/Hue.java +0 -0
- data/src/{toxi → main/java/toxi}/color/LuminanceAccessor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/NamedColor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/ProximityComparator.java +0 -0
- data/src/{toxi → main/java/toxi}/color/RGBAccessor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/RGBDistanceProxy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/ReadonlyTColor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/TColor.java +0 -0
- data/src/{toxi → main/java/toxi}/color/TColorAdapter.java +4 -4
- data/src/{toxi → main/java/toxi}/color/ToneMap.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/AnalogousStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/ColorTheoryRegistry.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/ColorTheoryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/ComplementaryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/CompoundTheoryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/LeftSplitComplementaryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/MonochromeTheoryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/RightSplitComplementaryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/SingleComplementStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/SplitComplementaryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/TetradTheoryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/color/theory/TriadTheoryStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/data/csv/CSVAdapter.java +0 -0
- data/src/{toxi → main/java/toxi}/data/csv/CSVFieldMapper.java +0 -0
- data/src/{toxi → main/java/toxi}/data/csv/CSVListener.java +0 -0
- data/src/{toxi → main/java/toxi}/data/csv/CSVParser.java +0 -0
- data/src/{toxi → main/java/toxi}/data/feeds/AtomAuthor.java +2 -2
- data/src/{toxi → main/java/toxi}/data/feeds/AtomContent.java +3 -4
- data/src/{toxi → main/java/toxi}/data/feeds/AtomEntry.java +9 -13
- data/src/main/java/toxi/data/feeds/AtomFeed.java +91 -0
- data/src/{toxi → main/java/toxi}/data/feeds/AtomLink.java +3 -2
- data/src/{toxi → main/java/toxi}/data/feeds/RSSChannel.java +10 -11
- data/src/{toxi → main/java/toxi}/data/feeds/RSSEnclosure.java +3 -3
- data/src/{toxi → main/java/toxi}/data/feeds/RSSItem.java +11 -13
- data/src/{toxi → main/java/toxi}/data/feeds/util/EntityStripper.java +0 -0
- data/src/{toxi → main/java/toxi}/data/feeds/util/Iso8601DateAdapter.java +6 -7
- data/src/{toxi → main/java/toxi}/data/feeds/util/Rfc822DateAdapter.java +5 -6
- data/src/{toxi → main/java/toxi}/geom/AABB.java +8 -9
- data/src/{toxi → main/java/toxi}/geom/Axis3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/AxisAlignedCylinder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/BernsteinPolynomial.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/BezierCurve2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/BezierCurve3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/BooleanShapeBuilder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/BoxIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Circle.java +2 -2
- data/src/{toxi → main/java/toxi}/geom/CircleIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Cone.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/ConvexPolygonClipper.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/CoordinateExtractor.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Ellipse.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/GMatrix.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/GVector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/GlobalGridTesselator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/GridTesselator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Intersector2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Intersector3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/IsectData2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/IsectData3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Line2D.java +1 -2
- data/src/{toxi → main/java/toxi}/geom/Line3D.java +1 -2
- data/src/{toxi → main/java/toxi}/geom/LineStrip2D.java +2 -2
- data/src/{toxi → main/java/toxi}/geom/LineStrip3D.java +2 -2
- data/src/{toxi → main/java/toxi}/geom/LocalGridTesselator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Matrix3d.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Matrix4f.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Matrix4x4.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/MatrixSizeException.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/OctreeVisitor.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Origin3D.java +12 -6
- data/src/{toxi → main/java/toxi}/geom/Plane.java +3 -5
- data/src/{toxi → main/java/toxi}/geom/PlaneIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/PointCloud3D.java +15 -12
- data/src/{toxi → main/java/toxi}/geom/PointOctree.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/PointQuadtree.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Polygon2D.java +34 -45
- data/src/{toxi → main/java/toxi}/geom/PolygonClipper2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/PolygonTesselator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/QuadtreeVisitor.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Quaternion.java +3 -5
- data/src/{toxi → main/java/toxi}/geom/Ray2D.java +4 -5
- data/src/{toxi → main/java/toxi}/geom/Ray3D.java +3 -5
- data/src/{toxi → main/java/toxi}/geom/Ray3DIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/ReadonlyVec2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/ReadonlyVec3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/ReadonlyVec4D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Rect.java +3 -5
- data/src/{toxi → main/java/toxi}/geom/Reflector3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Shape2D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Shape3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/SingularMatrixException.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/SpatialBins.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/SpatialIndex.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Sphere.java +3 -5
- data/src/{toxi → main/java/toxi}/geom/SphereIntersectorReflector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Spline2D.java +12 -16
- data/src/{toxi → main/java/toxi}/geom/Spline3D.java +12 -16
- data/src/{toxi → main/java/toxi}/geom/SutherlandHodgemanClipper.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Triangle2D.java +4 -7
- data/src/{toxi → main/java/toxi}/geom/Triangle3D.java +5 -8
- data/src/{toxi → main/java/toxi}/geom/TriangleIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/Vec2D.java +3 -3
- data/src/{toxi → main/java/toxi}/geom/Vec3D.java +4 -4
- data/src/{toxi → main/java/toxi}/geom/Vec4D.java +5 -5
- data/src/{toxi → main/java/toxi}/geom/VecMathUtil.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/XAxisCylinder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/YAxisCylinder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/ZAxisCylinder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/BezierPatch.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/BoxSelector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/DefaultSTLColorModel.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/DefaultSelector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/Face.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/LaplacianSmooth.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/MaterialiseSTLColorModel.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/Mesh3D.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/MeshIntersector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/OBJWriter.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/PLYWriter.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/PlaneSelector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/STLColorModel.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/STLReader.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/STLWriter.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/SphereFunction.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/SphericalHarmonics.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/SuperEllipsoid.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/SurfaceFunction.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/SurfaceMeshBuilder.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/Terrain.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/TriangleMesh.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/Vertex.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/VertexSelector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/WEFace.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/WEMeshFilterStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/WETriangleMesh.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/WEVertex.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/WingedEdge.java +2 -2
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/CentroidSubdiv.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/DisplacementSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/DualDisplacementSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/DualSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/EdgeLengthComparator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/FaceCountComparator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/MidpointSubdiv.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/MidpointSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/NewSubdivStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/NormalDisplacementSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/SubdivisionStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh/subdiv/TriSubdivision.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh2d/DelaunayTriangle.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh2d/DelaunayTriangulation.java +5 -7
- data/src/{toxi → main/java/toxi}/geom/mesh2d/DelaunayVertex.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/mesh2d/Voronoi.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/BasicNurbsCurve.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/BasicNurbsSurface.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/ControlNet.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/CurveCreator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/CurveUtils.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/InterpolationException.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/KnotVector.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/NurbsCreator.java +2 -2
- data/src/{toxi → main/java/toxi}/geom/nurbs/NurbsCurve.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/NurbsMeshCreator.java +0 -0
- data/src/{toxi → main/java/toxi}/geom/nurbs/NurbsSurface.java +0 -0
- data/src/{toxi → main/java/toxi}/image/util/Filter8bit.java +0 -0
- data/src/{toxi → main/java/toxi}/image/util/TiledFrameExporter.java +0 -0
- data/src/{toxi → main/java/toxi}/math/BezierInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/CircularInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/CosineInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/DecimatedInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/ExponentialInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/InterpolateStrategy.java +0 -0
- data/src/{toxi → main/java/toxi}/math/Interpolation2D.java +0 -0
- data/src/{toxi → main/java/toxi}/math/LinearInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/MathUtils.java +0 -0
- data/src/{toxi → main/java/toxi}/math/NonLinearScaleMap.java +0 -0
- data/src/{toxi → main/java/toxi}/math/ScaleMap.java +0 -0
- data/src/{toxi → main/java/toxi}/math/SigmoidInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/SinCosLUT.java +0 -0
- data/src/{toxi → main/java/toxi}/math/ThresholdInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/ZoomLensInterpolation.java +0 -0
- data/src/{toxi → main/java/toxi}/math/conversion/UnitTranslator.java +0 -0
- data/src/{toxi → main/java/toxi}/math/noise/PerlinNoise.java +0 -0
- data/src/{toxi → main/java/toxi}/math/noise/SimplexNoise.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/AMFMSineWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/AbstractWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/ConstantWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/FMHarmonicSquareWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/FMSawtoothWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/FMSineWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/FMSquareWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/FMTriangleWave.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/SineWave.java +2 -2
- data/src/{toxi → main/java/toxi}/math/waves/Wave2D.java +0 -0
- data/src/{toxi → main/java/toxi}/math/waves/WaveState.java +0 -0
- data/src/{toxi → main/java/toxi}/music/scale/AbstractScale.java +0 -0
- data/src/{toxi → main/java/toxi}/music/scale/GenericScale.java +0 -0
- data/src/{toxi → main/java/toxi}/music/scale/MajorScale.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/AttributedEdge.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/AttributedFace.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/IndexedTriangleMesh.java +70 -69
- data/src/{toxi → main/java/toxi}/newmesh/MeshAttributeCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/MeshFaceNormalCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/MeshUVCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/MeshVertexColorCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/MeshVertexCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/MeshVertexNormalCompiler.java +0 -0
- data/src/{toxi → main/java/toxi}/newmesh/SpatialIndex.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/ParticlePath2D.java +4 -3
- data/src/{toxi → main/java/toxi}/physics2d/ParticleString2D.java +2 -2
- data/src/{toxi → main/java/toxi}/physics2d/PullBackSpring2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/VerletConstrainedSpring2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/VerletMinDistanceSpring2D.java +0 -0
- data/src/main/java/toxi/physics2d/VerletParticle2D.java +449 -0
- data/src/main/java/toxi/physics2d/VerletPhysics2D.java +440 -0
- data/src/{toxi → main/java/toxi}/physics2d/VerletSpring2D.java +0 -0
- data/src/main/java/toxi/physics2d/behaviors/AttractionBehavior2D.java +211 -0
- data/src/{toxi → main/java/toxi}/physics2d/behaviors/ConstantForceBehavior2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/behaviors/GravityBehavior2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/behaviors/ParticleBehavior2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/AngularConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/AxisConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/CircularConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/MaxConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/MinConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/ParticleConstraint2D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/PolygonConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics2d/constraints/RectConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/ParticlePath3D.java +4 -3
- data/src/{toxi → main/java/toxi}/physics3d/ParticleString3D.java +2 -2
- data/src/{toxi → main/java/toxi}/physics3d/PullBackSpring3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/VerletConstrainedSpring3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/VerletMinDistanceSpring3D.java +0 -0
- data/src/main/java/toxi/physics3d/VerletParticle3D.java +377 -0
- data/src/{toxi → main/java/toxi}/physics3d/VerletPhysics3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/VerletSpring3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/behaviors/AttractionBehavior3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/behaviors/ConstantForceBehavior3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/behaviors/GravityBehavior3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/behaviors/ParticleBehavior3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/AxisConstraint.java +1 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/BoxConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/CylinderConstraint.java +1 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/MaxConstraint.java +1 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/MinConstraint.java +1 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/ParticleConstraint3D.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/PlaneConstraint.java +0 -0
- data/src/{toxi → main/java/toxi}/physics3d/constraints/SoftBoxConstraint.java +38 -38
- data/src/{toxi → main/java/toxi}/physics3d/constraints/SphereConstraint.java +1 -0
- data/src/{toxi → main/java/toxi}/processing/ArrowModifier.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/DashedLineModifier.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/DeltaOrientationMapper.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/Line2DRenderModifier.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/MeshToVBO.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/NormalMapper.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/POVInterface.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/POVMesh.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/POVWriter.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/RCOpaque.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/RCTransp.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/TextureBuilder.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/Textures.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/ToxiclibsSupport.java +3 -3
- data/src/{toxi → main/java/toxi}/processing/Tracing.java +0 -0
- data/src/{toxi → main/java/toxi}/processing/XYZNormalMapper.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/CAMatrix.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/CARule.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/CARule2D.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/CAWolfram1D.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/EvolvableMatrix.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/automata/MatrixEvolver.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/BottomUpOrder.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLA.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLAConfiguration.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLAEventAdapter.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLAEventListener.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLAGuideLines.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLAParticle.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/DLASegment.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/PipelineOrder.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/dla/RadialDistanceOrder.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/erosion/ErosionFunction.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/erosion/TalusAngleErosion.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/erosion/ThermalErosion.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/fluids/FluidSolver2D.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/fluids/FluidSolver3D.java +0 -0
- data/src/{toxi → main/java/toxi}/sim/grayscott/GrayScott.java +0 -0
- data/src/{toxi → main/java/toxi}/util/DateUtils.java +0 -0
- data/src/{toxi → main/java/toxi}/util/FileSequenceDescriptor.java +0 -0
- data/src/main/java/toxi/util/FileUtils.java +443 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/ArraySet.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/ArrayUtil.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/BiasedDoubleRange.java +3 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/BiasedFloatRange.java +2 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/BiasedIntegerRange.java +3 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/DoubleRange.java +3 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/FloatRange.java +3 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/GenericSet.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/IntegerRange.java +3 -3
- data/src/{toxi → main/java/toxi}/util/datatypes/IntegerSet.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/ItemIndex.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/SingletonRegistry.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/TypedProperties.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/UndirectedGraph.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/UniqueItemIndex.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/WeightedRandomEntry.java +0 -0
- data/src/{toxi → main/java/toxi}/util/datatypes/WeightedRandomSet.java +0 -0
- data/src/{toxi → main/java/toxi}/util/events/EventDispatcher.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/AdditiveBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/ArrayIsoSurface.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/BoxBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/BrushMode.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/HashIsoSurface.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/IsoSurface.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/MarchingCubesIndex.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/MeshLatticeBuilder.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/MeshVoxelizer.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/MultiplyBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/PeakBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/ReplaceBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/RoundBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/VolumetricBrush.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/VolumetricHashMap.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/VolumetricSpace.java +0 -0
- data/src/{toxi → main/java/toxi}/volume/VolumetricSpaceArray.java +0 -0
- data/src/test/java/module-info.java +10 -0
- data/src/{BooleanShapes.java → test/java/toxi/BooleanShapes.java} +2 -2
- data/toxiclibs.gemspec +7 -8
- metadata +357 -368
- data/.mvn/wrapper/maven-wrapper.properties +0 -1
- data/lib/args4j-2.0.31.jar +0 -0
- data/src/com/toxi/net/ClientListener.java +0 -41
- data/src/com/toxi/net/ServerListener.java +0 -70
- data/src/com/toxi/net/ServerListenerAdapter.java +0 -47
- data/src/com/toxi/net/ServerState.java +0 -18
- data/src/com/toxi/net/UDPConnection.java +0 -66
- data/src/com/toxi/net/UDPSyncClient.java +0 -81
- data/src/com/toxi/net/UDPSyncServer.java +0 -450
- data/src/com/toxi/nio/UDPClient.java +0 -121
- data/src/com/toxi/nio/UDPClientState.java +0 -32
- data/src/com/toxi/nio/UDPServer.java +0 -129
- data/src/toxi/data/feeds/AtomFeed.java +0 -129
- data/src/toxi/data/feeds/RSSFeed.java +0 -99
- data/src/toxi/physics2d/VerletParticle2D.java +0 -457
- data/src/toxi/physics2d/VerletPhysics2D.java +0 -448
- data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +0 -212
- data/src/toxi/physics3d/VerletParticle3D.java +0 -385
- data/src/toxi/util/FileUtils.java +0 -467
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
package com.toxi.net;
|
|
2
|
-
|
|
3
|
-
import java.io.FileInputStream;
|
|
4
|
-
import java.io.FileNotFoundException;
|
|
5
|
-
import java.io.IOException;
|
|
6
|
-
import java.net.DatagramPacket;
|
|
7
|
-
import java.net.DatagramSocket;
|
|
8
|
-
import java.net.InetAddress;
|
|
9
|
-
import java.net.SocketTimeoutException;
|
|
10
|
-
import java.util.HashMap;
|
|
11
|
-
import java.util.Iterator;
|
|
12
|
-
import java.util.logging.ConsoleHandler;
|
|
13
|
-
import java.util.logging.Level;
|
|
14
|
-
import java.util.logging.Logger;
|
|
15
|
-
|
|
16
|
-
import org.kohsuke.args4j.CmdLineException;
|
|
17
|
-
import org.kohsuke.args4j.CmdLineParser;
|
|
18
|
-
import org.kohsuke.args4j.Option;
|
|
19
|
-
|
|
20
|
-
import toxi.util.datatypes.TypedProperties;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* <p>
|
|
24
|
-
* An <a href="http://mostpixelsever.com">MPE</a> inspired synch server for
|
|
25
|
-
* networked multi-screen applications. All communication is realised via UDP.
|
|
26
|
-
* Clients are not requested to acknowledge every single packet received, but
|
|
27
|
-
* need to send a heart beat in a regular (configurable) interval. The server
|
|
28
|
-
* discards any data received from clients, so it doesn't matter what is being
|
|
29
|
-
* sent back. A single byte will suffice.
|
|
30
|
-
* </p>
|
|
31
|
-
*
|
|
32
|
-
* <p>
|
|
33
|
-
* The server can be configured via CLI arguments and/or Java property files and
|
|
34
|
-
* can be connected to an existing logger. When run on from the commandline a
|
|
35
|
-
* console logger is automatically added.
|
|
36
|
-
* </p>
|
|
37
|
-
*
|
|
38
|
-
* @author Karsten Schmidt <info@postspectacular.com>
|
|
39
|
-
*/
|
|
40
|
-
public class UDPSyncServer {
|
|
41
|
-
|
|
42
|
-
private static final int DEFAULT_RECEIVE_PACKET_SIZE = 32;
|
|
43
|
-
|
|
44
|
-
private static final int DEFAULT_NUM_CLIENTS = 1;
|
|
45
|
-
|
|
46
|
-
private static final int DEFAULT_FRAMERATE = 30;
|
|
47
|
-
|
|
48
|
-
private static final int DEFAULT_PORT = 9002;
|
|
49
|
-
|
|
50
|
-
private static final int DEFAULT_RECEIVE_TIMEOUT = 1;
|
|
51
|
-
|
|
52
|
-
private ServerState state;
|
|
53
|
-
|
|
54
|
-
DatagramSocket socket;
|
|
55
|
-
HashMap<String, UDPConnection> connections = new HashMap<>();
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
*
|
|
59
|
-
*/
|
|
60
|
-
@Option(name = "-port", aliases = "-p", usage = "server socket port number")
|
|
61
|
-
protected int port = DEFAULT_PORT;
|
|
62
|
-
|
|
63
|
-
@Option(name = "-config", aliases = "-c", usage = "path to configuration file", metaVar = "PATH")
|
|
64
|
-
private String configFile;
|
|
65
|
-
private TypedProperties config;
|
|
66
|
-
|
|
67
|
-
@Option(name = "-packetsize", aliases = "-s", usage = "receive packet size")
|
|
68
|
-
private int receivePacketSize = DEFAULT_RECEIVE_PACKET_SIZE;
|
|
69
|
-
private byte[] receiveData;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
*
|
|
73
|
-
*/
|
|
74
|
-
@Option(name = "-rectimeout", aliases = "-rt", usage = "receive timeout (in ms), minimum 1ms")
|
|
75
|
-
protected int receiveTimeOut = DEFAULT_RECEIVE_TIMEOUT;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
*
|
|
79
|
-
*/
|
|
80
|
-
@Option(name = "-ttl", usage = "client time-to-live, max. time interval after which clients expire")
|
|
81
|
-
protected int connectionTimeOut = UDPConnection.TTL;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
85
|
-
*/
|
|
86
|
-
@Option(name = "-numclients", aliases = "-num", usage = "number of clients")
|
|
87
|
-
protected int numClients = DEFAULT_NUM_CLIENTS;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*/
|
|
92
|
-
@Option(name = "-framerate", aliases = "-fps", usage = "target framerate")
|
|
93
|
-
protected int frameRate = DEFAULT_FRAMERATE;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
*
|
|
97
|
-
*/
|
|
98
|
-
protected int frameDuration;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
*
|
|
102
|
-
*/
|
|
103
|
-
protected int frameCount;
|
|
104
|
-
|
|
105
|
-
private static Logger logger;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Optional server event listener
|
|
109
|
-
*/
|
|
110
|
-
protected ServerListener listener;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
*
|
|
114
|
-
*/
|
|
115
|
-
public UDPSyncServer() {
|
|
116
|
-
config = new TypedProperties();
|
|
117
|
-
setMaxReceivePacketSize(DEFAULT_RECEIVE_PACKET_SIZE);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
*
|
|
122
|
-
* @param args
|
|
123
|
-
*/
|
|
124
|
-
public static void main(String args[]) {
|
|
125
|
-
new UDPSyncServer().execute(args);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Main entry point for CLI.
|
|
130
|
-
*
|
|
131
|
-
* @param args
|
|
132
|
-
* command line arguments
|
|
133
|
-
*/
|
|
134
|
-
public void execute(String[] args) {
|
|
135
|
-
CmdLineParser parser = new CmdLineParser(this);
|
|
136
|
-
parser.setUsageWidth(80);
|
|
137
|
-
try {
|
|
138
|
-
parser.parseArgument(args);
|
|
139
|
-
} catch (CmdLineException e) {
|
|
140
|
-
System.err.println(e.getMessage());
|
|
141
|
-
System.err.println("java UDPSyncServer [options]");
|
|
142
|
-
parser.printUsage(System.err);
|
|
143
|
-
System.err.println();
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
if (configFile != null)
|
|
149
|
-
config.load(new FileInputStream(configFile));
|
|
150
|
-
logger = Logger.getLogger("com.postspectacular");
|
|
151
|
-
logger.addHandler(new ConsoleHandler());
|
|
152
|
-
logger.setLevel(Level.CONFIG);
|
|
153
|
-
configure(config);
|
|
154
|
-
run();
|
|
155
|
-
} catch (FileNotFoundException e) {
|
|
156
|
-
System.err.println("cannot find config file @ " + args[0]);
|
|
157
|
-
} catch (IOException e) {
|
|
158
|
-
System.err.println("cannot read config file @ " + args[0]);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Configures the server with settings using the passed-in properties.
|
|
164
|
-
*
|
|
165
|
-
* @param config
|
|
166
|
-
*/
|
|
167
|
-
public void configure(TypedProperties config) {
|
|
168
|
-
this.config = config;
|
|
169
|
-
port = config.getInt("server.port", port);
|
|
170
|
-
setMaxReceivePacketSize(config.getInt("udp.packetsize",
|
|
171
|
-
receivePacketSize));
|
|
172
|
-
numClients = config.getInt("server.numclients", numClients);
|
|
173
|
-
frameRate = config.getInt("server.framerate", frameRate);
|
|
174
|
-
frameDuration = 1000 / frameRate;
|
|
175
|
-
connectionTimeOut = config.getInt("udp.ttl", connectionTimeOut);
|
|
176
|
-
UDPConnection.setTTL(connectionTimeOut);
|
|
177
|
-
receiveTimeOut = config.getInt("udp.receivetimeout", receiveTimeOut);
|
|
178
|
-
if (logger != null) {
|
|
179
|
-
logger.log(Level.INFO, "configured server... port:{0} clients:{1} fps:{2} ttl:{3} rto:{4}", new Object[]{port, numClients, frameRate, connectionTimeOut, receiveTimeOut});
|
|
180
|
-
}
|
|
181
|
-
setState(ServerState.WAITING_FOR_CLIENTS);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Main server loop/state machine. Creates socket and handles syncing of
|
|
186
|
-
* connected clients.
|
|
187
|
-
*/
|
|
188
|
-
public void run() {
|
|
189
|
-
try {
|
|
190
|
-
socket = new DatagramSocket(port);
|
|
191
|
-
if (logger != null)
|
|
192
|
-
logger.log(Level.INFO, "creating socket @ port {0}", port);
|
|
193
|
-
if (listener != null) {
|
|
194
|
-
listener.serverStarted();
|
|
195
|
-
}
|
|
196
|
-
while (true) {
|
|
197
|
-
switch (state) {
|
|
198
|
-
|
|
199
|
-
case WAITING_FOR_CLIENTS:
|
|
200
|
-
if (logger != null)
|
|
201
|
-
logger.info("Server running, waiting for connections...");
|
|
202
|
-
// disable timeout, i.e socket will block indefinitely
|
|
203
|
-
// until
|
|
204
|
-
// a packet is received
|
|
205
|
-
socket.setSoTimeout(0);
|
|
206
|
-
while (connections.size() < numClients) {
|
|
207
|
-
receiveAndAddConnection();
|
|
208
|
-
}
|
|
209
|
-
// all connected, start syncing...
|
|
210
|
-
setState(ServerState.SYNCHING);
|
|
211
|
-
break;
|
|
212
|
-
|
|
213
|
-
case SYNCHING:
|
|
214
|
-
socket.setSoTimeout(receiveTimeOut);
|
|
215
|
-
if (connections.size() > 0) {
|
|
216
|
-
doHeartBeat();
|
|
217
|
-
byte[] payload = getSyncPayload();
|
|
218
|
-
Iterator<UDPConnection> iter = connections.values()
|
|
219
|
-
.iterator();
|
|
220
|
-
// Uses nanoTime for better precision / more stable
|
|
221
|
-
// framerate, but unavailable on OSX!!!
|
|
222
|
-
long beginSynch = System.nanoTime();
|
|
223
|
-
while (iter.hasNext()) {
|
|
224
|
-
UDPConnection conn = iter.next();
|
|
225
|
-
if (!conn.isAlive()) {
|
|
226
|
-
iter.remove();
|
|
227
|
-
if (logger != null)
|
|
228
|
-
logger.log(Level.WARNING, "{0} disconnected", conn);
|
|
229
|
-
if (listener != null)
|
|
230
|
-
listener.clientDisconnected(conn);
|
|
231
|
-
}
|
|
232
|
-
conn.send(socket, payload);
|
|
233
|
-
}
|
|
234
|
-
int returnCount = 0;
|
|
235
|
-
while (returnCount < numClients
|
|
236
|
-
&& returnCount < connections.size() + 1) {
|
|
237
|
-
try {
|
|
238
|
-
DatagramPacket receivePacket = new DatagramPacket(
|
|
239
|
-
receiveData, receiveData.length);
|
|
240
|
-
socket.receive(receivePacket);
|
|
241
|
-
InetAddress ip = receivePacket.getAddress();
|
|
242
|
-
int portDP = receivePacket.getPort();
|
|
243
|
-
String connID = UDPConnection.buildHash(ip,
|
|
244
|
-
portDP);
|
|
245
|
-
UDPConnection conn = connections
|
|
246
|
-
.get(connID);
|
|
247
|
-
if (conn != null) {
|
|
248
|
-
conn.update();
|
|
249
|
-
returnCount++;
|
|
250
|
-
} else {
|
|
251
|
-
// renewed connection
|
|
252
|
-
conn = new UDPConnection(ip, portDP);
|
|
253
|
-
conn.send(socket, getSyncPayload());
|
|
254
|
-
connections.put(connID, conn);
|
|
255
|
-
if (logger != null)
|
|
256
|
-
logger.log(Level.FINE, "re-adding connection: {0}", conn);
|
|
257
|
-
}
|
|
258
|
-
if (listener != null)
|
|
259
|
-
listener.clientUpdated(conn,
|
|
260
|
-
receivePacket);
|
|
261
|
-
} catch (SocketTimeoutException e) {
|
|
262
|
-
// no further packets available
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
long endSynch = System.nanoTime();
|
|
267
|
-
long delta = (endSynch - beginSynch) / 1000000;
|
|
268
|
-
if (delta < frameDuration) {
|
|
269
|
-
int sleep = frameDuration - (int) delta;
|
|
270
|
-
if (logger != null)
|
|
271
|
-
logger.log(Level.FINEST, "sleeping: {0}", sleep);
|
|
272
|
-
Thread.sleep(sleep);
|
|
273
|
-
}
|
|
274
|
-
} else {
|
|
275
|
-
if (logger != null)
|
|
276
|
-
logger.info("all clients disconnected");
|
|
277
|
-
setState(ServerState.WAITING_FOR_CLIENTS);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
} catch (IOException | InterruptedException e) {
|
|
282
|
-
handleException(e);
|
|
283
|
-
} finally {
|
|
284
|
-
if (logger != null)
|
|
285
|
-
logger.info("server shutting down...");
|
|
286
|
-
if (socket != null)
|
|
287
|
-
socket.close();
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Attempts to receive data sent from clients to confirm they're still
|
|
293
|
-
* connected. The timeout for this action is set to 1ms by default, so
|
|
294
|
-
* currently not more than 25 machines can be reliably connected & synched
|
|
295
|
-
* at 25fps.
|
|
296
|
-
*
|
|
297
|
-
* If a connection times out it's removed from the list of active clients.
|
|
298
|
-
* On the other hand if a new connection hash is found we know a client has
|
|
299
|
-
* reconnected and will be added back to the pool.
|
|
300
|
-
*/
|
|
301
|
-
protected void receiveAndAddConnection() {
|
|
302
|
-
try {
|
|
303
|
-
DatagramPacket receivePacket = new DatagramPacket(receiveData,
|
|
304
|
-
receiveData.length);
|
|
305
|
-
if (logger != null)
|
|
306
|
-
logger.log(Level.INFO, "waiting for {0} more clients to reconnect...", (numClients - connections.size()));
|
|
307
|
-
socket.receive(receivePacket);
|
|
308
|
-
InetAddress ip = receivePacket.getAddress();
|
|
309
|
-
int portDP = receivePacket.getPort();
|
|
310
|
-
String connID = UDPConnection.buildHash(ip, portDP);
|
|
311
|
-
if (connections.get(connID) == null) {
|
|
312
|
-
if (connections.isEmpty()) {
|
|
313
|
-
frameCount = 0;
|
|
314
|
-
if (logger != null)
|
|
315
|
-
logger.info("resetting frame count");
|
|
316
|
-
}
|
|
317
|
-
UDPConnection conn = new UDPConnection(ip, portDP);
|
|
318
|
-
connections.put(connID, conn);
|
|
319
|
-
conn.send(socket, getSyncPayload());
|
|
320
|
-
if (logger != null)
|
|
321
|
-
logger.log(Level.FINE, "added new connection: {0}", conn);
|
|
322
|
-
if (listener != null) {
|
|
323
|
-
listener.clientConnected(conn);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
} catch (SocketTimeoutException e) {
|
|
327
|
-
} catch (IOException e) {
|
|
328
|
-
handleException(e);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
private void handleException(Exception e) {
|
|
333
|
-
if (listener != null)
|
|
334
|
-
listener.serverError(e);
|
|
335
|
-
if (logger != null)
|
|
336
|
-
logger.log(Level.SEVERE, "Server error", e);
|
|
337
|
-
else
|
|
338
|
-
e.printStackTrace();
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Updates the internal state of the heartbeat info sent out later.
|
|
343
|
-
*/
|
|
344
|
-
protected void doHeartBeat() {
|
|
345
|
-
frameCount++;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Collects and formats payload data sent via UDP to all clients. By default
|
|
350
|
-
* only the current frame number is sent. If more data is required you can
|
|
351
|
-
* either overwrite this method or append data via an attached
|
|
352
|
-
* {@link ServerListener}.
|
|
353
|
-
*
|
|
354
|
-
* @return payload data as byte array
|
|
355
|
-
*/
|
|
356
|
-
protected byte[] getSyncPayload() {
|
|
357
|
-
StringBuilder sb = new StringBuilder();
|
|
358
|
-
sb.append(frameCount);
|
|
359
|
-
byte[] defaultPayload = sb.toString().getBytes();
|
|
360
|
-
if (listener != null) {
|
|
361
|
-
byte[] userPayload = listener.getSyncPayload();
|
|
362
|
-
if (userPayload != null) {
|
|
363
|
-
byte[] combinedPayload = new byte[defaultPayload.length
|
|
364
|
-
+ userPayload.length];
|
|
365
|
-
System.arraycopy(defaultPayload, 0, combinedPayload, 0,
|
|
366
|
-
defaultPayload.length);
|
|
367
|
-
System.arraycopy(userPayload, 0, combinedPayload,
|
|
368
|
-
defaultPayload.length, userPayload.length);
|
|
369
|
-
return combinedPayload;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return defaultPayload;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Triggers and logs a new server state. If present, this will also notify
|
|
377
|
-
* the {@link ServerListener}.
|
|
378
|
-
*
|
|
379
|
-
* @param s
|
|
380
|
-
* new server state
|
|
381
|
-
*/
|
|
382
|
-
private void setState(ServerState s) {
|
|
383
|
-
state = s;
|
|
384
|
-
if (logger != null)
|
|
385
|
-
logger.log(Level.CONFIG, "new server state: {0}", state);
|
|
386
|
-
if (listener != null)
|
|
387
|
-
listener.serverStateChanged(s);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* @return Maximum size of UDP packets the server is able to receive
|
|
392
|
-
*/
|
|
393
|
-
public int getMaxPacketSize() {
|
|
394
|
-
return receiveData.length;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Sets the max. size of UDP packets the server is able to receive
|
|
399
|
-
*
|
|
400
|
-
* @param size
|
|
401
|
-
*/
|
|
402
|
-
public final void setMaxReceivePacketSize(int size) {
|
|
403
|
-
receivePacketSize = size;
|
|
404
|
-
if (receiveData == null) {
|
|
405
|
-
receiveData = new byte[size];
|
|
406
|
-
} else if (receiveData.length != size) {
|
|
407
|
-
synchronized (receiveData) {
|
|
408
|
-
receiveData = new byte[size];
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* @return configured number of clients the server is expecting and
|
|
415
|
-
* initially waiting for to connect before any syncing begins.
|
|
416
|
-
*/
|
|
417
|
-
public int getNumClients() {
|
|
418
|
-
return numClients;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* Sets the number of clients the server is expecting and initially waiting
|
|
423
|
-
* for to connect before any syncing begins.
|
|
424
|
-
*
|
|
425
|
-
* @param numClients
|
|
426
|
-
*/
|
|
427
|
-
public void setNumClients(int numClients) {
|
|
428
|
-
this.numClients = numClients;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Attaches a logger to the server.
|
|
433
|
-
*
|
|
434
|
-
* @param logger
|
|
435
|
-
*/
|
|
436
|
-
public void setLogger(Logger logger) {
|
|
437
|
-
UDPSyncServer.logger = logger;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Attaches an event listener to the server.
|
|
442
|
-
*
|
|
443
|
-
* @param listener
|
|
444
|
-
*/
|
|
445
|
-
public void setListener(ServerListener listener) {
|
|
446
|
-
this.listener = listener;
|
|
447
|
-
if (logger != null)
|
|
448
|
-
logger.log(Level.INFO, "new server listener: {0}", listener);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
package com.toxi.nio;
|
|
2
|
-
|
|
3
|
-
import java.net.*;
|
|
4
|
-
import java.io.*;
|
|
5
|
-
import java.nio.*;
|
|
6
|
-
import java.nio.channels.*;
|
|
7
|
-
import java.nio.channels.spi.SelectorProvider;
|
|
8
|
-
import java.util.*;
|
|
9
|
-
import java.util.logging.Level;
|
|
10
|
-
import java.util.logging.Logger;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
* @author tux
|
|
15
|
-
*/
|
|
16
|
-
public class UDPClient {
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
*/
|
|
21
|
-
public final static int DEFAULT_PORT = 9876;
|
|
22
|
-
|
|
23
|
-
int port = DEFAULT_PORT;
|
|
24
|
-
SocketAddress remote;
|
|
25
|
-
DatagramChannel channel;
|
|
26
|
-
Selector selector;
|
|
27
|
-
ByteBuffer buffer1;
|
|
28
|
-
ByteBuffer buffer2;
|
|
29
|
-
|
|
30
|
-
int clientID;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
* @param clientID
|
|
35
|
-
*/
|
|
36
|
-
public UDPClient(int clientID) {
|
|
37
|
-
this.clientID = clientID;
|
|
38
|
-
System.out.println("new client ID: " + clientID);
|
|
39
|
-
try {
|
|
40
|
-
remote = new InetSocketAddress("192.168.1.64", port);
|
|
41
|
-
channel = DatagramChannel.open();
|
|
42
|
-
channel.configureBlocking(false);
|
|
43
|
-
channel.connect(remote);
|
|
44
|
-
selector = SelectorProvider.provider().openSelector();
|
|
45
|
-
channel.register(selector, SelectionKey.OP_READ
|
|
46
|
-
| SelectionKey.OP_WRITE);
|
|
47
|
-
buffer1 = ByteBuffer.allocate(4);
|
|
48
|
-
buffer2 = ByteBuffer.allocate(4);
|
|
49
|
-
} catch (IOException ex) {
|
|
50
|
-
System.err.println(ex);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
* @param command
|
|
57
|
-
*/
|
|
58
|
-
public void send(int command) {
|
|
59
|
-
try {
|
|
60
|
-
selector.select(clientID);
|
|
61
|
-
Set readyKeys = selector.selectedKeys();
|
|
62
|
-
Iterator iterator = readyKeys.iterator();
|
|
63
|
-
if (iterator.hasNext()) {
|
|
64
|
-
SelectionKey key = (SelectionKey) iterator.next();
|
|
65
|
-
iterator.remove();
|
|
66
|
-
if (key.isWritable()) {
|
|
67
|
-
buffer1.clear();
|
|
68
|
-
buffer1.putInt(command);
|
|
69
|
-
buffer1.flip();
|
|
70
|
-
channel.write(buffer1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
} catch (IOException ex) {
|
|
74
|
-
System.err.println(ex);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
*
|
|
80
|
-
* @return
|
|
81
|
-
*/
|
|
82
|
-
public int receive() {
|
|
83
|
-
int r = 0;
|
|
84
|
-
try {
|
|
85
|
-
selector.select(clientID);
|
|
86
|
-
Set readyKeys2 = selector.selectedKeys();
|
|
87
|
-
Iterator iterator2 = readyKeys2.iterator();
|
|
88
|
-
if (iterator2.hasNext()) {
|
|
89
|
-
SelectionKey key2 = (SelectionKey) iterator2.next();
|
|
90
|
-
iterator2.remove();
|
|
91
|
-
if (key2.isReadable()) {
|
|
92
|
-
buffer2.clear();
|
|
93
|
-
channel.read(buffer2);
|
|
94
|
-
buffer2.flip();
|
|
95
|
-
int command = buffer2.getInt();
|
|
96
|
-
r = command;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} catch (IOException ex) {
|
|
100
|
-
System.err.println(ex);
|
|
101
|
-
}
|
|
102
|
-
return r;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
*
|
|
107
|
-
* @param args
|
|
108
|
-
*/
|
|
109
|
-
public static void main(String[] args) {
|
|
110
|
-
UDPClient client = new UDPClient(Integer.parseInt(args[0]));
|
|
111
|
-
client.send(1);
|
|
112
|
-
while (true) {
|
|
113
|
-
System.out.println(client.receive());
|
|
114
|
-
try {
|
|
115
|
-
Thread.sleep(33);
|
|
116
|
-
} catch (InterruptedException ex) {
|
|
117
|
-
Logger.getLogger(UDPClient.class.getName()).log(Level.SEVERE, null, ex);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
package com.toxi.nio;
|
|
2
|
-
|
|
3
|
-
import java.net.SocketAddress;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @author tux
|
|
8
|
-
*/
|
|
9
|
-
public class UDPClientState {
|
|
10
|
-
SocketAddress addr;
|
|
11
|
-
boolean isReady;
|
|
12
|
-
long lastUpdate;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param a
|
|
17
|
-
*/
|
|
18
|
-
public UDPClientState(SocketAddress a) {
|
|
19
|
-
addr = a;
|
|
20
|
-
isReady = true;
|
|
21
|
-
lastUpdate = System.currentTimeMillis();
|
|
22
|
-
System.out.println("new client: " + addr);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
* @return
|
|
28
|
-
*/
|
|
29
|
-
public SocketAddress getAddress() {
|
|
30
|
-
return addr;
|
|
31
|
-
}
|
|
32
|
-
}
|