* texture locking during vertex and edge manipulations

This commit is contained in:
Garux 2017-12-06 13:57:40 +03:00
parent 98270201b2
commit 723a615110
8 changed files with 128 additions and 77 deletions

View File

@ -36,6 +36,7 @@ QuantiseFunc Face::m_quantise;
EBrushType Face::m_type;
EBrushType FacePlane::m_type;
bool g_brush_texturelock_enabled = false;
bool g_brush_textureVertexlock_enabled = false;
EBrushType Brush::m_type;
double Brush::m_maxWorldCoord = 0;

View File

@ -883,6 +883,7 @@ void Brush_textureChanged();
extern bool g_brush_texturelock_enabled;
extern bool g_brush_textureVertexlock_enabled;
inline TexdefTypeId BrushType_getTexdefType( EBrushType type ){
switch ( type )
@ -1106,6 +1107,17 @@ void render( Renderer& renderer, const Matrix4& localToWorld ) const {
renderer.addRenderable( *this, localToWorld );
}
void texdef_from_points(){
Matrix4 local2tex;
Texdef_Construct_local2tex( m_texdef.m_projection, m_shader.width(), m_shader.height(), m_plane.plane3().normal(), local2tex );
DoubleVector3 st[3];
for ( std::size_t i = 0; i < 3; ++i )
st[i] = matrix4_transformed_point( local2tex, m_move_planepts[i] );
Texdef_from_ST( m_texdefTransformed, m_move_planeptsTransformed, st, m_shader.width(), m_shader.height() );
Brush_textureChanged();
}
void transform( const Matrix4& matrix, bool mirror ){
if ( g_brush_texturelock_enabled ) {
if( m_centroid_saved_reset ){
@ -2767,6 +2779,9 @@ void transformComponents( const Matrix4& matrix ){
m_face->assign_planepts( m_face->m_move_planeptsTransformed );
}
}
if ( g_brush_textureVertexlock_enabled && ( selectedVertices() || selectedEdges() ) ) {
m_face->texdef_from_points();
}
}
void snapto( float snap ){

View File

@ -1550,6 +1550,58 @@ double Det3x3( double a00, double a01, double a02,
+ a02 * ( a10 * a21 - a11 * a20 );
}
void BP_from_ST( brushprimit_texdef_t& bp, DoubleVector3 points[3], DoubleVector3 st[3], const DoubleVector3& normal ){
double xyI[2], xyJ[2], xyK[2];
double stI[2], stJ[2], stK[2];
double D, D0, D1, D2;
DoubleVector3 texX, texY;
ComputeAxisBase( normal, texX, texY );
xyI[0] = vector3_dot( points[0], texX );
xyI[1] = vector3_dot( points[0], texY );
xyJ[0] = vector3_dot( points[1], texX );
xyJ[1] = vector3_dot( points[1], texY );
xyK[0] = vector3_dot( points[2], texX );
xyK[1] = vector3_dot( points[2], texY );
stI[0] = st[0][0]; stI[1] = st[0][1];
stJ[0] = st[1][0]; stJ[1] = st[1][1];
stK[0] = st[2][0]; stK[1] = st[2][1];
// - solve linear equations:
// - (x, y) := xyz . (texX, texY)
// - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
// (for three vertices)
D = Det3x3(
xyI[0], xyI[1], 1,
xyJ[0], xyJ[1], 1,
xyK[0], xyK[1], 1
);
if ( D != 0 ) {
for ( std::size_t i = 0; i < 2; ++i )
{
D0 = Det3x3(
stI[i], xyI[1], 1,
stJ[i], xyJ[1], 1,
stK[i], xyK[1], 1
);
D1 = Det3x3(
xyI[0], stI[i], 1,
xyJ[0], stJ[i], 1,
xyK[0], stK[i], 1
);
D2 = Det3x3(
xyI[0], xyI[1], stI[i],
xyJ[0], xyJ[1], stJ[i],
xyK[0], xyK[1], stK[i]
);
bp.coords[i][0] = D0 / D;
bp.coords[i][1] = D1 / D;
bp.coords[i][2] = fmod( D2 / D, 1.0 );
}
// globalOutputStream() << "BP out: ( " << bp.coords[0][0] << " " << bp.coords[0][1] << " " << bp.coords[0][2] << " ) ( " << bp.coords[1][0] << " " << bp.coords[1][1] << " " << bp.coords[1][2] << " )\n";
}
}
Vector3 plane3_project_point( const Plane3& plane, const Vector3& point, const Vector3& direction ){
const float f = vector3_dot( plane.normal(), direction );
const float d = ( vector3_dot( plane.normal() * plane.dist() - point, plane.normal() ) ) / f;
@ -1620,9 +1672,6 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
matrix4_transform_point( identity2transformed, points[i] );
}
double xyI[2], xyJ[2], xyK[2];
double stI[2], stJ[2], stK[2];
double D, D0, D1, D2;
#if 0
Matrix4 maa( matrix4_affine_inverse( identity2transformed ) );
matrix4_transpose( maa );
@ -1633,51 +1682,7 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
if( matrix4_handedness( identity2transformed ) == MATRIX4_LEFTHANDED )
vector3_negate( normalTransformed );
#endif
ComputeAxisBase( normalTransformed, texX, texY );
xyI[0] = vector3_dot( points[0], texX );
xyI[1] = vector3_dot( points[0], texY );
xyJ[0] = vector3_dot( points[1], texX );
xyJ[1] = vector3_dot( points[1], texY );
xyK[0] = vector3_dot( points[2], texX );
xyK[1] = vector3_dot( points[2], texY );
stI[0] = st[0][0]; stI[1] = st[0][1];
stJ[0] = st[1][0]; stJ[1] = st[1][1];
stK[0] = st[2][0]; stK[1] = st[2][1];
// - solve linear equations:
// - (x, y) := xyz . (texX, texY)
// - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
// (for three vertices)
D = Det3x3(
xyI[0], xyI[1], 1,
xyJ[0], xyJ[1], 1,
xyK[0], xyK[1], 1
);
if ( D != 0 ) {
for ( std::size_t i = 0; i < 2; ++i )
{
D0 = Det3x3(
stI[i], xyI[1], 1,
stJ[i], xyJ[1], 1,
stK[i], xyK[1], 1
);
D1 = Det3x3(
xyI[0], stI[i], 1,
xyJ[0], stJ[i], 1,
xyK[0], stK[i], 1
);
D2 = Det3x3(
xyI[0], xyI[1], stI[i],
xyJ[0], xyJ[1], stJ[i],
xyK[0], xyK[1], stK[i]
);
projection.m_brushprimit_texdef.coords[i][0] = D0 / D;
projection.m_brushprimit_texdef.coords[i][1] = D1 / D;
projection.m_brushprimit_texdef.coords[i][2] = fmod( D2 / D, 1.0 );
}
// globalOutputStream() << "BP out: ( " << projection.m_brushprimit_texdef.coords[0][0] << " " << projection.m_brushprimit_texdef.coords[0][1] << " " << projection.m_brushprimit_texdef.coords[0][2] << " ) ( " << projection.m_brushprimit_texdef.coords[1][0] << " " << projection.m_brushprimit_texdef.coords[1][1] << " " << projection.m_brushprimit_texdef.coords[1][2] << " )\n";
}
BP_from_ST( projection.m_brushprimit_texdef, points, st, normalTransformed );
}
else if( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_QUAKE ) {
// globalOutputStream() << "\t\t***: " << centroid << "\n";
@ -2064,6 +2069,38 @@ void AP_from_BP( const Plane3& plane, TextureProjection& projection, std::size_t
Texdef_normalise( projection.m_texdef, (float)width, (float)height );
}
void Valve220_from_BP( const Plane3& plane, TextureProjection& projection, std::size_t width, std::size_t height ) {
// globalOutputStream() << "BP: ( " << projection.m_brushprimit_texdef.coords[0][0] << " " << projection.m_brushprimit_texdef.coords[0][1] << " " << projection.m_brushprimit_texdef.coords[0][2] << " ) ( " << projection.m_brushprimit_texdef.coords[1][0] << " " << projection.m_brushprimit_texdef.coords[1][1] << " " << projection.m_brushprimit_texdef.coords[1][2] << " )\n";
#if 0
projection.m_texdef.scale[0] = 1.0 / ( vector2_length( Vector2( projection.m_brushprimit_texdef.coords[0][0], projection.m_brushprimit_texdef.coords[0][1] ) ) * (double)width );
projection.m_texdef.scale[1] = 1.0 / ( vector2_length( Vector2( projection.m_brushprimit_texdef.coords[1][0], projection.m_brushprimit_texdef.coords[1][1] ) ) * (double)height );
projection.m_texdef.shift[0] = projection.m_brushprimit_texdef.coords[0][2] * (float)width;
projection.m_texdef.shift[1] = projection.m_brushprimit_texdef.coords[1][2] * (float)height;
projection.m_texdef.rotate = static_cast<float>( -radians_to_degrees( arctangent_yx( projection.m_brushprimit_texdef.coords[0][1], projection.m_brushprimit_texdef.coords[0][0] ) ) );
if( projection.m_brushprimit_texdef.coords[0][0] * projection.m_brushprimit_texdef.coords[1][1] < 0 )
projection.m_texdef.rotate = -projection.m_texdef.rotate;
DoubleVector3 texX, texY;
ComputeAxisBase( plane.normal(), texX, texY );
projection.m_basis_s = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[0][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[0][1] ) );
projection.m_basis_t = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[1][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[1][1] ) );
#else
/* more reliable values this way */
DoubleVector3 texX, texY;
ComputeAxisBase( plane.normal(), texX, texY );
projection.m_basis_s = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[0][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[0][1] ) );
projection.m_basis_t = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[1][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[1][1] ) );
projection.m_brushprimit_texdef.removeScale( width, height );
TexMatToFakeTexCoords( projection.m_brushprimit_texdef, projection.m_texdef );
projection.m_texdef.shift[0] *= -1.f;
if( projection.m_brushprimit_texdef.coords[0][0] < 0 )
projection.m_basis_s *= -1.f;
if( projection.m_brushprimit_texdef.coords[1][1] < 0 )
projection.m_basis_t *= -1.f;
#endif
// globalOutputStream() << "AP: scale( " << projection.m_texdef.scale[0] << " " << projection.m_texdef.scale[1] << " ) shift( " << projection.m_texdef.shift[0] << " " << projection.m_texdef.shift[1] << " ) rotate: " << projection.m_texdef.rotate << "\n";
}
/// g_bp_globals.m_texdefTypeId == 'in' during this
void Texdef_Convert( TexdefTypeId in, TexdefTypeId out, const Plane3& plane, TextureProjection& projection, std::size_t width, std::size_t height ) {
switch( out ) {
@ -2101,38 +2138,24 @@ void Texdef_Convert( TexdefTypeId in, TexdefTypeId out, const Plane3& plane, Tex
Valve220_rotate( projection, projection.m_texdef.rotate );
}
else if( in == TEXDEFTYPEID_BRUSHPRIMITIVES ){
// globalOutputStream() << "BP: ( " << projection.m_brushprimit_texdef.coords[0][0] << " " << projection.m_brushprimit_texdef.coords[0][1] << " " << projection.m_brushprimit_texdef.coords[0][2] << " ) ( " << projection.m_brushprimit_texdef.coords[1][0] << " " << projection.m_brushprimit_texdef.coords[1][1] << " " << projection.m_brushprimit_texdef.coords[1][2] << " )\n";
#if 0
projection.m_texdef.scale[0] = 1.0 / ( vector2_length( Vector2( projection.m_brushprimit_texdef.coords[0][0], projection.m_brushprimit_texdef.coords[0][1] ) ) * (double)width );
projection.m_texdef.scale[1] = 1.0 / ( vector2_length( Vector2( projection.m_brushprimit_texdef.coords[1][0], projection.m_brushprimit_texdef.coords[1][1] ) ) * (double)height );
projection.m_texdef.shift[0] = projection.m_brushprimit_texdef.coords[0][2] * (float)width;
projection.m_texdef.shift[1] = projection.m_brushprimit_texdef.coords[1][2] * (float)height;
projection.m_texdef.rotate = static_cast<float>( -radians_to_degrees( arctangent_yx( projection.m_brushprimit_texdef.coords[0][1], projection.m_brushprimit_texdef.coords[0][0] ) ) );
if( projection.m_brushprimit_texdef.coords[0][0] * projection.m_brushprimit_texdef.coords[1][1] < 0 )
projection.m_texdef.rotate = -projection.m_texdef.rotate;
DoubleVector3 texX, texY;
ComputeAxisBase( plane.normal(), texX, texY );
projection.m_basis_s = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[0][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[0][1] ) );
projection.m_basis_t = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[1][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[1][1] ) );
#else
/* more reliable values this way */
DoubleVector3 texX, texY;
ComputeAxisBase( plane.normal(), texX, texY );
projection.m_basis_s = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[0][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[0][1] ) );
projection.m_basis_t = vector3_normalised( texX * static_cast<double>( projection.m_brushprimit_texdef.coords[1][0] ) + texY * static_cast<double>( projection.m_brushprimit_texdef.coords[1][1] ) );
projection.m_brushprimit_texdef.removeScale( width, height );
TexMatToFakeTexCoords( projection.m_brushprimit_texdef, projection.m_texdef );
projection.m_texdef.shift[0] *= -1.f;
if( projection.m_brushprimit_texdef.coords[0][0] < 0 )
projection.m_basis_s *= -1.f;
if( projection.m_brushprimit_texdef.coords[1][1] < 0 )
projection.m_basis_t *= -1.f;
#endif
// globalOutputStream() << "AP: scale( " << projection.m_texdef.scale[0] << " " << projection.m_texdef.scale[1] << " ) shift( " << projection.m_texdef.shift[0] << " " << projection.m_texdef.shift[1] << " ) rotate: " << projection.m_texdef.rotate << "\n";
Valve220_from_BP( plane, projection, width, height );
}
break;
default:
break;
}
}
void Texdef_from_ST( TextureProjection& projection, DoubleVector3 points[3], DoubleVector3 st[3], std::size_t width, std::size_t height ){
const Plane3 plane( plane3_for_points( points ) );
BP_from_ST( projection.m_brushprimit_texdef, points, st, plane.normal() );
if( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_QUAKE ){
TexdefTypeId tmp = g_bp_globals.m_texdefTypeId;
g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES;
AP_from_BP( plane, projection, width, height );
g_bp_globals.m_texdefTypeId = tmp;
}
else if( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_VALVE ){
Valve220_from_BP( plane, projection, width, height );
}
}

