tBane Temat założony przez niniejszego użytkownika |
[SFML 2.X] Narzędzie Lasso w programie do edycji grafiki » 2025-08-28 14:14:03 Witam. Próbuję napisać narzędzie Lasso. Narzędzie to ma działać w taki sposób, że można zaznaczać przy jego użyciu dowolny kształt poprzez przesuwanie kursora z naciśniętym lewym przyciskiem myszy. Narzędzie działa poprawnie dla większej ilości punktów, ale przy małej ilości punktów się wykrzacza. Dlaczego ? zarysowany cały kształt  tu także więc jest ok  a tu dopiero co zacząłem zaznaczać w lewo w dół i się wykrzaczyło  #ifndef Lasso_hpp #define Lasso_hpp
enum class LassoState { None, Selecting, Selected, Moving };
class Lasso { public: LassoState state; std::vector < sf::Vector2f > points; sf::ConvexShape outline; Lasso() { state = LassoState::None; points.clear(); outline = sf::ConvexShape(); outline.setOutlineColor( sf::Color::Cyan ); outline.setOutlineThickness( 2.0f ); outline.setFillColor( sf::Color::Transparent ); } ~Lasso() { } void addPoint( sf::Vector2f p ) { if( points.empty() || sqrt( pow( points.back().x - p.x, 2 ) + pow( points.back().y - p.y, 2 ) ) > 4.0f ) { points.push_back( p ); outline.setPointCount( points.size() ); outline.setPoint( points.size() - 1, p ); } } void draw() { if( outline.getPointCount() > 2 ) window->draw( outline ); else { } } };
Lasso * lasso = nullptr; #endif
|
|
DejaVu |
» 2025-08-28 16:01:50 A czy przeczytałeś czy dozwolone jest tworzenie kształtu, gdzie 'obwódka' rysowana się przecina sama ze sobą? np. jeżeli liczbę 8 chciałbyś narysować. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-28 16:13:34 No właśnie nie wiem, ale wtedy też się wykrzacza. Czyli co, zastąpić sf::ConvexShape? Tylko czym?  |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-28 18:36:06 Dobra. Zrobię to z użyciem sf::VertexArray(sf::LineStrip);. Pomęczę ChatGPT z shaderami na obwódkę (właśnie dlatego chciałem użyć sf::ConvexShape) i dam znać czy się udało |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-28 19:00:30 Mam taki kod. Ale czasem przesuwa krawędzie .. #include <SFML/Graphics.hpp> #include <vector> #include <cmath>
std::string lasso_image_width_outline_source = R"(
uniform sampler2D texture;
uniform sampler2D mask;
uniform vec2 maskSize;
uniform float outlineSize;
uniform vec4 outlineColor;
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec2 muv = uv;
muv.y = 1.0 - muv.y;
vec4 base = texture2D(texture, uv);
float aCenter = texture2D(mask, muv).a;
vec2 texel = 1.0 / maskSize;
int r = int(floor(outlineSize + 0.5));
float aMax = 0.0;
float aMin = 1.0;
for (int j = -r; j <= r; ++j) {
for (int i = -r; i <= r; ++i) {
vec2 off = vec2(float(i), float(j)) * texel;
float s = texture2D(mask, muv + off).a;
aMax = max(aMax, s);
aMin = min(aMin, s);
}
}
float dilated = step(0.5, aMax);
float eroded = step(0.5, aMin);
float edge = clamp(dilated - eroded, 0.0, 1.0);
vec4 masked = vec4(base.rgb, base.a * aCenter);
vec3 outRGB = mix(masked.rgb, outlineColor.rgb, edge * outlineColor.a);
float outA = max(masked.a, edge * outlineColor.a);
gl_FragColor = vec4(outRGB, outA);
}
)";
std::string lasso_only_outline_source = R"(
uniform sampler2D mask;
uniform vec2 maskSize;
uniform float outlineSize;
uniform vec4 outlineColor;
void main() {
vec2 uv = gl_TexCoord[0].xy;
float aCenter = texture2D(mask, uv).a;
vec2 texel = 1.0 / maskSize;
int r = int(floor(outlineSize + 0.5));
float aMax = 0.0;
float aMin = 1.0;
for (int j = -r; j <= r; ++j) {
for (int i = -r; i <= r; ++i) {
vec2 off = vec2(float(i), float(j)) * texel;
float s = texture2D(mask, uv + off).a;
aMax = max(aMax, s);
aMin = min(aMin, s);
}
}
float dilated = step(0.5, aMax);
float eroded = step(0.5, aMin);
float edge = clamp(dilated - eroded, 0.0, 1.0);
gl_FragColor = vec4(outlineColor.rgb, outlineColor.a * edge);
}
)";
sf::RenderWindow * window;
sf::Texture texture; sf::Sprite sprite;
sf::RenderTexture mask; sf::Sprite maskSprite;
sf::Shader shader1; sf::Shader shader2;
std::vector < sf::Vector2f > points; sf::VertexArray outline;
bool pointInPolygon( std::vector < sf::Vector2f > & points, sf::Vector2f p ) { bool inside = false; for( int i = 0, j = points.size() - 1; i < points.size(); j = i++ ) { sf::Vector2f A = points[ i ]; sf::Vector2f B = points[ j ]; bool inter =(( A.y > p.y ) !=( B.y > p.y ) ) &&( p.x <( B.x - A.x ) *( p.y - A.y ) /( B.y - A.y ) + A.x ); if( inter ) inside = !inside; } return inside; }
void pushPoint( sf::Vector2f p, std::vector < sf::Vector2f > & points, sf::VertexArray & outline ) { if( points.empty() || std::hypot( points.back().x - p.x, points.back().y - p.y ) > 2.0f ) { points.push_back( p ); outline.append( sf::Vertex( p, sf::Color::Cyan ) ); } }
void generateImage( std::vector < sf::Vector2f > points ) { if( points.size() < 3 ) return; sf::Vector2f centroid( 0.f, 0.f ); for( auto & p: points ) centroid += p; centroid.x /= points.size(); centroid.y /= points.size(); sf::VertexArray fan( sf::TriangleFan ); fan.append( sf::Vertex( centroid, sf::Color::White ) ); for( auto & p: points ) fan.append( sf::Vertex( p, sf::Color::White ) ); fan.append( sf::Vertex( points.front(), sf::Color::White ) ); mask.clear( sf::Color::Transparent ); mask.draw( fan, sf::RenderStates( sf::BlendNone ) ); mask.display(); shader1.setUniform( "mask", mask.getTexture() ); }
void generateOutline( std::vector < sf::Vector2f > points ) { if( points.size() < 3 ) return; sf::Vector2f centroid( 0.f, 0.f ); for( auto & p: points ) centroid += p; centroid.x /= points.size(); centroid.y /= points.size(); sf::VertexArray fan( sf::TrianglesFan ); fan.append( sf::Vertex( centroid, sf::Color::White ) ); for( auto & p: points ) fan.append( sf::Vertex( p, sf::Color::White ) ); fan.append( sf::Vertex( points.front(), sf::Color::White ) ); mask.clear( sf::Color::Transparent ); mask.draw( fan, sf::RenderStates( sf::BlendNone ) ); mask.display(); shader2.setUniform( "mask", mask.getTexture() ); }
int main() { window = new sf::RenderWindow( sf::VideoMode( 1000, 600 ), "Lasso" ); texture.loadFromFile( "image.png" ); sprite = sf::Sprite( texture ); mask.create( texture.getSize().x, texture.getSize().y ); mask.clear( sf::Color::Transparent ); mask.display(); maskSprite = sf::Sprite( mask.getTexture() ); shader1.loadFromMemory( lasso_image_width_outline_source, sf::Shader::Fragment ); shader1.setUniform( "texture", texture ); shader1.setUniform( "mask", mask.getTexture() ); shader1.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); shader1.setUniform( "outlineSize", 1.f ); shader1.setUniform( "outlineColor", sf::Glsl::Vec4( 0, 1, 1, 1 ) ); shader2.loadFromMemory( lasso_only_outline_source, sf::Shader::Fragment ); shader2.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); shader2.setUniform( "outlineSize", 1.f ); shader2.setUniform( "outlineColor", sf::Glsl::Vec4( 0, 1, 1, 1 ) ); points.clear(); bool drawing = false; outline = sf::VertexArray( sf::LineStrip ); while( window->isOpen() ) { sf::Vector2i mousePosition = sf::Mouse::getPosition( * window ); sf::Vector2f worldMousePosition = window->mapPixelToCoords( mousePosition ); sf::Event ev; while( window->pollEvent( ev ) ) { if( ev.type == sf::Event::Closed ) window->close(); if( ev.type == sf::Event::MouseButtonPressed && ev.mouseButton.button == sf::Mouse::Left ) { drawing = true; points.clear(); outline.clear(); pushPoint( worldMousePosition, points, outline ); } if( ev.type == sf::Event::MouseMoved && drawing ) { pushPoint( worldMousePosition, points, outline ); generateOutline( points ); } if( ev.type == sf::Event::MouseButtonReleased && ev.mouseButton.button == sf::Mouse::Left ) { drawing = false; generateImage( points ); } if( ev.type == sf::Event::KeyPressed && ev.key.code == sf::Keyboard::C ) { mask.clear( sf::Color::Transparent ); mask.display(); shader1.setUniform( "mask", mask.getTexture() ); points.clear(); outline.clear(); } } window->clear( sf::Color( 30, 30, 34 ) ); if( !drawing && outline.getVertexCount() >= 3 ) { sf::RenderStates rs; rs.shader = & shader1; window->draw( sprite, rs ); } if( drawing && outline.getVertexCount() >= 3 ) { sf::RenderStates rs; rs.shader = & shader2; window->draw( maskSprite, rs ); } window->display(); } return 0; }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-28 19:55:49 Dobra. Udało sie napisać. Obwódka to sf::VertexArray fan( sf::LineStrip ); a obraz to sf::VertexArray fan( sf::TriangleFan ); #include <SFML/Graphics.hpp> #include <vector> #include <cmath>
std::string lasso_image_width_outline_source = R"(
uniform sampler2D texture;
uniform sampler2D mask;
uniform vec2 maskSize;
uniform float outlineSize;
uniform vec4 outlineColor;
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec2 muv = uv;
muv.y = 1.0 - muv.y;
vec4 base = texture2D(texture, uv);
float aCenter = texture2D(mask, muv).a;
vec2 texel = 1.0 / maskSize;
int r = int(floor(outlineSize + 0.5));
float aMax = 0.0;
float aMin = 1.0;
for (int j = -r; j <= r; ++j) {
for (int i = -r; i <= r; ++i) {
vec2 off = vec2(float(i), float(j)) * texel;
float s = texture2D(mask, muv + off).a;
aMax = max(aMax, s);
aMin = min(aMin, s);
}
}
float dilated = step(0.5, aMax);
float eroded = step(0.5, aMin);
float edge = clamp(dilated - eroded, 0.0, 1.0);
vec4 masked = vec4(base.rgb, base.a * aCenter);
vec3 outRGB = mix(masked.rgb, outlineColor.rgb, edge * outlineColor.a);
float outA = max(masked.a, edge * outlineColor.a);
gl_FragColor = vec4(outRGB, outA);
}
)";
std::string lasso_only_outline_source = R"(
uniform sampler2D mask;
uniform vec2 maskSize;
uniform float outlineSize;
uniform vec4 outlineColor;
void main() {
vec2 uv = gl_TexCoord[0].xy;
float aCenter = texture2D(mask, uv).a;
vec2 texel = 1.0 / maskSize;
int r = int(floor(outlineSize + 0.5));
float aMax = 0.0;
float aMin = 1.0;
for (int j = -r; j <= r; ++j) {
for (int i = -r; i <= r; ++i) {
vec2 off = vec2(float(i), float(j)) * texel;
float s = texture2D(mask, uv + off).a;
aMax = max(aMax, s);
aMin = min(aMin, s);
}
}
float dilated = step(0.5, aMax);
float eroded = step(0.5, aMin);
float edge = clamp(dilated - eroded, 0.0, 1.0);
gl_FragColor = vec4(outlineColor.rgb, outlineColor.a * edge);
}
)";
sf::RenderWindow * window;
sf::Texture texture; sf::Sprite sprite;
sf::RenderTexture mask; sf::Sprite maskSprite;
sf::Shader shader1; sf::Shader shader2;
std::vector < sf::Vector2f > points; sf::VertexArray outline;
bool pointInPolygon( std::vector < sf::Vector2f > & points, sf::Vector2f p ) { bool inside = false; for( int i = 0, j = points.size() - 1; i < points.size(); j = i++ ) { sf::Vector2f A = points[ i ]; sf::Vector2f B = points[ j ]; bool inter =(( A.y > p.y ) !=( B.y > p.y ) ) &&( p.x <( B.x - A.x ) *( p.y - A.y ) /( B.y - A.y ) + A.x ); if( inter ) inside = !inside; } return inside; }
void pushPoint( sf::Vector2f p, std::vector < sf::Vector2f > & points, sf::VertexArray & outline ) { if( points.empty() || std::hypot( points.back().x - p.x, points.back().y - p.y ) > 2.0f ) { points.push_back( p ); outline.append( sf::Vertex( p, sf::Color::Cyan ) ); } }
void generateImage( std::vector < sf::Vector2f > points ) { if( points.size() < 3 ) return; sf::Vector2f centroid( 0.f, 0.f ); for( auto & p: points ) centroid += p; centroid.x /= points.size(); centroid.y /= points.size(); sf::VertexArray fan( sf::TriangleFan ); fan.append( sf::Vertex( centroid, sf::Color::White ) ); for( auto & p: points ) fan.append( sf::Vertex( p, sf::Color::White ) ); fan.append( sf::Vertex( points.front(), sf::Color::White ) ); mask.clear( sf::Color::Transparent ); mask.draw( fan, sf::RenderStates( sf::BlendNone ) ); mask.display(); shader1.setUniform( "mask", mask.getTexture() ); }
void generateOutline( std::vector < sf::Vector2f > points ) { if( points.size() < 3 ) return; sf::VertexArray fan( sf::LineStrip ); for( auto & p: points ) fan.append( sf::Vertex( p, sf::Color::White ) ); mask.clear( sf::Color::Transparent ); mask.draw( fan, sf::RenderStates( sf::BlendNone ) ); mask.display(); shader2.setUniform( "mask", mask.getTexture() ); }
int main() { window = new sf::RenderWindow( sf::VideoMode( 1000, 600 ), "Lasso" ); texture.loadFromFile( "image.png" ); sprite = sf::Sprite( texture ); mask.create( texture.getSize().x, texture.getSize().y ); mask.clear( sf::Color::Transparent ); mask.display(); maskSprite = sf::Sprite( mask.getTexture() ); shader1.loadFromMemory( lasso_image_width_outline_source, sf::Shader::Fragment ); shader1.setUniform( "texture", texture ); shader1.setUniform( "mask", mask.getTexture() ); shader1.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); shader1.setUniform( "outlineSize", 1.f ); shader1.setUniform( "outlineColor", sf::Glsl::Vec4( 0, 1, 1, 1 ) ); shader2.loadFromMemory( lasso_only_outline_source, sf::Shader::Fragment ); shader2.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); shader2.setUniform( "outlineSize", 1.f ); shader2.setUniform( "outlineColor", sf::Glsl::Vec4( 0, 1, 1, 1 ) ); points.clear(); bool drawing = false; outline = sf::VertexArray( sf::LineStrip ); while( window->isOpen() ) { sf::Vector2i mousePosition = sf::Mouse::getPosition( * window ); sf::Vector2f worldMousePosition = window->mapPixelToCoords( mousePosition ); sf::Event ev; while( window->pollEvent( ev ) ) { if( ev.type == sf::Event::Closed ) window->close(); if( ev.type == sf::Event::MouseButtonPressed && ev.mouseButton.button == sf::Mouse::Left ) { drawing = true; points.clear(); outline.clear(); pushPoint( worldMousePosition, points, outline ); } if( ev.type == sf::Event::MouseMoved && drawing ) { pushPoint( worldMousePosition, points, outline ); generateOutline( points ); } if( ev.type == sf::Event::MouseButtonReleased && ev.mouseButton.button == sf::Mouse::Left ) { drawing = false; generateImage( points ); } if( ev.type == sf::Event::KeyPressed && ev.key.code == sf::Keyboard::C ) { mask.clear( sf::Color::Transparent ); mask.display(); shader1.setUniform( "mask", mask.getTexture() ); points.clear(); outline.clear(); } } window->clear( sf::Color( 30, 30, 34 ) ); if( !drawing && outline.getVertexCount() >= 3 ) { sf::RenderStates rs; rs.shader = & shader1; window->draw( sprite, rs ); } if( drawing && outline.getVertexCount() >= 3 ) { sf::RenderStates rs; rs.shader = & shader2; window->draw( maskSprite, rs ); } window->display(); } return 0; }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-31 14:41:24 Cześć ponownie :-) Nie potrafię pozycjonować zaznaczenia kształtu względem zewnętrznego prostokątnego zaznaczenia. Pierwsza funkcja do generowania outline (podczas zaznaczania) działa ale już druga - ta która jest odpowiedzialna za renderowanie zaznaczonego już zaznaczenia nie działa. Walczę z tym kodem od kilku godzin i nic nie wymyśliłem. Pomożecie ? link do repozytorium:https://github.com/tBane1995/Anim-Paint.gitPlik z kodem to Lasso.hpp video z programu:https://www.youtube.com/watch?v=HVOmRZ01Tv8tak to niestety wygląda a tak to powinno wyglądać: co nie działa:w funkcji lasso::draw() maskSprite.setScale( scale, scale ); maskSprite.setPosition( canvasPosition + sf::Vector2f( normRect.left * scale, normRect.top * scale ) );
lub void generateMovedOutline( float scale ) { if( points.size() < 3 ) return; sf::VertexArray lines( sf::LineStrip ); sf::IntRect normRect = normalizeRect(); for( auto & p: points ) lines.append( sf::Vertex( sf::Vector2f( p.x - normRect.width / 2, p.y - normRect.height / 2 ), sf::Color::White ) ); kod programu:#ifndef Lasso_hpp #define Lasso_hpp
std::string lasso_only_outline_source = R"(
uniform sampler2D mask;
uniform vec2 maskSize; // px
uniform float outlineSize; // PROMIEŃ w px
uniform vec4 outlineColor;
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec2 pix = uv * maskSize;
vec2 base = floor(pix);
// 1) r zaokrąglij do najbliższej całości
int r = int(floor(outlineSize + 0.5));
float aMax = 0.0;
float aMin = 1.0;
// 2) zakres ZAMKNIĘTY [-r .. r]
for (int j = -r; j < r; ++j) {
for (int i = -r; i < r; ++i) {
vec2 p = base + vec2(float(i), float(j));
// out-of-bounds = 0 (shader ogranicza współrzędne)
if (p.x < 0.0 || p.y < 0.0 || p.x > maskSize.x - 3.0 || p.y > maskSize.y - 1.0) {
aMax = max(aMax, 0.0);
aMin = min(aMin, 0.0);
} else {
vec2 coords = (p + vec2(0.5, 0.5)) / maskSize;
float s = texture2D(mask, coords).a;
aMax = max(aMax, s);
aMin = min(aMin, s);
}
}
}
float dilated = step(0.5, aMax);
float eroded = step(0.5, aMin);
float edge = clamp(dilated-eroded, 0.0, 1.0);
gl_FragColor = vec4(outlineColor.rgb, outlineColor.a * edge);
}
)";
enum class LassoState { None, Selecting, Selected, Moving };
class Lasso { public: LassoState state; std::vector < sf::Vector2f > points; sf::VertexArray outline; sf::Image * image; sf::Texture texture; sf::Sprite sprite; float margin = 1; sf::RenderTexture mask; sf::Sprite maskSprite; sf::Shader shaderOutline; sf::IntRect rect; sf::Vector2i offset; Lasso() { state = LassoState::None; points.clear(); outline = sf::VertexArray( sf::LineStrip ); image = nullptr; rect = sf::IntRect( 0, 0, 0, 0 ); offset = sf::Vector2i( 0, 0 ); } ~Lasso() { } void startSelecting( sf::Vector2f canvas_position, float scale ) { texture.loadFromImage( layers_dialog->getCurrentLayer()->image ); texture.setSmooth( false ); sprite = sf::Sprite( texture ); sprite.setScale( scale, scale ); sprite.setPosition( canvas_position ); margin = 1.0f; mask.create( texture.getSize().x + 2 * margin, texture.getSize().y + 2 * margin ); mask.setSmooth( false ); mask.clear( sf::Color( 127, 47, 47, 127 ) ); mask.display(); maskSprite = sf::Sprite( mask.getTexture() ); maskSprite.setScale( scale, scale ); maskSprite.setPosition( canvas_position - sf::Vector2f( margin * scale, margin * scale ) ); shaderOutline.loadFromMemory( lasso_only_outline_source, sf::Shader::Fragment ); shaderOutline.setUniform( "mask", mask.getTexture() ); shaderOutline.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); shaderOutline.setUniform( "outlineSize", 1.0f ); shaderOutline.setUniform( "outlineColor", sf::Glsl::Vec4( 47.0f / 255.0f, 127.0f / 255.0f, 127.0f / 255.0f, 255.0f / 255.0f ) ); points.clear(); outline.clear(); } sf::IntRect normalizeRect() { sf::IntRect r = rect; if( r.width < 0 ) { r.left += r.width; r.width = - r.width; } if( r.height < 0 ) { r.top += r.height; r.height = - r.height; } return r; } void addPoint( sf::Vector2f worldMousePosition, sf::Vector2f canvas_position, float scale ) { float lx =( worldMousePosition.x - canvas_position.x ) / scale; float ly =( worldMousePosition.y - canvas_position.y ) / scale; float mx = lx + margin; float my = ly + margin; int w = int( mask.getSize().x ); int h = int( mask.getSize().y ); float loX = margin; float hiX = float( w ) - 1.0f - margin; float loY = margin; float hiY = float( h ) - 1.0f - margin; if( hiX < loX ) hiX = loX; if( hiY < loY ) hiY = loY; mx = std::clamp( std::floor( mx ), loX, hiX ); my = std::clamp( std::floor( my ), loY, hiY ); sf::Vector2f q( mx, my ); if( points.empty() || std::hypot( points.back().x - q.x, points.back().y - q.y ) >= 1.0f ) { points.push_back( q ); outline.append( sf::Vertex( q, sf::Color::Cyan ) ); } } void unselect() { points.clear(); outline.clear(); } bool clickOnSelection( sf::Vector2i point ) { return rect.contains( point ); } void completeSelection( sf::Image & image ) { if( !points.empty() && outline.getVertexCount() > 2 ) { points.push_back( points.front() ); outline.append( outline[ 0 ] ); int minX = std::numeric_limits < int >::max(); int maxX = std::numeric_limits < int >::lowest(); int minY = std::numeric_limits < int >::max(); int maxY = std::numeric_limits < int >::lowest(); for( auto & p: points ) { minX = std::min( minX, int( p.x - 2 * margin ) ); maxX = std::max( maxX, int( p.x + 2 * margin ) ); minY = std::min( minY, int( p.y - 2 * margin ) ); maxY = std::max( maxY, int( p.y + 2 * margin ) ); } rect = sf::IntRect( minX, minY, maxX - minX, maxY - minY ); } } void generateOutline() { if( points.size() < 3 ) return; sf::VertexArray lines( sf::LineStrip ); for( auto & p: points ) lines.append( sf::Vertex( sf::Vector2f( p ), sf::Color::White ) ); mask.create( texture.getSize().x + 2 * margin, texture.getSize().y + 2 * margin ); mask.clear( sf::Color( 127, 47, 47, 127 ) ); mask.draw( lines, sf::RenderStates( sf::BlendNone ) ); mask.display(); shaderOutline.setUniform( "mask", mask.getTexture() ); shaderOutline.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); } void generateMovedOutline( float scale ) { if( points.size() < 3 ) return; sf::VertexArray lines( sf::LineStrip ); sf::IntRect normRect = normalizeRect(); for( auto & p: points ) lines.append( sf::Vertex( sf::Vector2f( p.x - normRect.width / 2, p.y - normRect.height / 2 ), sf::Color::White ) ); mask.create( texture.getSize().x + 2 * margin, texture.getSize().y + 2 * margin ); mask.clear( sf::Color( 127, 47, 47, 127 ) ); mask.draw( lines, sf::RenderStates( sf::BlendNone ) ); mask.display(); shaderOutline.setUniform( "mask", mask.getTexture() ); shaderOutline.setUniform( "maskSize", sf::Glsl::Vec2( mask.getSize().x, mask.getSize().y ) ); } void draw( sf::Vector2f canvasPosition, sf::Vector2i canvasSize, float scale ) { if( outline.getVertexCount() >= 3 ) { if( state == LassoState::Selecting ) { generateOutline(); maskSprite.setScale( scale, scale ); maskSprite.setPosition( canvasPosition - sf::Vector2f( margin * scale, margin * scale ) ); sf::RenderStates rs; rs.shader = & shaderOutline; window->draw( maskSprite, rs ); } if( state == LassoState::Selected || state == LassoState::Moving ) { generateMovedOutline( scale ); sf::IntRect normRect = normalizeRect(); if( image != nullptr ) { texture = sf::Texture(); texture.loadFromImage( * image ); sprite = sf::Sprite( texture ); sprite.setPosition( canvasPosition + sf::Vector2f( normRect.left * scale, normRect.top * scale ) ); sprite.setScale( scale, scale ); window->draw( sprite ); } maskSprite.setScale( scale, scale ); maskSprite.setPosition( canvasPosition + sf::Vector2f( normRect.left * scale, normRect.top * scale ) ); sf::RenderStates rs; rs.shader = & shaderOutline; window->draw( maskSprite, rs ); sf::RectangleShape r( sf::Vector2f( normRect.width * scale, normRect.height * scale ) ); r.setPosition( canvasPosition + sf::Vector2f( normRect.left * scale, normRect.top * scale ) ); r.setFillColor( sf::Color::Transparent ); r.setOutlineThickness( 4.0f ); r.setOutlineColor( sf::Color( 47, 127, 127, 255 ) ); window->draw( r ); } } } };
Lasso * lasso = nullptr; #endif
|
|
DejaVu |
» 2025-09-01 09:10:33 Jeżeli masz lasso, które przekłada się już na konkretne pixele, to jedyne co musisz zrobić to znaleźć na obrazku osobno: - min x, - min y, - max x, - max y
Te wartości wyznaczą Ci: - lewy górny róg - wysokość - szerokość
To umożliwi Ci poprawne wyrenderowanie prostokąta. |
|
« 1 » 2 3 4 5 |