#include "GraphicsObj.h" #include #include static const float EPSILON = 0.0000000001f; float GraphicsObj::Area( const std::vector &polygon_nodes ) { uint n = polygon_nodes.size(); float A = 0.0f; for ( uint p = n - 1, q = 0; q= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); }; bool GraphicsObj::Snip( const std::vector &contour, int u, int v, int w, int n, int *V ) { float Ax, Ay, Bx, By, Cx, Cy, Px, Py; Ax = contour[V[u]].x; Ay = contour[V[u]].y; Bx = contour[V[v]].x; By = contour[V[v]].y; Cx = contour[V[w]].x; Cy = contour[V[w]].y; if ( EPSILON > (((Bx - Ax)*(Cy - Ay)) - ((By - Ay)*(Cx - Ax))) ) return false; int p; for ( p = 0; p &polygon_verts, std::vector &triangle_verts ) { // allocate and initialize list of Vertices in polygon int n = polygon_verts.size(); if ( n < 3 ) return false; int *V = new int[n]; // we want a counter-clockwise polygon in V if ( 0.0f < Area(polygon_verts) ) for ( int v = 0; v < n; v++ ) V[v] = v; else for ( int v = 0; v < n; v++ ) V[v] = (n-1) - v; int nv = n; // remove nv-2 Vertices, creating 1 triangle every time int count = 2 * nv; // error detection for ( int m = 0, v = nv - 1; nv>2; ) { // If we loop, it is probably a non-simple polygon if ( 0 >= (count--) ) return false; // Triangulate: ERROR - probable bad polygon! // three consecutive vertices in current polygon, int u = v; if ( nv <= u ) u = 0; // previous v = u + 1; if ( nv <= v ) v = 0; // new v int w = v + 1; if ( nv <= w ) w = 0; // next if ( Snip(polygon_verts, u, v, w, nv, V) ) { int a, b, c, s, t; // true names of the vertices a = V[u]; b = V[v]; c = V[w]; // output Triangle triangle_verts.push_back( polygon_verts[a] ); triangle_verts.push_back( polygon_verts[b] ); triangle_verts.push_back( polygon_verts[c] ); m++; // remove v from remaining polygon for ( s = v, t = v + 1; taddChild( m_cocosSprite ); } if ( m_drawNode == NULL ) { m_drawNode = DrawNode::create(); m_cocosSprite->addChild( m_drawNode ); } } void GraphicsObj::lineStyle( int thickness, uint lineColour ) { m_lineThickness = thickness; m_line_color.r = ((float)((lineColour & 0xFF000000) >> 24)) / 255.0f; m_line_color.g = ((float)((lineColour & 0x00FF0000) >> 16)) / 255.0f; m_line_color.b = ((float)((lineColour & 0x0000FF00) >> 8)) / 255.0f; m_line_color.a = ((float)((lineColour & 0x000000FF) >> 0)) / 255.0f; } void GraphicsObj::beginFill( uint fillColour ) { m_bFilling = true; m_fill_color.r = ((float)((fillColour & 0xFF000000) >> 24)) / 255.0f; m_fill_color.g = ((float)((fillColour & 0x00FF0000) >> 16)) / 255.0f; m_fill_color.b = ((float)((fillColour & 0x0000FF00) >> 8)) / 255.0f; m_fill_color.a = ((float)((fillColour & 0x000000FF) >> 0)) / 255.0f; } void GraphicsObj::endFill() { if ( m_bFilling ) { m_bFilling = false; if ( m_fill_verts.size() <= 4 ) m_drawNode->drawSolidPoly( &m_fill_verts[0], m_fill_verts.size(), m_fill_color ); else { // Triangulate polygon verts bool ret = Process( m_fill_verts, m_triangulated_verts ); uint count = m_triangulated_verts.size() / 3; for ( uint i = 0; i < count; i++ ) { const Vec2 &p1 = m_triangulated_verts[i*3]; const Vec2 &p2 = m_triangulated_verts[i*3+1]; const Vec2 &p3 = m_triangulated_verts[i*3+2]; #if 1 // Try switching this to 0 to visualize each triangle as a random color - useful to judge efficiency { m_drawNode->drawTriangle( p1, p2, p3, m_fill_color ); } #else { m_drawNode->drawTriangle( p1, p2, p3, // Triangle points Color4F( random()*1.0f, // Rand red random()*1.0f, // Rand green random()*1.0f, // Rand blue 1.0f // Opaque ) ); } #endif } m_triangulated_verts.clear(); } m_fill_verts.clear(); } } void GraphicsObj::moveTo( float x, float y ) { m_pen_pos.x = x; m_pen_pos.y = Director::getInstance()->getVisibleSize().height - y; if ( m_bFilling ) { m_fill_verts.clear(); m_fill_verts.push_back( m_pen_pos ); } } void GraphicsObj::lineTo( float x, float y ) { Vec2 p; p.x = x; p.y = Director::getInstance()->getVisibleSize().height - y; // No line drawn if thickness < 1 if ( m_lineThickness > 0 ) { m_drawNode->drawLine( m_pen_pos, p, m_line_color ); m_pen_pos = p; } if ( m_bFilling ) m_fill_verts.push_back( p ); } void GraphicsObj::clear() { m_drawNode->clear(); m_fill_verts.clear(); m_triangulated_verts.clear(); m_bFilling = false; }