CCAutoPolygon.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2010-2012 cocos2d-x.org
  4. Copyright (c) 2011 Zynga Inc.
  5. Copyright (c) 2013-2017 Chukong Technologies Inc.
  6. http://www.cocos2d-x.org
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. ****************************************************************************/
  23. #ifndef COCOS_2D_CCAUTOPOLYGON_H__
  24. #define COCOS_2D_CCAUTOPOLYGON_H__
  25. #include <string>
  26. #include <vector>
  27. #include "platform/CCImage.h"
  28. #include "renderer/CCTrianglesCommand.h"
  29. NS_CC_BEGIN
  30. /**
  31. * @addtogroup _2d
  32. * @{
  33. */
  34. /**
  35. * PolygonInfo is an object holding the required data to display Sprites.
  36. * It can be a simple as a triangle, or as complex as a whole 3D mesh
  37. */
  38. class CC_DLL PolygonInfo
  39. {
  40. public:
  41. /// @name Creators
  42. /// @{
  43. /**
  44. * Creates an empty Polygon info
  45. * @memberof PolygonInfo
  46. * @return PolygonInfo object
  47. */
  48. PolygonInfo();
  49. /**
  50. * Create an polygoninfo from the data of another Polygoninfo
  51. * @param other another PolygonInfo to be copied
  52. * @return duplicate of the other PolygonInfo
  53. */
  54. PolygonInfo(const PolygonInfo& other);
  55. // end of creators group
  56. /// @}
  57. /**
  58. * Copy the member of the other PolygonInfo
  59. * @param other another PolygonInfo to be copied
  60. */
  61. PolygonInfo& operator= (const PolygonInfo &other);
  62. ~PolygonInfo();
  63. /**
  64. * set the data to be a pointer to a quad
  65. * the member verts will not be released when this PolygonInfo destructs
  66. * as the verts memory are managed by other objects
  67. * @param quad a pointer to the V3F_C4B_T2F_Quad object
  68. */
  69. void setQuad(V3F_C4B_T2F_Quad *quad);
  70. /**
  71. * set the data to be a pointer to a number of Quads
  72. * the member verts will not be released when this PolygonInfo destructs
  73. * as the verts memory are managed by other objects
  74. * @param quad a pointer to the V3F_C4B_T2F_Quad quads
  75. */
  76. void setQuads(V3F_C4B_T2F_Quad *quads, int numberOfQuads);
  77. /**
  78. * set the data to be a pointer to a triangles
  79. * the member verts will not be released when this PolygonInfo destructs
  80. * as the verts memory are managed by other objects
  81. * @param triangles a pointer to the TrianglesCommand::Triangles object
  82. */
  83. void setTriangles(const TrianglesCommand::Triangles& triangles);
  84. /**
  85. * get vertex count
  86. * @return number of vertices
  87. */
  88. unsigned int getVertCount() const;
  89. /**
  90. * get triangles count
  91. * @return number of triangles
  92. */
  93. unsigned int getTrianglesCount() const;
  94. /** @deprecated Use method getTrianglesCount() instead */
  95. CC_DEPRECATED_ATTRIBUTE unsigned int getTriaglesCount() const;
  96. /**
  97. * get sum of all triangle area size
  98. * @return sum of all triangle area size
  99. */
  100. float getArea() const;
  101. const Rect& getRect() const { return _rect; }
  102. void setRect(const Rect& rect) { _rect = rect; }
  103. const std::string& getFilename() const { return _filename; }
  104. void setFilename(const std::string& filename ) { _filename = filename; }
  105. // FIXME: this should be a property, not a public ivar
  106. TrianglesCommand::Triangles triangles;
  107. protected:
  108. bool _isVertsOwner;
  109. Rect _rect;
  110. std::string _filename;
  111. private:
  112. void releaseVertsAndIndices();
  113. };
  114. /**
  115. * AutoPolygon is a helper Object
  116. * AutoPolygon's purpose is to process an image into 2d polygon mesh in runtime
  117. * It has functions for each step in the process, from tracing all the points, to triangulation
  118. * the result can be then passed to Sprite::create() to create a Polygon Sprite
  119. */
  120. class CC_DLL AutoPolygon
  121. {
  122. public:
  123. /**
  124. * create an AutoPolygon and initialize it with an image file
  125. * the image must be a 32bit PNG for current version 3.7
  126. * @param filename a path to image file, e.g., "scene1/monster.png".
  127. * @return an AutoPolygon object;
  128. */
  129. AutoPolygon(const std::string &filename);
  130. /**
  131. * Destructor of AutoPolygon.
  132. */
  133. ~AutoPolygon();
  134. /**
  135. * trace all the points along the outline of the image,
  136. * @warning must create AutoPolygon with filename to use this function
  137. * @param rect a texture rect for specify an area of the image
  138. * @param threshold the value when alpha is greater than this value will be counted as opaque, default to 0.0
  139. * @return a vector of vec2 of all the points found in clockwise order
  140. * @code
  141. * auto ap = AutoPolygon("grossini.png");
  142. * auto rect = Rect(100, 100, 200, 200);
  143. * std::vector<Vec2> points = ap.trace(rect);//default threshold is 0.0
  144. * @endcode
  145. */
  146. std::vector<Vec2> trace(const cocos2d::Rect& rect, float threshold = 0.0f);
  147. /**
  148. * reduce the amount of points so its faster for GPU to process and draw
  149. * based on Ramer-Douglas-Peucker algorithm
  150. * @param points a vector of Vec2 points as input
  151. * @param rect a texture rect for specify an area of the image to avoid over reduction
  152. * @param epsilon the perpendicular distance where points smaller than this value will be discarded
  153. * @return a vector of Vec2 of the remaining points in clockwise order
  154. * @code
  155. * auto ap = AutoPolygon();
  156. * std::vector<Vec2> reduced = ap.reduce(inputPoints, rect);//default epsilon is 2
  157. * @endcode
  158. */
  159. std::vector<Vec2> reduce(const std::vector<Vec2>& points, const Rect& rect, float epsilon = 2.0f);
  160. /**
  161. * expand the points along their edge, useful after you reduce the points that cuts into the sprite
  162. * using ClipperLib
  163. * @param points a vector of Vec2 points as input
  164. * @param rect a texture rect for specify an area of the image, the expanded points will be clamped in this rect, ultimately resulting in a quad if the expansion is too great
  165. * @param epsilon the distance which the edges will expand
  166. * @return a vector of Vec2 as the result of the expansion
  167. * @code
  168. * auto ap = AutoPolygon();
  169. * std::vector<Vec2> expanded = ap.expand(inputPoints, rect, 2.0);
  170. * @endcode
  171. */
  172. std::vector<Vec2> expand(const std::vector<Vec2>& points, const Rect& rect, float epsilon);
  173. /**
  174. * Triangulate the input points into triangles for rendering
  175. * using poly2tri
  176. * @warning points must be closed loop, cannot have 2 points sharing the same position and cannot intersect itself
  177. * @param points a vector of vec2 points as input
  178. * @return a Triangles object with points and indices
  179. * @code
  180. * auto ap = AutoPolygon();
  181. * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
  182. * @endcode
  183. */
  184. TrianglesCommand::Triangles triangulate(const std::vector<Vec2>& points);
  185. /**
  186. * calculate the UV coordinates for each points based on a texture rect
  187. * @warning This method requires the AutoPolygon object to know the texture file dimension
  188. * @param rect a texture rect to specify where to map the UV
  189. * @param verts a pointer to the verts array, served both as input and output verts
  190. * @param count the count for the verts array
  191. * @code
  192. * auto ap = AutoPolygon("grossini.png");
  193. * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
  194. * ap.calculateUV(rect, myPolygons.verts, 20);
  195. * @endcode
  196. */
  197. void calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count);
  198. /**
  199. * a helper function, packing trace, reduce, expand, triangulate and calculate uv in one function
  200. * @param rect texture rect, use Rect::ZERO for the size of the texture, default is Rect::ZERO
  201. * @param epsilon the value used to reduce and expand, default to 2.0
  202. * @param threshold the value where bigger than the threshold will be counted as opaque, used in trace
  203. * @return a PolygonInfo, to use with sprite
  204. * @code
  205. * auto ap = AutoPolygon("grossini.png");
  206. * PolygonInfo myInfo = ap.generateTriangles();//use all default values
  207. * auto sp1 = Sprite::create(myInfo);
  208. * polygonInfo myInfo2 = ap.generateTriangles(Rect::ZERO, 5.0, 0.1);//ap can be reused to generate another set of PolygonInfo with different settings
  209. * auto sp2 = Sprite::create(myInfo2);
  210. * @endcode
  211. */
  212. PolygonInfo generateTriangles(const Rect& rect = Rect::ZERO, float epsilon = 2.0f, float threshold = 0.05f);
  213. /**
  214. * a helper function, packing autoPolygon creation, trace, reduce, expand, triangulate and calculate uv in one function
  215. * @warning if you want to repetitively generate polygons, consider create an AutoPolygon object, and use generateTriangles function, as it only reads the file once
  216. * @param filename A path to image file, e.g., "scene1/monster.png".
  217. * @param rect texture rect, use Rect::ZERO for the size of the texture, default is Rect::ZERO
  218. * @param epsilon the value used to reduce and expand, default to 2.0
  219. * @param threshold the value where bigger than the threshold will be counted as opaque, used in trace
  220. * @return a PolygonInfo, to use with sprite
  221. * @code
  222. * auto sp = Sprite::create(AutoPolygon::generatePolygon("grossini.png"));
  223. * @endcode
  224. */
  225. static PolygonInfo generatePolygon(const std::string& filename, const Rect& rect = Rect::ZERO, float epsilon = 2.0f, float threshold = 0.05f);
  226. protected:
  227. Vec2 findFirstNoneTransparentPixel(const Rect& rect, float threshold);
  228. std::vector<cocos2d::Vec2> marchSquare(const Rect& rect, const Vec2& first, float threshold);
  229. unsigned int getSquareValue(unsigned int x, unsigned int y, const Rect& rect, float threshold);
  230. unsigned char getAlphaByIndex(unsigned int i);
  231. unsigned char getAlphaByPos(const Vec2& pos);
  232. int getIndexFromPos(unsigned int x, unsigned int y) { return y*_width+x; }
  233. cocos2d::Vec2 getPosFromIndex(unsigned int i) { return cocos2d::Vec2(static_cast<float>(i%_width), static_cast<float>(i/_width)); }
  234. std::vector<cocos2d::Vec2> rdp(const std::vector<cocos2d::Vec2>& v, float optimization);
  235. float perpendicularDistance(const cocos2d::Vec2& i, const cocos2d::Vec2& start, const cocos2d::Vec2& end);
  236. //real rect is the size that is in scale with the texture file
  237. Rect getRealRect(const Rect& rect);
  238. Image* _image;
  239. unsigned char * _data;
  240. std::string _filename;
  241. unsigned int _width;
  242. unsigned int _height;
  243. float _scaleFactor;
  244. unsigned int _threshold;
  245. };
  246. NS_CC_END
  247. #endif // #ifndef COCOS_2D_CCAUTOPOLYGON_H__