View File

@ -91,6 +91,7 @@ class texdef_t;
struct Winding;
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
typedef BasicVector3<double> DoubleVector3;
template<typename Element> class BasicVector4;
typedef BasicVector4<float> Vector4;
typedef Vector4 Quaternion;
@ -135,6 +136,7 @@ extern bp_globals_t g_bp_globals;
extern float g_texdef_default_scale;
void Texdef_Convert( TexdefTypeId in, TexdefTypeId out, const Plane3& plane, TextureProjection& projection, std::size_t width, std::size_t height );
void Texdef_from_ST( TextureProjection& projection, DoubleVector3 points[3], DoubleVector3 st[3], std::size_t width, std::size_t height );
//void ComputeAxisBase( const Vector3& normal, Vector3& texS, Vector3& texT );
template <typename Element>
void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<Element>& texS, BasicVector3<Element>& texT );

View File

@ -1515,12 +1515,19 @@ void Texdef_ToggleMoveLock(){
g_texture_lock_status_changed();
}
BoolExportCaller g_texdef_moveVlock_caller( g_brush_textureVertexlock_enabled );
ToggleItem g_texdef_moveVlock_item( g_texdef_moveVlock_caller );
void Texdef_ToggleMoveVLock(){
g_brush_textureVertexlock_enabled = !g_brush_textureVertexlock_enabled;
g_texdef_moveVlock_item.update();
}
void Brush_registerCommands(){
GlobalToggles_insert( "TogTexLock", FreeCaller<Texdef_ToggleMoveLock>(), ToggleItem::AddCallbackCaller( g_texdef_movelock_item ), Accelerator( 'T', (GdkModifierType)GDK_SHIFT_MASK ) );
GlobalToggles_insert( "TogTexVertexLock", FreeCaller<Texdef_ToggleMoveVLock>(), ToggleItem::AddCallbackCaller( g_texdef_moveVlock_item ), accelerator_null() );
GlobalCommands_insert( "BrushPrism", BrushPrefab::SetCaller( g_brushprism ) );
GlobalCommands_insert( "BrushCone", BrushPrefab::SetCaller( g_brushcone ) );
@ -1578,6 +1585,7 @@ void Brush_constructMenu( GtkMenu* menu ){
// create_menu_item_with_mnemonic( menu, "Snap selection to _grid", "SnapToGrid" );
create_check_menu_item_with_mnemonic( menu, "Texture Lock", "TogTexLock" );
create_check_menu_item_with_mnemonic( menu, "Texture Vertex Lock", "TogTexVertexLock" );
menu_separator( menu );
create_menu_item_with_mnemonic( menu, "Copy Face Texture", "FaceCopyTexture" );
create_menu_item_with_mnemonic( menu, "Paste Face Texture", "FacePasteTexture" );

View File

@ -167,6 +167,7 @@ void Brush_Construct( EBrushType type ){
}
GlobalPreferenceSystem().registerPreference( "TextureLock", BoolImportStringCaller( g_brush_texturelock_enabled ), BoolExportStringCaller( g_brush_texturelock_enabled ) );
GlobalPreferenceSystem().registerPreference( "TextureVertexLock", BoolImportStringCaller( g_brush_textureVertexlock_enabled ), BoolExportStringCaller( g_brush_textureVertexlock_enabled ) );
GlobalPreferenceSystem().registerPreference( "BrushSnapPlanes", makeBoolStringImportCallback( FaceImportSnapPlanesCaller() ), makeBoolStringExportCallback( FaceExportSnapPlanesCaller() ) );
GlobalPreferenceSystem().registerPreference( "TexdefDefaultScale", FloatImportStringCaller( g_texdef_default_scale ), FloatExportStringCaller( g_texdef_default_scale ) );

View File

@ -2512,6 +2512,7 @@ GtkToolbar* create_main_toolbar( MainFrame::EViewStyle style ){
}
toolbar_append_toggle_button( toolbar, "Texture Lock (SHIFT + T)", "texture_lock.png", "TogTexLock" );
toolbar_append_toggle_button( toolbar, "Texture Vertex Lock", "texture_vertexlock.png", "TogTexVertexLock" );
gtk_toolbar_append_space( toolbar );
toolbar_append_button( toolbar, "Entities (N)", "entities.png", "ToggleEntityInspector" );

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B