/* Copyright 2004, 2005 Nicholas Bishop * * This file is part of SharpConstruct. * * SharpConstruct is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * SharpConstruct is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SharpConstruct; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "DisplaceBrush.hh" #include "GrabBrush.hh" #include "LayerBrush.hh" #include "PinchBrush.hh" #include "SmoothBrush.hh" #include "Brush.h" #include "Math.hh" #include "Mesh.h" #include "Sculpt.hh" #include "config.h" #include "prefix.h" #include #include using namespace SharpConstruct; SymmetryData::SymmetryData() : x_( false ), y_( false ), z_( false ) {} SymmetryData::SymmetryData( bool x, bool y, bool z ) : x_( x ), y_( y ), z_( z ) {} bool SymmetryData::X() const { return x_; } void SymmetryData::SetX( const bool x ) { x_ = x; } bool SymmetryData::Y() const { return y_; } void SymmetryData::SetY( const bool y ) { y_ = y; } bool SymmetryData::Z() const { return z_; } void SymmetryData::SetZ( const bool z ) { z_ = z; } Brush::Brush() : mode_( DISPLACE ), position_edit_( ADD ), color_edit_( false ), flip_( false ), radius_( 10 ), strength_( -0.025 ), intensity_( 0.025 ), pressure_( 1 ), radius_pressure_( true ), strength_pressure_( true ), intensity_pressure_( true ), once_( false ), dot_( false ) {} void Brush::StartSculpt( Mesh& mesh ) { mesh.ClearModifiedVertexIndices(); mesh.CurrentBrush()._sculpt< SculptStart >( mesh ); } void Brush::ContinueSculpt( Mesh& mesh ) { mesh.CurrentBrush()._sculpt< SculptContinue >( mesh ); mesh.AdaptiveSubdivide(); } Brush::BrushMode Brush::Mode() const { return mode_; } void Brush::SetMode( const BrushMode& m ) { mode_ = m; } Brush::PositionMode Brush::PositionEdit() const { return position_edit_; } void Brush::SetPositionEdit( PositionMode p ) { position_edit_ = p; } bool Brush::ColorEdit() const { return color_edit_; } void Brush::SetColorEdit( bool c ) { color_edit_ = c; } bool Brush::Flip() const { return flip_; } void Brush::SetFlip( bool f ) { flip_ = f; } unsigned Brush::Radius() const { if( Pressure() == 0 || !radius_pressure_ ) return radius_; else return radius_ * Pressure(); } void Brush::SetRadius( float r ) { radius_ = lroundf( r ); } float Brush::Strength() const { float strength( strength_ ); if( strength_pressure_ ) strength *= Pressure(); if( ( PositionEdit() == ADD && !Flip() ) || ( PositionEdit() == SUB && Flip() ) ) return -strength; else return strength; } void Brush::SetStrength( float s ) { strength_ = std::abs( s ); } float Brush::Intensity() const { if( intensity_pressure_ ) return intensity_ * Pressure(); else return intensity_; } void Brush::SetIntensity( float i ) { intensity_ = i; } float Brush::Pressure() const { return pressure_; } void Brush::SetPressure( const float p ) { pressure_ = p; } void Brush::SetRadiusPressure( const bool p ) { radius_pressure_ = p; } void Brush::SetStrengthPressure( const bool p ) { strength_pressure_ = p; } void Brush::SetIntensityPressure( const bool p ) { intensity_pressure_ = p; } const Color& Brush::CurrentColor() const { return color_; } void Brush::SetColor( const Color& c ) { color_ = c; } const SymmetryData& Brush::Symmetry() const { return symmetry_; } void Brush::SetSymmetry( const SymmetryData& s ) { symmetry_ = s; } bool Brush::Once() const { return once_; } void Brush::SetOnce( bool o ) { once_ = o; } bool Brush::Dot() const { return dot_; } void Brush::SetDot( bool d ) { dot_ = d; } void Brush::SetShape( Glib::RefPtr< Gdk::Pixbuf > t ) { shape_ = t; } /* Note that in the interests of speed, this function only uses the red component of the image, instead of averaging the components together. Since the shapes are usually grey, this should be fine... */ float Brush::AlphaStrength( Math::PolarPoint l ) { // Find alpha's center Math::Point2D< float > c( shape_->get_width() / 2.0f, shape_->get_height() / 2.0f ); // Scale the magnitude to match the size of the alpha l.SetMagnitude( l.Magnitude() * c.X() ); // FIXME: NOT SURE IF THIS +C BUSINESS IS CORRECT.... // Find the pixel in the alpha Math::Point2D< int > x( static_cast< int >( l.Magnitude() * cos( l.Angle() ) + c.X() ), static_cast< int >( l.Magnitude() * sin( l.Angle() ) + c.Y() ) ); const guint8* pixels( shape_->get_pixels() ); const guint8* p( pixels + x.Y() * shape_->get_rowstride() + x.X() * shape_->get_n_channels() ); return p[ 0 ] / 255.0f; } float Brush::AlphaStrength( const float x, const float y ) { /*const unsigned row( lroundf( ( 1 - y ) * shape_->H() ) ); const unsigned col( lroundf( x * shape_->W() ) ); return shape_->PixelLightness( col, row );*/ return 0; } float Brush::BackLimit() const { return back_limit_; } void Brush::SetBackLimit( const float l ) { back_limit_ = l; } float Brush::FrontLimit() const { return front_limit_; } void Brush::SetFrontLimit( const float l ) { front_limit_ = l; } float Brush::CursorZ() const { return cursor_z_; } void Brush::SetCursorZ( const float z ) { cursor_z_ = z; }