diff --git a/libs/math/vector.h b/libs/math/vector.h index e5e7f0be..db2927e9 100644 --- a/libs/math/vector.h +++ b/libs/math/vector.h @@ -273,6 +273,22 @@ inline double vector2_cross( const BasicVector2& self, const BasicVecto return self.x() * other.y() - self.y() * other.x(); } +template +inline Element float_divided( Element f, Element other ){ + //ASSERT_MESSAGE(other != 0, "float_divided: invalid divisor"); + return f / other; +} + +template +inline BasicVector2 vector2_normalised( const BasicVector2& self ){ + return vector2_scaled( self, float_divided( 1.0, vector2_length( self ) ) ); +} + +template +inline void vector2_normalise( BasicVector2& self ){ + self = vector2_normalised( self ); +} + const Vector3 g_vector3_identity( 0, 0, 0 ); const Vector3 g_vector3_max = Vector3( FLT_MAX, FLT_MAX, FLT_MAX ); const Vector3 g_vector3_axis_x( 1, 0, 0 ); @@ -498,12 +514,6 @@ inline double vector3_length( const BasicVector3& self ){ return sqrt( vector3_length_squared( self ) ); } -template -inline Element float_divided( Element f, Element other ){ - //ASSERT_MESSAGE(other != 0, "float_divided: invalid divisor"); - return f / other; -} - template inline BasicVector3 vector3_normalised( const BasicVector3& self ){ return vector3_scaled( self, float_divided( 1.0, vector3_length( self ) ) ); diff --git a/radiant/brush.h b/radiant/brush.h index ec122141..41539fa1 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -569,6 +569,12 @@ void setTexdef( const TextureProjection& projection ){ addScale(); } +void setTexdef( const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + removeScale(); + Texdef_Assign( m_projection, hShift, vShift, hScale, vScale, rotation ); + addScale(); +} + void shift( float s, float t ){ ASSERT_MESSAGE( texdef_sane( m_projection.m_texdef ), "FaceTexdef::shift: bad texdef" ); removeScale(); @@ -1167,6 +1173,12 @@ void SetTexdef( const TextureProjection& projection ){ texdefChanged(); } +void SetTexdef( const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + undoSave(); + m_texdef.setTexdef( hShift, vShift, hScale, vScale, rotation ); + texdefChanged(); +} + void GetFlags( ContentsFlagsValue& flags ) const { flags = m_shader.getFlags(); } diff --git a/radiant/brush_primit.cpp b/radiant/brush_primit.cpp index db7aee12..905b84bf 100644 --- a/radiant/brush_primit.cpp +++ b/radiant/brush_primit.cpp @@ -344,14 +344,54 @@ void Texdef_Assign( texdef_t& td, const texdef_t& other ){ td = other; } + +void Texdef_Assign( texdef_t& td, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + if( hShift ){ + td.shift[0] = *hShift; + } + if( vShift ){ + td.shift[1] = *vShift; + } + if( hScale ){ + if( fabs( *hScale ) > 1e-5 ){ + td.scale[0] = *hScale; + } + else{ + td.scale[0] = -td.scale[0]; + } + } + if( vScale ){ + if( fabs( *vScale ) > 1e-5 ){ + td.scale[1] = *vScale; + } + else{ + td.scale[1] = -td.scale[1]; + } + } + if( rotation ){ + td.rotate = *rotation; + td.rotate = static_cast( float_to_integer( td.rotate ) % 360 ); + } +} + void Texdef_Shift( texdef_t& td, float s, float t ){ td.shift[0] += s; td.shift[1] += t; } void Texdef_Scale( texdef_t& td, float s, float t ){ - td.scale[0] += s; - td.scale[1] += t; + if( fabs( td.scale[0] + s ) > 1e-5 ){ + td.scale[0] += s; + } + else{ + td.scale[0] = -td.scale[0]; + } + if( fabs( td.scale[1] + t ) > 1e-5 ){ + td.scale[1] += t; + } + else{ + td.scale[1] = -td.scale[1]; + } } void Texdef_Rotate( texdef_t& td, float angle ){ @@ -635,6 +675,7 @@ void ConvertTexMatWithQTexture( const brushprimit_texdef_t *texMat1, const qtext // Note: this code looks similar to Texdef_fromTransform, but the algorithm is slightly different. void TexMatToFakeTexCoords( const brushprimit_texdef_t& bp_texdef, texdef_t& texdef ){ +#if 0 texdef.scale[0] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[1][0] ) ) ); texdef.scale[1] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][1], bp_texdef.coords[1][1] ) ) ); @@ -659,6 +700,26 @@ void TexMatToFakeTexCoords( const brushprimit_texdef_t& bp_texdef, texdef_t& tex texdef.scale[1] = -texdef.scale[1]; } } +#else + texdef.scale[0] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[0][1] ) ) ); + texdef.scale[1] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[1][0], bp_texdef.coords[1][1] ) ) ); + if( bp_texdef.coords[0][0] < 0 ){ + texdef.scale[0] = -texdef.scale[0]; + } + if( bp_texdef.coords[1][1] < 0 ){ + texdef.scale[1] = -texdef.scale[1]; + } +#if 1 + texdef.rotate = static_cast( radians_to_degrees( acos( vector2_normalised( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[0][1] ) )[0] ) ) ); + if( bp_texdef.coords[0][1] < 0 ){ + texdef.rotate = -texdef.rotate; + } +#else + texdef.rotate = static_cast( radians_to_degrees( arctangent_yx( bp_texdef.coords[0][1], bp_texdef.coords[0][0] ) ) ); +#endif + texdef.shift[0] = -bp_texdef.coords[0][2]; + texdef.shift[1] = bp_texdef.coords[1][2]; +#endif } // compute back the texture matrix from fake shift scale rot @@ -1028,6 +1089,7 @@ void BPTexdef_Shift( brushprimit_texdef_t& bp_td, float s, float t ){ } void BPTexdef_Scale( brushprimit_texdef_t& bp_td, float s, float t ){ +#if 0 // apply same scale as the spinner button of the surface inspector texdef_t texdef; // compute fake shift scale rot @@ -1037,9 +1099,27 @@ void BPTexdef_Scale( brushprimit_texdef_t& bp_td, float s, float t ){ texdef.scale[1] += t; // compute new normalized texture matrix FakeTexCoordsToTexMat( texdef, bp_td ); +#else + texdef_t texdef; + TexMatToFakeTexCoords( bp_td, texdef ); + + float scaleS = -1.f; + float scaleT = -1.f; + if( fabs( texdef.scale[0] + s ) > 1e-5 ){ + scaleS = texdef.scale[0] / ( texdef.scale[0] + s ); + } + if( fabs( texdef.scale[1] + t ) > 1e-5 ){ + scaleT = texdef.scale[1] / ( texdef.scale[1] + t ); + } + bp_td.coords[0][0] *= scaleS; + bp_td.coords[0][1] *= scaleS; + bp_td.coords[1][0] *= scaleT; + bp_td.coords[1][1] *= scaleT; +#endif } void BPTexdef_Rotate( brushprimit_texdef_t& bp_td, float angle ){ +#if 0 // apply same scale as the spinner button of the surface inspector texdef_t texdef; // compute fake shift scale rot @@ -1048,6 +1128,49 @@ void BPTexdef_Rotate( brushprimit_texdef_t& bp_td, float angle ){ texdef.rotate += angle; // compute new normalized texture matrix FakeTexCoordsToTexMat( texdef, bp_td ); +#else + const float x = bp_td.coords[0][0]; + const float y = bp_td.coords[0][1]; + const float x1 = bp_td.coords[1][0]; + const float y1 = bp_td.coords[1][1]; + const float s = sin( degrees_to_radians( angle ) ); + const float c = cos( degrees_to_radians( angle ) ); + bp_td.coords[0][0] = x * c - y * s ; + bp_td.coords[0][1] = x * s + y * c; + bp_td.coords[1][0] = x1 * c - y1 * s; + bp_td.coords[1][1] = x1 * s + y1 * c; +#endif +} + +void BPTexdef_Assign( brushprimit_texdef_t& bp_td, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + texdef_t texdef; + TexMatToFakeTexCoords( bp_td, texdef ); + + if( hShift ){ + bp_td.coords[0][2] = -*hShift; + } + if( vShift ){ + bp_td.coords[1][2] = *vShift; + } + if( hScale ){ + float scaleS = -1.f; + if( fabs( *hScale ) > 1e-5 ){ + scaleS = texdef.scale[0] / *hScale; + } + bp_td.coords[0][0] *= scaleS; + bp_td.coords[0][1] *= scaleS; + } + if( vScale ){ + float scaleT = -1.f; + if( fabs( *vScale ) > 1e-5 ){ + scaleT = texdef.scale[1] / *vScale; + } + bp_td.coords[1][0] *= scaleT; + bp_td.coords[1][1] *= scaleT; + } + if( rotation ){ + BPTexdef_Rotate( bp_td, *rotation - texdef.rotate ); + } } void BPTexdef_Construct( brushprimit_texdef_t& bp_td, std::size_t width, std::size_t height ){ @@ -1070,6 +1193,20 @@ void Texdef_Assign( TextureProjection& projection, const TextureProjection& othe } } +void Texdef_Assign( TextureProjection& projection, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { + BPTexdef_Assign( projection.m_brushprimit_texdef, hShift, vShift, hScale, vScale, rotation ); + } + else + { + Texdef_Assign( projection.m_texdef, hShift, vShift, hScale, vScale, rotation); +// if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) { +// projection.m_basis_s = other.m_basis_s; +// projection.m_basis_t = other.m_basis_t; +// } + } +} + void Texdef_Shift( TextureProjection& projection, float s, float t ){ if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { BPTexdef_Shift( projection.m_brushprimit_texdef, s, t ); diff --git a/radiant/brush_primit.h b/radiant/brush_primit.h index 8de1cbbd..c9e29c2e 100644 --- a/radiant/brush_primit.h +++ b/radiant/brush_primit.h @@ -102,6 +102,7 @@ void Normal_GetTransform( const Vector3& normal, Matrix4& transform ); void TexDef_Construct_Default( TextureProjection& projection ); void Texdef_Assign( TextureProjection& projection, const TextureProjection& other ); +void Texdef_Assign( TextureProjection& projection, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ); void Texdef_Shift( TextureProjection& projection, float s, float t ); void Texdef_Scale( TextureProjection& projection, float s, float t ); void Texdef_Rotate( TextureProjection& projection, float angle ); diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index f43cecd8..79a2c7d8 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -511,6 +511,32 @@ void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const Texture SceneChangeNotify(); } +class FaceSetTexdef_ +{ +const float* m_hShift; +const float* m_vShift; +const float* m_hScale; +const float* m_vScale; +const float* m_rotation; +public: +FaceSetTexdef_( const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ) : + m_hShift( hShift ), m_vShift( vShift ), m_hScale( hScale ), m_vScale( vScale ), m_rotation( rotation ) { +} +void operator()( Face& face ) const { + face.SetTexdef( m_hShift, m_vShift, m_hScale, m_vScale, m_rotation ); +} +}; + +void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceSetTexdef_( hShift, vShift, hScale, vScale, rotation ) ); + SceneChangeNotify(); +} + +void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + Scene_ForEachSelectedBrushFace( graph, FaceSetTexdef_( hShift, vShift, hScale, vScale, rotation ) ); + SceneChangeNotify(); +} + class FaceSetFlags { diff --git a/radiant/brushmanip.h b/radiant/brushmanip.h index 605348a8..12a97d24 100644 --- a/radiant/brushmanip.h +++ b/radiant/brushmanip.h @@ -49,6 +49,8 @@ void Scene_BrushResize_Selected( scene::Graph& graph, const AABB& bounds, const void Brush_ConstructPlacehoderCuboid( scene::Node& node, const AABB& bounds ); void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const TextureProjection& projection ); void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const TextureProjection& projection ); +void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ); +void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ); void Scene_BrushGetTexdef_Selected( scene::Graph& graph, TextureProjection& projection ); void Scene_BrushGetTexdef_Component_Selected( scene::Graph& graph, TextureProjection& projection ); void Scene_BrushGetShaderSize_Component_Selected( scene::Graph& graph, size_t& width, size_t& height ); diff --git a/radiant/select.cpp b/radiant/select.cpp index 19ee8be6..739f6fd7 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -524,6 +524,13 @@ void Select_SetTexdef( const TextureProjection& projection ){ Scene_BrushSetTexdef_Component_Selected( GlobalSceneGraph(), projection ); } +void Select_SetTexdef( const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ){ + if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { + Scene_BrushSetTexdef_Selected( GlobalSceneGraph(), hShift, vShift, hScale, vScale, rotation ); + } + Scene_BrushSetTexdef_Component_Selected( GlobalSceneGraph(), hShift, vShift, hScale, vScale, rotation ); +} + void Select_SetFlags( const ContentsFlagsValue& flags ){ if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { Scene_BrushSetFlags_Selected( GlobalSceneGraph(), flags ); diff --git a/radiant/select.h b/radiant/select.h index ed314fc9..962677cb 100644 --- a/radiant/select.h +++ b/radiant/select.h @@ -59,6 +59,7 @@ void Select_SetShader_Undo( const char* shader ); class TextureProjection; void Select_SetTexdef( const TextureProjection& projection ); +void Select_SetTexdef( const float* hShift, const float* vShift, const float* hScale, const float* vScale, const float* rotation ); class ContentsFlagsValue; void Select_SetFlags( const ContentsFlagsValue& flags ); diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index 1f4ccd92..6824e2dc 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -186,15 +186,15 @@ GtkEntry* m_texture; SurfaceInspector() : m_textureEntry( ApplyShaderCaller( *this ), UpdateCaller( *this ) ), - m_hshiftSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), + m_hshiftSpinner( ApplyTexdef_HShiftCaller( *this ), UpdateCaller( *this ) ), m_hshiftEntry( Increment::ApplyCaller( m_hshiftIncrement ), Increment::CancelCaller( m_hshiftIncrement ) ), - m_vshiftSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), + m_vshiftSpinner( ApplyTexdef_VShiftCaller( *this ), UpdateCaller( *this ) ), m_vshiftEntry( Increment::ApplyCaller( m_vshiftIncrement ), Increment::CancelCaller( m_vshiftIncrement ) ), - m_hscaleSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), + m_hscaleSpinner( ApplyTexdef_HScaleCaller( *this ), UpdateCaller( *this ) ), m_hscaleEntry( Increment::ApplyCaller( m_hscaleIncrement ), Increment::CancelCaller( m_hscaleIncrement ) ), - m_vscaleSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), + m_vscaleSpinner( ApplyTexdef_VScaleCaller( *this ), UpdateCaller( *this ) ), m_vscaleEntry( Increment::ApplyCaller( m_vscaleIncrement ), Increment::CancelCaller( m_vscaleIncrement ) ), - m_rotateSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), + m_rotateSpinner( ApplyTexdef_RotationCaller( *this ), UpdateCaller( *this ) ), m_rotateEntry( Increment::ApplyCaller( m_rotateIncrement ), Increment::CancelCaller( m_rotateIncrement ) ), m_idleDraw( UpdateCaller( *this ) ), m_valueEntry( ApplyFlagsCaller( *this ), UpdateCaller( *this ) ), @@ -232,8 +232,20 @@ void Update(); typedef MemberCaller UpdateCaller; void ApplyShader(); typedef MemberCaller ApplyShaderCaller; -void ApplyTexdef(); -typedef MemberCaller ApplyTexdefCaller; + +//void ApplyTexdef(); +//typedef MemberCaller ApplyTexdefCaller; +void ApplyTexdef_HShift(); +typedef MemberCaller ApplyTexdef_HShiftCaller; +void ApplyTexdef_VShift(); +typedef MemberCaller ApplyTexdef_VShiftCaller; +void ApplyTexdef_HScale(); +typedef MemberCaller ApplyTexdef_HScaleCaller; +void ApplyTexdef_VScale(); +typedef MemberCaller ApplyTexdef_VScaleCaller; +void ApplyTexdef_Rotation(); +typedef MemberCaller ApplyTexdef_RotationCaller; + void ApplyFlags(); typedef MemberCaller ApplyFlagsCaller; }; @@ -1318,7 +1330,7 @@ void SurfaceInspector::ApplyShader(){ UndoableCommand undo( "textureNameSetSelected" ); Select_SetShader( name.c_str() ); } - +#if 0 void SurfaceInspector::ApplyTexdef(){ texdef_t shiftScaleRotate; @@ -1337,6 +1349,46 @@ void SurfaceInspector::ApplyTexdef(){ UndoableCommand undo( "textureProjectionSetSelected" ); Select_SetTexdef( projection ); } +#endif +void SurfaceInspector::ApplyTexdef_HShift(){ + const float value = static_cast( gtk_spin_button_get_value_as_float( m_hshiftIncrement.m_spin ) ); + StringOutputStream command; + command << "textureProjectionSetSelected -hShift " << value; + UndoableCommand undo( command.c_str() ); + Select_SetTexdef( &value, 0, 0, 0, 0 ); +} + +void SurfaceInspector::ApplyTexdef_VShift(){ + const float value = static_cast( gtk_spin_button_get_value_as_float( m_vshiftIncrement.m_spin ) ); + StringOutputStream command; + command << "textureProjectionSetSelected -vShift " << value; + UndoableCommand undo( command.c_str() ); + Select_SetTexdef( 0, &value, 0, 0, 0 ); +} + +void SurfaceInspector::ApplyTexdef_HScale(){ + const float value = static_cast( gtk_spin_button_get_value_as_float( m_hscaleIncrement.m_spin ) ); + StringOutputStream command; + command << "textureProjectionSetSelected -hScale " << value; + UndoableCommand undo( command.c_str() ); + Select_SetTexdef( 0, 0, &value, 0, 0 ); +} + +void SurfaceInspector::ApplyTexdef_VScale(){ + const float value = static_cast( gtk_spin_button_get_value_as_float( m_vscaleIncrement.m_spin ) ); + StringOutputStream command; + command << "textureProjectionSetSelected -vScale " << value; + UndoableCommand undo( command.c_str() ); + Select_SetTexdef( 0, 0, 0, &value, 0 ); +} + +void SurfaceInspector::ApplyTexdef_Rotation(){ + const float value = static_cast( gtk_spin_button_get_value_as_float( m_rotateIncrement.m_spin ) ); + StringOutputStream command; + command << "textureProjectionSetSelected -rotation " << value; + UndoableCommand undo( command.c_str() ); + Select_SetTexdef( 0, 0, 0, 0, &value ); +} void SurfaceInspector::ApplyFlags(){ unsigned int surfaceflags = 0;