toxiclibs 0.4.0 → 0.8.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 +4 -4
- data/.gitignore +16 -0
- data/.mvn/extensions.xml +8 -0
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +7 -0
- data/COPYING.md +14 -0
- data/Gemfile +10 -0
- data/LICENSE +675 -0
- data/README.md +9 -7
- data/Rakefile +25 -81
- data/examples/README.md +5 -0
- 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/ReplicaBold.ttf +0 -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 +74 -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 +43 -0
- data/examples/physics_type.rb +77 -0
- data/examples/povmesh/data/mask.jpg +0 -0
- data/examples/povmesh/ftest.rb +59 -0
- data/examples/povmesh/mesh_align.rb +47 -0
- data/examples/povmesh/tentacle.rb +71 -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/examples/spherical_harmonics_mesh.rb +50 -0
- data/examples/test_rect.rb +32 -0
- data/lib/toxiclibs.jar +0 -0
- data/lib/toxiclibs.rb +72 -22
- data/lib/toxiclibs/version.rb +1 -1
- data/pom.rb +63 -0
- data/pom.xml +124 -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/audio/AudioBuffer.java +229 -0
- data/src/toxi/audio/AudioSource.java +288 -0
- data/src/toxi/audio/DecompressInputStream.java +159 -0
- data/src/toxi/audio/IIRFilter.java +197 -0
- data/src/toxi/audio/JOALUtil.java +388 -0
- data/src/toxi/audio/MultiTimbralManager.java +162 -0
- data/src/toxi/audio/SoundListener.java +154 -0
- data/src/toxi/audio/SynthUtil.java +109 -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 +127 -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 +28 -0
- metadata +442 -31
@@ -0,0 +1,47 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
*/
|
4
|
+
package com.toxi.net;
|
5
|
+
|
6
|
+
import java.net.DatagramPacket;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @author toxi
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
public class ServerListenerAdapter implements ServerListener {
|
13
|
+
|
14
|
+
@Override
|
15
|
+
public void clientConnected(UDPConnection conn) {
|
16
|
+
|
17
|
+
}
|
18
|
+
|
19
|
+
@Override
|
20
|
+
public void clientDisconnected(UDPConnection conn) {
|
21
|
+
}
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public void clientUpdated(UDPConnection conn, DatagramPacket receivePacket) {
|
25
|
+
}
|
26
|
+
|
27
|
+
@Override
|
28
|
+
public byte[] getSyncPayload() {
|
29
|
+
return new byte[0];
|
30
|
+
}
|
31
|
+
|
32
|
+
@Override
|
33
|
+
public void serverError(Exception e) {
|
34
|
+
}
|
35
|
+
|
36
|
+
@Override
|
37
|
+
public void serverShutdown() {
|
38
|
+
}
|
39
|
+
|
40
|
+
@Override
|
41
|
+
public void serverStarted() {
|
42
|
+
}
|
43
|
+
|
44
|
+
@Override
|
45
|
+
public void serverStateChanged(ServerState s) {
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
package com.toxi.net;
|
2
|
+
|
3
|
+
import java.io.*;
|
4
|
+
import java.net.*;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @author Karsten Schmidt <info@postspectacular.com>
|
8
|
+
*/
|
9
|
+
|
10
|
+
class UDPConnection {
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Default time-to-live duration
|
14
|
+
*/
|
15
|
+
static int TTL = 10000;
|
16
|
+
|
17
|
+
protected InetAddress ip;
|
18
|
+
protected int port;
|
19
|
+
|
20
|
+
protected long lastUpdate;
|
21
|
+
|
22
|
+
UDPConnection(InetAddress ip, int port) {
|
23
|
+
this.ip = ip;
|
24
|
+
this.port = port;
|
25
|
+
lastUpdate = System.currentTimeMillis();
|
26
|
+
}
|
27
|
+
|
28
|
+
public boolean isAlive() {
|
29
|
+
return System.currentTimeMillis() - lastUpdate < TTL;
|
30
|
+
}
|
31
|
+
|
32
|
+
public void update() {
|
33
|
+
lastUpdate = System.currentTimeMillis();
|
34
|
+
}
|
35
|
+
|
36
|
+
public void send(DatagramSocket socket, byte[] data) throws IOException {
|
37
|
+
DatagramPacket sendPacket = new DatagramPacket(data, data.length, ip,
|
38
|
+
port);
|
39
|
+
socket.send(sendPacket);
|
40
|
+
}
|
41
|
+
|
42
|
+
public InetAddress getIP() {
|
43
|
+
return ip;
|
44
|
+
}
|
45
|
+
|
46
|
+
public int getPort() {
|
47
|
+
return port;
|
48
|
+
}
|
49
|
+
|
50
|
+
public long getLastUpdate() {
|
51
|
+
return lastUpdate;
|
52
|
+
}
|
53
|
+
|
54
|
+
@Override
|
55
|
+
public String toString() {
|
56
|
+
return UDPConnection.buildHash(ip, port);
|
57
|
+
}
|
58
|
+
|
59
|
+
static final void setTTL(int ttl) {
|
60
|
+
TTL = ttl;
|
61
|
+
}
|
62
|
+
|
63
|
+
public static final String buildHash(InetAddress ip, int port) {
|
64
|
+
return ip.getHostAddress() + ":" + port;
|
65
|
+
}
|
66
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
package com.toxi.net;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.net.*;
|
5
|
+
import java.util.logging.Level;
|
6
|
+
import java.util.logging.Logger;
|
7
|
+
|
8
|
+
class UDPSyncClient extends Thread {
|
9
|
+
private ClientListener listener;
|
10
|
+
|
11
|
+
protected String serverName;
|
12
|
+
protected int port;
|
13
|
+
protected int clientID;
|
14
|
+
protected int ttl;
|
15
|
+
|
16
|
+
private int frameCount;
|
17
|
+
protected long lastUpdate;
|
18
|
+
|
19
|
+
private static final Logger logger = Logger.getLogger(UDPSyncClient.class
|
20
|
+
.getName());
|
21
|
+
|
22
|
+
UDPSyncClient(String serverName, int port, int clientID, int ttl) {
|
23
|
+
this.serverName = serverName;
|
24
|
+
this.port = port;
|
25
|
+
this.clientID = clientID;
|
26
|
+
this.ttl = ttl;
|
27
|
+
}
|
28
|
+
|
29
|
+
@Override
|
30
|
+
public void run() {
|
31
|
+
DatagramSocket clientSocket = null;
|
32
|
+
lastUpdate = System.currentTimeMillis();
|
33
|
+
try {
|
34
|
+
clientSocket = new DatagramSocket();
|
35
|
+
InetAddress ip = InetAddress.getByName(serverName);
|
36
|
+
byte[] sendData = new byte[] { 1 };
|
37
|
+
byte[] receiveData = new byte[8];
|
38
|
+
// do initial sign on by sending a message to the server
|
39
|
+
DatagramPacket sendPacket = new DatagramPacket(sendData,
|
40
|
+
sendData.length, ip, port);
|
41
|
+
clientSocket.send(sendPacket);
|
42
|
+
while (true) {
|
43
|
+
DatagramPacket receivePacket = new DatagramPacket(receiveData,
|
44
|
+
receiveData.length);
|
45
|
+
clientSocket.receive(receivePacket);
|
46
|
+
String payload = new String(receivePacket.getData(), 0,
|
47
|
+
receivePacket.getLength());
|
48
|
+
if (logger != null)
|
49
|
+
logger.finest(payload);
|
50
|
+
int newFrameCount = Integer.parseInt(payload);
|
51
|
+
if (newFrameCount > 0) {
|
52
|
+
while (frameCount < newFrameCount) {
|
53
|
+
if (listener != null)
|
54
|
+
listener.triggerUpdate();
|
55
|
+
frameCount++;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
if (listener != null)
|
59
|
+
listener.triggerFrame();
|
60
|
+
long now = System.currentTimeMillis();
|
61
|
+
if (now - lastUpdate > ttl) {
|
62
|
+
sendPacket = new DatagramPacket(sendData, sendData.length,
|
63
|
+
ip, port);
|
64
|
+
clientSocket.send(sendPacket);
|
65
|
+
lastUpdate = now;
|
66
|
+
if (logger != null)
|
67
|
+
logger.log(Level.FINER, "TTL updated on: {0}", lastUpdate);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
} catch (IOException | NumberFormatException ex) {
|
71
|
+
logger.log(Level.SEVERE, null, ex);
|
72
|
+
} finally {
|
73
|
+
if (clientSocket != null)
|
74
|
+
clientSocket.close();
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
public void setListener(ClientListener l) {
|
79
|
+
listener = l;
|
80
|
+
}
|
81
|
+
}
|
@@ -0,0 +1,450 @@
|
|
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
|
+
}
|