toxiclibs 0.4.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (404) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/.travis.yml +23 -0
  6. data/CHANGELOG.md +7 -0
  7. data/COPYING.md +14 -0
  8. data/Gemfile +10 -0
  9. data/LICENSE +675 -0
  10. data/README.md +9 -7
  11. data/Rakefile +25 -81
  12. data/examples/README.md +5 -0
  13. data/examples/attract_repel/attract_repel.rb +30 -0
  14. data/examples/attract_repel/attractor.rb +23 -0
  15. data/examples/attract_repel/particle.rb +27 -0
  16. data/examples/data/ReplicaBold.ttf +0 -0
  17. data/examples/data/ti_yong.png +0 -0
  18. data/examples/force_directed/cluster.rb +76 -0
  19. data/examples/force_directed/force_directed_graph.rb +92 -0
  20. data/examples/force_directed/node.rb +26 -0
  21. data/examples/gray_scott_image.rb +74 -0
  22. data/examples/gray_scott_tone_map.rb +77 -0
  23. data/examples/implicit.rb +139 -0
  24. data/examples/inflate_mesh.rb +89 -0
  25. data/examples/model_align.rb +43 -0
  26. data/examples/physics_type.rb +77 -0
  27. data/examples/povmesh/data/mask.jpg +0 -0
  28. data/examples/povmesh/ftest.rb +59 -0
  29. data/examples/povmesh/mesh_align.rb +47 -0
  30. data/examples/povmesh/tentacle.rb +71 -0
  31. data/examples/simple_cluster/cluster.rb +47 -0
  32. data/examples/simple_cluster/node.rb +27 -0
  33. data/examples/simple_cluster/simple_cluster.rb +60 -0
  34. data/examples/soft_body/blanket.rb +45 -0
  35. data/examples/soft_body/connection.rb +16 -0
  36. data/examples/soft_body/particle.rb +22 -0
  37. data/examples/soft_body/soft_body_square_adapted.rb +55 -0
  38. data/examples/spherical_harmonics_mesh.rb +50 -0
  39. data/examples/test_rect.rb +32 -0
  40. data/lib/toxiclibs.jar +0 -0
  41. data/lib/toxiclibs.rb +72 -22
  42. data/lib/toxiclibs/version.rb +1 -1
  43. data/pom.rb +63 -0
  44. data/pom.xml +124 -0
  45. data/src/com/toxi/net/ClientListener.java +41 -0
  46. data/src/com/toxi/net/ServerListener.java +70 -0
  47. data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
  48. data/src/com/toxi/net/ServerState.java +18 -0
  49. data/src/com/toxi/net/UDPConnection.java +66 -0
  50. data/src/com/toxi/net/UDPSyncClient.java +81 -0
  51. data/src/com/toxi/net/UDPSyncServer.java +450 -0
  52. data/src/com/toxi/nio/UDPClient.java +121 -0
  53. data/src/com/toxi/nio/UDPClientState.java +32 -0
  54. data/src/com/toxi/nio/UDPServer.java +129 -0
  55. data/src/toxi/audio/AudioBuffer.java +229 -0
  56. data/src/toxi/audio/AudioSource.java +288 -0
  57. data/src/toxi/audio/DecompressInputStream.java +159 -0
  58. data/src/toxi/audio/IIRFilter.java +197 -0
  59. data/src/toxi/audio/JOALUtil.java +388 -0
  60. data/src/toxi/audio/MultiTimbralManager.java +162 -0
  61. data/src/toxi/audio/SoundListener.java +154 -0
  62. data/src/toxi/audio/SynthUtil.java +109 -0
  63. data/src/toxi/color/AccessCriteria.java +114 -0
  64. data/src/toxi/color/AlphaAccessor.java +67 -0
  65. data/src/toxi/color/CMYKAccessor.java +122 -0
  66. data/src/toxi/color/CMYKDistanceProxy.java +40 -0
  67. data/src/toxi/color/ColorGradient.java +260 -0
  68. data/src/toxi/color/ColorList.java +699 -0
  69. data/src/toxi/color/ColorRange.java +671 -0
  70. data/src/toxi/color/ColorTheme.java +163 -0
  71. data/src/toxi/color/DistanceProxy.java +44 -0
  72. data/src/toxi/color/HSVAccessor.java +113 -0
  73. data/src/toxi/color/HSVDistanceProxy.java +40 -0
  74. data/src/toxi/color/HistEntry.java +85 -0
  75. data/src/toxi/color/Histogram.java +185 -0
  76. data/src/toxi/color/Hue.java +249 -0
  77. data/src/toxi/color/LuminanceAccessor.java +78 -0
  78. data/src/toxi/color/NamedColor.java +935 -0
  79. data/src/toxi/color/ProximityComparator.java +70 -0
  80. data/src/toxi/color/RGBAccessor.java +113 -0
  81. data/src/toxi/color/RGBDistanceProxy.java +41 -0
  82. data/src/toxi/color/ReadonlyTColor.java +296 -0
  83. data/src/toxi/color/TColor.java +1677 -0
  84. data/src/toxi/color/TColorAdapter.java +68 -0
  85. data/src/toxi/color/ToneMap.java +218 -0
  86. data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
  87. data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
  88. data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
  89. data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
  90. data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
  91. data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
  92. data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
  93. data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
  94. data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
  95. data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
  96. data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
  97. data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
  98. data/src/toxi/data/csv/CSVAdapter.java +74 -0
  99. data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
  100. data/src/toxi/data/csv/CSVListener.java +61 -0
  101. data/src/toxi/data/csv/CSVParser.java +202 -0
  102. data/src/toxi/data/feeds/AtomAuthor.java +49 -0
  103. data/src/toxi/data/feeds/AtomContent.java +50 -0
  104. data/src/toxi/data/feeds/AtomEntry.java +111 -0
  105. data/src/toxi/data/feeds/AtomFeed.java +129 -0
  106. data/src/toxi/data/feeds/AtomLink.java +62 -0
  107. data/src/toxi/data/feeds/RSSChannel.java +88 -0
  108. data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
  109. data/src/toxi/data/feeds/RSSFeed.java +99 -0
  110. data/src/toxi/data/feeds/RSSItem.java +104 -0
  111. data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
  112. data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
  113. data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
  114. data/src/toxi/geom/AABB.java +658 -0
  115. data/src/toxi/geom/Axis3D.java +116 -0
  116. data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
  117. data/src/toxi/geom/BernsteinPolynomial.java +94 -0
  118. data/src/toxi/geom/BezierCurve2D.java +159 -0
  119. data/src/toxi/geom/BezierCurve3D.java +148 -0
  120. data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
  121. data/src/toxi/geom/BoxIntersector.java +52 -0
  122. data/src/toxi/geom/Circle.java +230 -0
  123. data/src/toxi/geom/CircleIntersector.java +85 -0
  124. data/src/toxi/geom/Cone.java +150 -0
  125. data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
  126. data/src/toxi/geom/CoordinateExtractor.java +16 -0
  127. data/src/toxi/geom/Ellipse.java +250 -0
  128. data/src/toxi/geom/GMatrix.java +2599 -0
  129. data/src/toxi/geom/GVector.java +833 -0
  130. data/src/toxi/geom/GlobalGridTesselator.java +54 -0
  131. data/src/toxi/geom/GridTesselator.java +108 -0
  132. data/src/toxi/geom/Intersector2D.java +49 -0
  133. data/src/toxi/geom/Intersector3D.java +51 -0
  134. data/src/toxi/geom/IsectData2D.java +103 -0
  135. data/src/toxi/geom/IsectData3D.java +103 -0
  136. data/src/toxi/geom/Line2D.java +534 -0
  137. data/src/toxi/geom/Line3D.java +471 -0
  138. data/src/toxi/geom/LineStrip2D.java +430 -0
  139. data/src/toxi/geom/LineStrip3D.java +230 -0
  140. data/src/toxi/geom/LocalGridTesselator.java +57 -0
  141. data/src/toxi/geom/Matrix3d.java +3048 -0
  142. data/src/toxi/geom/Matrix4f.java +3446 -0
  143. data/src/toxi/geom/Matrix4x4.java +1076 -0
  144. data/src/toxi/geom/MatrixSizeException.java +58 -0
  145. data/src/toxi/geom/OctreeVisitor.java +44 -0
  146. data/src/toxi/geom/Origin3D.java +148 -0
  147. data/src/toxi/geom/Plane.java +293 -0
  148. data/src/toxi/geom/PlaneIntersector.java +57 -0
  149. data/src/toxi/geom/PointCloud3D.java +253 -0
  150. data/src/toxi/geom/PointOctree.java +502 -0
  151. data/src/toxi/geom/PointQuadtree.java +375 -0
  152. data/src/toxi/geom/Polygon2D.java +1038 -0
  153. data/src/toxi/geom/PolygonClipper2D.java +45 -0
  154. data/src/toxi/geom/PolygonTesselator.java +20 -0
  155. data/src/toxi/geom/QuadtreeVisitor.java +44 -0
  156. data/src/toxi/geom/Quaternion.java +641 -0
  157. data/src/toxi/geom/Ray2D.java +146 -0
  158. data/src/toxi/geom/Ray3D.java +150 -0
  159. data/src/toxi/geom/Ray3DIntersector.java +75 -0
  160. data/src/toxi/geom/ReadonlyVec2D.java +575 -0
  161. data/src/toxi/geom/ReadonlyVec3D.java +628 -0
  162. data/src/toxi/geom/ReadonlyVec4D.java +431 -0
  163. data/src/toxi/geom/Rect.java +720 -0
  164. data/src/toxi/geom/Reflector3D.java +58 -0
  165. data/src/toxi/geom/Shape2D.java +94 -0
  166. data/src/toxi/geom/Shape3D.java +42 -0
  167. data/src/toxi/geom/SingularMatrixException.java +57 -0
  168. data/src/toxi/geom/SpatialBins.java +182 -0
  169. data/src/toxi/geom/SpatialIndex.java +61 -0
  170. data/src/toxi/geom/Sphere.java +224 -0
  171. data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
  172. data/src/toxi/geom/Spline2D.java +349 -0
  173. data/src/toxi/geom/Spline3D.java +351 -0
  174. data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
  175. data/src/toxi/geom/Triangle2D.java +422 -0
  176. data/src/toxi/geom/Triangle3D.java +456 -0
  177. data/src/toxi/geom/TriangleIntersector.java +105 -0
  178. data/src/toxi/geom/Vec2D.java +1328 -0
  179. data/src/toxi/geom/Vec3D.java +1832 -0
  180. data/src/toxi/geom/Vec4D.java +985 -0
  181. data/src/toxi/geom/VecMathUtil.java +100 -0
  182. data/src/toxi/geom/XAxisCylinder.java +64 -0
  183. data/src/toxi/geom/YAxisCylinder.java +65 -0
  184. data/src/toxi/geom/ZAxisCylinder.java +64 -0
  185. data/src/toxi/geom/mesh/BezierPatch.java +200 -0
  186. data/src/toxi/geom/mesh/BoxSelector.java +62 -0
  187. data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
  188. data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
  189. data/src/toxi/geom/mesh/Face.java +176 -0
  190. data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
  191. data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
  192. data/src/toxi/geom/mesh/Mesh3D.java +224 -0
  193. data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
  194. data/src/toxi/geom/mesh/OBJWriter.java +194 -0
  195. data/src/toxi/geom/mesh/PLYWriter.java +167 -0
  196. data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
  197. data/src/toxi/geom/mesh/STLColorModel.java +54 -0
  198. data/src/toxi/geom/mesh/STLReader.java +185 -0
  199. data/src/toxi/geom/mesh/STLWriter.java +323 -0
  200. data/src/toxi/geom/mesh/SphereFunction.java +156 -0
  201. data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
  202. data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
  203. data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
  204. data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
  205. data/src/toxi/geom/mesh/Terrain.java +451 -0
  206. data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
  207. data/src/toxi/geom/mesh/Vertex.java +78 -0
  208. data/src/toxi/geom/mesh/VertexSelector.java +193 -0
  209. data/src/toxi/geom/mesh/WEFace.java +100 -0
  210. data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
  211. data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
  212. data/src/toxi/geom/mesh/WEVertex.java +134 -0
  213. data/src/toxi/geom/mesh/WingedEdge.java +115 -0
  214. data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
  215. data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
  216. data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
  217. data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
  218. data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
  219. data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
  220. data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
  221. data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
  222. data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
  223. data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
  224. data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
  225. data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
  226. data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
  227. data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
  228. data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
  229. data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
  230. data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
  231. data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
  232. data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
  233. data/src/toxi/geom/nurbs/ControlNet.java +148 -0
  234. data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
  235. data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
  236. data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
  237. data/src/toxi/geom/nurbs/KnotVector.java +333 -0
  238. data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
  239. data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
  240. data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
  241. data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
  242. data/src/toxi/image/util/Filter8bit.java +331 -0
  243. data/src/toxi/image/util/TiledFrameExporter.java +162 -0
  244. data/src/toxi/math/BezierInterpolation.java +102 -0
  245. data/src/toxi/math/CircularInterpolation.java +88 -0
  246. data/src/toxi/math/CosineInterpolation.java +51 -0
  247. data/src/toxi/math/DecimatedInterpolation.java +77 -0
  248. data/src/toxi/math/ExponentialInterpolation.java +68 -0
  249. data/src/toxi/math/InterpolateStrategy.java +60 -0
  250. data/src/toxi/math/Interpolation2D.java +93 -0
  251. data/src/toxi/math/LinearInterpolation.java +46 -0
  252. data/src/toxi/math/MathUtils.java +990 -0
  253. data/src/toxi/math/NonLinearScaleMap.java +101 -0
  254. data/src/toxi/math/ScaleMap.java +183 -0
  255. data/src/toxi/math/SigmoidInterpolation.java +78 -0
  256. data/src/toxi/math/SinCosLUT.java +141 -0
  257. data/src/toxi/math/ThresholdInterpolation.java +58 -0
  258. data/src/toxi/math/ZoomLensInterpolation.java +126 -0
  259. data/src/toxi/math/conversion/UnitTranslator.java +161 -0
  260. data/src/toxi/math/noise/PerlinNoise.java +281 -0
  261. data/src/toxi/math/noise/SimplexNoise.java +542 -0
  262. data/src/toxi/math/waves/AMFMSineWave.java +143 -0
  263. data/src/toxi/math/waves/AbstractWave.java +248 -0
  264. data/src/toxi/math/waves/ConstantWave.java +48 -0
  265. data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
  266. data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
  267. data/src/toxi/math/waves/FMSineWave.java +142 -0
  268. data/src/toxi/math/waves/FMSquareWave.java +143 -0
  269. data/src/toxi/math/waves/FMTriangleWave.java +126 -0
  270. data/src/toxi/math/waves/SineWave.java +81 -0
  271. data/src/toxi/math/waves/Wave2D.java +68 -0
  272. data/src/toxi/math/waves/WaveState.java +69 -0
  273. data/src/toxi/music/scale/AbstractScale.java +117 -0
  274. data/src/toxi/music/scale/GenericScale.java +66 -0
  275. data/src/toxi/music/scale/MajorScale.java +41 -0
  276. data/src/toxi/newmesh/AttributedEdge.java +106 -0
  277. data/src/toxi/newmesh/AttributedFace.java +63 -0
  278. data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
  279. data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
  280. data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
  281. data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
  282. data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
  283. data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
  284. data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
  285. data/src/toxi/newmesh/SpatialIndex.java +78 -0
  286. data/src/toxi/physics2d/ParticlePath2D.java +100 -0
  287. data/src/toxi/physics2d/ParticleString2D.java +184 -0
  288. data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
  289. data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
  290. data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
  291. data/src/toxi/physics2d/VerletParticle2D.java +457 -0
  292. data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
  293. data/src/toxi/physics2d/VerletSpring2D.java +181 -0
  294. data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
  295. data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
  296. data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
  297. data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
  298. data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
  299. data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
  300. data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
  301. data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
  302. data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
  303. data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
  304. data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
  305. data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
  306. data/src/toxi/physics3d/ParticlePath3D.java +100 -0
  307. data/src/toxi/physics3d/ParticleString3D.java +184 -0
  308. data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
  309. data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
  310. data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
  311. data/src/toxi/physics3d/VerletParticle3D.java +385 -0
  312. data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
  313. data/src/toxi/physics3d/VerletSpring3D.java +180 -0
  314. data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
  315. data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
  316. data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
  317. data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
  318. data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
  319. data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
  320. data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
  321. data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
  322. data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
  323. data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
  324. data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
  325. data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
  326. data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
  327. data/src/toxi/processing/ArrowModifier.java +116 -0
  328. data/src/toxi/processing/DashedLineModifier.java +48 -0
  329. data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
  330. data/src/toxi/processing/Line2DRenderModifier.java +18 -0
  331. data/src/toxi/processing/MeshToVBO.java +127 -0
  332. data/src/toxi/processing/NormalMapper.java +18 -0
  333. data/src/toxi/processing/POVInterface.java +121 -0
  334. data/src/toxi/processing/POVMesh.java +219 -0
  335. data/src/toxi/processing/POVWriter.java +460 -0
  336. data/src/toxi/processing/RCOpaque.java +77 -0
  337. data/src/toxi/processing/RCTransp.java +78 -0
  338. data/src/toxi/processing/TextureBuilder.java +232 -0
  339. data/src/toxi/processing/Textures.java +110 -0
  340. data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
  341. data/src/toxi/processing/Tracing.java +25 -0
  342. data/src/toxi/processing/XYZNormalMapper.java +30 -0
  343. data/src/toxi/sim/automata/CAMatrix.java +297 -0
  344. data/src/toxi/sim/automata/CARule.java +76 -0
  345. data/src/toxi/sim/automata/CARule2D.java +354 -0
  346. data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
  347. data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
  348. data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
  349. data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
  350. data/src/toxi/sim/dla/DLA.java +497 -0
  351. data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
  352. data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
  353. data/src/toxi/sim/dla/DLAEventListener.java +57 -0
  354. data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
  355. data/src/toxi/sim/dla/DLAParticle.java +102 -0
  356. data/src/toxi/sim/dla/DLASegment.java +88 -0
  357. data/src/toxi/sim/dla/PipelineOrder.java +50 -0
  358. data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
  359. data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
  360. data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
  361. data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
  362. data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
  363. data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
  364. data/src/toxi/sim/grayscott/GrayScott.java +469 -0
  365. data/src/toxi/util/DateUtils.java +141 -0
  366. data/src/toxi/util/FileSequenceDescriptor.java +181 -0
  367. data/src/toxi/util/FileUtils.java +467 -0
  368. data/src/toxi/util/datatypes/ArraySet.java +128 -0
  369. data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
  370. data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
  371. data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
  372. data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
  373. data/src/toxi/util/datatypes/DoubleRange.java +251 -0
  374. data/src/toxi/util/datatypes/FloatRange.java +251 -0
  375. data/src/toxi/util/datatypes/GenericSet.java +215 -0
  376. data/src/toxi/util/datatypes/IntegerRange.java +247 -0
  377. data/src/toxi/util/datatypes/IntegerSet.java +149 -0
  378. data/src/toxi/util/datatypes/ItemIndex.java +72 -0
  379. data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
  380. data/src/toxi/util/datatypes/TypedProperties.java +291 -0
  381. data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
  382. data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
  383. data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
  384. data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
  385. data/src/toxi/util/events/EventDispatcher.java +86 -0
  386. data/src/toxi/volume/AdditiveBrush.java +19 -0
  387. data/src/toxi/volume/ArrayIsoSurface.java +297 -0
  388. data/src/toxi/volume/BoxBrush.java +100 -0
  389. data/src/toxi/volume/BrushMode.java +16 -0
  390. data/src/toxi/volume/HashIsoSurface.java +354 -0
  391. data/src/toxi/volume/IsoSurface.java +59 -0
  392. data/src/toxi/volume/MarchingCubesIndex.java +312 -0
  393. data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
  394. data/src/toxi/volume/MeshVoxelizer.java +216 -0
  395. data/src/toxi/volume/MultiplyBrush.java +20 -0
  396. data/src/toxi/volume/PeakBrush.java +21 -0
  397. data/src/toxi/volume/ReplaceBrush.java +19 -0
  398. data/src/toxi/volume/RoundBrush.java +113 -0
  399. data/src/toxi/volume/VolumetricBrush.java +160 -0
  400. data/src/toxi/volume/VolumetricHashMap.java +179 -0
  401. data/src/toxi/volume/VolumetricSpace.java +195 -0
  402. data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
  403. data/toxiclibs.gemspec +28 -0
  404. metadata +442 -31
@@ -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
+ }