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.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -0
  3. data/CHANGELOG.md +4 -0
  4. data/LICENSE +675 -0
  5. data/README.md +12 -5
  6. data/Rakefile +25 -82
  7. data/examples/attract_repel/attract_repel.rb +30 -0
  8. data/examples/attract_repel/attractor.rb +23 -0
  9. data/examples/attract_repel/particle.rb +27 -0
  10. data/examples/data/ti_yong.png +0 -0
  11. data/examples/force_directed/cluster.rb +76 -0
  12. data/examples/force_directed/force_directed_graph.rb +92 -0
  13. data/examples/force_directed/node.rb +26 -0
  14. data/examples/gray_scott_image.rb +75 -0
  15. data/examples/gray_scott_tone_map.rb +77 -0
  16. data/examples/implicit.rb +139 -0
  17. data/examples/inflate_mesh.rb +89 -0
  18. data/examples/model_align.rb +44 -0
  19. data/examples/povmesh/ftest.rb +46 -0
  20. data/examples/povmesh/tentacle.rb +73 -0
  21. data/examples/simple_cluster/cluster.rb +47 -0
  22. data/examples/simple_cluster/node.rb +27 -0
  23. data/examples/simple_cluster/simple_cluster.rb +60 -0
  24. data/examples/soft_body/blanket.rb +45 -0
  25. data/examples/soft_body/connection.rb +16 -0
  26. data/examples/soft_body/particle.rb +22 -0
  27. data/examples/soft_body/soft_body_square_adapted.rb +55 -0
  28. data/lib/toxiclibs.jar +0 -0
  29. data/lib/toxiclibs.rb +91 -32
  30. data/lib/toxiclibs/version.rb +1 -1
  31. data/pom.xml +122 -0
  32. data/src/com/toxi/net/ClientListener.java +41 -0
  33. data/src/com/toxi/net/ServerListener.java +70 -0
  34. data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
  35. data/src/com/toxi/net/ServerState.java +18 -0
  36. data/src/com/toxi/net/UDPConnection.java +66 -0
  37. data/src/com/toxi/net/UDPSyncClient.java +81 -0
  38. data/src/com/toxi/net/UDPSyncServer.java +450 -0
  39. data/src/com/toxi/nio/UDPClient.java +121 -0
  40. data/src/com/toxi/nio/UDPClientState.java +32 -0
  41. data/src/com/toxi/nio/UDPServer.java +129 -0
  42. data/src/toxi/color/AccessCriteria.java +114 -0
  43. data/src/toxi/color/AlphaAccessor.java +67 -0
  44. data/src/toxi/color/CMYKAccessor.java +122 -0
  45. data/src/toxi/color/CMYKDistanceProxy.java +40 -0
  46. data/src/toxi/color/ColorGradient.java +260 -0
  47. data/src/toxi/color/ColorList.java +699 -0
  48. data/src/toxi/color/ColorRange.java +671 -0
  49. data/src/toxi/color/ColorTheme.java +163 -0
  50. data/src/toxi/color/DistanceProxy.java +44 -0
  51. data/src/toxi/color/HSVAccessor.java +113 -0
  52. data/src/toxi/color/HSVDistanceProxy.java +40 -0
  53. data/src/toxi/color/HistEntry.java +85 -0
  54. data/src/toxi/color/Histogram.java +185 -0
  55. data/src/toxi/color/Hue.java +249 -0
  56. data/src/toxi/color/LuminanceAccessor.java +78 -0
  57. data/src/toxi/color/NamedColor.java +935 -0
  58. data/src/toxi/color/ProximityComparator.java +70 -0
  59. data/src/toxi/color/RGBAccessor.java +113 -0
  60. data/src/toxi/color/RGBDistanceProxy.java +41 -0
  61. data/src/toxi/color/ReadonlyTColor.java +296 -0
  62. data/src/toxi/color/TColor.java +1677 -0
  63. data/src/toxi/color/TColorAdapter.java +68 -0
  64. data/src/toxi/color/ToneMap.java +218 -0
  65. data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
  66. data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
  67. data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
  68. data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
  69. data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
  70. data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
  71. data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
  72. data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
  73. data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
  74. data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
  75. data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
  76. data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
  77. data/src/toxi/data/csv/CSVAdapter.java +74 -0
  78. data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
  79. data/src/toxi/data/csv/CSVListener.java +61 -0
  80. data/src/toxi/data/csv/CSVParser.java +202 -0
  81. data/src/toxi/data/feeds/AtomAuthor.java +49 -0
  82. data/src/toxi/data/feeds/AtomContent.java +50 -0
  83. data/src/toxi/data/feeds/AtomEntry.java +111 -0
  84. data/src/toxi/data/feeds/AtomFeed.java +129 -0
  85. data/src/toxi/data/feeds/AtomLink.java +62 -0
  86. data/src/toxi/data/feeds/RSSChannel.java +88 -0
  87. data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
  88. data/src/toxi/data/feeds/RSSFeed.java +99 -0
  89. data/src/toxi/data/feeds/RSSItem.java +104 -0
  90. data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
  91. data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
  92. data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
  93. data/src/toxi/geom/AABB.java +658 -0
  94. data/src/toxi/geom/Axis3D.java +116 -0
  95. data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
  96. data/src/toxi/geom/BernsteinPolynomial.java +94 -0
  97. data/src/toxi/geom/BezierCurve2D.java +159 -0
  98. data/src/toxi/geom/BezierCurve3D.java +148 -0
  99. data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
  100. data/src/toxi/geom/BoxIntersector.java +52 -0
  101. data/src/toxi/geom/Circle.java +230 -0
  102. data/src/toxi/geom/CircleIntersector.java +85 -0
  103. data/src/toxi/geom/Cone.java +150 -0
  104. data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
  105. data/src/toxi/geom/CoordinateExtractor.java +16 -0
  106. data/src/toxi/geom/Ellipse.java +250 -0
  107. data/src/toxi/geom/GMatrix.java +2599 -0
  108. data/src/toxi/geom/GVector.java +833 -0
  109. data/src/toxi/geom/GlobalGridTesselator.java +54 -0
  110. data/src/toxi/geom/GridTesselator.java +108 -0
  111. data/src/toxi/geom/Intersector2D.java +49 -0
  112. data/src/toxi/geom/Intersector3D.java +51 -0
  113. data/src/toxi/geom/IsectData2D.java +103 -0
  114. data/src/toxi/geom/IsectData3D.java +103 -0
  115. data/src/toxi/geom/Line2D.java +534 -0
  116. data/src/toxi/geom/Line3D.java +471 -0
  117. data/src/toxi/geom/LineStrip2D.java +430 -0
  118. data/src/toxi/geom/LineStrip3D.java +230 -0
  119. data/src/toxi/geom/LocalGridTesselator.java +57 -0
  120. data/src/toxi/geom/Matrix3d.java +3048 -0
  121. data/src/toxi/geom/Matrix4f.java +3446 -0
  122. data/src/toxi/geom/Matrix4x4.java +1076 -0
  123. data/src/toxi/geom/MatrixSizeException.java +58 -0
  124. data/src/toxi/geom/OctreeVisitor.java +44 -0
  125. data/src/toxi/geom/Origin3D.java +148 -0
  126. data/src/toxi/geom/Plane.java +293 -0
  127. data/src/toxi/geom/PlaneIntersector.java +57 -0
  128. data/src/toxi/geom/PointCloud3D.java +253 -0
  129. data/src/toxi/geom/PointOctree.java +502 -0
  130. data/src/toxi/geom/PointQuadtree.java +375 -0
  131. data/src/toxi/geom/Polygon2D.java +1038 -0
  132. data/src/toxi/geom/PolygonClipper2D.java +45 -0
  133. data/src/toxi/geom/PolygonTesselator.java +20 -0
  134. data/src/toxi/geom/QuadtreeVisitor.java +44 -0
  135. data/src/toxi/geom/Quaternion.java +641 -0
  136. data/src/toxi/geom/Ray2D.java +146 -0
  137. data/src/toxi/geom/Ray3D.java +150 -0
  138. data/src/toxi/geom/Ray3DIntersector.java +75 -0
  139. data/src/toxi/geom/ReadonlyVec2D.java +575 -0
  140. data/src/toxi/geom/ReadonlyVec3D.java +628 -0
  141. data/src/toxi/geom/ReadonlyVec4D.java +431 -0
  142. data/src/toxi/geom/Rect.java +720 -0
  143. data/src/toxi/geom/Reflector3D.java +58 -0
  144. data/src/toxi/geom/Shape2D.java +94 -0
  145. data/src/toxi/geom/Shape3D.java +42 -0
  146. data/src/toxi/geom/SingularMatrixException.java +57 -0
  147. data/src/toxi/geom/SpatialBins.java +182 -0
  148. data/src/toxi/geom/SpatialIndex.java +61 -0
  149. data/src/toxi/geom/Sphere.java +224 -0
  150. data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
  151. data/src/toxi/geom/Spline2D.java +349 -0
  152. data/src/toxi/geom/Spline3D.java +351 -0
  153. data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
  154. data/src/toxi/geom/Triangle2D.java +422 -0
  155. data/src/toxi/geom/Triangle3D.java +456 -0
  156. data/src/toxi/geom/TriangleIntersector.java +105 -0
  157. data/src/toxi/geom/Vec2D.java +1328 -0
  158. data/src/toxi/geom/Vec3D.java +1832 -0
  159. data/src/toxi/geom/Vec4D.java +985 -0
  160. data/src/toxi/geom/VecMathUtil.java +100 -0
  161. data/src/toxi/geom/XAxisCylinder.java +64 -0
  162. data/src/toxi/geom/YAxisCylinder.java +65 -0
  163. data/src/toxi/geom/ZAxisCylinder.java +64 -0
  164. data/src/toxi/geom/mesh/BezierPatch.java +200 -0
  165. data/src/toxi/geom/mesh/BoxSelector.java +62 -0
  166. data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
  167. data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
  168. data/src/toxi/geom/mesh/Face.java +176 -0
  169. data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
  170. data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
  171. data/src/toxi/geom/mesh/Mesh3D.java +224 -0
  172. data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
  173. data/src/toxi/geom/mesh/OBJWriter.java +194 -0
  174. data/src/toxi/geom/mesh/PLYWriter.java +167 -0
  175. data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
  176. data/src/toxi/geom/mesh/STLColorModel.java +54 -0
  177. data/src/toxi/geom/mesh/STLReader.java +185 -0
  178. data/src/toxi/geom/mesh/STLWriter.java +323 -0
  179. data/src/toxi/geom/mesh/SphereFunction.java +156 -0
  180. data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
  181. data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
  182. data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
  183. data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
  184. data/src/toxi/geom/mesh/Terrain.java +451 -0
  185. data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
  186. data/src/toxi/geom/mesh/Vertex.java +78 -0
  187. data/src/toxi/geom/mesh/VertexSelector.java +193 -0
  188. data/src/toxi/geom/mesh/WEFace.java +100 -0
  189. data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
  190. data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
  191. data/src/toxi/geom/mesh/WEVertex.java +134 -0
  192. data/src/toxi/geom/mesh/WingedEdge.java +115 -0
  193. data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
  194. data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
  195. data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
  196. data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
  197. data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
  198. data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
  199. data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
  200. data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
  201. data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
  202. data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
  203. data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
  204. data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
  205. data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
  206. data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
  207. data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
  208. data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
  209. data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
  210. data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
  211. data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
  212. data/src/toxi/geom/nurbs/ControlNet.java +148 -0
  213. data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
  214. data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
  215. data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
  216. data/src/toxi/geom/nurbs/KnotVector.java +333 -0
  217. data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
  218. data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
  219. data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
  220. data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
  221. data/src/toxi/image/util/Filter8bit.java +331 -0
  222. data/src/toxi/image/util/TiledFrameExporter.java +162 -0
  223. data/src/toxi/math/BezierInterpolation.java +102 -0
  224. data/src/toxi/math/CircularInterpolation.java +88 -0
  225. data/src/toxi/math/CosineInterpolation.java +51 -0
  226. data/src/toxi/math/DecimatedInterpolation.java +77 -0
  227. data/src/toxi/math/ExponentialInterpolation.java +68 -0
  228. data/src/toxi/math/InterpolateStrategy.java +60 -0
  229. data/src/toxi/math/Interpolation2D.java +93 -0
  230. data/src/toxi/math/LinearInterpolation.java +46 -0
  231. data/src/toxi/math/MathUtils.java +990 -0
  232. data/src/toxi/math/NonLinearScaleMap.java +101 -0
  233. data/src/toxi/math/ScaleMap.java +183 -0
  234. data/src/toxi/math/SigmoidInterpolation.java +78 -0
  235. data/src/toxi/math/SinCosLUT.java +141 -0
  236. data/src/toxi/math/ThresholdInterpolation.java +58 -0
  237. data/src/toxi/math/ZoomLensInterpolation.java +126 -0
  238. data/src/toxi/math/conversion/UnitTranslator.java +161 -0
  239. data/src/toxi/math/noise/PerlinNoise.java +281 -0
  240. data/src/toxi/math/noise/SimplexNoise.java +542 -0
  241. data/src/toxi/math/waves/AMFMSineWave.java +143 -0
  242. data/src/toxi/math/waves/AbstractWave.java +248 -0
  243. data/src/toxi/math/waves/ConstantWave.java +48 -0
  244. data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
  245. data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
  246. data/src/toxi/math/waves/FMSineWave.java +142 -0
  247. data/src/toxi/math/waves/FMSquareWave.java +143 -0
  248. data/src/toxi/math/waves/FMTriangleWave.java +126 -0
  249. data/src/toxi/math/waves/SineWave.java +81 -0
  250. data/src/toxi/math/waves/Wave2D.java +68 -0
  251. data/src/toxi/math/waves/WaveState.java +69 -0
  252. data/src/toxi/music/scale/AbstractScale.java +117 -0
  253. data/src/toxi/music/scale/GenericScale.java +66 -0
  254. data/src/toxi/music/scale/MajorScale.java +41 -0
  255. data/src/toxi/newmesh/AttributedEdge.java +106 -0
  256. data/src/toxi/newmesh/AttributedFace.java +63 -0
  257. data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
  258. data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
  259. data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
  260. data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
  261. data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
  262. data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
  263. data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
  264. data/src/toxi/newmesh/SpatialIndex.java +78 -0
  265. data/src/toxi/physics2d/ParticlePath2D.java +100 -0
  266. data/src/toxi/physics2d/ParticleString2D.java +184 -0
  267. data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
  268. data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
  269. data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
  270. data/src/toxi/physics2d/VerletParticle2D.java +457 -0
  271. data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
  272. data/src/toxi/physics2d/VerletSpring2D.java +181 -0
  273. data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
  274. data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
  275. data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
  276. data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
  277. data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
  278. data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
  279. data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
  280. data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
  281. data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
  282. data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
  283. data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
  284. data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
  285. data/src/toxi/physics3d/ParticlePath3D.java +100 -0
  286. data/src/toxi/physics3d/ParticleString3D.java +184 -0
  287. data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
  288. data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
  289. data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
  290. data/src/toxi/physics3d/VerletParticle3D.java +385 -0
  291. data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
  292. data/src/toxi/physics3d/VerletSpring3D.java +180 -0
  293. data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
  294. data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
  295. data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
  296. data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
  297. data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
  298. data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
  299. data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
  300. data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
  301. data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
  302. data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
  303. data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
  304. data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
  305. data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
  306. data/src/toxi/processing/ArrowModifier.java +116 -0
  307. data/src/toxi/processing/DashedLineModifier.java +48 -0
  308. data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
  309. data/src/toxi/processing/Line2DRenderModifier.java +18 -0
  310. data/src/toxi/processing/MeshToVBO.java +94 -0
  311. data/src/toxi/processing/NormalMapper.java +18 -0
  312. data/src/toxi/processing/POVInterface.java +121 -0
  313. data/src/toxi/processing/POVMesh.java +219 -0
  314. data/src/toxi/processing/POVWriter.java +460 -0
  315. data/src/toxi/processing/RCOpaque.java +77 -0
  316. data/src/toxi/processing/RCTransp.java +78 -0
  317. data/src/toxi/processing/TextureBuilder.java +232 -0
  318. data/src/toxi/processing/Textures.java +110 -0
  319. data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
  320. data/src/toxi/processing/Tracing.java +25 -0
  321. data/src/toxi/processing/XYZNormalMapper.java +30 -0
  322. data/src/toxi/sim/automata/CAMatrix.java +297 -0
  323. data/src/toxi/sim/automata/CARule.java +76 -0
  324. data/src/toxi/sim/automata/CARule2D.java +354 -0
  325. data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
  326. data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
  327. data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
  328. data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
  329. data/src/toxi/sim/dla/DLA.java +497 -0
  330. data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
  331. data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
  332. data/src/toxi/sim/dla/DLAEventListener.java +57 -0
  333. data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
  334. data/src/toxi/sim/dla/DLAParticle.java +102 -0
  335. data/src/toxi/sim/dla/DLASegment.java +88 -0
  336. data/src/toxi/sim/dla/PipelineOrder.java +50 -0
  337. data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
  338. data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
  339. data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
  340. data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
  341. data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
  342. data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
  343. data/src/toxi/sim/grayscott/GrayScott.java +469 -0
  344. data/src/toxi/util/DateUtils.java +141 -0
  345. data/src/toxi/util/FileSequenceDescriptor.java +181 -0
  346. data/src/toxi/util/FileUtils.java +467 -0
  347. data/src/toxi/util/datatypes/ArraySet.java +128 -0
  348. data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
  349. data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
  350. data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
  351. data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
  352. data/src/toxi/util/datatypes/DoubleRange.java +251 -0
  353. data/src/toxi/util/datatypes/FloatRange.java +251 -0
  354. data/src/toxi/util/datatypes/GenericSet.java +215 -0
  355. data/src/toxi/util/datatypes/IntegerRange.java +247 -0
  356. data/src/toxi/util/datatypes/IntegerSet.java +149 -0
  357. data/src/toxi/util/datatypes/ItemIndex.java +72 -0
  358. data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
  359. data/src/toxi/util/datatypes/TypedProperties.java +291 -0
  360. data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
  361. data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
  362. data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
  363. data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
  364. data/src/toxi/util/events/EventDispatcher.java +86 -0
  365. data/src/toxi/volume/AdditiveBrush.java +19 -0
  366. data/src/toxi/volume/ArrayIsoSurface.java +297 -0
  367. data/src/toxi/volume/BoxBrush.java +100 -0
  368. data/src/toxi/volume/BrushMode.java +16 -0
  369. data/src/toxi/volume/HashIsoSurface.java +354 -0
  370. data/src/toxi/volume/IsoSurface.java +59 -0
  371. data/src/toxi/volume/MarchingCubesIndex.java +312 -0
  372. data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
  373. data/src/toxi/volume/MeshVoxelizer.java +216 -0
  374. data/src/toxi/volume/MultiplyBrush.java +20 -0
  375. data/src/toxi/volume/PeakBrush.java +21 -0
  376. data/src/toxi/volume/ReplaceBrush.java +19 -0
  377. data/src/toxi/volume/RoundBrush.java +113 -0
  378. data/src/toxi/volume/VolumetricBrush.java +160 -0
  379. data/src/toxi/volume/VolumetricHashMap.java +179 -0
  380. data/src/toxi/volume/VolumetricSpace.java +195 -0
  381. data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
  382. data/toxiclibs.gemspec +34 -0
  383. metadata +424 -27
