PolygonSprite的特性就是可以动态改变绘制Sprite的顶点数量,顶点数量越多意味着Sprite的三角化程度越细,绘制的空白像素也将越少,可以提高绘制效率,但顶点数量的增加会增加内存消耗。
当一张纹理的像素宽高比较大,空白区域或者接近透明的区域比较多,那么可以使用PolygonSprite。

一、使用示例

cocos2dx_精灵(Sprite)

二、PolygonInfo:网格数据

  1. // 保存了绘制一个图形需要的所有数据
  2. // 1、顶点数据:3D网格,最简单的情况就是一个三角形
  3. // 2、着色器
  4. // 3、混合
  5. // 4、纹理
  6. // 5、材质
  7. // 不过在这里,主要是处理顶点数据的变化,其他数据不做改变。
  8. // 比如三角形数量增加,顶点数量增加(内存消耗增加),绘制的图形不变,结果是绘制的空白像素将减少,提升绘制效率。
  9. // 这是以空间换时间。
  10. // 当图片文件像素宽高较大,空白较多,那么使用PolygonSprite的效果将比较明显。
  11. class CC_DLL PolygonInfo
  12. {
  13. public:
  14. PolygonInfo(); // 空数据
  15. PolygonInfo(const PolygonInfo& other); // 复制网格数据
  16. PolygonInfo& operator= (const PolygonInfo &other); // 复制网格数据
  17. ~PolygonInfo();
  18. // 设置为一个矩形的顶点数据,注意这些顶点数据是从外部传入,因为在这为weak reference
  19. void setQuad(V3F_C4B_T2F_Quad *quad);
  20. // 设置为numberOfQuads个矩形的顶点数据,其他同上。
  21. void setQuads(V3F_C4B_T2F_Quad *quads, int numberOfQuads);
  22. // 设置为一个三角形的顶点数据,其他同上。
  23. void setTriangles(const TrianglesCommand::Triangles& triangles);
  24. unsigned int getVertCount() const; // 顶点数量
  25. unsigned int getTrianglesCount() const; // 三角形数量
  26. float getArea() const; // 获得总面积(三角形总面积)
  27. const Rect& getRect() const; // 如果是一个矩形,比如用来计算使用多边形之后,像素面积变化了多少
  28. void setRect(const Rect& rect); // 又外部来设置
  29. const std::string& getFilename() const; //
  30. void setFilename(const std::string& filename ); //
  31. protected:
  32. bool _isVertsOwner; // 顶点数据是不是在这里管理
  33. Rect _rect; // 一般是设置为如果是普通Sprite时的矩形框
  34. std::string _filename;
  35. TrianglesCommand::Triangles triangles; // 保存的顶点数据
  36. private:
  37. void releaseVertsAndIndices(); // 如果是_isVertsOwner,则要我们自己及时清楚顶点数据及其索引。
  38. };

三、AutoPolygon:生成网格数据

  1. // 是一个工具类,用于动态生成一个图像的2D(三角形)网格数据。
  2. // 输出的就是上面的PolygonInfo。
  3. class CC_DLL AutoPolygon
  4. {
  5. public:
  6. // filename: 必须是一个32bit PNG格式。
  7. AutoPolygon(const std::string &filename);
  8. // 获得image中的rect区域中alpha > threshold的像素
  9. // 沿着rect的outline顺时针遍历寻找。
  10. std::vector<Vec2> trace(const cocos2d::Rect& rect, float threshold = 0.0f);
  11. /**
  12. * reduce the amount of points so its faster for GPU to process and draw
  13. * based on Ramer-Douglas-Peucker algorithm
  14. * @param points a vector of Vec2 points as input
  15. * @param rect a texture rect for specify an area of the image to avoid over reduction
  16. * @param epsilon the perpendicular distance where points smaller than this value will be discarded
  17. * @return a vector of Vec2 of the remaining points in clockwise order
  18. * @code
  19. * auto ap = AutoPolygon();
  20. * std::vector<Vec2> reduced = ap.reduce(inputPoints, rect);//default epsilon is 2
  21. * @endcode
  22. */
  23. //
  24. std::vector<Vec2> reduce(const std::vector<Vec2>& points, const Rect& rect, float epsilon = 2.0f);
  25. /**
  26. * expand the points along their edge, useful after you reduce the points that cuts into
  27. the sprite
  28. * using ClipperLib
  29. * @param points a vector of Vec2 points as input
  30. * @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
  31. * @param epsilon the distance which the edges will expand
  32. * @return a vector of Vec2 as the result of the expansion
  33. * @code
  34. * auto ap = AutoPolygon();
  35. * std::vector<Vec2> expanded = ap.expand(inputPoints, rect, 2.0);
  36. * @endcode
  37. */
  38. std::vector<Vec2> expand(const std::vector<Vec2>& points, const Rect& rect, float epsilon);
  39. /**
  40. * Triangulate the input points into triangles for rendering
  41. * using poly2tri
  42. * @warning points must be closed loop, cannot have 2 points sharing the same position and cannot intersect itself
  43. * @param points a vector of vec2 points as input
  44. * @return a Triangles object with points and indices
  45. * @code
  46. * auto ap = AutoPolygon();
  47. * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
  48. * @endcode
  49. */
  50. TrianglesCommand::Triangles triangulate(const std::vector<Vec2>& points);
  51. /**
  52. * calculate the UV coordinates for each points based on a texture rect
  53. * @warning This method requires the AutoPolygon object to know the texture file dimension
  54. * @param rect a texture rect to specify where to map the UV
  55. * @param verts a pointer to the verts array, served both as input and output verts
  56. * @param count the count for the verts array
  57. * @code
  58. * auto ap = AutoPolygon("grossini.png");
  59. * TrianglesCommand::Triangles myPolygons = ap.triangulate(myPoints);
  60. * ap.calculateUV(rect, myPolygons.verts, 20);
  61. * @endcode
  62. */
  63. void calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count);
  64. /**
  65. * packing trace, reduce, expand, triangulate and calculate uv in one function
  66. * @param rect texture rect, use Rect::ZERO for the size of the texture, default is Rect::ZERO
  67. * @param epsilon the value used to reduce and expand, default to 2.0
  68. * @param threshold the value where bigger than the threshold will be counted as opaque, used in trace
  69. * @return a PolygonInfo, to use with sprite
  70. * @code
  71. * auto ap = AutoPolygon("grossini.png");
  72. * PolygonInfo myInfo = ap.generateTriangles();//use all default values
  73. * auto sp1 = Sprite::create(myInfo);
  74. * polygonInfo myInfo2 = ap.generateTriangles(Rect::ZERO, 5.0, 0.1);//ap can be reused to generate another set of PolygonInfo with different settings
  75. * auto sp2 = Sprite::create(myInfo2);
  76. * @endcode
  77. */
  78. PolygonInfo generateTriangles(const Rect& rect = Rect::ZERO, float epsilon = 2.0f, float threshold = 0.05f);
  79. // 等价于下面:
  80. // AutoPolygon ap(filename);
  81. // ap.generateTriangles(rect, epsilon, threshold);
  82. // 一般用于只需创建一次的情况,因为每次都要通过filename创建image,所以一般采用以下方法:
  83. // AutoPolygon ap(filename); // 创建一次
  84. // ap.generateTriangles(rect, epsilon, threshold); // 多次生成网格数据
  85. // ap.generateTriangles(rect, epsilon, threshold); // 多次生成网格数据
  86. static PolygonInfo generatePolygon(const std::string& filename,
  87. const Rect& rect = Rect::ZERO,
  88. float epsilon = 2.0f,
  89. float threshold = 0.05f);
  90. }