tBane Temat założony przez niniejszego użytkownika |
» 2025-09-01 11:13:27 Tak też zrobiłem, ale problem polega na tym że przesuwa mi punkty nieregularnego zaznaczenia. |
|
DejaVu |
» 2025-09-01 11:34:43 Jeżeli zaznaczenie jest dobre, a prostokąt jest zły, to nie zrobiłeś tego dobrze. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-09-01 11:36:13 Zobacz jak to wygląda na nagraniu na youtube. https://www.youtube.com/watch?v=HVOmRZ01Tv8Zaznaczanie jest dobre, po czym gdy kończymy zaznaczać to zaznaczenie nieregularne się przesuwa a prostokąt jest generowany poprawnie |
|
DejaVu |
» 2025-09-01 14:38:09 No to jeżeli prostokąt rysuje się dobrze, a lasso źle, to masz zły punkt początkowy wyznaczony dla lasso. może jest wyznaczony względem punktu startowego w którym zaczynasz rysować, zamiast wyliczyć offset do lewego górnego rogu. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-09-01 15:36:25 Spróbuję dodać offset i dam znać |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-09-01 16:01:34 Nie mam pojęcia jak to zrobić. Dodałem zmienną maskOffset i przypisuje jej wartosć podczas dodawania pierwszego punktu czyli offset = firstPointCoords. Następnie w funkcji draw rysuje lasso z przesunięciem o offset ale nie działa. #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::Vector2f maskOffset; 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 ); maskOffset = sf::Vector2f( 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 ); if( points.empty() ) { offset = sf::Vector2i( mx, my ); } 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( p + sf::Vector2f( offset ) * scale, 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( offset ) ); std::cout << "canvas: " << canvasPosition.x << ", " << canvasPosition.y << "\n"; std::cout << "mask: " << maskSprite.getGlobalBounds().getPosition().x << ", " << maskSprite.getGlobalBounds().getPosition().y << "\n"; 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
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-09-01 19:37:55 Skasuję ten kod i zacznę od nowa... :-/ |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-09-02 16:02:59 Prawie napisałem od nowa zaznaczanie lasso, tylko jest bug - czasami ucina fragment zaznaczenia :-/ Jeśli kodu jest za mało to zaktualizowałem repo: https://github.com/tBane1995/Anim-Paint.gitkod jest w plikach Anim-Paint/lasso.hpp oraz Anim-Paint/canvas.hpp  #ifndef Lasso_hpp #define Lasso_hpp
enum class LassoState { None, Selecting, Selected, Moving };
class Lasso { public: LassoState state; std::vector < sf::Vector2i > points; sf::Image * image; sf::Texture texture; sf::Sprite sprite; sf::RenderTexture mask; sf::Sprite maskSprite; sf::Vector2i maskOffset; sf::IntRect rect; Lasso() { state = LassoState::None; points.clear(); image = nullptr; rect = sf::IntRect( 0, 0, 0, 0 ); maskOffset = sf::Vector2i( 0, 0 ); } ~Lasso() { } void shiftOriginIfNeeded( sf::Vector2i & point ) { sf::Vector2i shift( 0, 0 ); if( point.x < 0 ) { shift.x = point.x; point.x = 0; } if( point.y < 0 ) { shift.y = point.y; point.y = 0; } if( shift.x != 0 || shift.y != 0 ) { maskOffset += shift; for( auto & p: points ) p -= shift; } } void addPoint( sf::Vector2i point ) { point = point - maskOffset; shiftOriginIfNeeded( point ); if( points.empty() || std::hypot( float( points.back().x - point.x ), float( points.back().y - point.y ) ) >= 1.0f ) { points.push_back( point ); } } void unselect() { points.clear(); generateRect(); } void generateRect() { if( points.size() > 2 ) { 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, p.x ); maxX = std::max( maxX, p.x ); minY = std::min( minY, p.y ); maxY = std::max( maxY, p.y ); } int left = minX + maskOffset.x; int top = minY + maskOffset.y; int width =( maxX - minX + 1 ); int height =( maxY - minY + 1 ); if( width > 0 && height > 0 ) rect = sf::IntRect( left, top, width, height ); else rect = sf::IntRect( 0, 0, 0, 0 ); } else { rect = sf::IntRect( 0, 0, 0, 0 ); } } bool clickOnSelection( sf::Vector2i point ) { return rect.contains( point ); } void generateOutline( float scale ) { if( points.size() < 3 ) return; sf::VertexArray lines( sf::LineStrip ); for( auto & p: points ) lines.append( sf::Vertex( sf::Vector2f( p ), sf::Color::White ) ); if( image != nullptr ) { texture = sf::Texture(); texture.create( image->getSize().x, image->getSize().y ); texture.loadFromImage( * image ); mask.create( texture.getSize().x, texture.getSize().y ); mask.clear( sf::Color( 127, 47, 47, 127 ) ); sf::RenderStates rs; rs.blendMode = sf::BlendNone; rs.transform.translate( 0.5f, 0.5f ); mask.draw( lines, rs ); mask.display(); } } void drawOutline( sf::Vector2f canvasPosition, float scale ) { maskSprite = sf::Sprite( mask.getTexture() ); maskSprite.setScale( scale, scale ); maskSprite.setPosition( canvasPosition + sf::Vector2f( maskOffset ) * scale ); window->draw( maskSprite ); } void draw( sf::Vector2f canvasPosition, float scale ) { if( points.size() >= 3 ) { if( true ) { generateOutline( scale ); drawOutline( canvasPosition, scale ); } } } };
Lasso * lasso = nullptr; #endif
|
|
1 « 2 » 3 4 5 |