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)
This commit is contained in:
Garux 2017-08-02 09:47:05 +03:00
parent b0c4caa9d1
commit da43652df1
10 changed files with 225 additions and 46 deletions

View File

@ -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 ); 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 ){ 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 ); 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(); 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 ){ void FitTexture( float s_repeat, float t_repeat ){
undoSave(); undoSave();
m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat ); m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat );

View File

@ -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 ){ 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 ) { if ( w.numpoints < 3 ) {
return; return;
@ -1552,8 +1561,7 @@ void Q3_to_BP( const texdef_t& texdef, float width, float height, const Vector3&
/// for arbitrary texture projections /// 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 ){ void Texdef_Construct_local2tex4projection( const texdef_t& texdef, std::size_t width, std::size_t height, const Vector3& normal, const Vector3* direction, Matrix4& local2tex ){
Matrix4 local2tex;
Texdef_toTransform( texdef, (float)width, (float)height, local2tex ); Texdef_toTransform( texdef, (float)width, (float)height, local2tex );
{ {
if( direction ){ //arbitrary 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 ); 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 ){ 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[0] = anchor;
points[1] = texX + anchor; points[1] = texX + anchor;
points[2] = texY + 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 // compute texture matrix
projection.m_brushprimit_texdef.coords[0][2] = st[0][0]; 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[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 ); 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;
}
}
}

View File

@ -107,7 +107,10 @@ void Texdef_Shift( TextureProjection& projection, float s, float t );
void Texdef_Scale( TextureProjection& projection, float s, float t ); void Texdef_Scale( TextureProjection& projection, float s, float t );
void Texdef_Rotate( TextureProjection& projection, float angle ); 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, 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_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 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 ); void ShiftScaleRotate_fromFace( texdef_t& shiftScaleRotate, const TextureProjection& projection );

View File

@ -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 ){ 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 ){ inline int texture_axis( const Vector3& normal ){
// axis dominance order: Z, X, Y // axis dominance order: Z, X, Y
return ( normal.x() >= normal.y() ) ? ( normal.x() > normal.z() ) ? 0 : 2 : ( normal.y() > normal.z() ) ? 1 : 2; return ( normal.x() >= normal.y() ) ? ( normal.x() > normal.z() ) ? 0 : 2 : ( normal.y() > normal.z() ) ? 1 : 2;
} }
void Patch::CapTexture(){ void Patch::CapTexture(){
#if 0
const PatchControl& p1 = m_ctrl[m_width]; const PatchControl& p1 = m_ctrl[m_width];
const PatchControl& p2 = m_ctrl[m_width * ( m_height - 1 )]; const PatchControl& p2 = m_ctrl[m_width * ( m_height - 1 )];
const PatchControl& p3 = 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] ); normal[2] = fabs( normal[2] );
ProjectTexture( texture_axis( normal ) ); 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 // 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(); CapTexture();
controlPointsChanged(); controlPointsChanged();
} }
#if 0
void Patch::ProjectTexture( int nAxis ){ void Patch::ProjectTexture( int nAxis ){
undoSave(); undoSave();
@ -1161,6 +1186,41 @@ void Patch::ProjectTexture( int nAxis ){
controlPointsChanged(); 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 ){ void Patch::constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ){
setDims( width, height ); setDims( width, height );

View File

@ -64,6 +64,8 @@
#include "xml/ixml.h" #include "xml/ixml.h"
#include "dragplanes.h" #include "dragplanes.h"
#include "brush_primit.h"
enum EPatchType enum EPatchType
{ {
ePatchTypeQuake3, ePatchTypeQuake3,
@ -467,7 +469,7 @@ void construct(){
public: public:
Callback m_lightsChanged; Callback m_lightsChanged;
static int m_CycleCapIndex; // = 0; //static int m_CycleCapIndex; // = 0;
static EPatchType m_type; static EPatchType m_type;
STRING_CONSTANT( Name, "Patch" ); 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 SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT
void CapTexture(); void CapTexture();
void NaturalTexture(); 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 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); void createThickenedWall(const Patch& sourcePatch, const Patch& targetPatch, const int wallIndex);

View File

@ -291,13 +291,31 @@ class PatchCapTexture
{ {
public: public:
void operator()( Patch& patch ) const { void operator()( Patch& patch ) const {
patch.ProjectTexture( Patch::m_CycleCapIndex ); //patch.ProjectTexture( Patch::m_CycleCapIndex );
patch.CapTexture();
} }
}; };
void Scene_PatchCapTexture_Selected( scene::Graph& graph ){ void Scene_PatchCapTexture_Selected( scene::Graph& graph ){
Scene_forEachVisibleSelectedPatch( PatchCapTexture() ); 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(); SceneChangeNotify();
} }
@ -674,12 +692,6 @@ void Patch_Cap(){
Scene_PatchDoCap_Selected( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); Scene_PatchDoCap_Selected( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
} }
void Patch_CycleProjection(){
UndoableCommand undo( "patchCycleUVProjectionAxis" );
Scene_PatchCapTexture_Selected( GlobalSceneGraph() );
}
///\todo Unfinished. ///\todo Unfinished.
void Patch_OverlayOn(){ void Patch_OverlayOn(){
} }
@ -849,7 +861,7 @@ void Patch_registerCommands(){
GlobalCommands_insert( "SmoothCols", FreeCaller<Patch_SmoothCols>(), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); GlobalCommands_insert( "SmoothCols", FreeCaller<Patch_SmoothCols>(), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
GlobalCommands_insert( "MatrixTranspose", FreeCaller<Patch_Transpose>(), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); GlobalCommands_insert( "MatrixTranspose", FreeCaller<Patch_Transpose>(), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
GlobalCommands_insert( "CapCurrentCurve", FreeCaller<Patch_Cap>(), Accelerator( 'C', (GdkModifierType)GDK_SHIFT_MASK ) ); GlobalCommands_insert( "CapCurrentCurve", FreeCaller<Patch_Cap>(), Accelerator( 'C', (GdkModifierType)GDK_SHIFT_MASK ) );
GlobalCommands_insert( "CycleCapTexturePatch", FreeCaller<Patch_CycleProjection>(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) ); GlobalCommands_insert( "PatchCapTexture", FreeCaller<Patch_CapTexture>(), Accelerator( 'N', (GdkModifierType)GDK_SHIFT_MASK ) );
// GlobalCommands_insert( "MakeOverlayPatch", FreeCaller<Patch_OverlayOn>(), Accelerator( 'Y' ) ); // GlobalCommands_insert( "MakeOverlayPatch", FreeCaller<Patch_OverlayOn>(), Accelerator( 'Y' ) );
// GlobalCommands_insert( "ClearPatchOverlays", FreeCaller<Patch_OverlayOff>(), Accelerator( 'L', (GdkModifierType)GDK_CONTROL_MASK ) ); // GlobalCommands_insert( "ClearPatchOverlays", FreeCaller<Patch_OverlayOff>(), Accelerator( 'L', (GdkModifierType)GDK_CONTROL_MASK ) );
GlobalCommands_insert( "PatchDeform", FreeCaller<Patch_Deform>() ); GlobalCommands_insert( "PatchDeform", FreeCaller<Patch_Deform>() );
@ -928,7 +940,7 @@ void Patch_constructMenu( GtkMenu* menu ){
if ( g_Layout_enableDetachableMenus.m_value ) { if ( g_Layout_enableDetachableMenus.m_value ) {
menu_tearoff( menu_in_menu ); 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, "Naturalize", "NaturalizePatch" );
create_menu_item_with_mnemonic( menu_in_menu, "Invert X", "InvertCurveTextureX" ); create_menu_item_with_mnemonic( menu_in_menu, "Invert X", "InvertCurveTextureX" );
create_menu_item_with_mnemonic( menu_in_menu, "Invert Y", "InvertCurveTextureY" ); create_menu_item_with_mnemonic( menu_in_menu, "Invert Y", "InvertCurveTextureY" );

View File

@ -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_PatchFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace );
void Scene_PatchCapTexture_Selected( scene::Graph& graph ); void Scene_PatchCapTexture_Selected( scene::Graph& graph );
class texdef_t;
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction );
void Scene_PatchNaturalTexture_Selected( scene::Graph& graph ); void Scene_PatchNaturalTexture_Selected( scene::Graph& graph );
void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ); void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t );

View File

@ -891,6 +891,7 @@ void Select_Touching( void ){
void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){ void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){
if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) {
Scene_BrushProjectTexture_Selected( GlobalSceneGraph(), texdef, direction ); Scene_BrushProjectTexture_Selected( GlobalSceneGraph(), texdef, direction );
Scene_PatchProjectTexture_Selected( GlobalSceneGraph(), texdef, direction );
} }
Scene_BrushProjectTexture_Component_Selected( GlobalSceneGraph(), texdef, direction ); Scene_BrushProjectTexture_Component_Selected( GlobalSceneGraph(), texdef, direction );

View File

@ -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 ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_face;
const ButtonIdentifier c_button_texture = c_buttonMiddle; 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_texture2_seamless = c_modifierControl;
const ModifierFlags c_modifier_apply_texture3 = c_modifierShift; const ModifierFlags c_modifier_apply_texture3 = c_modifierShift;
const ModifierFlags c_modifier_copy_texture = c_modifierNone; 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_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_ class TexManipulator_
{ {
@ -4118,10 +4119,10 @@ void mouseDown( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) ); ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored ); 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; m_undo_begun = true;
GlobalUndoSystem().start(); 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 ) { else if ( m_state == c_modifier_copy_texture ) {
Scene_copyClosestTexture( volume ); Scene_copyClosestTexture( volume );
@ -4134,14 +4135,14 @@ void mouseMoved( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) ); ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored ); 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<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller; typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller;
void mouseUp( DeviceVector position ){ void mouseUp( DeviceVector position ){
if( m_undo_begun ){ if( m_undo_begun ){
GlobalUndoSystem().finish( "paintTexture" ); GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project ) ? "projectTexture" : "paintTexture" );
m_undo_begun = false; m_undo_begun = false;
} }
g_mouseMovedCallback.clear(); g_mouseMovedCallback.clear();

View File

@ -549,8 +549,8 @@ static void OnBtnReset( GtkWidget *widget, gpointer data ){
static void OnBtnProject( GtkWidget *widget, gpointer data ){ static void OnBtnProject( GtkWidget *widget, gpointer data ){
if ( g_bp_globals.m_texdefTypeId != TEXDEFTYPEID_BRUSHPRIMITIVES ) { if ( g_bp_globals.m_texdefTypeId != TEXDEFTYPEID_BRUSHPRIMITIVES ) {
globalErrorStream() << "function is implemented for BRUSHPRIMITIVES map format only\n"; globalErrorStream() << "function doesn't work for *brushes* in map formats other than BRUSHPRIMITIVES\n";
return; //return;
} }
getSurfaceInspector().exportData(); getSurfaceInspector().exportData();
SurfaceInspector_ProjectTexture(); SurfaceInspector_ProjectTexture();
@ -1453,7 +1453,7 @@ void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& proje
typedef Function4<Face&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Face_getTexture> FaceGetTexture; typedef Function4<Face&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Face_getTexture> FaceGetTexture;
/* copied from winding.cpp */
inline bool float_is_largest_absolute( double axis, double other ){ inline bool float_is_largest_absolute( double axis, double other ){
return fabs( axis ) > fabs( other ); return fabs( axis ) > fabs( other );
} }
@ -1502,7 +1502,8 @@ void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProj
face.SetShader( shader ); face.SetShader( shader );
DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() ); 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<float>( 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<float>( 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() ); //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() ); //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"; //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<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Seamless> FaceSetTextureSeamless; typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Seamless> 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<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Project> FaceSetTextureProject;
void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader ); face.SetShader( shader );
face.SetTexdef( projection ); face.SetTexdef( projection );
@ -1555,6 +1566,12 @@ void Patch_getTexture( Patch& patch, CopiedString& shader, TextureProjection& pr
} }
typedef Function4<Patch&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Patch_getTexture> PatchGetTexture; typedef Function4<Patch&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Patch_getTexture> 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<Patch&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Patch_setTexture_Project> PatchSetTextureProject;
void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
patch.SetShader( shader ); 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() ) { if ( face.isFiltered() ) {
return; return;
} }
@ -1580,7 +1597,9 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be
if ( intersection.valid() if ( intersection.valid()
&& SelectionIntersection_closer( intersection, bestIntersection ) ) { && SelectionIntersection_closer( intersection, bestIntersection ) ) {
bestIntersection = intersection; bestIntersection = intersection;
if( seamless ) if( project )
texturable.setTexture = makeCallback3( FaceSetTextureProject(), face );
else if( seamless )
texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face ); texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face );
else else
texturable.setTexture = makeCallback3( FaceSetTexture(), face ); texturable.setTexture = makeCallback3( FaceSetTexture(), face );
@ -1614,9 +1633,10 @@ class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker
SelectionTest& m_test; SelectionTest& m_test;
Texturable& m_texturable; Texturable& m_texturable;
bool m_seamless; bool m_seamless;
bool m_project;
mutable SelectionIntersection m_bestIntersection; mutable SelectionIntersection m_bestIntersection;
public: 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 { bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( path.top().get().visible() ) { 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 ) 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 else
@ -1639,6 +1659,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( occluded ) { if ( occluded ) {
Patch* patch = Node_getPatch( path.top() ); Patch* patch = Node_getPatch( path.top() );
if ( patch != 0 ) { if ( patch != 0 ) {
if( m_project )
m_texturable.setTexture = makeCallback3( PatchSetTextureProject(), *patch );
else
m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch ); m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch );
m_texturable.getTexture = makeCallback3( PatchGetTexture(), *patch ); m_texturable.getTexture = makeCallback3( PatchGetTexture(), *patch );
} }
@ -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; Texturable texturable;
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless ) ); graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless, project ) );
return texturable; return texturable;
} }
@ -1672,8 +1695,8 @@ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedSt
return false; return false;
} }
void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool 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 ); Texturable texturable = Scene_getClosestTexturable( graph, test, seamless, project );
if ( texturable.setTexture != SetTextureCallback() ) { if ( texturable.setTexture != SetTextureCallback() ) {
texturable.setTexture( shader, projection, flags ); 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" ); // 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(); SceneChangeNotify();
} }