- Main Page
- Namespaces
- Classes
- Files

- File List

# Shape.cpp

    00001
    00002 //
    00003 // SFML - Simple and Fast Multimedia Library
    00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
    00005 //
    00006 // This software is provided 'as-is', without any express or implied warranty.
    00007 // In no event will the authors be held liable for any damages arising from the use of this software.
    00008 //
    00009 // Permission is granted to anyone to use this software for any purpose,
    00010 // including commercial applications, and to alter it and redistribute it freely,
    00011 // subject to the following restrictions:
    00012 //
    00013 // 1. The origin of this software must not be misrepresented;
    00014 //    you must not claim that you wrote the original software.
    00015 //    If you use this software in a product, an acknowledgment
    00016 //    in the product documentation would be appreciated but is not required.
    00017 //
    00018 // 2. Altered source versions must be plainly marked as such,
    00019 //    and must not be misrepresented as being the original software.
    00020 //
    00021 // 3. This notice may not be removed or altered from any source distribution.
    00022 //
    00024
    00026 // Headers
    00028 #include <SFML/Graphics/Shape.hpp>
    00029 #include <SFML/Graphics/GraphicsContext.hpp>
    00030 #include <math.h>
    00031
    00032
    00033 namespace sf
    00034 {
    00038 Shape::Shape() :
    00039 myOutline         (0.f),
    00040 myIsFillEnabled   (true),
    00041 myIsOutlineEnabled(true),
    00042 myIsCompiled      (false)
    00043 {
    00044     // Put a placeholder for the center of the shape
    00045     myPoints.push_back(Point());
    00046 }
    00047
    00048
    00052 void Shape::AddPoint(float X, float Y, const Color& Col, const Color& OutlineCol)
    00053 {
    00054     AddPoint(Vector2f(X, Y), Col, OutlineCol);
    00055 }
    00056
    00057
    00061 void Shape::AddPoint(const Vector2f& Position, const Color& Col, const Color& OutlineCol)
    00062 {
    00063     myPoints.push_back(Point(Position, Col, OutlineCol));
    00064     myIsCompiled = false;
    00065 }
    00066
    00067
    00071 unsigned int Shape::GetNbPoints() const
    00072 {
    00073     return static_cast<unsigned int>(myPoints.size() - 1);
    00074 }
    00075
    00076
    00081 void Shape::EnableFill(bool Enable)
    00082 {
    00083     myIsFillEnabled = Enable;
    00084 }
    00085
    00086
    00091 void Shape::EnableOutline(bool Enable)
    00092 {
    00093     myIsOutlineEnabled = Enable;
    00094 }
    00095
    00096
    00100 void Shape::SetPointPosition(unsigned int Index, const Vector2f& Position)
    00101 {
    00102     myPoints[Index + 1].Position = Position;
    00103     myIsCompiled = false;
    00104 }
    00105
    00106
    00110 void Shape::SetPointPosition(unsigned int Index, float X, float Y)
    00111 {
    00112     SetPointPosition(Index, Vector2f(X, Y));
    00113 }
    00114
    00115
    00119 void Shape::SetPointColor(unsigned int Index, const Color& Col)
    00120 {
    00121     myPoints[Index + 1].Col = Col;
    00122     myIsCompiled = false;
    00123 }
    00124
    00125
    00129 void Shape::SetPointOutlineColor(unsigned int Index, const Color& OutlineCol)
    00130 {
    00131     myPoints[Index + 1].OutlineCol = OutlineCol;
    00132     myIsCompiled = false;
    00133 }
    00134
    00135
    00139 void Shape::SetOutlineWidth(float Width)
    00140 {
    00141     myOutline = Width;
    00142 }
    00143
    00144
    00148 const Vector2f& Shape::GetPointPosition(unsigned int Index) const
    00149 {
    00150     return myPoints[Index + 1].Position;
    00151 }
    00152
    00153
    00157 const Color& Shape::GetPointColor(unsigned int Index) const
    00158 {
    00159     return myPoints[Index + 1].Col;
    00160 }
    00161
    00162
    00166 const Color& Shape::GetPointOutlineColor(unsigned int Index) const
    00167 {
    00168     return myPoints[Index + 1].OutlineCol;
    00169 }
    00170
    00171
    00175 float Shape::GetOutlineWidth() const
    00176 {
    00177     return myOutline;
    00178 }
    00179
    00180
    00184 Shape Shape::Line(float P1X, float P1Y, float P2X, float P2Y, float Thickness, const Color& Col, float Outline, const Color& OutlineCol)
    00185 {
    00186     Vector2f P1(P1X, P1Y);
    00187     Vector2f P2(P2X, P2Y);
    00188
    00189     // Compute the extrusion direction
    00190     Vector2f Normal;
    00191     ComputeNormal(P1, P2, Normal);
    00192     Normal *= Thickness / 2;
    00193
    00194     // Create the shape's points
    00195     Shape S;
    00196     S.AddPoint(P1 - Normal, Col, OutlineCol);
    00197     S.AddPoint(P2 - Normal, Col, OutlineCol);
    00198     S.AddPoint(P2 + Normal, Col, OutlineCol);
    00199     S.AddPoint(P1 + Normal, Col, OutlineCol);
    00200     S.SetOutlineWidth(Outline);
    00201
    00202     // Compile it
    00203     S.Compile();
    00204
    00205     return S;
    00206 }
    00207
    00208
    00212 Shape Shape::Line(const Vector2f& P1, const Vector2f& P2, float Thickness, const Color& Col, float Outline, const Color& OutlineCol)
    00213 {
    00214     return Shape::Line(P1.x, P1.y, P2.x, P2.y, Thickness, Col, Outline, OutlineCol);
    00215 }
    00216
    00217
    00221 Shape Shape::Rectangle(float P1X, float P1Y, float P2X, float P2Y, const Color& Col, float Outline, const Color& OutlineCol)
    00222 {
    00223     // Create the shape's points
    00224     Shape S;
    00225     S.AddPoint(Vector2f(P1X, P1Y), Col, OutlineCol);
    00226     S.AddPoint(Vector2f(P2X, P1Y), Col, OutlineCol);
    00227     S.AddPoint(Vector2f(P2X, P2Y), Col, OutlineCol);
    00228     S.AddPoint(Vector2f(P1X, P2Y), Col, OutlineCol);
    00229     S.SetOutlineWidth(Outline);
    00230
    00231     // Compile it
    00232     S.Compile();
    00233
    00234     return S;
    00235 }
    00236
    00237
    00241 Shape Shape::Rectangle(const Vector2f& P1, const Vector2f& P2, const Color& Col, float Outline, const Color& OutlineCol)
    00242 {
    00243     return Shape::Rectangle(P1.x, P1.y, P2.x, P2.y, Col, Outline, OutlineCol);
    00244 }
    00245
    00246
    00250 Shape Shape::Circle(float X, float Y, float Radius, const Color& Col, float Outline, const Color& OutlineCol)
    00251 {
    00252     static const int NbSegments = 40;
    00253
    00254     // Create the points set
    00255     Shape S;
    00256     Vector2f Center(X, Y);
    00257     for (int i = 0; i < NbSegments; ++i)
    00258     {
    00259         float Angle = i * 2 * 3.141592654f / NbSegments;
    00260         Vector2f Offset(cos(Angle), sin(Angle));
    00261
    00262         S.AddPoint(Center + Offset * Radius, Col, OutlineCol);
    00263     }
    00264
    00265     // Compile it
    00266     S.SetOutlineWidth(Outline);
    00267     S.Compile();
    00268
    00269     return S;
    00270 }
    00271
    00272
    00276 Shape Shape::Circle(const Vector2f& Center, float Radius, const Color& Col, float Outline, const Color& OutlineCol)
    00277 {
    00278     return Shape::Circle(Center.x, Center.y, Radius, Col, Outline, OutlineCol);
    00279 }
    00280
    00281
    00285 void Shape::Render(RenderTarget&) const
    00286 {
    00287     // Make sure the shape has at least 3 points (4 if we count the center)
    00288     if (myPoints.size() < 4)
    00289         return;
    00290
    00291     // Make sure the shape is compiled
    00292     if (!myIsCompiled)
    00293         const_cast<Shape*>(this)->Compile();
    00294
    00295     // Shapes only use color, no texture
    00296     GLCheck(glDisable(GL_TEXTURE_2D));
    00297
    00298     // Draw the shape
    00299     if (myIsFillEnabled)
    00300     {
    00301         glBegin(GL_TRIANGLE_FAN);
    00302         {
    00303             for (std::vector<Point>::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i)
    00304             {
    00305                 Color PointColor = i->Col * GetColor();
    00306                 glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00307                 glVertex2f(i->Position.x, i->Position.y);
    00308             }
    00309
    00310             // Close the shape by duplicating the first point at the end
    00311             Color PointColor = myPoints[1].Col * GetColor();
    00312             glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00313             glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
    00314         }
    00315         glEnd();
    00316     }
    00317
    00318     // Draw the outline
    00319     if (myIsOutlineEnabled)
    00320     {
    00321         glBegin(GL_TRIANGLE_STRIP);
    00322         {
    00323             for (std::size_t i = 1; i < myPoints.size(); ++i)
    00324             {
    00325                 Color PointColor = myPoints[i].OutlineCol * GetColor();
    00326                 glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00327                 glVertex2f(myPoints[i].Position.x, myPoints[i].Position.y);
    00328                 glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00329                 glVertex2f(myPoints[i].Position.x + myPoints[i].Normal.x * myOutline, myPoints[i].Position.y + myPoints[i].Normal.y * myOutline);
    00330             }
    00331
    00332             // Close the shape by duplicating the first point at the end
    00333             Color PointColor = myPoints[1].OutlineCol * GetColor();
    00334             glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00335             glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
    00336             glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
    00337             glVertex2f(myPoints[1].Position.x + myPoints[1].Normal.x * myOutline, myPoints[1].Position.y + myPoints[1].Normal.y * myOutline);
    00338         }
    00339         glEnd();
    00340     }
    00341 }
    00342
    00343
    00347 void Shape::Compile()
    00348 {
    00349     // Compute the center
    00350     float NbPoints = static_cast<float>(myPoints.size() - 1);
    00351     float R = 0, G = 0, B = 0, A = 0;
    00352     Point Center(Vector2f(0, 0), Color(0, 0, 0, 0));
    00353     for (std::size_t i = 1; i < myPoints.size(); ++i)
    00354     {
    00355         Center.Position += myPoints[i].Position / NbPoints;
    00356         R += myPoints[i].Col.r / NbPoints;
    00357         G += myPoints[i].Col.g / NbPoints;
    00358         B += myPoints[i].Col.b / NbPoints;
    00359         A += myPoints[i].Col.a / NbPoints;
    00360     }
    00361     Center.Col.r = static_cast<Uint8>(R);
    00362     Center.Col.g = static_cast<Uint8>(G);
    00363     Center.Col.b = static_cast<Uint8>(B);
    00364     Center.Col.a = static_cast<Uint8>(A);
    00365     myPoints[0] = Center;
    00366
    00367     // Compute the outline
    00368     for (std::size_t i = 1; i < myPoints.size(); ++i)
    00369     {
    00370         // Get the two segments shared by the current point
    00371         Point& P0 = (i == 1) ? myPoints[myPoints.size() - 1] : myPoints[i - 1];
    00372         Point& P1 = myPoints[i];
    00373         Point& P2 = (i == myPoints.size() - 1) ? myPoints[1] : myPoints[i + 1];
    00374
    00375         // Compute their normal
    00376         Vector2f Normal1, Normal2;
    00377         if (!ComputeNormal(P0.Position, P1.Position, Normal1) || !ComputeNormal(P1.Position, P2.Position, Normal2))
    00378             continue;
    00379
    00380         // Add them to get the extrusion direction
    00381         float Factor = 1.f + (Normal1.x * Normal2.x + Normal1.y * Normal2.y);
    00382         P1.Normal = (Normal1 + Normal2) / Factor;
    00383
    00384         // Make sure it points towards the outside of the shape
    00385         float Dot = (P1.Position.x - Center.Position.x) * P1.Normal.x + (P1.Position.y - Center.Position.y) * P1.Normal.y;
    00386         if (Dot < 0)
    00387             P1.Normal = -P1.Normal;
    00388     }
    00389
    00390     myIsCompiled = true;
    00391 }
    00392
    00393
    00397 bool Shape::ComputeNormal(const Vector2f& P1, const Vector2f& P2, Vector2f& Normal)
    00398 {
    00399     Normal.x = P1.y - P2.y;
    00400     Normal.y = P2.x - P1.x;
    00401
    00402     float Len = sqrt(Normal.x * Normal.x + Normal.y * Normal.y);
    00403     if (Len == 0.f)
    00404         return false;
    00405
    00406     Normal.x /= Len;
    00407     Normal.y /= Len;
    00408
    00409     return true;
    00410 }
    00411
    00412
    00416 Shape::Point::Point(const Vector2f& Pos, const Color& C, const Color& OutlineC) :
    00417 Position  (Pos),
    00418 Normal    (0.f, 0.f),
    00419 Col       (C),
    00420 OutlineCol(OutlineC)
    00421 {
    00422
    00423 }
    00424
    00425 } // namespace sf

:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::