@@ -0,0 +1,1201 @@
1
+ /*
2
+ * __ .__ .__ ._____.
3
+ * _/ |_ _______ __|__| ____ | | |__\_ |__ ______
4
+ * \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
5
+ * | | ( <_> > <| \ \___| |_| || \_\ \\___ \
6
+ * |__| \____/__/\_ \__|\___ >____/__||___ /____ >
7
+ * \/ \/ \/ \/
8
+ *
9
+ * Copyright (c) 2006-2011 Karsten Schmidt
10
+ *
11
+ * This library is free software; you can redistribute it and/or
12
+ * modify it under the terms of the GNU Lesser General Public
13
+ * License as published by the Free Software Foundation; either
14
+ * version 2.1 of the License, or (at your option) any later version.
15
+ *
16
+ * http://creativecommons.org/licenses/LGPL/2.1/
17
+ *
18
+ * This library is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
+ * Lesser General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU Lesser General Public
24
+ * License along with this library; if not, write to the Free Software
25
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26
+ */
27
+
28
+ package toxi.geom.mesh;
29
+
30
+ import java.io.OutputStream;
31
+ import java.util.ArrayList;
32
+ import java.util.Collection;
33
+ import java.util.LinkedHashMap;
34
+ import java.util.List;
35
+ import java.util.logging.Level;
36
+ import java.util.logging.Logger;
37
+
38
+ import toxi.geom.AABB;
39
+ import toxi.geom.Intersector3D;
40
+ import toxi.geom.IsectData3D;
41
+ import toxi.geom.Matrix4x4;
42
+ import toxi.geom.Quaternion;
43
+ import toxi.geom.Ray3D;
44
+ import toxi.geom.ReadonlyVec3D;
45
+ import toxi.geom.Sphere;
46
+ import toxi.geom.Triangle3D;
47
+ import toxi.geom.TriangleIntersector;
48
+ import toxi.geom.Vec2D;
49
+ import toxi.geom.Vec3D;
50
+ import toxi.math.MathUtils;
51
+
52
+ /**
53
+ * An extensible class to dynamically build, manipulate & export triangle
54
+ * meshes. Meshes are built face by face. This implementation automatically
55
+ * re-uses existing vertices and can generate smooth vertex normals. Vertice and
56
+ * face lists are directly accessible for speed & convenience.
57
+ */
58
+ public class TriangleMesh implements Mesh3D, Intersector3D {
59
+
60
+ /**
61
+ * Default size for vertex list
62
+ */
63
+ public static final int DEFAULT_NUM_VERTICES = 1000;
64
+
65
+ /**
66
+ * Default size for face list
67
+ */
68
+ public static final int DEFAULT_NUM_FACES = 3000;
69
+
70
+ /**
71
+ * Default stride setting used for serializing mesh properties into arrays.
72
+ */
73
+ public static final int DEFAULT_STRIDE = 4;
74
+
75
+ /**
76
+ *
77
+ */
78
+ protected static final Logger logger = Logger.getLogger(TriangleMesh.class
79
+ .getName());
80
+
81
+ /**
82
+ * Mesh name
83
+ */
84
+ public String name;
85
+
86
+ /**
87
+ * Vertex buffer & lookup index when adding new faces
88
+ */
89
+ public LinkedHashMap<Vec3D, Vertex> vertices;
90
+
91
+ /**
92
+ * Face list
93
+ */
94
+ public ArrayList<Face> faces;
95
+
96
+ /**
97
+ *
98
+ */
99
+ protected AABB bounds;
100
+
101
+ /**
102
+ *
103
+ */
104
+ protected Vec3D centroid = new Vec3D();
105
+
106
+ /**
107
+ *
108
+ */
109
+ protected int numVertices;
110
+
111
+ /**
112
+ *
113
+ */
114
+ protected int numFaces;
115
+
116
+ /**
117
+ *
118
+ */
119
+ protected Matrix4x4 matrix = new Matrix4x4();
120
+
121
+ /**
122
+ *
123
+ */
124
+ protected TriangleIntersector intersector = new TriangleIntersector();
125
+
126
+ /**
127
+ *
128
+ */
129
+ protected int uniqueVertexID;
130
+
131
+ /**
132
+ *
133
+ */
134
+ public TriangleMesh() {
135
+ this("untitled");
136
+ }
137
+
138
+ /**
139
+ * Creates a new mesh instance with initial default buffer sizes.
140
+ *
141
+ * @param name
142
+ * mesh name
143
+ */
144
+ public TriangleMesh(String name) {
145
+ this(name, DEFAULT_NUM_VERTICES, DEFAULT_NUM_FACES);
146
+ }
147
+
148
+ /**
149
+ * Creates a new mesh instance with the given initial buffer sizes. These
150
+ * numbers are no limits and the mesh can be smaller or grow later on.
151
+ * They're only used to initialise the underlying collections.
152
+ *
153
+ * @param name
154
+ * mesh name
155
+ * @param numV
156
+ * initial vertex buffer size
157
+ * @param numF
158
+ * initial face list size
159
+ */
160
+ public TriangleMesh(String name, int numV, int numF) {
161
+ init(name, numV, numF);
162
+ }
163
+
164
+ @Override
165
+ public TriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c) {
166
+ return addFace(a, b, c, null, null, null, null);
167
+ }
168
+
169
+ @Override
170
+ public TriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec2D uvA,
171
+ Vec2D uvB, Vec2D uvC) {
172
+ return addFace(a, b, c, null, uvA, uvB, uvC);
173
+ }
174
+
175
+ /**
176
+ *
177
+ * @param a
178
+ * @param b
179
+ * @param c
180
+ * @param n
181
+ * @return
182
+ */
183
+ @Override
184
+ public TriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec3D n) {
185
+ return addFace(a, b, c, n, null, null, null);
186
+ }
187
+
188
+ /**
189
+ *
190
+ * @param a
191
+ * @param b
192
+ * @param c
193
+ * @param n
194
+ * @param uvA
195
+ * @param uvB
196
+ * @param uvC
197
+ * @return
198
+ */
199
+ @Override
200
+ public TriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec3D n, Vec2D uvA,
201
+ Vec2D uvB, Vec2D uvC) {
202
+ Vertex va = checkVertex(a);
203
+ Vertex vb = checkVertex(b);
204
+ Vertex vc = checkVertex(c);
205
+ if (va.id == vb.id || va.id == vc.id || vb.id == vc.id) {
206
+ if (logger.isLoggable(Level.FINE)) {
207
+ logger.log(Level.FINE, "ignorning invalid face: {0},{1},{2}", new Object[]{a, b, c});
208
+ }
209
+ } else {
210
+ if (n != null) {
211
+ Vec3D nc = va.sub(vc).crossSelf(va.sub(vb));
212
+ if (n.dot(nc) < 0) {
213
+ Vertex t = va;
214
+ va = vb;
215
+ vb = t;
216
+ }
217
+ }
218
+ Face f = new Face(va, vb, vc, uvA, uvB, uvC);
219
+ faces.add(f);
220
+ numFaces++;
221
+ }
222
+ return this;
223
+ }
224
+
225
+ /**
226
+ * Adds all faces from the given mesh to this one.
227
+ *
228
+ * @param m
229
+ * source mesh instance
230
+ * @return
231
+ */
232
+ @Override
233
+ public TriangleMesh addMesh(Mesh3D m) {
234
+ m.getFaces().stream().forEach((f) -> {
235
+ addFace(f.a, f.b, f.c, f.uvA, f.uvB, f.uvC);
236
+ });
237
+ return this;
238
+ }
239
+
240
+ @Override
241
+ public AABB center(ReadonlyVec3D origin) {
242
+ computeCentroid();
243
+ Vec3D delta = origin != null ? origin.sub(centroid) : centroid
244
+ .getInverted();
245
+ vertices.values().stream().forEach((v) -> {
246
+ v.addSelf(delta);
247
+ });
248
+ getBoundingBox();
249
+ return bounds;
250
+ }
251
+
252
+ private Vertex checkVertex(Vec3D v) {
253
+ Vertex vertex = vertices.get(v);
254
+ if (vertex == null) {
255
+ vertex = createVertex(v, uniqueVertexID++);
256
+ vertices.put(vertex, vertex);
257
+ numVertices++;
258
+ }
259
+ return vertex;
260
+ }
261
+
262
+ /**
263
+ * Clears all counters, and vertex & face buffers.
264
+ */
265
+ @Override
266
+ public TriangleMesh clear() {
267
+ vertices.clear();
268
+ faces.clear();
269
+ bounds = null;
270
+ numVertices = 0;
271
+ numFaces = 0;
272
+ uniqueVertexID = 0;
273
+ return this;
274
+ }
275
+
276
+ @Override
277
+ public Vec3D computeCentroid() {
278
+ centroid.clear();
279
+ vertices.values().stream().forEach((v) -> {
280
+ centroid.addSelf(v);
281
+ });
282
+ return centroid.scaleSelf(1f / numVertices).copy();
283
+ }
284
+
285
+ /**
286
+ * Re-calculates all face normals.
287
+ */
288
+ @Override
289
+ public TriangleMesh computeFaceNormals() {
290
+ faces.stream().forEach((f) -> {
291
+ f.computeNormal();
292
+ });
293
+ return this;
294
+ }
295
+
296
+ /**
297
+ * Computes the smooth vertex normals for the entire mesh.
298
+ */
299
+ @Override
300
+ public TriangleMesh computeVertexNormals() {
301
+ vertices.values().stream().forEach((v) -> {
302
+ v.clearNormal();
303
+ });
304
+ faces.stream().map((f) -> {
305
+ f.a.addFaceNormal(f.normal);
306
+ return f;
307
+ }).map((f) -> {
308
+ f.b.addFaceNormal(f.normal);
309
+ return f;
310
+ }).forEach((f) -> {
311
+ f.c.addFaceNormal(f.normal);
312
+ });
313
+ vertices.values().stream().forEach((v) -> {
314
+ v.computeNormal();
315
+ });
316
+ return this;
317
+ }
318
+
319
+ /**
320
+ * Creates a deep clone of the mesh. The new mesh name will have "-copy" as
321
+ * suffix.
322
+ *
323
+ * @return new mesh instance
324
+ */
325
+ public TriangleMesh copy() {
326
+ TriangleMesh m = new TriangleMesh(name + "-copy", numVertices, numFaces);
327
+ faces.stream().forEach((f) -> {
328
+ m.addFace(f.a, f.b, f.c, f.normal, f.uvA, f.uvB, f.uvC);
329
+ });
330
+ return m;
331
+ }
332
+
333
+ /**
334
+ *
335
+ * @param v
336
+ * @param id
337
+ * @return
338
+ */
339
+ protected Vertex createVertex(Vec3D v, int id) {
340
+ return new Vertex(v, id);
341
+ }
342
+
343
+ @Override
344
+ public TriangleMesh faceOutwards() {
345
+ computeCentroid();
346
+ faces.stream().forEach((f) -> {
347
+ Vec3D n = f.getCentroid().sub(centroid);
348
+ float dot = n.dot(f.normal);
349
+ if (dot < 0) {
350
+ f.flipVertexOrder();
351
+ }
352
+ });
353
+ return this;
354
+ }
355
+
356
+ @Override
357
+ public TriangleMesh flipVertexOrder() {
358
+ faces.stream().map((f) -> {
359
+ Vertex t = f.a;
360
+ f.a = f.b;
361
+ f.b = t;
362
+ return f;
363
+ }).map((f) -> {
364
+ Vec2D tuv = f.uvA;
365
+ f.uvA = f.uvB;
366
+ f.uvB = tuv;
367
+ return f;
368
+ }).forEach((f) -> {
369
+ f.normal.invert();
370
+ });
371
+ return this;
372
+ }
373
+
374
+ @Override
375
+ public TriangleMesh flipYAxis() {
376
+ transform(new Matrix4x4().scaleSelf(1, -1, 1));
377
+ flipVertexOrder();
378
+ return this;
379
+ }
380
+
381
+ @Override
382
+ public AABB getBoundingBox() {
383
+ final Vec3D minBounds = Vec3D.MAX_VALUE.copy();
384
+ final Vec3D maxBounds = Vec3D.NEG_MAX_VALUE.copy();
385
+ vertices.values().stream().map((v) -> {
386
+ minBounds.minSelf(v);
387
+ return v;
388
+ }).forEach((v) -> {
389
+ maxBounds.maxSelf(v);
390
+ });
391
+ bounds = AABB.fromMinMax(minBounds, maxBounds);
392
+ return bounds;
393
+ }
394
+
395
+ @Override
396
+ public Sphere getBoundingSphere() {
397
+ float radius = 0;
398
+ computeCentroid();
399
+ for (Vertex v : vertices.values()) {
400
+ radius = MathUtils.max(radius, v.distanceToSquared(centroid));
401
+ }
402
+ return new Sphere(centroid, (float) Math.sqrt(radius));
403
+ }
404
+
405
+ /**
406
+ *
407
+ * @param p
408
+ * @return
409
+ */
410
+ @Override
411
+ public Vertex getClosestVertexToPoint(ReadonlyVec3D p) {
412
+ Vertex closest = null;
413
+ float minDist = Float.MAX_VALUE;
414
+ for (Vertex v : vertices.values()) {
415
+ float d = v.distanceToSquared(p);
416
+ if (d < minDist) {
417
+ closest = v;
418
+ minDist = d;
419
+ }
420
+ }
421
+ return closest;
422
+ }
423
+
424
+ /**
425
+ * Creates an array of unravelled normal coordinates. For each vertex the
426
+ * normal vector of its parent face is used. This is a convienence
427
+ * invocation of {@link #getFaceNormalsAsArray(float[], int, int)} with a
428
+ * default stride = 4.
429
+ *
430
+ * @return array of xyz normal coords
431
+ */
432
+ public float[] getFaceNormalsAsArray() {
433
+ return getFaceNormalsAsArray(null, 0, DEFAULT_STRIDE);
434
+ }
435
+
436
+ /**
437
+ * Creates an array of unravelled normal coordinates. For each vertex the
438
+ * normal vector of its parent face is used. This method can be used to
439
+ * translate the internal mesh data structure into a format suitable for
440
+ * OpenGL Vertex Buffer Objects (by choosing stride=4). For more detail,
441
+ * please see {@link #getMeshAsVertexArray(float[], int, int)}
442
+ *
443
+ * @see #getMeshAsVertexArray(float[], int, int)
444
+ *
445
+ * @param normals
446
+ * existing float array or null to automatically create one
447
+ * @param offset
448
+ * start index in array to place normals
449
+ * @param stride
450
+ * stride/alignment setting for individual coordinates (min value
451
+ * = 3)
452
+ * @return array of xyz normal coords
453
+ */
454
+ public float[] getFaceNormalsAsArray(float[] normals, int offset, int stride) {
455
+ stride = MathUtils.max(stride, 3);
456
+ if (normals == null) {
457
+ normals = new float[faces.size() * 3 * stride];
458
+ }
459
+ int i = offset;
460
+ for (Face f : faces) {
461
+ normals[i] = f.normal.x;
462
+ normals[i + 1] = f.normal.y;
463
+ normals[i + 2] = f.normal.z;
464
+ i += stride;
465
+ normals[i] = f.normal.x;
466
+ normals[i + 1] = f.normal.y;
467
+ normals[i + 2] = f.normal.z;
468
+ i += stride;
469
+ normals[i] = f.normal.x;
470
+ normals[i + 1] = f.normal.y;
471
+ normals[i + 2] = f.normal.z;
472
+ i += stride;
473
+ }
474
+ return normals;
475
+ }
476
+
477
+ /**
478
+ *
479
+ * @return
480
+ */
481
+ @Override
482
+ public List<Face> getFaces() {
483
+ return faces;
484
+ }
485
+
486
+ /**
487
+ * Builds an array of vertex indices of all faces. Each vertex ID
488
+ * corresponds to its position in the {@link #vertices} HashMap. The
489
+ * resulting array will be 3 times the face count.
490
+ *
491
+ * @return array of vertex indices
492
+ */
493
+ public int[] getFacesAsArray() {
494
+ int[] faceList = new int[faces.size() * 3];
495
+ int i = 0;
496
+ for (Face f : faces) {
497
+ faceList[i++] = f.a.id;
498
+ faceList[i++] = f.b.id;
499
+ faceList[i++] = f.c.id;
500
+ }
501
+ return faceList;
502
+ }
503
+
504
+ @Override
505
+ public IsectData3D getIntersectionData() {
506
+ return intersector.getIntersectionData();
507
+ }
508
+
509
+ /**
510
+ * Creates an array of unravelled vertex coordinates for all faces using a
511
+ * stride setting of 4, resulting in a serialized version of all mesh vertex
512
+ * coordinates suitable for VBOs.
513
+ *
514
+ * @see #getMeshAsVertexArray(float[], int, int)
515
+ * @return float array of vertex coordinates
516
+ */
517
+ public float[] getMeshAsVertexArray() {
518
+ return getMeshAsVertexArray(null, 0, DEFAULT_STRIDE);
519
+ }
520
+
521
+ /**
522
+ * Creates an array of unravelled vertex coordinates for all faces. This
523
+ * method can be used to translate the internal mesh data structure into a
524
+ * format suitable for OpenGL Vertex Buffer Objects (by choosing stride=4).
525
+ * The order of the array will be as follows:
526
+ *
527
+ * <ul>
528
+ * <li>Face 1:
529
+ * <ul>
530
+ * <li>Vertex #1
531
+ * <ul>
532
+ * <li>x</li>
533
+ * <li>y</li>
534
+ * <li>z</li>
535
+ * <li>[optional empty indices to match stride setting]</li>
536
+ * </ul>
537
+ * </li>
538
+ * <li>Vertex #2
539
+ * <ul>
540
+ * <li>x</li>
541
+ * <li>y</li>
542
+ * <li>z</li>
543
+ * <li>[optional empty indices to match stride setting]</li>
544
+ * </ul>
545
+ * </li>
546
+ * <li>Vertex #3
547
+ * <ul>
548
+ * <li>x</li>
549
+ * <li>y</li>
550
+ * <li>z</li>
551
+ * <li>[optional empty indices to match stride setting]</li>
552
+ * </ul>
553
+ * </li>
554
+ * </ul>
555
+ * <li>Face 2:
556
+ * <ul>
557
+ * <li>Vertex #1</li>
558
+ * <li>...etc.</li>
559
+ * </ul>
560
+ * </ul>
561
+ *
562
+ * @param verts
563
+ * an existing target array or null to automatically create one
564
+ * @param offset
565
+ * start index in arrtay to place vertices
566
+ * @param stride
567
+ * stride/alignment setting for individual coordinates
568
+ * @return array of xyz vertex coords
569
+ */
570
+ public float[] getMeshAsVertexArray(float[] verts, int offset, int stride) {
571
+ stride = MathUtils.max(stride, 3);
572
+ if (verts == null) {
573
+ verts = new float[faces.size() * 3 * stride];
574
+ }
575
+ int i = offset;
576
+ for (Face f : faces) {
577
+ verts[i] = f.a.x;
578
+ verts[i + 1] = f.a.y;
579
+ verts[i + 2] = f.a.z;
580
+ i += stride;
581
+ verts[i] = f.b.x;
582
+ verts[i + 1] = f.b.y;
583
+ verts[i + 2] = f.b.z;
584
+ i += stride;
585
+ verts[i] = f.c.x;
586
+ verts[i + 1] = f.c.y;
587
+ verts[i + 2] = f.c.z;
588
+ i += stride;
589
+ }
590
+ return verts;
591
+ }
592
+
593
+ /**
594
+ *
595
+ * @return
596
+ */
597
+ public float[] getNormalsForUniqueVerticesAsArray() {
598
+ float[] normals = new float[numVertices * 3];
599
+ int i = 0;
600
+ for (Vertex v : vertices.values()) {
601
+ normals[i++] = v.normal.x;
602
+ normals[i++] = v.normal.y;
603
+ normals[i++] = v.normal.z;
604
+ }
605
+ return normals;
606
+ }
607
+
608
+ @Override
609
+ public int getNumFaces() {
610
+ return numFaces;
611
+ }
612
+
613
+ @Override
614
+ public int getNumVertices() {
615
+ return numVertices;
616
+ }
617
+
618
+ /**
619
+ *
620
+ * @param axis
621
+ * @param theta
622
+ * @return
623
+ */
624
+ public TriangleMesh getRotatedAroundAxis(Vec3D axis, float theta) {
625
+ return copy().rotateAroundAxis(axis, theta);
626
+ }
627
+
628
+ /**
629
+ *
630
+ * @param theta
631
+ * @return
632
+ */
633
+ public TriangleMesh getRotatedX(float theta) {
634
+ return copy().rotateX(theta);
635
+ }
636
+
637
+ /**
638
+ *
639
+ * @param theta
640
+ * @return
641
+ */
642
+ public TriangleMesh getRotatedY(float theta) {
643
+ return copy().rotateY(theta);
644
+ }
645
+
646
+ /**
647
+ *
648
+ * @param theta
649
+ * @return
650
+ */
651
+ public TriangleMesh getRotatedZ(float theta) {
652
+ return copy().rotateZ(theta);
653
+ }
654
+
655
+ /**
656
+ *
657
+ * @param scale
658
+ * @return
659
+ */
660
+ public TriangleMesh getScaled(float scale) {
661
+ return copy().scale(scale);
662
+ }
663
+
664
+ /**
665
+ *
666
+ * @param scale
667
+ * @return
668
+ */
669
+ public TriangleMesh getScaled(Vec3D scale) {
670
+ return copy().scale(scale);
671
+ }
672
+
673
+ /**
674
+ *
675
+ * @param trans
676
+ * @return
677
+ */
678
+ public TriangleMesh getTranslated(Vec3D trans) {
679
+ return copy().translate(trans);
680
+ }
681
+
682
+ /**
683
+ *
684
+ * @return
685
+ */
686
+ public float[] getUniqueVerticesAsArray() {
687
+ float[] verts = new float[numVertices * 3];
688
+ int i = 0;
689
+ for (Vertex v : vertices.values()) {
690
+ verts[i++] = v.x;
691
+ verts[i++] = v.y;
692
+ verts[i++] = v.z;
693
+ }
694
+ return verts;
695
+ }
696
+
697
+ /**
698
+ *
699
+ * @param v
700
+ * @return
701
+ */
702
+ public Vertex getVertexAtPoint(Vec3D v) {
703
+ return vertices.get(v);
704
+ }
705
+
706
+ /**
707
+ *
708
+ * @param id
709
+ * @return
710
+ */
711
+ public Vertex getVertexForID(int id) {
712
+ Vertex vertex = null;
713
+ for (Vertex v : vertices.values()) {
714
+ if (v.id == id) {
715
+ vertex = v;
716
+ break;
717
+ }
718
+ }
719
+ return vertex;
720
+ }
721
+
722
+ /**
723
+ * Creates an array of unravelled vertex normal coordinates for all faces.
724
+ * Uses default stride = 4.
725
+ *
726
+ * @see #getVertexNormalsAsArray(float[], int, int)
727
+ * @return array of xyz normal coords
728
+ */
729
+ public float[] getVertexNormalsAsArray() {
730
+ return getVertexNormalsAsArray(null, 0, DEFAULT_STRIDE);
731
+ }
732
+
733
+ /**
734
+ * Creates an array of unravelled vertex normal coordinates for all faces.
735
+ * This method can be used to translate the internal mesh data structure
736
+ * into a format suitable for OpenGL Vertex Buffer Objects (by choosing
737
+ * stride=4). For more detail, please see
738
+ * {@link #getMeshAsVertexArray(float[], int, int)}
739
+ *
740
+ * @see #getMeshAsVertexArray(float[], int, int)
741
+ *
742
+ * @param normals
743
+ * existing float array or null to automatically create one
744
+ * @param offset
745
+ * start index in array to place normals
746
+ * @param stride
747
+ * stride/alignment setting for individual coordinates (min value
748
+ * = 3)
749
+ * @return array of xyz normal coords
750
+ */
751
+ public float[] getVertexNormalsAsArray(float[] normals, int offset,
752
+ int stride) {
753
+ stride = MathUtils.max(stride, 3);
754
+ if (normals == null) {
755
+ normals = new float[faces.size() * 3 * stride];
756
+ }
757
+ int i = offset;
758
+ for (Face f : faces) {
759
+ normals[i] = f.a.normal.x;
760
+ normals[i + 1] = f.a.normal.y;
761
+ normals[i + 2] = f.a.normal.z;
762
+ i += stride;
763
+ normals[i] = f.b.normal.x;
764
+ normals[i + 1] = f.b.normal.y;
765
+ normals[i + 2] = f.b.normal.z;
766
+ i += stride;
767
+ normals[i] = f.c.normal.x;
768
+ normals[i + 1] = f.c.normal.y;
769
+ normals[i + 2] = f.c.normal.z;
770
+ i += stride;
771
+ }
772
+ return normals;
773
+ }
774
+
775
+ /**
776
+ *
777
+ * @return
778
+ */
779
+ @Override
780
+ public Collection<Vertex> getVertices() {
781
+ return vertices.values();
782
+ }
783
+
784
+ /**
785
+ *
786
+ * @param stl
787
+ * @param useFlippedY
788
+ */
789
+ protected void handleSaveAsSTL(STLWriter stl, boolean useFlippedY) {
790
+ if (useFlippedY) {
791
+ stl.setScale(new Vec3D(1, -1, 1));
792
+ faces.stream().forEach((f) -> {
793
+ stl.face(f.a, f.b, f.c, f.normal, STLWriter.DEFAULT_RGB);
794
+ });
795
+ } else {
796
+ faces.stream().forEach((f) -> {
797
+ stl.face(f.b, f.a, f.c, f.normal, STLWriter.DEFAULT_RGB);
798
+ });
799
+ }
800
+ stl.endSave();
801
+ logger.log(Level.INFO, "{0} faces written", numFaces);
802
+ }
803
+
804
+ /**
805
+ *
806
+ * @param name
807
+ * @param numV
808
+ * @param numF
809
+ * @return
810
+ */
811
+ @Override
812
+ public TriangleMesh init(String name, int numV, int numF) {
813
+ setName(name);
814
+ vertices = new LinkedHashMap<>(numV, 1.5f, false);
815
+ faces = new ArrayList<>(numF);
816
+ return this;
817
+ }
818
+
819
+ @Override
820
+ public boolean intersectsRay(Ray3D ray) {
821
+ Triangle3D tri = intersector.getTriangle();
822
+ return faces.stream().map((f) -> {
823
+ tri.set(f.a, f.b, f.c);
824
+ return f;
825
+ }).anyMatch((_item) -> (intersector.intersectsRay(ray)));
826
+ }
827
+
828
+ /**
829
+ *
830
+ * @param f
831
+ * @param size
832
+ * @return
833
+ */
834
+ public Triangle3D perforateFace(Face f, float size) {
835
+ Vec3D centrd = f.getCentroid();
836
+ float d = 1 - size;
837
+ Vec3D a2 = f.a.interpolateTo(centrd, d);
838
+ Vec3D b2 = f.b.interpolateTo(centrd, d);
839
+ Vec3D c2 = f.c.interpolateTo(centrd, d);
840
+ removeFace(f);
841
+ addFace(f.a, b2, a2);
842
+ addFace(f.a, f.b, b2);
843
+ addFace(f.b, c2, b2);
844
+ addFace(f.b, f.c, c2);
845
+ addFace(f.c, a2, c2);
846
+ addFace(f.c, f.a, a2);
847
+ return new Triangle3D(a2, b2, c2);
848
+ }
849
+
850
+ /**
851
+ * Rotates the mesh in such a way so that its "forward" axis is aligned with
852
+ * the given direction. This version uses the positive Z-axis as default
853
+ * forward direction.
854
+ *
855
+ * @param dir
856
+ * new target direction to point in
857
+ * @return itself
858
+ */
859
+ public TriangleMesh pointTowards(ReadonlyVec3D dir) {
860
+ return transform(Quaternion.getAlignmentQuat(dir, Vec3D.Z_AXIS)
861
+ .toMatrix4x4(matrix), true);
862
+ }
863
+
864
+ /**
865
+ * Rotates the mesh in such a way so that its "forward" axis is aligned with
866
+ * the given direction. This version allows to specify the forward
867
+ * direction.
868
+ *
869
+ * @param dir
870
+ * new target direction to point in
871
+ * @param forward
872
+ * current forward axis
873
+ * @return itself
874
+ */
875
+ public TriangleMesh pointTowards(ReadonlyVec3D dir, ReadonlyVec3D forward) {
876
+ return transform(
877
+ Quaternion.getAlignmentQuat(dir, forward).toMatrix4x4(matrix),
878
+ true);
879
+ }
880
+
881
+ /**
882
+ *
883
+ * @param f
884
+ */
885
+ public void removeFace(Face f) {
886
+ faces.remove(f);
887
+ }
888
+
889
+ /**
890
+ *
891
+ * @param axis
892
+ * @param theta
893
+ * @return
894
+ */
895
+ public TriangleMesh rotateAroundAxis(Vec3D axis, float theta) {
896
+ return transform(matrix.identity().rotateAroundAxis(axis, theta));
897
+ }
898
+
899
+ /**
900
+ *
901
+ * @param theta
902
+ * @return
903
+ */
904
+ public TriangleMesh rotateX(float theta) {
905
+ return transform(matrix.identity().rotateX(theta));
906
+ }
907
+
908
+ /**
909
+ *
910
+ * @param theta
911
+ * @return
912
+ */
913
+ public TriangleMesh rotateY(float theta) {
914
+ return transform(matrix.identity().rotateY(theta));
915
+ }
916
+
917
+ /**
918
+ *
919
+ * @param theta
920
+ * @return
921
+ */
922
+ public TriangleMesh rotateZ(float theta) {
923
+ return transform(matrix.identity().rotateZ(theta));
924
+ }
925
+
926
+ /**
927
+ * Saves the mesh as OBJ format by appending it to the given mesh
928
+ * {@link OBJWriter} instance.
929
+ *
930
+ * @param obj
931
+ */
932
+ public void saveAsOBJ(OBJWriter obj) {
933
+ saveAsOBJ(obj, true);
934
+ }
935
+
936
+ /**
937
+ *
938
+ * @param obj
939
+ * @param saveNormals
940
+ */
941
+ public void saveAsOBJ(OBJWriter obj, boolean saveNormals) {
942
+ int vOffset = obj.getCurrVertexOffset() + 1;
943
+ int nOffset = obj.getCurrNormalOffset() + 1;
944
+ logger.log(Level.INFO, "writing OBJMesh: {0}", this.toString());
945
+ obj.newObject(name);
946
+ // vertices
947
+ vertices.values().stream().forEach((v) -> {
948
+ obj.vertex(v);
949
+ });
950
+ // faces
951
+ if (saveNormals) {
952
+ // normals
953
+ vertices.values().stream().forEach((v) -> {
954
+ obj.normal(v.normal);
955
+ });
956
+ faces.stream().forEach((f) -> {
957
+ obj.faceWithNormals(f.b.id + vOffset, f.a.id + vOffset, f.c.id
958
+ + vOffset, f.b.id + nOffset, f.a.id + nOffset, f.c.id
959
+ + nOffset);
960
+ });
961
+ } else {
962
+ faces.stream().forEach((f) -> {
963
+ obj.face(f.b.id + vOffset, f.a.id + vOffset, f.c.id + vOffset);
964
+ });
965
+ }
966
+ }
967
+
968
+ /**
969
+ * Saves the mesh as OBJ format to the given {@link OutputStream}. Currently
970
+ * no texture coordinates are supported or written.
971
+ *
972
+ * @param stream
973
+ */
974
+ public void saveAsOBJ(OutputStream stream) {
975
+ OBJWriter obj = new OBJWriter();
976
+ obj.beginSave(stream);
977
+ saveAsOBJ(obj);
978
+ obj.endSave();
979
+ }
980
+
981
+ /**
982
+ * Saves the mesh as OBJ format to the given file path. Existing files will
983
+ * be overwritten.
984
+ *
985
+ * @param path
986
+ */
987
+ public void saveAsOBJ(String path) {
988
+ saveAsOBJ(path, true);
989
+ }
990
+
991
+ /**
992
+ *
993
+ * @param path
994
+ * @param saveNormals
995
+ */
996
+ public void saveAsOBJ(String path, boolean saveNormals) {
997
+ OBJWriter obj = new OBJWriter();
998
+ obj.beginSave(path);
999
+ saveAsOBJ(obj, saveNormals);
1000
+ obj.endSave();
1001
+ }
1002
+
1003
+ /**
1004
+ * Saves the mesh as binary STL format to the given {@link OutputStream}.
1005
+ *
1006
+ * @param stream
1007
+ * @see #saveAsSTL(OutputStream, boolean)
1008
+ */
1009
+ public final void saveAsSTL(OutputStream stream) {
1010
+ saveAsSTL(stream, false);
1011
+ }
1012
+
1013
+ /**
1014
+ * Saves the mesh as binary STL format to the given {@link OutputStream}.
1015
+ * The exported mesh can optionally have it's Y axis flipped by setting the
1016
+ * useFlippedY flag to true.
1017
+ *
1018
+ * @param stream
1019
+ * @param useFlippedY
1020
+ */
1021
+ public final void saveAsSTL(OutputStream stream, boolean useFlippedY) {
1022
+ STLWriter stl = new STLWriter();
1023
+ stl.beginSave(stream, numFaces);
1024
+ handleSaveAsSTL(stl, useFlippedY);
1025
+ }
1026
+
1027
+ /**
1028
+ * Saves the mesh as binary STL format to the given {@link OutputStream} and
1029
+ * using the supplied {@link STLWriter} instance. Use this method to export
1030
+ * data in a custom {@link STLColorModel}. The exported mesh can optionally
1031
+ * have it's Y axis flipped by setting the useFlippedY flag to true.
1032
+ *
1033
+ * @param stream
1034
+ * @param stl
1035
+ * @param useFlippedY
1036
+ */
1037
+ public final void saveAsSTL(OutputStream stream, STLWriter stl,
1038
+ boolean useFlippedY) {
1039
+ stl.beginSave(stream, numFaces);
1040
+ handleSaveAsSTL(stl, useFlippedY);
1041
+ }
1042
+
1043
+ /**
1044
+ * Saves the mesh as binary STL format to the given file path. Existing
1045
+ * files will be overwritten.
1046
+ *
1047
+ * @param fileName
1048
+ */
1049
+ public final void saveAsSTL(String fileName) {
1050
+ saveAsSTL(fileName, false);
1051
+ }
1052
+
1053
+ /**
1054
+ * Saves the mesh as binary STL format to the given file path. The exported
1055
+ * mesh can optionally have it's Y axis flipped by setting the useFlippedY
1056
+ * flag to true. Existing files will be overwritten.
1057
+ *
1058
+ * @param fileName
1059
+ * @param useFlippedY
1060
+ */
1061
+ public final void saveAsSTL(String fileName, boolean useFlippedY) {
1062
+ saveAsSTL(fileName, new STLWriter(), useFlippedY);
1063
+ }
1064
+
1065
+ /**
1066
+ *
1067
+ * @param fileName
1068
+ * @param stl
1069
+ * @param useFlippedY
1070
+ */
1071
+ public final void saveAsSTL(String fileName, STLWriter stl,
1072
+ boolean useFlippedY) {
1073
+ stl.beginSave(fileName, numFaces);
1074
+ handleSaveAsSTL(stl, useFlippedY);
1075
+ }
1076
+
1077
+ /**
1078
+ *
1079
+ * @param scale
1080
+ * @return
1081
+ */
1082
+ public TriangleMesh scale(float scale) {
1083
+ return transform(matrix.identity().scaleSelf(scale));
1084
+ }
1085
+
1086
+ /**
1087
+ *
1088
+ * @param x
1089
+ * @param y
1090
+ * @param z
1091
+ * @return
1092
+ */
1093
+ public TriangleMesh scale(float x, float y, float z) {
1094
+ return transform(matrix.identity().scaleSelf(x, y, z));
1095
+ }
1096
+
1097
+ /**
1098
+ *
1099
+ * @param scale
1100
+ * @return
1101
+ */
1102
+ public TriangleMesh scale(Vec3D scale) {
1103
+ return transform(matrix.identity().scaleSelf(scale));
1104
+ }
1105
+
1106
+ /**
1107
+ *
1108
+ * @param name
1109
+ * @return
1110
+ */
1111
+ @Override
1112
+ public TriangleMesh setName(String name) {
1113
+ this.name = name;
1114
+ return this;
1115
+ }
1116
+
1117
+ /**
1118
+ *
1119
+ * @return
1120
+ */
1121
+ @Override
1122
+ public String toString() {
1123
+ return "TriangleMesh: " + name + " vertices: " + getNumVertices()
1124
+ + " faces: " + getNumFaces();
1125
+ }
1126
+
1127
+ /**
1128
+ *
1129
+ * @return
1130
+ */
1131
+ public WETriangleMesh toWEMesh() {
1132
+ return new WETriangleMesh(name, vertices.size(), faces.size())
1133
+ .addMesh(this);
1134
+ }
1135
+
1136
+ /**
1137
+ * Applies the given matrix transform to all mesh vertices and updates all
1138
+ * face normals.
1139
+ *
1140
+ * @param mat
1141
+ * @return itself
1142
+ */
1143
+ public TriangleMesh transform(Matrix4x4 mat) {
1144
+ return transform(mat, true);
1145
+ }
1146
+
1147
+ /**
1148
+ * Applies the given matrix transform to all mesh vertices. If the
1149
+ * updateNormals flag is true, all face normals are updated automatically,
1150
+ * however vertex normals need a manual update.
1151
+ *
1152
+ * @param mat
1153
+ * @param updateNormals
1154
+ * @return itself
1155
+ */
1156
+ public TriangleMesh transform(Matrix4x4 mat, boolean updateNormals) {
1157
+ vertices.values().stream().forEach((v) -> {
1158
+ v.set(mat.applyTo(v));
1159
+ });
1160
+ if (updateNormals) {
1161
+ computeFaceNormals();
1162
+ }
1163
+ return this;
1164
+ }
1165
+
1166
+ /**
1167
+ *
1168
+ * @param x
1169
+ * @param y
1170
+ * @param z
1171
+ * @return
1172
+ */
1173
+ public TriangleMesh translate(float x, float y, float z) {
1174
+ return transform(matrix.identity().translateSelf(x, y, z));
1175
+ }
1176
+
1177
+ /**
1178
+ *
1179
+ * @param trans
1180
+ * @return
1181
+ */
1182
+ public TriangleMesh translate(Vec3D trans) {
1183
+ return transform(matrix.identity().translateSelf(trans));
1184
+ }
1185
+
1186
+ /**
1187
+ *
1188
+ * @param orig
1189
+ * @param newPos
1190
+ * @return
1191
+ */
1192
+ public TriangleMesh updateVertex(Vec3D orig, Vec3D newPos) {
1193
+ Vertex v = vertices.get(orig);
1194
+ if (v != null) {
1195
+ vertices.remove(v);
1196
+ v.set(newPos);
1197
+ vertices.put(v, v);
1198
+ }
1199
+ return this;
1200
+ }
1201
+ }