Shape.cpp
00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 Laurent Gomila ([email protected]) 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 ::