From da43652df198a88278e6c4f007c36371a42eab1f Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:47:05 +0300 Subject: [PATCH] Radiant: binds... * ctrl + shift + m3/drag: project tex from face in tex clipboard to brushes(BP format) and curves misc... * fixed and improved normal finding in patch texture autocap algorithm * removed axis cycling in patch cap texture; using autocap * patch cap texture: project, using brush texture projection math of current mapformat to make it seamless with brushes by default * Surface inspector->Project functions work for curves (in AP map format too) --- radiant/brush.h | 10 +++++ radiant/brush_primit.cpp | 83 +++++++++++++++++++++++++++++++++------ radiant/brush_primit.h | 3 ++ radiant/patch.cpp | 64 +++++++++++++++++++++++++++++- radiant/patch.h | 8 +++- radiant/patchmanip.cpp | 32 ++++++++++----- radiant/patchmanip.h | 4 ++ radiant/select.cpp | 1 + radiant/selection.cpp | 13 +++--- radiant/surfacedialog.cpp | 53 ++++++++++++++++++------- 10 files changed, 225 insertions(+), 46 deletions(-) diff --git a/radiant/brush.h b/radiant/brush.h index 7761a862..7356c809 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -598,6 +598,10 @@ void ProjectTexture( const Plane3& plane, const texdef_t& texdef, const Vector3* Texdef_ProjectTexture( m_projection, m_shader.width(), m_shader.height(), plane, texdef, direction ); } +void ProjectTexture( const Plane3& plane, const TextureProjection& projection, const Vector3& normal ){ + Texdef_ProjectTexture( m_projection, m_shader.width(), m_shader.height(), plane, projection, normal ); +} + void fit( const Vector3& normal, const Winding& winding, float s_repeat, float t_repeat ){ Texdef_FitTexture( m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat ); } @@ -1213,6 +1217,12 @@ void ProjectTexture( const texdef_t& texdef, const Vector3* direction ){ texdefChanged(); } +void ProjectTexture( const TextureProjection& projection, const Vector3& normal ){ + undoSave(); + m_texdef.ProjectTexture( m_plane.plane3(), projection, normal ); + texdefChanged(); +} + void FitTexture( float s_repeat, float t_repeat ){ undoSave(); m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat ); diff --git a/radiant/brush_primit.cpp b/radiant/brush_primit.cpp index f4701a2a..c706eb26 100644 --- a/radiant/brush_primit.cpp +++ b/radiant/brush_primit.cpp @@ -256,6 +256,15 @@ void Texdef_basisForNormal( const TextureProjection& projection, const Vector3& } } +void Texdef_Construct_local2tex( const TextureProjection& projection, std::size_t width, std::size_t height, const Vector3& normal, Matrix4& local2tex ){ + Texdef_toTransform( projection, (float)width, (float)height, local2tex ); + { + Matrix4 xyz2st; + Texdef_basisForNormal( projection, normal, xyz2st ); + matrix4_multiply_by_matrix4( local2tex, xyz2st ); + } +} + void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld ){ if ( w.numpoints < 3 ) { return; @@ -1552,8 +1561,7 @@ void Q3_to_BP( const texdef_t& texdef, float width, float height, const Vector3& /// for arbitrary texture projections -void Emit3TextureCoordinates( const texdef_t& texdef, std::size_t width, std::size_t height, const Vector3& normal, DoubleVector3 points[3], DoubleVector3 st[3], const Vector3* direction ){ - Matrix4 local2tex; +void Texdef_Construct_local2tex4projection( const texdef_t& texdef, std::size_t width, std::size_t height, const Vector3& normal, const Vector3* direction, Matrix4& local2tex ){ Texdef_toTransform( texdef, (float)width, (float)height, local2tex ); { if( direction ){ //arbitrary @@ -1570,14 +1578,6 @@ void Emit3TextureCoordinates( const texdef_t& texdef, std::size_t width, std::si matrix4_multiply_by_matrix4( local2tex, xyz2st ); } } - - for ( std::size_t i = 0; i < 3; ++i ) - { - DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] ); - //globalOutputStream() << texcoord << "\n"; - st[i][0] = texcoord[0]; - st[i][1] = texcoord[1]; - } } void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const texdef_t& texdef, const Vector3* direction ){ @@ -1602,7 +1602,16 @@ void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, st points[0] = anchor; points[1] = texX + anchor; points[2] = texY + anchor; - Emit3TextureCoordinates( texdef, width, height, plane.normal(), points, st, direction ); + + Matrix4 local2tex; + Texdef_Construct_local2tex4projection( texdef, width, height, plane.normal(), direction, local2tex ); + for ( std::size_t i = 0; i < 3; ++i ) + { + DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] ); + //globalOutputStream() << texcoord << "\n"; + st[i][0] = texcoord[0]; + st[i][1] = texcoord[1]; + } // compute texture matrix projection.m_brushprimit_texdef.coords[0][2] = st[0][0]; projection.m_brushprimit_texdef.coords[1][2] = st[0][1]; @@ -1613,3 +1622,55 @@ void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, st Texdef_normalise( projection, (float)width, (float)height ); } + +void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, TextureProjection other_proj, const Vector3& other_normal ){ + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { + other_proj.m_brushprimit_texdef.addScale( width, height ); + + DoubleVector3 texX, texY; + + // compute axis base + ComputeAxisBase( plane.normal(), texX, texY ); + // compute projection vector + const DoubleVector3 anchor = plane.normal() * plane.dist(); + + // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the affine plane + // (1,0) in plane axis base is texX in world coordinates + projection on the affine plane + // (0,1) in plane axis base is texY in world coordinates + projection on the affine plane + // use old texture code to compute the ST coords of these points + // ST of (0,0) (1,0) (0,1) + DoubleVector3 points[3]; + DoubleVector3 st[3]; + + points[0] = anchor; + points[1] = texX + anchor; + points[2] = texY + anchor; + + Matrix4 local2tex; + Texdef_Construct_local2tex( other_proj, width, height, other_normal, local2tex ); + for ( std::size_t i = 0; i < 3; ++i ) + { + DoubleVector3 texcoord = matrix4_transformed_point( local2tex, points[i] ); + //globalOutputStream() << texcoord << "\n"; + st[i][0] = texcoord[0]; + st[i][1] = texcoord[1]; + } + // compute texture matrix + projection.m_brushprimit_texdef.coords[0][2] = st[0][0]; + projection.m_brushprimit_texdef.coords[1][2] = st[0][1]; + projection.m_brushprimit_texdef.coords[0][0] = st[1][0] - st[0][0]; + projection.m_brushprimit_texdef.coords[1][0] = st[1][1] - st[0][1]; + projection.m_brushprimit_texdef.coords[0][1] = st[2][0] - st[0][0]; + projection.m_brushprimit_texdef.coords[1][1] = st[2][1] - st[0][1]; + + Texdef_normalise( projection, (float)width, (float)height ); + } + else + { + Texdef_Assign( projection.m_texdef, other_proj.m_texdef ); + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) { + projection.m_basis_s = other_proj.m_basis_s; + projection.m_basis_t = other_proj.m_basis_t; + } + } +} diff --git a/radiant/brush_primit.h b/radiant/brush_primit.h index 61e3d06c..074ca502 100644 --- a/radiant/brush_primit.h +++ b/radiant/brush_primit.h @@ -107,7 +107,10 @@ 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 ); void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const texdef_t& texdef, const Vector3* direction ); +void Texdef_ProjectTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, TextureProjection other_proj, const Vector3& other_normal ); void Texdef_FitTexture( TextureProjection& projection, std::size_t width, std::size_t height, const Vector3& normal, const Winding& w, float s_repeat, float t_repeat ); +void Texdef_Construct_local2tex( const TextureProjection& projection, std::size_t width, std::size_t height, const Vector3& normal, Matrix4& local2tex ); +void Texdef_Construct_local2tex4projection( const texdef_t& texdef, std::size_t width, std::size_t height, const Vector3& normal, const Vector3* direction, Matrix4& local2tex ); void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld ); void ShiftScaleRotate_fromFace( texdef_t& shiftScaleRotate, const TextureProjection& projection ); diff --git a/radiant/patch.cpp b/radiant/patch.cpp index 890087d3..f0f4461b 100644 --- a/radiant/patch.cpp +++ b/radiant/patch.cpp @@ -168,7 +168,7 @@ void BezierCurveTree_FromCurveList( BezierCurveTree *pTree, GSList *pCurveList, } -int Patch::m_CycleCapIndex = 0; +//int Patch::m_CycleCapIndex = 0; void Patch::setDims( std::size_t w, std::size_t h ){ @@ -600,12 +600,31 @@ void Patch::SetTextureRepeat( float s, float t ){ } */ +Vector3 Patch::Calculate_AvgNormal(){ + Vector3 wDir( 0, 0, 0 ), hDir( 0, 0, 0 ); + for ( std::size_t i = 0; i < m_height; ++i ){ + wDir += ctrlAt( i, m_width - 1 ).m_vertex - ctrlAt( i, 0 ).m_vertex; + } + for ( std::size_t i = 0; i < m_width; ++i ){ + hDir += ctrlAt( m_height - 1, i ).m_vertex - ctrlAt( 0, i ).m_vertex; + } + Vector3 normal( vector3_cross( wDir, hDir ) ); + if ( vector3_equal( normal, g_vector3_identity ) ) { + normal = Vector3( 0, 0, 1 ); + } + else{ + vector3_normalise( normal ); + } + return normal; +} + inline int texture_axis( const Vector3& normal ){ // axis dominance order: Z, X, Y return ( normal.x() >= normal.y() ) ? ( normal.x() > normal.z() ) ? 0 : 2 : ( normal.y() > normal.z() ) ? 1 : 2; } void Patch::CapTexture(){ +#if 0 const PatchControl& p1 = m_ctrl[m_width]; const PatchControl& p2 = m_ctrl[m_width * ( m_height - 1 )]; const PatchControl& p3 = m_ctrl[( m_width * m_height ) - 1]; @@ -636,6 +655,12 @@ void Patch::CapTexture(){ normal[2] = fabs( normal[2] ); ProjectTexture( texture_axis( normal ) ); +#else + Vector3 normal = Calculate_AvgNormal(); + TextureProjection projection; + TexDef_Construct_Default( projection ); + ProjectTexture( projection, normal ); +#endif } // uses longest parallel chord to calculate texture coords for each row/col @@ -1125,7 +1150,7 @@ void Patch::ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ){ CapTexture(); controlPointsChanged(); } - +#if 0 void Patch::ProjectTexture( int nAxis ){ undoSave(); @@ -1161,6 +1186,41 @@ void Patch::ProjectTexture( int nAxis ){ controlPointsChanged(); } +#else +void Patch::ProjectTexture( TextureProjection projection, const Vector3& normal ){ + undoSave(); + + projection.m_brushprimit_texdef.addScale( m_state->getTexture().width, m_state->getTexture().height ); + + Matrix4 local2tex; + Texdef_Construct_local2tex( projection, m_state->getTexture().width, m_state->getTexture().height, normal, local2tex ); + + for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) + { + Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).m_vertex ); + ( *i ).m_texcoord[0] = texcoord[0]; + ( *i ).m_texcoord[1] = texcoord[1]; + } + + controlPointsChanged(); +} +#endif + +void Patch::ProjectTexture( const texdef_t& texdef, const Vector3* direction ){ + undoSave(); + + Matrix4 local2tex; + Texdef_Construct_local2tex4projection( texdef, m_state->getTexture().width, m_state->getTexture().height, Calculate_AvgNormal(), direction, local2tex ); + + for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) + { + Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).m_vertex ); + ( *i ).m_texcoord[0] = texcoord[0]; + ( *i ).m_texcoord[1] = texcoord[1]; + } + + controlPointsChanged(); +} void Patch::constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ){ setDims( width, height ); diff --git a/radiant/patch.h b/radiant/patch.h index 19e70383..bf7329e4 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -64,6 +64,8 @@ #include "xml/ixml.h" #include "dragplanes.h" +#include "brush_primit.h" + enum EPatchType { ePatchTypeQuake3, @@ -467,7 +469,7 @@ void construct(){ public: Callback m_lightsChanged; -static int m_CycleCapIndex; // = 0; +//static int m_CycleCapIndex; // = 0; static EPatchType m_type; STRING_CONSTANT( Name, "Patch" ); @@ -921,7 +923,9 @@ void RotateTexture( float angle ); void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT void CapTexture(); void NaturalTexture(); -void ProjectTexture( int nAxis ); +Vector3 Calculate_AvgNormal(); +void ProjectTexture( TextureProjection projection, const Vector3& normal ); +void ProjectTexture( const texdef_t& texdef, const Vector3* direction ); void createThickenedOpposite(const Patch& sourcePatch, const float thickness, const int axis, bool& no12, bool& no34 ); void createThickenedWall(const Patch& sourcePatch, const Patch& targetPatch, const int wallIndex); diff --git a/radiant/patchmanip.cpp b/radiant/patchmanip.cpp index 33bf6472..46089fdd 100644 --- a/radiant/patchmanip.cpp +++ b/radiant/patchmanip.cpp @@ -291,13 +291,31 @@ class PatchCapTexture { public: void operator()( Patch& patch ) const { - patch.ProjectTexture( Patch::m_CycleCapIndex ); + //patch.ProjectTexture( Patch::m_CycleCapIndex ); + patch.CapTexture(); } }; void Scene_PatchCapTexture_Selected( scene::Graph& graph ){ Scene_forEachVisibleSelectedPatch( PatchCapTexture() ); - Patch::m_CycleCapIndex = ( Patch::m_CycleCapIndex + 1 ) % 3; + //Patch::m_CycleCapIndex = ( Patch::m_CycleCapIndex + 1 ) % 3; + SceneChangeNotify(); +} + +class PatchProjectTexture +{ + const texdef_t& m_texdef; + const Vector3* m_direction; +public: + PatchProjectTexture( const texdef_t& texdef, const Vector3* direction ) : m_texdef( texdef ), m_direction( direction ) { + } + void operator()( Patch& patch ) const { + patch.ProjectTexture( m_texdef, m_direction ); + } +}; + +void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ){ + Scene_forEachVisibleSelectedPatch( PatchProjectTexture( texdef, direction ) ); SceneChangeNotify(); } @@ -674,12 +692,6 @@ void Patch_Cap(){ Scene_PatchDoCap_Selected( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); } -void Patch_CycleProjection(){ - UndoableCommand undo( "patchCycleUVProjectionAxis" ); - - Scene_PatchCapTexture_Selected( GlobalSceneGraph() ); -} - ///\todo Unfinished. void Patch_OverlayOn(){ } @@ -849,7 +861,7 @@ void Patch_registerCommands(){ GlobalCommands_insert( "SmoothCols", FreeCaller(), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); GlobalCommands_insert( "MatrixTranspose", FreeCaller(), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); GlobalCommands_insert( "CapCurrentCurve", FreeCaller(), Accelerator( 'C', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "CycleCapTexturePatch", FreeCaller(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "PatchCapTexture", FreeCaller(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) ); // GlobalCommands_insert( "MakeOverlayPatch", FreeCaller(), Accelerator( 'Y' ) ); // GlobalCommands_insert( "ClearPatchOverlays", FreeCaller(), Accelerator( 'L', (GdkModifierType)GDK_CONTROL_MASK ) ); GlobalCommands_insert( "PatchDeform", FreeCaller() ); @@ -928,7 +940,7 @@ void Patch_constructMenu( GtkMenu* menu ){ if ( g_Layout_enableDetachableMenus.m_value ) { menu_tearoff( menu_in_menu ); } - create_menu_item_with_mnemonic( menu_in_menu, "Cycle Projection", "CycleCapTexturePatch" ); + create_menu_item_with_mnemonic( menu_in_menu, "Project", "PatchCapTexture" ); create_menu_item_with_mnemonic( menu_in_menu, "Naturalize", "NaturalizePatch" ); create_menu_item_with_mnemonic( menu_in_menu, "Invert X", "InvertCurveTextureX" ); create_menu_item_with_mnemonic( menu_in_menu, "Invert Y", "InvertCurveTextureY" ); diff --git a/radiant/patchmanip.h b/radiant/patchmanip.h index d6d8764c..c97fc61e 100644 --- a/radiant/patchmanip.h +++ b/radiant/patchmanip.h @@ -42,6 +42,10 @@ void Scene_PatchFindReplaceShader( scene::Graph& graph, const char* find, const void Scene_PatchFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ); void Scene_PatchCapTexture_Selected( scene::Graph& graph ); +class texdef_t; +template class BasicVector3; +typedef BasicVector3 Vector3; +void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); void Scene_PatchNaturalTexture_Selected( scene::Graph& graph ); void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ); diff --git a/radiant/select.cpp b/radiant/select.cpp index d71e5714..20eccbab 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -891,6 +891,7 @@ void Select_Touching( void ){ void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){ if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { Scene_BrushProjectTexture_Selected( GlobalSceneGraph(), texdef, direction ); + Scene_PatchProjectTexture_Selected( GlobalSceneGraph(), texdef, direction ); } Scene_BrushProjectTexture_Component_Selected( GlobalSceneGraph(), texdef, direction ); diff --git a/radiant/selection.cpp b/radiant/selection.cpp index 6681c37e..9d2b412c 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -4092,7 +4092,7 @@ const ModifierFlags c_modifier_toggle_face = c_modifier_toggle | c_modifier_face const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_face; const ButtonIdentifier c_button_texture = c_buttonMiddle; -const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift; +const ModifierFlags c_modifier_apply_texture1_project = c_modifierControl | c_modifierShift; const ModifierFlags c_modifier_apply_texture2_seamless = c_modifierControl; const ModifierFlags c_modifier_apply_texture3 = c_modifierShift; const ModifierFlags c_modifier_copy_texture = c_modifierNone; @@ -4100,7 +4100,8 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone; void Scene_copyClosestTexture( SelectionTest& test ); -void Scene_applyClosestTexture( SelectionTest& test, bool seamless ); +void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project ); +void Scene_projectClosestTexture( SelectionTest& test ); class TexManipulator_ { @@ -4118,10 +4119,10 @@ void mouseDown( DeviceVector position ){ ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) ); SelectionVolume volume( scissored ); - if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) { + if ( m_state == c_modifier_apply_texture1_project || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) { m_undo_begun = true; GlobalUndoSystem().start(); - Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless ); + Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project ); } else if ( m_state == c_modifier_copy_texture ) { Scene_copyClosestTexture( volume ); @@ -4134,14 +4135,14 @@ void mouseMoved( DeviceVector position ){ ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) ); SelectionVolume volume( scissored ); - Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless ); + Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project ); } } typedef MemberCaller1 MouseMovedCaller; void mouseUp( DeviceVector position ){ if( m_undo_begun ){ - GlobalUndoSystem().finish( "paintTexture" ); + GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project ) ? "projectTexture" : "paintTexture" ); m_undo_begun = false; } g_mouseMovedCallback.clear(); diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index 07b34399..797ba2ad 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -549,8 +549,8 @@ static void OnBtnReset( GtkWidget *widget, gpointer data ){ static void OnBtnProject( GtkWidget *widget, gpointer data ){ if ( g_bp_globals.m_texdefTypeId != TEXDEFTYPEID_BRUSHPRIMITIVES ) { - globalErrorStream() << "function is implemented for BRUSHPRIMITIVES map format only\n"; - return; + globalErrorStream() << "function doesn't work for *brushes* in map formats other than BRUSHPRIMITIVES\n"; + //return; } getSurfaceInspector().exportData(); SurfaceInspector_ProjectTexture(); @@ -1453,7 +1453,7 @@ void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& proje typedef Function4 FaceGetTexture; - +/* copied from winding.cpp */ inline bool float_is_largest_absolute( double axis, double other ){ return fabs( axis ) > fabs( other ); } @@ -1502,7 +1502,8 @@ void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProj face.SetShader( shader ); DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() ); - Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ), static_cast( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) ); + Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ), + static_cast( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) ); //Quaternion rotation = quaternion_for_unit_vectors( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ); //rotation.w() = sqrt( vector3_length_squared( g_faceTextureClipboard.m_plane.normal() ) * vector3_length_squared( face.getPlane().plane3().normal() ) ) + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ); //globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n"; @@ -1540,6 +1541,16 @@ void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProj typedef Function4 FaceSetTextureSeamless; +void Face_setTexture_Project( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ + face.SetShader( shader ); + //face.SetTexdef( projection ); + face.SetFlags( flags ); + + face.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() ); +} +typedef Function4 FaceSetTextureProject; + + void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ face.SetShader( shader ); face.SetTexdef( projection ); @@ -1555,6 +1566,12 @@ void Patch_getTexture( Patch& patch, CopiedString& shader, TextureProjection& pr } typedef Function4 PatchGetTexture; +void Patch_setTexture_Project( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ + patch.SetShader( shader ); + patch.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() ); +} +typedef Function4 PatchSetTextureProject; + void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ patch.SetShader( shader ); } @@ -1571,7 +1588,7 @@ struct Texturable }; -void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless ){ +void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless, bool project ){ if ( face.isFiltered() ) { return; } @@ -1580,7 +1597,9 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be if ( intersection.valid() && SelectionIntersection_closer( intersection, bestIntersection ) ) { bestIntersection = intersection; - if( seamless ) + if( project ) + texturable.setTexture = makeCallback3( FaceSetTextureProject(), face ); + else if( seamless ) texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face ); else texturable.setTexture = makeCallback3( FaceSetTexture(), face ); @@ -1614,9 +1633,10 @@ class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker SelectionTest& m_test; Texturable& m_texturable; bool m_seamless; +bool m_project; mutable SelectionIntersection m_bestIntersection; public: -BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ){ +BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless, bool project ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ), m_project( project ){ } bool pre( const scene::Path& path, scene::Instance& instance ) const { if ( path.top().get().visible() ) { @@ -1626,7 +1646,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) { - Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless ); + Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless, m_project ); } } else @@ -1639,7 +1659,10 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { if ( occluded ) { Patch* patch = Node_getPatch( path.top() ); if ( patch != 0 ) { - m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch ); + if( m_project ) + m_texturable.setTexture = makeCallback3( PatchSetTextureProject(), *patch ); + else + m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch ); m_texturable.getTexture = makeCallback3( PatchGetTexture(), *patch ); } else @@ -1657,9 +1680,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { } }; -Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false ){ +Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false, bool project = false ){ Texturable texturable; - graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless ) ); + graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless, project ) ); return texturable; } @@ -1672,8 +1695,8 @@ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedSt return false; } -void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless ){ - Texturable texturable = Scene_getClosestTexturable( graph, test, seamless ); +void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless, bool project ){ + Texturable texturable = Scene_getClosestTexturable( graph, test, seamless, project ); if ( texturable.setTexture != SetTextureCallback() ) { texturable.setTexture( shader, projection, flags ); } @@ -1694,10 +1717,10 @@ void Scene_copyClosestTexture( SelectionTest& test ){ } } -void Scene_applyClosestTexture( SelectionTest& test, bool seamless ){ +void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project ){ // UndoableCommand command( "facePaintTexture" ); - Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless ); + Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless, project ); SceneChangeNotify(); }