CCAutoPolygon.h 11 KB

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