misc...
	* changed surface inspector behavior from 'set whole texture projection' to 'set modified value' (makes sense for multiple surfaces selected)
	* BP: surface inspector and Tex* binds scale texture by its axes, not world axes
	* BP: fix rotation of tex projection with scale S != scale T
	* BP: fix ruining nonregular tex projections by surface inspector (for example after fit/seamless/arbitrary projection)
	* jump over tex projection scale = 0 case, while modifying one (AP and BP)
This commit is contained in:
Garux 2017-08-02 09:45:26 +03:00
parent 492f00b729
commit a102c41b48
9 changed files with 264 additions and 16 deletions

View File

@ -273,6 +273,22 @@ inline double vector2_cross( const BasicVector2<Element>& self, const BasicVecto
return self.x() * other.y() - self.y() * other.x();
}
template<typename Element>
inline Element float_divided( Element f, Element other ){
//ASSERT_MESSAGE(other != 0, "float_divided: invalid divisor");
return f / other;
}
template<typename Element>
inline BasicVector2<Element> vector2_normalised( const BasicVector2<Element>& self ){
return vector2_scaled( self, float_divided( 1.0, vector2_length( self ) ) );
}
template<typename Element>
inline void vector2_normalise( BasicVector2<Element>& 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<Element>& self ){
return sqrt( vector3_length_squared( self ) );
}
template<typename Element>
inline Element float_divided( Element f, Element other ){
//ASSERT_MESSAGE(other != 0, "float_divided: invalid divisor");
return f / other;
}
template<typename Element>
inline BasicVector3<Element> vector3_normalised( const BasicVector3<Element>& self ){
return vector3_scaled( self, float_divided( 1.0, vector3_length( self ) ) );

View File

@ -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();
}

View File

@ -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>( 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<float>( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[1][0] ) ) );
texdef.scale[1] = static_cast<float>( 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<float>( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[0][1] ) ) );
texdef.scale[1] = static_cast<float>( 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<float>( 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<float>( 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 );

View File

@ -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 );

View File

@ -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
{

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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<SurfaceInspector, &SurfaceInspector::Update> UpdateCaller;
void ApplyShader();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyShader> ApplyShaderCaller;
void ApplyTexdef();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef> ApplyTexdefCaller;
//void ApplyTexdef();
//typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef> ApplyTexdefCaller;
void ApplyTexdef_HShift();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef_HShift> ApplyTexdef_HShiftCaller;
void ApplyTexdef_VShift();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef_VShift> ApplyTexdef_VShiftCaller;
void ApplyTexdef_HScale();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef_HScale> ApplyTexdef_HScaleCaller;
void ApplyTexdef_VScale();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef_VScale> ApplyTexdef_VScaleCaller;
void ApplyTexdef_Rotation();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyTexdef_Rotation> ApplyTexdef_RotationCaller;
void ApplyFlags();
typedef MemberCaller<SurfaceInspector, &SurfaceInspector::ApplyFlags> 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<float>( 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<float>( 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<float>( 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<float>( 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<float>( 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;